Add ephemeral groups

This commit is contained in:
outfoxxed 2023-07-19 03:53:23 -07:00
parent e93aa49b23
commit 51d3991783
No known key found for this signature in database
GPG key ID: 4C88A185FB89301E
7 changed files with 80 additions and 35 deletions

View file

@ -90,7 +90,9 @@ plugin {
``` ```
### Dispatcher list ### Dispatcher list
- `hy3:makegroup, <h | v | opposite | tab>` - make a vertical / horizontal split or tab group - `hy3:makegroup, <h | v | opposite | tab>, [ephemeral | force_ephemeral]` - make a vertical / horizontal split or tab group
- `ephemeral` - the group will be removed once it contains only one node. does not affect existing groups.
- `force_ephemeral` - same as ephemeral, but converts existing single windows groups.
- `hy3:movefocus, <l | u | d | r | left | down | up | right>, [visible]` - move the focus left, up, down, or right - `hy3:movefocus, <l | u | d | r | left | down | up | right>, [visible]` - move the focus left, up, down, or right
- `visible` - only move between visible nodes, not hidden tabs - `visible` - only move between visible nodes, not hidden tabs
- `hy3:movewindow, <l | u | d | r | left | down | up | right>, [once]` - move a window left, up, down, or right - `hy3:movewindow, <l | u | d | r | left | down | up | right>, [once]` - move a window left, up, down, or right

12
flake.lock generated
View file

@ -8,11 +8,11 @@
"xdph": "xdph" "xdph": "xdph"
}, },
"locked": { "locked": {
"lastModified": 1689264334, "lastModified": 1689720698,
"narHash": "sha256-CJv3Qi00et2dFBWXTx9ysYdYauFtxxs+3pXr0gq/UX0=", "narHash": "sha256-DjW5GZlzULXKdEVag13OEV3/hog1k/5ZjSIRIPOHrcQ=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "Hyprland", "repo": "Hyprland",
"rev": "f8def68e7e761e33dd51c197ac89194a51fcb60f", "rev": "81f4a4f47182c15ee9436d9ab7b2e425a096ce5b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -67,11 +67,11 @@
"flake": false, "flake": false,
"locked": { "locked": {
"host": "gitlab.freedesktop.org", "host": "gitlab.freedesktop.org",
"lastModified": 1686753331, "lastModified": 1689611045,
"narHash": "sha256-KovjVFwcuoUO0eu/UiWrnD3+m/K+SHSAVIz4xF9K1XA=", "narHash": "sha256-3RTOlQabkNetQ4O4UzSf57JPco9VGVHhSU1ls5uKBeE=",
"owner": "wlroots", "owner": "wlroots",
"repo": "wlroots", "repo": "wlroots",
"rev": "7e7633abf09b362d0bad9e3fc650fd692369291d", "rev": "7791ffe0584c4ac13c170e1661ce33bdbd4a9b9e",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {

View file

@ -44,7 +44,8 @@ void Hy3Layout::onWindowCreatedTiling(CWindow* window) {
// opening_after->parent cannot be nullptr // opening_after->parent cannot be nullptr
if (opening_after == root) { if (opening_after == root) {
opening_after = opening_after->intoGroup(Hy3GroupLayout::SplitH); opening_after
= opening_after->intoGroup(Hy3GroupLayout::SplitH, GroupEphemeralityOption::Standard);
} }
} }
} }
@ -158,11 +159,13 @@ void Hy3Layout::onWindowRemovedTiling(CWindow* window) {
auto* parent = node->removeFromParentRecursive(); auto* parent = node->removeFromParentRecursive();
this->nodes.remove(*node); this->nodes.remove(*node);
auto& group = parent->data.as_group;
if (parent != nullptr) { if (parent != nullptr) {
parent->recalcSizePosRecursive(); parent->recalcSizePosRecursive();
if (parent->data.as_group.children.size() == 1 if (group.children.size() == 1
&& parent->data.as_group.children.front()->data.type == Hy3NodeType::Group) && (group.ephemeral || group.children.front()->data.type == Hy3NodeType::Group))
{ {
auto* target_parent = parent; auto* target_parent = parent;
while (target_parent != nullptr && Hy3Node::swallowGroups(target_parent)) { while (target_parent != nullptr && Hy3Node::swallowGroups(target_parent)) {
@ -633,36 +636,47 @@ void Hy3Layout::onDisable() {
this->nodes.clear(); this->nodes.clear();
} }
void Hy3Layout::makeGroupOnWorkspace(int workspace, Hy3GroupLayout layout) { void Hy3Layout::makeGroupOnWorkspace(
int workspace,
Hy3GroupLayout layout,
GroupEphemeralityOption ephemeral
) {
auto* node = this->getWorkspaceFocusedNode(workspace); auto* node = this->getWorkspaceFocusedNode(workspace);
this->makeGroupOn(node, layout); this->makeGroupOn(node, layout, ephemeral);
} }
void Hy3Layout::makeOppositeGroupOnWorkspace(int workspace) { void Hy3Layout::makeOppositeGroupOnWorkspace(int workspace, GroupEphemeralityOption ephemeral) {
auto* node = this->getWorkspaceFocusedNode(workspace); auto* node = this->getWorkspaceFocusedNode(workspace);
this->makeOppositeGroupOn(node); this->makeOppositeGroupOn(node, ephemeral);
} }
void Hy3Layout::makeGroupOn(Hy3Node* node, Hy3GroupLayout layout) { void Hy3Layout::makeGroupOn(
Hy3Node* node,
Hy3GroupLayout layout,
GroupEphemeralityOption ephemeral
) {
if (node == nullptr) return; if (node == nullptr) return;
if (node->parent != nullptr) { if (node->parent != nullptr) {
auto& group = node->parent->data.as_group; auto& group = node->parent->data.as_group;
if (group.children.size() == 1) { if (group.children.size() == 1) {
group.layout = layout; group.layout = layout;
group.ephemeral = ephemeral == GroupEphemeralityOption::ForceEphemeral ? true
: ephemeral == GroupEphemeralityOption::Ephemeral ? group.ephemeral
: false;
node->parent->recalcSizePosRecursive(); node->parent->recalcSizePosRecursive();
return; return;
} }
} }
node->intoGroup(layout); node->intoGroup(layout, ephemeral);
} }
void Hy3Layout::makeOppositeGroupOn(Hy3Node* node) { void Hy3Layout::makeOppositeGroupOn(Hy3Node* node, GroupEphemeralityOption ephemeral) {
if (node == nullptr) return; if (node == nullptr) return;
if (node->parent == nullptr) { if (node->parent == nullptr) {
node->intoGroup(Hy3GroupLayout::SplitH); node->intoGroup(Hy3GroupLayout::SplitH, ephemeral);
} else { } else {
auto& group = node->parent->data.as_group; auto& group = node->parent->data.as_group;
auto layout auto layout
@ -670,9 +684,12 @@ void Hy3Layout::makeOppositeGroupOn(Hy3Node* node) {
if (group.children.size() == 1) { if (group.children.size() == 1) {
group.layout = layout; group.layout = layout;
group.ephemeral = ephemeral == GroupEphemeralityOption::ForceEphemeral ? true
: ephemeral == GroupEphemeralityOption::Ephemeral ? group.ephemeral
: false;
node->parent->recalcSizePosRecursive(); node->parent->recalcSizePosRecursive();
} else { } else {
node->intoGroup(layout); node->intoGroup(layout, ephemeral);
} }
} }
} }
@ -1336,7 +1353,15 @@ Hy3Node* Hy3Layout::shiftOrGetFocus(
node.parent = target_group; node.parent = target_group;
node.size_ratio = 1.0; node.size_ratio = 1.0;
if (old_parent != nullptr) old_parent->recalcSizePosRecursive(); if (old_parent != nullptr) {
auto& group = old_parent->data.as_group;
if (old_parent->parent != nullptr && group.ephemeral && group.children.size() == 1) {
Hy3Node::swallowGroups(old_parent);
}
old_parent->recalcSizePosRecursive();
}
target_group->recalcSizePosRecursive(); target_group->recalcSizePosRecursive();
auto* target_parent = target_group->parent; auto* target_parent = target_group->parent;

View file

@ -2,6 +2,12 @@
class Hy3Layout; class Hy3Layout;
enum class GroupEphemeralityOption {
Ephemeral,
Standard,
ForceEphemeral,
};
#include <list> #include <list>
#include <hyprland/src/layout/IHyprLayout.hpp> #include <hyprland/src/layout/IHyprLayout.hpp>
@ -60,10 +66,10 @@ public:
virtual void onEnable(); virtual void onEnable();
virtual void onDisable(); virtual void onDisable();
void makeGroupOnWorkspace(int workspace, Hy3GroupLayout); void makeGroupOnWorkspace(int workspace, Hy3GroupLayout, GroupEphemeralityOption);
void makeOppositeGroupOnWorkspace(int workspace); void makeOppositeGroupOnWorkspace(int workspace, GroupEphemeralityOption);
void makeGroupOn(Hy3Node*, Hy3GroupLayout); void makeGroupOn(Hy3Node*, Hy3GroupLayout, GroupEphemeralityOption);
void makeOppositeGroupOn(Hy3Node*); void makeOppositeGroupOn(Hy3Node*, GroupEphemeralityOption);
void shiftWindow(int workspace, ShiftDirection, bool once); void shiftWindow(int workspace, ShiftDirection, bool once);
void shiftFocus(int workspace, ShiftDirection, bool visible); void shiftFocus(int workspace, ShiftDirection, bool visible);
void changeFocus(int workspace, FocusShift); void changeFocus(int workspace, FocusShift);

View file

@ -620,7 +620,7 @@ Hy3Node* Hy3Node::removeFromParentRecursive() {
return parent; return parent;
} }
Hy3Node* Hy3Node::intoGroup(Hy3GroupLayout layout) { Hy3Node* Hy3Node::intoGroup(Hy3GroupLayout layout, GroupEphemeralityOption ephemeral) {
this->layout->nodes.push_back({ this->layout->nodes.push_back({
.parent = this, .parent = this,
.data = layout, .data = layout,
@ -635,6 +635,8 @@ Hy3Node* Hy3Node::intoGroup(Hy3GroupLayout layout) {
this->data.as_group.children.push_back(node); this->data.as_group.children.push_back(node);
this->data.as_group.group_focused = false; this->data.as_group.group_focused = false;
this->data.as_group.focused_child = node; this->data.as_group.focused_child = node;
this->data.as_group.ephemeral = ephemeral == GroupEphemeralityOption::Ephemeral
|| ephemeral == GroupEphemeralityOption::ForceEphemeral;
this->recalcSizePosRecursive(); this->recalcSizePosRecursive();
this->updateTabBarRecursive(); this->updateTabBarRecursive();

View file

@ -26,6 +26,7 @@ struct Hy3GroupData {
std::list<Hy3Node*> children; std::list<Hy3Node*> children;
bool group_focused = true; bool group_focused = true;
Hy3Node* focused_child = nullptr; Hy3Node* focused_child = nullptr;
bool ephemeral = false;
Hy3TabGroup* tab_bar = nullptr; Hy3TabGroup* tab_bar = nullptr;
Hy3GroupData(Hy3GroupLayout layout); Hy3GroupData(Hy3GroupLayout layout);
@ -104,7 +105,7 @@ struct Hy3Node {
Hy3Node* removeFromParentRecursive(); Hy3Node* removeFromParentRecursive();
// Replace this node with a group, returning this node's new address. // Replace this node with a group, returning this node's new address.
Hy3Node* intoGroup(Hy3GroupLayout); Hy3Node* intoGroup(Hy3GroupLayout, GroupEphemeralityOption);
// Attempt to swallow a group. returns true if swallowed // Attempt to swallow a group. returns true if swallowed
static bool swallowGroups(Hy3Node* into); static bool swallowGroups(Hy3Node* into);

View file

@ -19,18 +19,27 @@ int workspace_for_action() {
return workspace_id; return workspace_id;
} }
void dispatch_makegroup(std::string arg) { void dispatch_makegroup(std::string value) {
int workspace = workspace_for_action(); int workspace = workspace_for_action();
if (workspace == -1) return; if (workspace == -1) return;
if (arg == "h") { auto args = CVarList(value);
g_Hy3Layout->makeGroupOnWorkspace(workspace, Hy3GroupLayout::SplitH);
} else if (arg == "v") { GroupEphemeralityOption ephemeral = GroupEphemeralityOption::Standard;
g_Hy3Layout->makeGroupOnWorkspace(workspace, Hy3GroupLayout::SplitV); if (args[1] == "ephemeral") {
} else if (arg == "tab") { ephemeral = GroupEphemeralityOption::Ephemeral;
g_Hy3Layout->makeGroupOnWorkspace(workspace, Hy3GroupLayout::Tabbed); } else if (args[1] == "force_ephemeral") {
} else if (arg == "opposite") { ephemeral = GroupEphemeralityOption::ForceEphemeral;
g_Hy3Layout->makeOppositeGroupOnWorkspace(workspace); }
if (args[0] == "h") {
g_Hy3Layout->makeGroupOnWorkspace(workspace, Hy3GroupLayout::SplitH, ephemeral);
} else if (args[0] == "v") {
g_Hy3Layout->makeGroupOnWorkspace(workspace, Hy3GroupLayout::SplitV, ephemeral);
} else if (args[0] == "tab") {
g_Hy3Layout->makeGroupOnWorkspace(workspace, Hy3GroupLayout::Tabbed, ephemeral);
} else if (args[0] == "opposite") {
g_Hy3Layout->makeOppositeGroupOnWorkspace(workspace, ephemeral);
} }
} }