From 51d39917839032ba4cb7e336a99fa32938854ba6 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Wed, 19 Jul 2023 03:53:23 -0700 Subject: [PATCH] Add ephemeral groups --- README.md | 4 +++- flake.lock | 12 +++++------ src/Hy3Layout.cpp | 51 +++++++++++++++++++++++++++++++++------------ src/Hy3Layout.hpp | 14 +++++++++---- src/Hy3Node.cpp | 4 +++- src/Hy3Node.hpp | 3 ++- src/dispatchers.cpp | 27 ++++++++++++++++-------- 7 files changed, 80 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index b447ddc..d815e9e 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,9 @@ plugin { ``` ### Dispatcher list - - `hy3:makegroup, ` - make a vertical / horizontal split or tab group + - `hy3:makegroup, , [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, , [visible]` - move the focus left, up, down, or right - `visible` - only move between visible nodes, not hidden tabs - `hy3:movewindow, , [once]` - move a window left, up, down, or right diff --git a/flake.lock b/flake.lock index 966481a..a32c989 100644 --- a/flake.lock +++ b/flake.lock @@ -8,11 +8,11 @@ "xdph": "xdph" }, "locked": { - "lastModified": 1689264334, - "narHash": "sha256-CJv3Qi00et2dFBWXTx9ysYdYauFtxxs+3pXr0gq/UX0=", + "lastModified": 1689720698, + "narHash": "sha256-DjW5GZlzULXKdEVag13OEV3/hog1k/5ZjSIRIPOHrcQ=", "owner": "hyprwm", "repo": "Hyprland", - "rev": "f8def68e7e761e33dd51c197ac89194a51fcb60f", + "rev": "81f4a4f47182c15ee9436d9ab7b2e425a096ce5b", "type": "github" }, "original": { @@ -67,11 +67,11 @@ "flake": false, "locked": { "host": "gitlab.freedesktop.org", - "lastModified": 1686753331, - "narHash": "sha256-KovjVFwcuoUO0eu/UiWrnD3+m/K+SHSAVIz4xF9K1XA=", + "lastModified": 1689611045, + "narHash": "sha256-3RTOlQabkNetQ4O4UzSf57JPco9VGVHhSU1ls5uKBeE=", "owner": "wlroots", "repo": "wlroots", - "rev": "7e7633abf09b362d0bad9e3fc650fd692369291d", + "rev": "7791ffe0584c4ac13c170e1661ce33bdbd4a9b9e", "type": "gitlab" }, "original": { diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp index 5b06766..d6ff9f3 100644 --- a/src/Hy3Layout.cpp +++ b/src/Hy3Layout.cpp @@ -44,7 +44,8 @@ void Hy3Layout::onWindowCreatedTiling(CWindow* window) { // opening_after->parent cannot be nullptr 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(); this->nodes.remove(*node); + auto& group = parent->data.as_group; + if (parent != nullptr) { parent->recalcSizePosRecursive(); - if (parent->data.as_group.children.size() == 1 - && parent->data.as_group.children.front()->data.type == Hy3NodeType::Group) + if (group.children.size() == 1 + && (group.ephemeral || group.children.front()->data.type == Hy3NodeType::Group)) { auto* target_parent = parent; while (target_parent != nullptr && Hy3Node::swallowGroups(target_parent)) { @@ -633,36 +636,47 @@ void Hy3Layout::onDisable() { this->nodes.clear(); } -void Hy3Layout::makeGroupOnWorkspace(int workspace, Hy3GroupLayout layout) { +void Hy3Layout::makeGroupOnWorkspace( + int workspace, + Hy3GroupLayout layout, + GroupEphemeralityOption ephemeral +) { 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); - 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->parent != nullptr) { auto& group = node->parent->data.as_group; if (group.children.size() == 1) { group.layout = layout; + group.ephemeral = ephemeral == GroupEphemeralityOption::ForceEphemeral ? true + : ephemeral == GroupEphemeralityOption::Ephemeral ? group.ephemeral + : false; node->parent->recalcSizePosRecursive(); 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->parent == nullptr) { - node->intoGroup(Hy3GroupLayout::SplitH); + node->intoGroup(Hy3GroupLayout::SplitH, ephemeral); } else { auto& group = node->parent->data.as_group; auto layout @@ -670,9 +684,12 @@ void Hy3Layout::makeOppositeGroupOn(Hy3Node* node) { if (group.children.size() == 1) { group.layout = layout; + group.ephemeral = ephemeral == GroupEphemeralityOption::ForceEphemeral ? true + : ephemeral == GroupEphemeralityOption::Ephemeral ? group.ephemeral + : false; node->parent->recalcSizePosRecursive(); } else { - node->intoGroup(layout); + node->intoGroup(layout, ephemeral); } } } @@ -1336,7 +1353,15 @@ Hy3Node* Hy3Layout::shiftOrGetFocus( node.parent = target_group; 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(); auto* target_parent = target_group->parent; diff --git a/src/Hy3Layout.hpp b/src/Hy3Layout.hpp index d87f945..dfe1beb 100644 --- a/src/Hy3Layout.hpp +++ b/src/Hy3Layout.hpp @@ -2,6 +2,12 @@ class Hy3Layout; +enum class GroupEphemeralityOption { + Ephemeral, + Standard, + ForceEphemeral, +}; + #include #include @@ -60,10 +66,10 @@ public: virtual void onEnable(); virtual void onDisable(); - void makeGroupOnWorkspace(int workspace, Hy3GroupLayout); - void makeOppositeGroupOnWorkspace(int workspace); - void makeGroupOn(Hy3Node*, Hy3GroupLayout); - void makeOppositeGroupOn(Hy3Node*); + void makeGroupOnWorkspace(int workspace, Hy3GroupLayout, GroupEphemeralityOption); + void makeOppositeGroupOnWorkspace(int workspace, GroupEphemeralityOption); + void makeGroupOn(Hy3Node*, Hy3GroupLayout, GroupEphemeralityOption); + void makeOppositeGroupOn(Hy3Node*, GroupEphemeralityOption); void shiftWindow(int workspace, ShiftDirection, bool once); void shiftFocus(int workspace, ShiftDirection, bool visible); void changeFocus(int workspace, FocusShift); diff --git a/src/Hy3Node.cpp b/src/Hy3Node.cpp index f02be7b..6a35409 100644 --- a/src/Hy3Node.cpp +++ b/src/Hy3Node.cpp @@ -620,7 +620,7 @@ Hy3Node* Hy3Node::removeFromParentRecursive() { return parent; } -Hy3Node* Hy3Node::intoGroup(Hy3GroupLayout layout) { +Hy3Node* Hy3Node::intoGroup(Hy3GroupLayout layout, GroupEphemeralityOption ephemeral) { this->layout->nodes.push_back({ .parent = this, .data = layout, @@ -635,6 +635,8 @@ Hy3Node* Hy3Node::intoGroup(Hy3GroupLayout layout) { this->data.as_group.children.push_back(node); this->data.as_group.group_focused = false; this->data.as_group.focused_child = node; + this->data.as_group.ephemeral = ephemeral == GroupEphemeralityOption::Ephemeral + || ephemeral == GroupEphemeralityOption::ForceEphemeral; this->recalcSizePosRecursive(); this->updateTabBarRecursive(); diff --git a/src/Hy3Node.hpp b/src/Hy3Node.hpp index 449486a..59107bb 100644 --- a/src/Hy3Node.hpp +++ b/src/Hy3Node.hpp @@ -26,6 +26,7 @@ struct Hy3GroupData { std::list children; bool group_focused = true; Hy3Node* focused_child = nullptr; + bool ephemeral = false; Hy3TabGroup* tab_bar = nullptr; Hy3GroupData(Hy3GroupLayout layout); @@ -104,7 +105,7 @@ struct Hy3Node { Hy3Node* removeFromParentRecursive(); // 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 static bool swallowGroups(Hy3Node* into); diff --git a/src/dispatchers.cpp b/src/dispatchers.cpp index 5937bd7..1480a24 100644 --- a/src/dispatchers.cpp +++ b/src/dispatchers.cpp @@ -19,18 +19,27 @@ int workspace_for_action() { return workspace_id; } -void dispatch_makegroup(std::string arg) { +void dispatch_makegroup(std::string value) { int workspace = workspace_for_action(); if (workspace == -1) return; - if (arg == "h") { - g_Hy3Layout->makeGroupOnWorkspace(workspace, Hy3GroupLayout::SplitH); - } else if (arg == "v") { - g_Hy3Layout->makeGroupOnWorkspace(workspace, Hy3GroupLayout::SplitV); - } else if (arg == "tab") { - g_Hy3Layout->makeGroupOnWorkspace(workspace, Hy3GroupLayout::Tabbed); - } else if (arg == "opposite") { - g_Hy3Layout->makeOppositeGroupOnWorkspace(workspace); + auto args = CVarList(value); + + GroupEphemeralityOption ephemeral = GroupEphemeralityOption::Standard; + if (args[1] == "ephemeral") { + ephemeral = GroupEphemeralityOption::Ephemeral; + } else if (args[1] == "force_ephemeral") { + ephemeral = GroupEphemeralityOption::ForceEphemeral; + } + + 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); } }