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