f3e8d2ff9af7cb9c834abcfee598c14d18e13929

Author
Pete Appleton <pete+git@catcity.me.uk>
Committer
Pete Appleton <pete+git@catcity.me.uk>
Date

Message

Fix resize breakage with expanded nodes

Diff

This diff is truncated to protect this page.

  1diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp
  2index 369aa9f872ec7f2345fd15f2bdc5a1793558b002..91865caaf28f0784bdb75163f004f44f58420628 100644
  3--- a/src/Hy3Layout.cpp
  4+++ b/src/Hy3Layout.cpp
  5@@ -395,9 +395,9 @@ void Hy3Layout::resizeActiveWindow(const Vector2D& delta, eRectCorner corner, CW
  6 	if (!g_pCompositor->windowValidMapped(window)) return;
  7 
  8 	auto* node = this->getNodeFromWindow(window);
  9+
 10 	if(node != nullptr) {
 11-		if (node->parent != nullptr && node->parent->data.as_group.focused_child == node)
 12-			node = &node->getExpandActor();
 13+		node = &node->getExpandActor();
 14 
 15 		auto monitor = g_pCompositor->getMonitorFromID(window->m_iMonitorID);
 16 
 17@@ -423,44 +423,26 @@ void Hy3Layout::resizeActiveWindow(const Vector2D& delta, eRectCorner corner, CW
 18 
 19 		// Determine the direction in which we're going to look for the sibling node
 20 		// that will be resized
 21-		if(corner == CORNER_NONE) {			// It's probably a keyboard event
 22-			// If the horizontal delta is negative & there's space available to the left,
 23-			// or if the horizontal delta is positive but space ISN'T available to the right
 24-			// then resize against the left-hand sibling.
 25-			// Otherwise, resize against the right-hand sibling
 26-			target_edge_x = (delta.x < 0 && display_left) || (delta.x > 0 && !display_right)
 27-				? ShiftDirection::Left : ShiftDirection::Right;
 28-
 29-			// If the vertical delta is negative & there's space available above it,
 30-			// or if the vertical delta is positive but space ISN'T available below
 31-			// then resize against the upper sibling.
 32-			// Otherwise, resize against the lower sibling
 33-			target_edge_y = (delta.y < 0 && display_top) || (delta.y >0 && !display_bottom)
 34-				? ShiftDirection::Up : ShiftDirection::Down;
 35-		} else {							// It's probaly a mouse event
 36-			// If the event was triggered from the right-hand side then resize
 37-			// against the previous [left] sibling - otherwise, resize against
 38-			// the next [right] sibling
 39-			target_edge_x = corner == CORNER_TOPRIGHT || corner == CORNER_BOTTOMRIGHT
 40+		if(corner == CORNER_NONE) {			// It's probably a keyboard event.
 41+			target_edge_x = display_right ? ShiftDirection::Left : ShiftDirection::Right;
 42+			target_edge_y = display_bottom ? ShiftDirection::Up : ShiftDirection::Down;
 43+		} else {							// It's probably a mouse event
 44+			// Resize against the edges corresponding to the selected corner
 45+			target_edge_x = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT
 46 				? ShiftDirection::Left : ShiftDirection::Right;
 47-
 48-			// If the event was triggered from the bottom edge then resize
 49-			// against the previous [upper] sibling - otherwise, resize against
 50-			// the next [lower] sibling
 51-			target_edge_y = corner == CORNER_BOTTOMLEFT || corner == CORNER_BOTTOMRIGHT
 52+			target_edge_y = corner == CORNER_TOPLEFT || corner == CORNER_TOPRIGHT
 53 				? ShiftDirection::Up : ShiftDirection::Down;
 54 		}
 55 
 56-		node = node->findSibling(node->data.as_group.layout, target_edge_x, target_edge_y);
 57-		auto* parent_node = node->parent;
 58+		auto sibling_node_x = node->findSibling(target_edge_x);
 59+		auto sibling_node_y = node->findSibling(target_edge_y);
 60 
 61-		if (parent_node != nullptr) {
 62-			resizeNode(node, resize_delta, target_edge_x, target_edge_y);
 63+		if(sibling_node_x) {
 64+			sibling_node_x->resize(resize_delta.x, target_edge_x);
 65+		}
 66 
 67-			auto* outer_node = node->findSibling(parent_node->data.as_group.layout, target_edge_x, target_edge_y);
 68-			if (outer_node != nullptr && outer_node->parent != nullptr) {
 69-				resizeNode(outer_node, resize_delta, target_edge_x, target_edge_y);
 70-			}
 71+		if(sibling_node_y) {
 72+			sibling_node_y->resize(resize_delta.y, target_edge_y);
 73 		}
 74 	} else {
 75 		// No parent node - is this a floating window?  If so, use the same logic as the `main` layout
 76@@ -474,64 +456,6 @@ void Hy3Layout::resizeActiveWindow(const Vector2D& delta, eRectCorner corner, CW
 77 	}
 78 }
 79 
 80-void Hy3Layout::resizeNode(
 81-	Hy3Node* node,
 82-	Vector2D resize_delta,
 83-	ShiftDirection target_edge_x,
 84-	ShiftDirection target_edge_y
 85-) {
 86-	auto& parent_node = node->parent;
 87-	auto& containing_group = parent_node->data.as_group;
 88-	const auto animate =
 89-		&g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
 90-
 91-	switch (containing_group.layout) {
 92-	case Hy3GroupLayout::SplitH: {
 93-		auto ratio_mod =
 94-		    resize_delta.x * (float) containing_group.children.size() / parent_node->size.x;
 95-
 96-		auto iter = std::find(containing_group.children.begin(), containing_group.children.end(), node);
 97-
 98-		if (target_edge_x == ShiftDirection::Left) {
 99-			if (node == containing_group.children.back()) break;
100-			iter = std::next(iter);
101-		} else {
102-			if (node == containing_group.children.front()) break;
103-			iter = std::prev(iter);
104-			ratio_mod = -ratio_mod;
105diff --git a/src/Hy3Layout.hpp b/src/Hy3Layout.hpp
106index 29f4e2ac6135bffdaa89eb311d6f97d717ecf018..f9128493a1591a80908831a78e2e2df9a153d04d 100644
107--- a/src/Hy3Layout.hpp
108+++ b/src/Hy3Layout.hpp
109@@ -20,6 +20,12 @@ enum class ShiftDirection {
110 	Right,
111 };
112 
113+enum class Axis {
114+	None,
115+	Horizontal,
116+	Vertical
117+};
118+
119 #include "Hy3Node.hpp"
120 #include "TabGroup.hpp"
121 
122diff --git a/src/Hy3Node.cpp b/src/Hy3Node.cpp
123index 4640d370d5c68ab13c11d741b3b02e40f27b75f2..f44ae7819c8ab2064dd7bf9e6eb75370e66366bc 100644
124--- a/src/Hy3Node.cpp
125+++ b/src/Hy3Node.cpp
126@@ -7,6 +7,8 @@
127 #include "Hy3Node.hpp"
128 #include "globals.hpp"
129 
130+const float MIN_RATIO = 0.02f;
131+
132 // Hy3GroupData //
133 
134 Hy3GroupData::Hy3GroupData(Hy3GroupLayout layout): layout(layout) {
135@@ -812,52 +814,128 @@ Hy3Node* getOuterChild(Hy3GroupData &group, ShiftDirection direction) {
136 	switch (direction) {
137 		case ShiftDirection::Left:
138 		case ShiftDirection::Up:
139-			return group.children.back();
140+			return group.children.front();
141 			break;
142 		case ShiftDirection::Right:
143 		case ShiftDirection::Down:
144-			return group.children.front();
145+			return group.children.back();
146 			break;
147 		default:
148 			return nullptr;
149 	}
150 }
151 
152-Hy3Node* Hy3Node::findSibling(Hy3GroupLayout inner_layout, ShiftDirection direction_x, ShiftDirection direction_y) {
153-	// break into parent groups when encountering a corner we're dragging in, a
154-	// tab group, or a layout matching the inner_parent.
155+Hy3Node* Hy3Node::getImmediateSibling(ShiftDirection direction) {
156+	const auto& group = this->parent->data.as_group;
157+
158+	auto iter = std::find(group.children.begin(), group.children.end(), this);
159+
160+	std::__cxx11::list<Hy3Node *>::const_iterator list_sibling;
161+
162+	switch (direction) {
163+		case ShiftDirection::Left:
164+		case ShiftDirection::Up:
165+			list_sibling = std::prev(iter);
166+			break;
167+		case ShiftDirection::Right:
168+		case ShiftDirection::Down:
169+			list_sibling = std::next(iter);
170+			break;
171+		default:
172+			list_sibling = iter;
173+	}
174+
175+	if(list_sibling == group.children.end()) {
176+		hy3_log(WARN, "getImmediateSibling: sibling not found");
177+		list_sibling = iter;
178+	}
179+
180+	return *list_sibling;
181+}
182+
183+Axis getAxis(Hy3GroupLayout layout) {
184+	switch (layout)
185+	{
186+	case Hy3GroupLayout::SplitH:
187+		return Axis::Horizontal;
188+	case Hy3GroupLayout::SplitV:
189+		return Axis::Vertical;
190+	default:
191+		return Axis::None;
192+	}
193+}
194+
195+Axis getAxis(ShiftDirection direction) {
196+	switch (direction)
197+	{
198+	case ShiftDirection::Left:
199+	case ShiftDirection::Right:
200+		return Axis::Horizontal;
201+	case ShiftDirection::Down:
202+	case ShiftDirection::Up:
203+		return Axis::Vertical;
204+	default:
205+		return Axis::None;
206+	}
207+}
208 
209+Hy3Node* Hy3Node::findSibling(ShiftDirection direction) {
210 	auto current_node = this;
211-	while (current_node->parent != nullptr) {
212+	Hy3Node* sibling = nullptr;
213+
214+	while (sibling == nullptr && current_node->parent != nullptr) {
215 		auto& parent_group = current_node->parent->data.as_group;
216 
217-		// break out of all layouts that match the orientation of the inner_parent
218-		if (parent_group.layout == inner_layout) {
219-			goto cont2;
220+		if(parent_group.layout != Hy3GroupLayout::Tabbed && getAxis(parent_group.layout) == getAxis(direction)) {
221+			// If the current node is the outermost child of its parent group then proceed
222+			// then we need to look at the parent - otherwise, the sibling is simply the immediate
223+			// sibling in the child collection
224+			if(getOuterChild(parent_group, direction) != current_node) {
225+				sibling = current_node->getImmediateSibling(direction);
226diff --git a/src/Hy3Node.hpp b/src/Hy3Node.hpp
227index 77ed7e931eef9af3c7b4bf220b81853ea8c0ec4c..148cc47189073a12aee5e1e094ced11c51959170 100644
228--- a/src/Hy3Node.hpp
229+++ b/src/Hy3Node.hpp
230@@ -99,7 +99,9 @@ struct Hy3Node {
231 	void markFocused();
232 	void raiseToTop();
233 	Hy3Node* getFocusedNode(bool ignore_group_focus = false, bool stop_at_expanded = false);
234-	Hy3Node* findSibling(Hy3GroupLayout inner_layout, ShiftDirection direction_x, ShiftDirection direction_y);
235+	Hy3Node* findSibling(ShiftDirection);
236+	Hy3Node* getImmediateSibling(ShiftDirection);
237+	void resize(double, ShiftDirection);
238 	bool isIndirectlyFocused();
239 	Hy3Node& getExpandActor();
240