51d39917839032ba4cb7e336a99fa32938854ba6

Author
outfoxxed <outfoxxed@outfoxxed.me>
Committer
outfoxxed <outfoxxed@outfoxxed.me>
Date

Message

Add ephemeral groups

Diff

This diff is truncated to protect this page.

  1diff --git a/README.md b/README.md
  2index b447ddcd6f5e8e7c3f325823dc1d75983fb8589d..d815e9e2aa35a20756c06ec2b627c9d0b598bc94 100644
  3--- a/README.md
  4+++ b/README.md
  5@@ -90,7 +90,9 @@ plugin {
  6 ```
  7 
  8 ### Dispatcher list
  9- - `hy3:makegroup, <h | v | opposite | tab>` - make a vertical / horizontal split or tab group
 10+ - `hy3:makegroup, <h | v | opposite | tab>, [ephemeral | force_ephemeral]` - make a vertical / horizontal split or tab group
 11+   - `ephemeral` - the group will be removed once it contains only one node. does not affect existing groups.
 12+   - `force_ephemeral` - same as ephemeral, but converts existing single windows groups.
 13  - `hy3:movefocus, <l | u | d | r | left | down | up | right>, [visible]` - move the focus left, up, down, or right
 14    - `visible` - only move between visible nodes, not hidden tabs
 15  - `hy3:movewindow, <l | u | d | r | left | down | up | right>, [once]` - move a window left, up, down, or right
 16diff --git a/flake.lock b/flake.lock
 17index 966481a7be1c1816b979161ff5632c692a6a11cb..a32c989355e6bb83a37944f2585edeaa639dbc7c 100644
 18--- a/flake.lock
 19+++ b/flake.lock
 20@@ -8,11 +8,11 @@
 21         "xdph": "xdph"
 22       },
 23       "locked": {
 24-        "lastModified": 1689264334,
 25-        "narHash": "sha256-CJv3Qi00et2dFBWXTx9ysYdYauFtxxs+3pXr0gq/UX0=",
 26+        "lastModified": 1689720698,
 27+        "narHash": "sha256-DjW5GZlzULXKdEVag13OEV3/hog1k/5ZjSIRIPOHrcQ=",
 28         "owner": "hyprwm",
 29         "repo": "Hyprland",
 30-        "rev": "f8def68e7e761e33dd51c197ac89194a51fcb60f",
 31+        "rev": "81f4a4f47182c15ee9436d9ab7b2e425a096ce5b",
 32         "type": "github"
 33       },
 34       "original": {
 35@@ -67,11 +67,11 @@
 36       "flake": false,
 37       "locked": {
 38         "host": "gitlab.freedesktop.org",
 39-        "lastModified": 1686753331,
 40-        "narHash": "sha256-KovjVFwcuoUO0eu/UiWrnD3+m/K+SHSAVIz4xF9K1XA=",
 41+        "lastModified": 1689611045,
 42+        "narHash": "sha256-3RTOlQabkNetQ4O4UzSf57JPco9VGVHhSU1ls5uKBeE=",
 43         "owner": "wlroots",
 44         "repo": "wlroots",
 45-        "rev": "7e7633abf09b362d0bad9e3fc650fd692369291d",
 46+        "rev": "7791ffe0584c4ac13c170e1661ce33bdbd4a9b9e",
 47         "type": "gitlab"
 48       },
 49       "original": {
 50diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp
 51index 5b0676622586c268efce67324283232ac6eae797..d6ff9f3c9c4de89e0f8cdd217e3dc497a1a31dad 100644
 52--- a/src/Hy3Layout.cpp
 53+++ b/src/Hy3Layout.cpp
 54@@ -44,7 +44,8 @@ void Hy3Layout::onWindowCreatedTiling(CWindow* window) {
 55 
 56 			// opening_after->parent cannot be nullptr
 57 			if (opening_after == root) {
 58-				opening_after = opening_after->intoGroup(Hy3GroupLayout::SplitH);
 59+				opening_after
 60+				    = opening_after->intoGroup(Hy3GroupLayout::SplitH, GroupEphemeralityOption::Standard);
 61 			}
 62 		}
 63 	}
 64@@ -158,11 +159,13 @@ void Hy3Layout::onWindowRemovedTiling(CWindow* window) {
 65 	auto* parent = node->removeFromParentRecursive();
 66 	this->nodes.remove(*node);
 67 
 68+	auto& group = parent->data.as_group;
 69+
 70 	if (parent != nullptr) {
 71 		parent->recalcSizePosRecursive();
 72 
 73-		if (parent->data.as_group.children.size() == 1
 74-		    && parent->data.as_group.children.front()->data.type == Hy3NodeType::Group)
 75+		if (group.children.size() == 1
 76+		    && (group.ephemeral || group.children.front()->data.type == Hy3NodeType::Group))
 77 		{
 78 			auto* target_parent = parent;
 79 			while (target_parent != nullptr && Hy3Node::swallowGroups(target_parent)) {
 80@@ -633,36 +636,47 @@ void Hy3Layout::onDisable() {
 81 	this->nodes.clear();
 82 }
 83 
 84-void Hy3Layout::makeGroupOnWorkspace(int workspace, Hy3GroupLayout layout) {
 85+void Hy3Layout::makeGroupOnWorkspace(
 86+    int workspace,
 87+    Hy3GroupLayout layout,
 88+    GroupEphemeralityOption ephemeral
 89+) {
 90 	auto* node = this->getWorkspaceFocusedNode(workspace);
 91-	this->makeGroupOn(node, layout);
 92+	this->makeGroupOn(node, layout, ephemeral);
 93 }
 94 
 95-void Hy3Layout::makeOppositeGroupOnWorkspace(int workspace) {
 96+void Hy3Layout::makeOppositeGroupOnWorkspace(int workspace, GroupEphemeralityOption ephemeral) {
 97 	auto* node = this->getWorkspaceFocusedNode(workspace);
 98-	this->makeOppositeGroupOn(node);
 99+	this->makeOppositeGroupOn(node, ephemeral);
100 }
101 
102-void Hy3Layout::makeGroupOn(Hy3Node* node, Hy3GroupLayout layout) {
103+void Hy3Layout::makeGroupOn(
104+    Hy3Node* node,
105+    Hy3GroupLayout layout,
106+    GroupEphemeralityOption ephemeral
107+) {
108 	if (node == nullptr) return;
109 
110 	if (node->parent != nullptr) {
111 		auto& group = node->parent->data.as_group;
112 		if (group.children.size() == 1) {
113 			group.layout = layout;
114+			group.ephemeral = ephemeral == GroupEphemeralityOption::ForceEphemeral ? true
115+			                : ephemeral == GroupEphemeralityOption::Ephemeral      ? group.ephemeral
116+			                                                                       : false;
117 			node->parent->recalcSizePosRecursive();
118 			return;
119 		}
120 	}
121 
122-	node->intoGroup(layout);
123+	node->intoGroup(layout, ephemeral);
124 }
125 
126-void Hy3Layout::makeOppositeGroupOn(Hy3Node* node) {
127+void Hy3Layout::makeOppositeGroupOn(Hy3Node* node, GroupEphemeralityOption ephemeral) {
128 	if (node == nullptr) return;
129 
130 	if (node->parent == nullptr) {
131-		node->intoGroup(Hy3GroupLayout::SplitH);
132+		node->intoGroup(Hy3GroupLayout::SplitH, ephemeral);
133 	} else {
134 		auto& group = node->parent->data.as_group;
135 		auto layout
136@@ -670,9 +684,12 @@ void Hy3Layout::makeOppositeGroupOn(Hy3Node* node) {
137 
138 		if (group.children.size() == 1) {
139 			group.layout = layout;
140+			group.ephemeral = ephemeral == GroupEphemeralityOption::ForceEphemeral ? true
141+			                : ephemeral == GroupEphemeralityOption::Ephemeral      ? group.ephemeral
142+			                                                                       : false;
143 			node->parent->recalcSizePosRecursive();
144 		} else {
145-			node->intoGroup(layout);
146+			node->intoGroup(layout, ephemeral);
147 		}
148 	}
149 }
150@@ -1336,7 +1353,15 @@ Hy3Node* Hy3Layout::shiftOrGetFocus(
151 		node.parent = target_group;
152 		node.size_ratio = 1.0;
153 
154diff --git a/src/Hy3Layout.hpp b/src/Hy3Layout.hpp
155index d87f945233a654162e19e84dad02f53d2f01a0d1..dfe1beb15ab80df59ff9a1c4a804dd7b146bd150 100644
156--- a/src/Hy3Layout.hpp
157+++ b/src/Hy3Layout.hpp
158@@ -2,6 +2,12 @@
159 
160 class Hy3Layout;
161 
162+enum class GroupEphemeralityOption {
163+	Ephemeral,
164+	Standard,
165+	ForceEphemeral,
166+};
167+
168 #include <list>
169 
170 #include <hyprland/src/layout/IHyprLayout.hpp>
171@@ -60,10 +66,10 @@ public:
172 	virtual void onEnable();
173 	virtual void onDisable();
174 
175-	void makeGroupOnWorkspace(int workspace, Hy3GroupLayout);
176-	void makeOppositeGroupOnWorkspace(int workspace);
177-	void makeGroupOn(Hy3Node*, Hy3GroupLayout);
178-	void makeOppositeGroupOn(Hy3Node*);
179+	void makeGroupOnWorkspace(int workspace, Hy3GroupLayout, GroupEphemeralityOption);
180+	void makeOppositeGroupOnWorkspace(int workspace, GroupEphemeralityOption);
181+	void makeGroupOn(Hy3Node*, Hy3GroupLayout, GroupEphemeralityOption);
182+	void makeOppositeGroupOn(Hy3Node*, GroupEphemeralityOption);
183 	void shiftWindow(int workspace, ShiftDirection, bool once);
184 	void shiftFocus(int workspace, ShiftDirection, bool visible);
185 	void changeFocus(int workspace, FocusShift);
186diff --git a/src/Hy3Node.cpp b/src/Hy3Node.cpp
187index f02be7b25bf2747464b2c9567c37b314172d52f0..6a35409eeb4b3c6543c0c4c2ef754dbdf54b83fa 100644
188--- a/src/Hy3Node.cpp
189+++ b/src/Hy3Node.cpp
190@@ -620,7 +620,7 @@ Hy3Node* Hy3Node::removeFromParentRecursive() {
191 	return parent;
192 }
193 
194-Hy3Node* Hy3Node::intoGroup(Hy3GroupLayout layout) {
195+Hy3Node* Hy3Node::intoGroup(Hy3GroupLayout layout, GroupEphemeralityOption ephemeral) {
196 	this->layout->nodes.push_back({
197 	    .parent = this,
198 	    .data = layout,
199@@ -635,6 +635,8 @@ Hy3Node* Hy3Node::intoGroup(Hy3GroupLayout layout) {
200 	this->data.as_group.children.push_back(node);
201 	this->data.as_group.group_focused = false;
202 	this->data.as_group.focused_child = node;
203+	this->data.as_group.ephemeral = ephemeral == GroupEphemeralityOption::Ephemeral
204+	                             || ephemeral == GroupEphemeralityOption::ForceEphemeral;
205 	this->recalcSizePosRecursive();
206 	this->updateTabBarRecursive();
207 
208diff --git a/src/Hy3Node.hpp b/src/Hy3Node.hpp
209index 449486a4159bd65f3001400d4f71a5dc07fc5acf..59107bb6c17fac56a0e3b1937104689c8e303667 100644
210--- a/src/Hy3Node.hpp
211+++ b/src/Hy3Node.hpp
212@@ -26,6 +26,7 @@ struct Hy3GroupData {
213 	std::list<Hy3Node*> children;
214 	bool group_focused = true;
215 	Hy3Node* focused_child = nullptr;
216+	bool ephemeral = false;
217 	Hy3TabGroup* tab_bar = nullptr;
218 
219 	Hy3GroupData(Hy3GroupLayout layout);
220@@ -104,7 +105,7 @@ struct Hy3Node {
221 	Hy3Node* removeFromParentRecursive();
222 
223 	// Replace this node with a group, returning this node's new address.
224-	Hy3Node* intoGroup(Hy3GroupLayout);
225+	Hy3Node* intoGroup(Hy3GroupLayout, GroupEphemeralityOption);
226 
227 	// Attempt to swallow a group. returns true if swallowed
228 	static bool swallowGroups(Hy3Node* into);
229diff --git a/src/dispatchers.cpp b/src/dispatchers.cpp
230index 5937bd79ca687c0f307a660f7b81dd55a558e370..1480a2432e7869b47bca904617f0fac8412e8514 100644
231--- a/src/dispatchers.cpp
232+++ b/src/dispatchers.cpp
233@@ -19,18 +19,27 @@ int workspace_for_action() {
234 	return workspace_id;
235 }
236 
237-void dispatch_makegroup(std::string arg) {
238+void dispatch_makegroup(std::string value) {
239 	int workspace = workspace_for_action();
240 	if (workspace == -1) return;
241 
242-	if (arg == "h") {
243-		g_Hy3Layout->makeGroupOnWorkspace(workspace, Hy3GroupLayout::SplitH);
244-	} else if (arg == "v") {
245-		g_Hy3Layout->makeGroupOnWorkspace(workspace, Hy3GroupLayout::SplitV);
246-	} else if (arg == "tab") {
247-		g_Hy3Layout->makeGroupOnWorkspace(workspace, Hy3GroupLayout::Tabbed);
248-	} else if (arg == "opposite") {
249-		g_Hy3Layout->makeOppositeGroupOnWorkspace(workspace);
250+	auto args = CVarList(value);
251+
252+	GroupEphemeralityOption ephemeral = GroupEphemeralityOption::Standard;
253+	if (args[1] == "ephemeral") {
254+		ephemeral = GroupEphemeralityOption::Ephemeral;
255+	} else if (args[1] == "force_ephemeral") {
256+		ephemeral = GroupEphemeralityOption::ForceEphemeral;
257+	}
258+
259+	if (args[0] == "h") {
260+		g_Hy3Layout->makeGroupOnWorkspace(workspace, Hy3GroupLayout::SplitH, ephemeral);
261+	} else if (args[0] == "v") {
262+		g_Hy3Layout->makeGroupOnWorkspace(workspace, Hy3GroupLayout::SplitV, ephemeral);
263+	} else if (args[0] == "tab") {
264+		g_Hy3Layout->makeGroupOnWorkspace(workspace, Hy3GroupLayout::Tabbed, ephemeral);
265+	} else if (args[0] == "opposite") {
266+		g_Hy3Layout->makeOppositeGroupOnWorkspace(workspace, ephemeral);
267 	}
268 }
269