dad1589d2185d32243f8089a67ad2637d6233eae

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

Message

Improve iteration handling and validate results

Diff

  1diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp
  2index 91865caaf28f0784bdb75163f004f44f58420628..c62b306d17505f3a58d9396541a4c85dfce9f231 100644
  3--- a/src/Hy3Layout.cpp
  4+++ b/src/Hy3Layout.cpp
  5@@ -390,6 +390,17 @@ void Hy3Layout::recalculateWindow(CWindow* window) {
  6 	node->recalcSizePosRecursive();
  7 }
  8 
  9+ShiftDirection reverse(ShiftDirection direction) {
 10+	switch (direction)
 11+	{
 12+	case ShiftDirection::Left: return ShiftDirection::Right;
 13+	case ShiftDirection::Right: return ShiftDirection::Left;
 14+	case ShiftDirection::Up: return ShiftDirection::Down;
 15+	case ShiftDirection::Down: return ShiftDirection::Up;
 16+	default: return direction;
 17+	}
 18+}
 19+
 20 void Hy3Layout::resizeActiveWindow(const Vector2D& delta, eRectCorner corner, CWindow* pWindow) {
 21 	auto window = pWindow ? pWindow : g_pCompositor->m_pLastWindow;
 22 	if (!g_pCompositor->windowValidMapped(window)) return;
 23@@ -421,11 +432,15 @@ void Hy3Layout::resizeActiveWindow(const Vector2D& delta, eRectCorner corner, CW
 24 		ShiftDirection target_edge_x;
 25 		ShiftDirection target_edge_y;
 26 
 27-		// Determine the direction in which we're going to look for the sibling node
 28+		// Determine the direction in which we're going to look for the neighbor node
 29 		// that will be resized
 30 		if(corner == CORNER_NONE) {			// It's probably a keyboard event.
 31 			target_edge_x = display_right ? ShiftDirection::Left : ShiftDirection::Right;
 32 			target_edge_y = display_bottom ? ShiftDirection::Up : ShiftDirection::Down;
 33+
 34+			// If the anchor is not at the top/left then reverse the delta
 35+			if(target_edge_x == ShiftDirection::Left) resize_delta.x = -resize_delta.x;
 36+			if(target_edge_y == ShiftDirection::Up) resize_delta.y = -resize_delta.y;
 37 		} else {							// It's probably a mouse event
 38 			// Resize against the edges corresponding to the selected corner
 39 			target_edge_x = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT
 40@@ -434,25 +449,32 @@ void Hy3Layout::resizeActiveWindow(const Vector2D& delta, eRectCorner corner, CW
 41 				? ShiftDirection::Up : ShiftDirection::Down;
 42 		}
 43 
 44-		auto sibling_node_x = node->findSibling(target_edge_x);
 45-		auto sibling_node_y = node->findSibling(target_edge_y);
 46+		// Find the neighboring node in each axis, which will be either above or at the
 47+		// same level as the initiating node in the layout hierarchy.  These are the nodes
 48+		// which must get resized (rather than the initiator) because they are the
 49+		// highest point in the hierarchy
 50+		auto horizontal_neighbor = node->findNeighbor(target_edge_x);
 51+		auto vertical_neighbor = node->findNeighbor(target_edge_y);
 52 
 53-		if(sibling_node_x) {
 54-			sibling_node_x->resize(resize_delta.x, target_edge_x);
 55+		const auto animate =
 56+			&g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
 57+
 58+		// Note that the resize direction is reversed, because from the neighbor's perspective
 59+		// the edge to be moved is the opposite way round.  However, the delta is still the same.
 60+		if(horizontal_neighbor) {
 61+			horizontal_neighbor->resize(reverse(target_edge_x), resize_delta.x, *animate == 0);
 62 		}
 63 
 64-		if(sibling_node_y) {
 65-			sibling_node_y->resize(resize_delta.y, target_edge_y);
 66+		if(vertical_neighbor) {
 67+			vertical_neighbor->resize(reverse(target_edge_y), resize_delta.y, *animate == 0);
 68 		}
 69-	} else {
 70+	} else if(window->m_bIsFloating) {
 71 		// No parent node - is this a floating window?  If so, use the same logic as the `main` layout
 72-		if(window->m_bIsFloating) {
 73-			const auto required_size = Vector2D(
 74-				std::max((window->m_vRealSize.goalv() + delta).x, 20.0),
 75-				std::max((window->m_vRealSize.goalv() + delta).y, 20.0)
 76-			);
 77-			window->m_vRealSize = required_size;
 78-		}
 79+		const auto required_size = Vector2D(
 80+			std::max((window->m_vRealSize.goalv() + delta).x, 20.0),
 81+			std::max((window->m_vRealSize.goalv() + delta).y, 20.0)
 82+		);
 83+		window->m_vRealSize = required_size;
 84 	}
 85 }
 86 
 87diff --git a/src/Hy3Node.cpp b/src/Hy3Node.cpp
 88index f44ae7819c8ab2064dd7bf9e6eb75370e66366bc..6c2c415f05878dd83bdbdd94927d161ca19f2ee2 100644
 89--- a/src/Hy3Node.cpp
 90+++ b/src/Hy3Node.cpp
 91@@ -7,7 +7,7 @@
 92 #include "Hy3Node.hpp"
 93 #include "globals.hpp"
 94 
 95-const float MIN_RATIO = 0.02f;
 96+const float MIN_WINDOW_SIZE = 20;
 97 
 98 // Hy3GroupData //
 99 
100@@ -879,7 +879,7 @@ Axis getAxis(ShiftDirection direction) {
101 	}
102 }
103 
104-Hy3Node* Hy3Node::findSibling(ShiftDirection direction) {
105+Hy3Node* Hy3Node::findNeighbor(ShiftDirection direction) {
106 	auto current_node = this;
107 	Hy3Node* sibling = nullptr;
108 
109@@ -901,39 +901,56 @@ Hy3Node* Hy3Node::findSibling(ShiftDirection direction) {
110 	return sibling;
111 }
112 
113+int directionToIteratorIncrement(ShiftDirection direction) {
114+	switch (direction)
115+	{
116+		case ShiftDirection::Left:
117+		case ShiftDirection::Up:
118+			return -1;
119+		case ShiftDirection::Right:
120+		case ShiftDirection::Down:
121+			return 1;
122+		default:
123+			hy3_log(WARN, "Unknown ShiftDirection enum value: {}", (int)direction);
124+			return 1;
125+	}
126+}
127+
128 void Hy3Node::resize(
129-	double resize_delta,
130-	ShiftDirection target_edge_x
131+	ShiftDirection direction,
132+	double delta,
133+	bool no_animation
134 ) {
135 	auto& parent_node = this->parent;
136 	auto& containing_group = parent_node->data.as_group;
137-	const auto animate =
138-		&g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
139 
140-	if(containing_group.layout != Hy3GroupLayout::Tabbed && getAxis(target_edge_x) == getAxis(containing_group.layout)) {
141-		double parent_size = getAxis(target_edge_x) == Axis::Horizontal ? parent_node->size.x
142+	if(containing_group.layout != Hy3GroupLayout::Tabbed && getAxis(direction) == getAxis(containing_group.layout)) {
143+		double parent_size = getAxis(direction) == Axis::Horizontal ? parent_node->size.x
144 																		 : parent_node->size.y;
145-		auto ratio_mod = resize_delta * (float) containing_group.children.size() / parent_size;
146+		auto ratio_mod = delta * (float) containing_group.children.size() / parent_size;
147 
148-		auto iter = std::find(containing_group.children.begin(), containing_group.children.end(), this);
149+		const auto end_of_children = containing_group.children.end();
150+		auto iter = std::find(containing_group.children.begin(), end_of_children, this);
151 
152-		if (target_edge_x == ShiftDirection::Left || target_edge_x == ShiftDirection::Up) {
153-			if (this != containing_group.children.back()) {
154-				iter = std::next(iter);
155-			}
156-		} else {
157-			if (this != containing_group.children.front()) {
158-				iter = std::prev(iter);
159-				ratio_mod = -ratio_mod;
160+		if(iter != end_of_children) {
161+			const auto outermost_node_in_group = getOuterChild(containing_group, direction);
162+			if(this != outermost_node_in_group) {
163+				auto inc = directionToIteratorIncrement(direction);
164+				iter = std::next(iter, inc);
165+				ratio_mod *= inc;
166 			}
167-		}
168 
169-		auto* neighbor = *iter;
170+			if(iter != end_of_children) {
171+				auto* neighbor = *iter;
172+				auto requested_size_ratio = this->size_ratio + ratio_mod;
173+				auto requested_neighbor_size_ratio = neighbor->size_ratio -ratio_mod;
174 
175-		if(this->size_ratio + ratio_mod > MIN_RATIO && neighbor->size_ratio - ratio_mod > MIN_RATIO) {
176-			this->size_ratio += ratio_mod;
177-			neighbor->size_ratio -= ratio_mod;
178-			parent_node->recalcSizePosRecursive(*animate == 0);
179+				if(requested_size_ratio * parent_size >= MIN_WINDOW_SIZE) {
180+					this->size_ratio = requested_size_ratio;
181+					neighbor->size_ratio = requested_neighbor_size_ratio;
182+					parent_node->recalcSizePosRecursive(no_animation);
183+				}
184+			}
185 		}
186 	}
187 }
188diff --git a/src/Hy3Node.hpp b/src/Hy3Node.hpp
189index 148cc47189073a12aee5e1e094ced11c51959170..f892efb5ef772b1eca5508de63d0747bbb3169ec 100644
190--- a/src/Hy3Node.hpp
191+++ b/src/Hy3Node.hpp
192@@ -99,9 +99,9 @@ struct Hy3Node {
193 	void markFocused();
194 	void raiseToTop();
195 	Hy3Node* getFocusedNode(bool ignore_group_focus = false, bool stop_at_expanded = false);
196-	Hy3Node* findSibling(ShiftDirection);
197+	Hy3Node* findNeighbor(ShiftDirection);
198 	Hy3Node* getImmediateSibling(ShiftDirection);
199-	void resize(double, ShiftDirection);
200+	void resize(ShiftDirection, double, bool no_animation = false);
201 	bool isIndirectlyFocused();
202 	Hy3Node& getExpandActor();
203