aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Brian Ashworth <bosrsf04@gmail.com>2019-01-14 21:45:14 -0500
committerLibravatar GitHub <noreply@github.com>2019-01-14 21:45:14 -0500
commitbbd312c95a35db9604cfac1c7b179c3d716ff094 (patch)
treea46789c96e74e56ef9bf84d83e26c1937bdfe57e
parentDisarm key repeat on reload (diff)
parentFix invalid pointers when using resize grow width on first/last siblings (diff)
downloadsway-bbd312c95a35db9604cfac1c7b179c3d716ff094.tar.gz
sway-bbd312c95a35db9604cfac1c7b179c3d716ff094.tar.zst
sway-bbd312c95a35db9604cfac1c7b179c3d716ff094.zip
Merge pull request #3422 from RyanDwyer/resize-immediate-siblings
Resize only current and immediate siblings rather than all siblings
-rw-r--r--include/sway/commands.h5
-rw-r--r--sway/commands/resize.c246
-rw-r--r--sway/input/seatop_resize_tiling.c67
3 files changed, 140 insertions, 178 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h
index 657f909e..68487879 100644
--- a/include/sway/commands.h
+++ b/include/sway/commands.h
@@ -92,9 +92,12 @@ struct cmd_results *add_color(char *buffer, const char *color);
92/** 92/**
93 * TODO: Move this function and its dependent functions to container.c. 93 * TODO: Move this function and its dependent functions to container.c.
94 */ 94 */
95void container_resize_tiled(struct sway_container *parent, enum wlr_edges edge, 95void container_resize_tiled(struct sway_container *parent, uint32_t axis,
96 int amount); 96 int amount);
97 97
98struct sway_container *container_find_resize_parent(struct sway_container *con,
99 uint32_t edge);
100
98sway_cmd cmd_assign; 101sway_cmd cmd_assign;
99sway_cmd cmd_bar; 102sway_cmd cmd_bar;
100sway_cmd cmd_bindcode; 103sway_cmd cmd_bindcode;
diff --git a/sway/commands/resize.c b/sway/commands/resize.c
index fad1ecb1..6cdeb90c 100644
--- a/sway/commands/resize.c
+++ b/sway/commands/resize.c
@@ -130,177 +130,117 @@ static bool is_horizontal(uint32_t axis) {
130 return axis & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT); 130 return axis & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
131} 131}
132 132
133static int parallel_coord(struct sway_container *c, uint32_t axis) { 133struct sway_container *container_find_resize_parent(struct sway_container *con,
134 return is_horizontal(axis) ? c->x : c->y; 134 uint32_t axis) {
135} 135 enum sway_container_layout parallel_layout =
136 136 is_horizontal(axis) ? L_HORIZ : L_VERT;
137static int parallel_size(struct sway_container *c, uint32_t axis) { 137 bool allow_first = axis != WLR_EDGE_TOP && axis != WLR_EDGE_LEFT;
138 return is_horizontal(axis) ? c->width : c->height; 138 bool allow_last = axis != WLR_EDGE_RIGHT && axis != WLR_EDGE_BOTTOM;
139} 139
140 140 while (con) {
141static void container_recursive_resize(struct sway_container *container, 141 list_t *siblings = container_get_siblings(con);
142 double amount, enum wlr_edges edge) { 142 int index = container_sibling_index(con);
143 bool layout_match = true; 143 if (container_parent_layout(con) == parallel_layout &&
144 wlr_log(WLR_DEBUG, "Resizing %p with amount: %f", container, amount); 144 siblings->length > 1 && (allow_first || index > 0) &&
145 if (edge & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT)) { 145 (allow_last || index < siblings->length - 1)) {
146 container->width += amount; 146 return con;
147 layout_match = container->layout == L_HORIZ;
148 } else if (edge & (WLR_EDGE_TOP | WLR_EDGE_BOTTOM)) {
149 container->height += amount;
150 layout_match = container->layout == L_VERT;
151 }
152 if (container->children) {
153 for (int i = 0; i < container->children->length; i++) {
154 struct sway_container *child = container->children->items[i];
155 double amt = layout_match ?
156 amount / container->children->length : amount;
157 container_recursive_resize(child, amt, edge);
158 } 147 }
148 con = con->parent;
159 } 149 }
150
151 return NULL;
160} 152}
161 153
162static void resize_tiled(struct sway_container *parent, int amount, 154void container_resize_tiled(struct sway_container *con,
163 uint32_t axis) { 155 uint32_t axis, int amount) {
164 struct sway_container *focused = parent; 156 if (!con) {
165 if (!parent) {
166 return; 157 return;
167 } 158 }
168 159
169 enum sway_container_layout parallel_layout = 160 con = container_find_resize_parent(con, axis);
170 is_horizontal(axis) ? L_HORIZ : L_VERT; 161 if (!con) {
171 int minor_weight = 0;
172 int major_weight = 0;
173 while (parent) {
174 list_t *siblings = container_get_siblings(parent);
175 if (container_parent_layout(parent) == parallel_layout) {
176 for (int i = 0; i < siblings->length; i++) {
177 struct sway_container *sibling = siblings->items[i];
178
179 int sibling_pos = parallel_coord(sibling, axis);
180 int focused_pos = parallel_coord(focused, axis);
181 int parent_pos = parallel_coord(parent, axis);
182
183 if (sibling_pos != focused_pos) {
184 if (sibling_pos < parent_pos) {
185 minor_weight++;
186 } else if (sibling_pos > parent_pos) {
187 major_weight++;
188 }
189 }
190 }
191 if (major_weight || minor_weight) {
192 break;
193 }
194 }
195 parent = parent->parent;
196 }
197 if (!parent) {
198 // Can't resize in this direction 162 // Can't resize in this direction
199 return; 163 return;
200 } 164 }
201 165
202 // Implement up/down/left/right direction by zeroing one of the weights 166 // For HORIZONTAL or VERTICAL, we are growing in two directions so select
203 if (axis == WLR_EDGE_TOP || axis == WLR_EDGE_LEFT) { 167 // both adjacent siblings. For RIGHT or DOWN, just select the next sibling.
204 major_weight = 0; 168 // For LEFT or UP, convert it to a RIGHT or DOWN resize and reassign con to
205 } else if (axis == WLR_EDGE_RIGHT || axis == WLR_EDGE_BOTTOM) { 169 // the previous sibling.
206 minor_weight = 0; 170 struct sway_container *prev = NULL;
207 } 171 struct sway_container *next = NULL;
208 172 list_t *siblings = container_get_siblings(con);
209 bool horizontal = is_horizontal(axis); 173 int index = container_sibling_index(con);
210 int min_sane = horizontal ? MIN_SANE_W : MIN_SANE_H; 174
211 175 if (axis == AXIS_HORIZONTAL || axis == AXIS_VERTICAL) {
212 //TODO: Ensure rounding is done in such a way that there are NO pixel leaks 176 if (index == 0) {
213 // ^ ????? 177 next = siblings->items[1];
214 list_t *siblings = container_get_siblings(parent); 178 } else if (index == siblings->length - 1) {
215 179 // Convert edge to top/left
216 for (int i = 0; i < siblings->length; i++) { 180 next = con;
217 struct sway_container *sibling = siblings->items[i]; 181 con = siblings->items[index - 1];
218 182 amount = -amount;
219 int sibling_pos = parallel_coord(sibling, axis);
220 int focused_pos = parallel_coord(focused, axis);
221 int parent_pos = parallel_coord(parent, axis);
222
223 int sibling_size = parallel_size(sibling, axis);
224 int parent_size = parallel_size(parent, axis);
225
226 if (sibling_pos != focused_pos) {
227 if (sibling_pos < parent_pos && minor_weight) {
228 double pixels = -amount / minor_weight;
229 if (major_weight && (sibling_size + pixels / 2) < min_sane) {
230 return; // Too small
231 } else if (!major_weight && sibling_size + pixels < min_sane) {
232 return; // Too small
233 }
234 } else if (sibling_pos > parent_pos && major_weight) {
235 double pixels = -amount / major_weight;
236 if (minor_weight && (sibling_size + pixels / 2) < min_sane) {
237 return; // Too small
238 } else if (!minor_weight && sibling_size + pixels < min_sane) {
239 return; // Too small
240 }
241 }
242 } else { 183 } else {
243 double pixels = amount; 184 prev = siblings->items[index - 1];
244 if (parent_size + pixels < min_sane) { 185 next = siblings->items[index + 1];
245 return; // Too small 186 }
246 } 187 } else if (axis == WLR_EDGE_TOP || axis == WLR_EDGE_LEFT) {
188 if (!sway_assert(index > 0, "Didn't expect first child")) {
189 return;
247 } 190 }
191 next = con;
192 con = siblings->items[index - 1];
193 amount = -amount;
194 } else {
195 if (!sway_assert(index < siblings->length - 1,
196 "Didn't expect last child")) {
197 return;
198 }
199 next = siblings->items[index + 1];
248 } 200 }
249 201
250 enum wlr_edges minor_edge = horizontal ? WLR_EDGE_LEFT : WLR_EDGE_TOP; 202 // Apply new dimensions
251 enum wlr_edges major_edge = horizontal ? WLR_EDGE_RIGHT : WLR_EDGE_BOTTOM; 203 int sibling_amount = prev ? amount / 2 : amount;
252 204
253 for (int i = 0; i < siblings->length; i++) { 205 if (is_horizontal(axis)) {
254 struct sway_container *sibling = siblings->items[i]; 206 if (con->width + amount < MIN_SANE_W) {
255 207 return;
256 int sibling_pos = parallel_coord(sibling, axis); 208 }
257 int focused_pos = parallel_coord(focused, axis); 209 if (next->width - sibling_amount < MIN_SANE_W) {
258 int parent_pos = parallel_coord(parent, axis); 210 return;
259 211 }
260 if (sibling_pos != focused_pos) { 212 if (prev && prev->width - sibling_amount < MIN_SANE_W) {
261 if (sibling_pos < parent_pos && minor_weight) { 213 return;
262 double pixels = -1 * amount; 214 }
263 pixels /= minor_weight; 215 con->width += amount;
264 if (major_weight) { 216 next->width -= sibling_amount;
265 container_recursive_resize(sibling, pixels / 2, major_edge); 217 if (prev) {
266 } else { 218 prev->width -= sibling_amount;
267 container_recursive_resize(sibling, pixels, major_edge); 219 }
268 } 220 } else {
269 } else if (sibling_pos > parent_pos && major_weight) { 221 if (con->height + amount < MIN_SANE_H) {
270 double pixels = -1 * amount; 222 return;
271 pixels /= major_weight; 223 }
272 if (minor_weight) { 224 if (next->height - sibling_amount < MIN_SANE_H) {
273 container_recursive_resize(sibling, pixels / 2, minor_edge); 225 return;
274 } else { 226 }
275 container_recursive_resize(sibling, pixels, minor_edge); 227 if (prev && prev->height - sibling_amount < MIN_SANE_H) {
276 } 228 return;
277 } 229 }
278 } else { 230 con->height += amount;
279 if (major_weight != 0 && minor_weight != 0) { 231 next->height -= sibling_amount;
280 double pixels = amount; 232 if (prev) {
281 pixels /= 2; 233 prev->height -= sibling_amount;
282 container_recursive_resize(parent, pixels, minor_edge);
283 container_recursive_resize(parent, pixels, major_edge);
284 } else if (major_weight) {
285 container_recursive_resize(parent, amount, major_edge);
286 } else if (minor_weight) {
287 container_recursive_resize(parent, amount, minor_edge);
288 }
289 } 234 }
290 } 235 }
291 236
292 if (parent->parent) { 237 if (con->parent) {
293 arrange_container(parent->parent); 238 arrange_container(con->parent);
294 } else { 239 } else {
295 arrange_workspace(parent->workspace); 240 arrange_workspace(con->workspace);
296 } 241 }
297} 242}
298 243
299void container_resize_tiled(struct sway_container *parent,
300 enum wlr_edges edge, int amount) {
301 resize_tiled(parent, amount, edge);
302}
303
304/** 244/**
305 * Implement `resize <grow|shrink>` for a floating container. 245 * Implement `resize <grow|shrink>` for a floating container.
306 */ 246 */
@@ -379,7 +319,7 @@ static struct cmd_results *resize_adjust_tiled(uint32_t axis,
379 319
380 double old_width = current->width; 320 double old_width = current->width;
381 double old_height = current->height; 321 double old_height = current->height;
382 resize_tiled(current, amount->amount, axis); 322 container_resize_tiled(current, axis, amount->amount);
383 if (current->width == old_width && current->height == old_height) { 323 if (current->width == old_width && current->height == old_height) {
384 return cmd_results_new(CMD_INVALID, "Cannot resize any further"); 324 return cmd_results_new(CMD_INVALID, "Cannot resize any further");
385 } 325 }
@@ -407,7 +347,8 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con,
407 width->unit = RESIZE_UNIT_PX; 347 width->unit = RESIZE_UNIT_PX;
408 } 348 }
409 if (width->unit == RESIZE_UNIT_PX) { 349 if (width->unit == RESIZE_UNIT_PX) {
410 resize_tiled(con, width->amount - con->width, AXIS_HORIZONTAL); 350 container_resize_tiled(con, AXIS_HORIZONTAL,
351 width->amount - con->width);
411 } 352 }
412 } 353 }
413 354
@@ -427,7 +368,8 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con,
427 height->unit = RESIZE_UNIT_PX; 368 height->unit = RESIZE_UNIT_PX;
428 } 369 }
429 if (height->unit == RESIZE_UNIT_PX) { 370 if (height->unit == RESIZE_UNIT_PX) {
430 resize_tiled(con, height->amount - con->height, AXIS_VERTICAL); 371 container_resize_tiled(con, AXIS_VERTICAL,
372 height->amount - con->height);
431 } 373 }
432 } 374 }
433 375
diff --git a/sway/input/seatop_resize_tiling.c b/sway/input/seatop_resize_tiling.c
index 30431f04..cb0f723d 100644
--- a/sway/input/seatop_resize_tiling.c
+++ b/sway/input/seatop_resize_tiling.c
@@ -1,15 +1,22 @@
1#define _POSIX_C_SOURCE 200809L 1#define _POSIX_C_SOURCE 200809L
2#include <wlr/types/wlr_cursor.h> 2#include <wlr/types/wlr_cursor.h>
3#include <wlr/util/edges.h>
3#include "sway/commands.h" 4#include "sway/commands.h"
4#include "sway/input/cursor.h" 5#include "sway/input/cursor.h"
5#include "sway/input/seat.h" 6#include "sway/input/seat.h"
6 7
7struct seatop_resize_tiling_event { 8struct seatop_resize_tiling_event {
8 struct sway_container *con; 9 struct sway_container *con; // leaf container
10
11 // con, or ancestor of con which will be resized horizontally/vertically
12 struct sway_container *h_con;
13 struct sway_container *v_con;
14
9 enum wlr_edges edge; 15 enum wlr_edges edge;
16 enum wlr_edges edge_x, edge_y;
10 double ref_lx, ref_ly; // cursor's x/y at start of op 17 double ref_lx, ref_ly; // cursor's x/y at start of op
11 double ref_width, ref_height; // container's size at start of op 18 double h_con_orig_width; // width of the horizontal ancestor at start
12 double ref_con_lx, ref_con_ly; // container's x/y at start of op 19 double v_con_orig_height; // height of the vertical ancestor at start
13}; 20};
14 21
15static void handle_motion(struct sway_seat *seat, uint32_t time_msec) { 22static void handle_motion(struct sway_seat *seat, uint32_t time_msec) {
@@ -18,30 +25,27 @@ static void handle_motion(struct sway_seat *seat, uint32_t time_msec) {
18 int amount_y = 0; 25 int amount_y = 0;
19 int moved_x = seat->cursor->cursor->x - e->ref_lx; 26 int moved_x = seat->cursor->cursor->x - e->ref_lx;
20 int moved_y = seat->cursor->cursor->y - e->ref_ly; 27 int moved_y = seat->cursor->cursor->y - e->ref_ly;
21 enum wlr_edges edge_x = WLR_EDGE_NONE; 28
22 enum wlr_edges edge_y = WLR_EDGE_NONE; 29 if (e->h_con) {
23 struct sway_container *con = e->con; 30 if (e->edge & WLR_EDGE_LEFT) {
24 31 amount_x = (e->h_con_orig_width - moved_x) - e->h_con->width;
25 if (e->edge & WLR_EDGE_TOP) { 32 } else if (e->edge & WLR_EDGE_RIGHT) {
26 amount_y = (e->ref_height - moved_y) - con->height; 33 amount_x = (e->h_con_orig_width + moved_x) - e->h_con->width;
27 edge_y = WLR_EDGE_TOP; 34 }
28 } else if (e->edge & WLR_EDGE_BOTTOM) {
29 amount_y = (e->ref_height + moved_y) - con->height;
30 edge_y = WLR_EDGE_BOTTOM;
31 } 35 }
32 if (e->edge & WLR_EDGE_LEFT) { 36 if (e->v_con) {
33 amount_x = (e->ref_width - moved_x) - con->width; 37 if (e->edge & WLR_EDGE_TOP) {
34 edge_x = WLR_EDGE_LEFT; 38 amount_y = (e->v_con_orig_height - moved_y) - e->v_con->height;
35 } else if (e->edge & WLR_EDGE_RIGHT) { 39 } else if (e->edge & WLR_EDGE_BOTTOM) {
36 amount_x = (e->ref_width + moved_x) - con->width; 40 amount_y = (e->v_con_orig_height + moved_y) - e->v_con->height;
37 edge_x = WLR_EDGE_RIGHT; 41 }
38 } 42 }
39 43
40 if (amount_x != 0) { 44 if (amount_x != 0) {
41 container_resize_tiled(e->con, edge_x, amount_x); 45 container_resize_tiled(e->h_con, e->edge_x, amount_x);
42 } 46 }
43 if (amount_y != 0) { 47 if (amount_y != 0) {
44 container_resize_tiled(e->con, edge_y, amount_y); 48 container_resize_tiled(e->v_con, e->edge_y, amount_y);
45 } 49 }
46} 50}
47 51
@@ -81,10 +85,23 @@ void seatop_begin_resize_tiling(struct sway_seat *seat,
81 85
82 e->ref_lx = seat->cursor->cursor->x; 86 e->ref_lx = seat->cursor->cursor->x;
83 e->ref_ly = seat->cursor->cursor->y; 87 e->ref_ly = seat->cursor->cursor->y;
84 e->ref_con_lx = con->x; 88
85 e->ref_con_ly = con->y; 89 if (edge & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT)) {
86 e->ref_width = con->width; 90 e->edge_x = edge & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
87 e->ref_height = con->height; 91 e->h_con = container_find_resize_parent(e->con, e->edge_x);
92
93 if (e->h_con) {
94 e->h_con_orig_width = e->h_con->width;
95 }
96 }
97 if (edge & (WLR_EDGE_TOP | WLR_EDGE_BOTTOM)) {
98 e->edge_y = edge & (WLR_EDGE_TOP | WLR_EDGE_BOTTOM);
99 e->v_con = container_find_resize_parent(e->con, e->edge_y);
100
101 if (e->v_con) {
102 e->v_con_orig_height = e->v_con->height;
103 }
104 }
88 105
89 seat->seatop_impl = &seatop_impl; 106 seat->seatop_impl = &seatop_impl;
90 seat->seatop_data = e; 107 seat->seatop_data = e;