summaryrefslogtreecommitdiffstats
path: root/sway/resize.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/resize.c')
-rw-r--r--sway/resize.c491
1 files changed, 491 insertions, 0 deletions
diff --git a/sway/resize.c b/sway/resize.c
new file mode 100644
index 00000000..a08ef4a1
--- /dev/null
+++ b/sway/resize.c
@@ -0,0 +1,491 @@
1#include <wlc/wlc.h>
2#include <math.h>
3#include "layout.h"
4#include "focus.h"
5#include "log.h"
6#include "input_state.h"
7#include "handlers.h"
8
9bool mouse_resize_tiled(struct wlc_origin prev_pos) {
10 swayc_t *view = container_under_pointer();
11 bool valid = true;
12 bool changed_tiling = false;
13 double dx = mouse_origin.x - prev_pos.x;
14 double dy = mouse_origin.y - prev_pos.y;
15 if (view != pointer_state.tiling.init_view) {
16 changed_tiling = true;
17 valid = false;
18 if (view->type != C_WORKSPACE) {
19 if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_LEFT) == view) {
20 pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20;
21 pointer_state.lock.temp_left = true;
22 } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_RIGHT) == view) {
23 pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20;
24 pointer_state.lock.temp_right = true;
25 } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_UP) == view) {
26 pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20;
27 pointer_state.lock.temp_up = true;
28 } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_DOWN) == view) {
29 pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20;
30 pointer_state.lock.temp_down = true;
31 }
32 }
33 }
34
35 if ((dx < 0 || mouse_origin.x < pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_left) {
36 changed_tiling = true;
37 valid = false;
38 } else if (dx > 0 && pointer_state.lock.temp_left) {
39 pointer_state.lock.temp_left = false;
40 pointer_state.tiling.lock_pos.x = 0;
41 }
42
43 if ((dx > 0 || mouse_origin.x > pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_right) {
44 changed_tiling = true;
45 valid = false;
46 } else if (dx < 0 && pointer_state.lock.temp_right) {
47 pointer_state.lock.temp_right = false;
48 pointer_state.tiling.lock_pos.x = 0;
49 }
50
51 if ((dy < 0 || mouse_origin.y < pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_up) {
52 changed_tiling = true;
53 valid = false;
54 } else if (dy > 0 && pointer_state.lock.temp_up) {
55 pointer_state.lock.temp_up = false;
56 pointer_state.tiling.lock_pos.y = 0;
57 }
58
59 if ((dy > 0 || mouse_origin.y > pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_down) {
60 changed_tiling = true;
61 valid = false;
62 } else if (dy < 0 && pointer_state.lock.temp_down) {
63 pointer_state.lock.temp_down = false;
64 pointer_state.tiling.lock_pos.y = 0;
65 }
66
67 if (!view->is_floating && valid) {
68 // Handle layout resizes -- Find the biggest parent container then apply resizes to that
69 // and its bordering siblings
70 swayc_t *parent = view;
71 if (!pointer_state.lock.bottom) {
72 while (parent->type != C_WORKSPACE) {
73 // TODO: Absolute value is a bad hack here to compensate for rounding. Find a better
74 // way of doing this.
75 if (fabs(parent->parent->y + parent->parent->height - (view->y + view->height)) <= 1) {
76 parent = parent->parent;
77 } else {
78 break;
79 }
80 }
81 if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) {
82 swayc_t *sibling = get_swayc_in_direction(parent, MOVE_DOWN);
83 if (sibling) {
84 if ((parent->height > min_sane_h || dy > 0) && (sibling->height > min_sane_h || dy < 0)) {
85 recursive_resize(parent, dy, WLC_RESIZE_EDGE_BOTTOM);
86 recursive_resize(sibling, -1 * dy, WLC_RESIZE_EDGE_TOP);
87 changed_tiling = true;
88 } else {
89 if (parent->height < min_sane_h) {
90 //pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20;
91 pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20;
92 pointer_state.lock.temp_up = true;
93 } else if (sibling->height < min_sane_h) {
94 pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20;
95 pointer_state.lock.temp_down = true;
96 }
97 }
98 }
99 }
100 } else if (!pointer_state.lock.top) {
101 while (parent->type != C_WORKSPACE) {
102 if (fabs(parent->parent->y - view->y) <= 1) {
103 parent = parent->parent;
104 } else {
105 break;
106 }
107 }
108 if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) {
109 swayc_t *sibling = get_swayc_in_direction(parent, MOVE_UP);
110 if (sibling) {
111 if ((parent->height > min_sane_h || dy < 0) && (sibling->height > min_sane_h || dy > 0)) {
112 recursive_resize(parent, -1 * dy, WLC_RESIZE_EDGE_TOP);
113 recursive_resize(sibling, dy, WLC_RESIZE_EDGE_BOTTOM);
114 changed_tiling = true;
115 } else {
116 if (parent->height < min_sane_h) {
117 //pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20;
118 pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20;
119 pointer_state.lock.temp_down = true;
120 } else if (sibling->height < min_sane_h) {
121 pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20;
122 pointer_state.lock.temp_up = true;
123 }
124 }
125 }
126 }
127 }
128
129 parent = view;
130 if (!pointer_state.lock.right) {
131 while (parent->type != C_WORKSPACE) {
132 if (fabs(parent->parent->x + parent->parent->width - (view->x + view->width)) <= 1) {
133 parent = parent->parent;
134 } else {
135 sway_log(L_DEBUG, "view: %f vs parent: %f", view->x + view->width, parent->parent->x + parent->parent->width);
136 break;
137 }
138 }
139 if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) {
140 swayc_t *sibling = get_swayc_in_direction(parent, MOVE_RIGHT);
141 if (sibling) {
142 if ((parent->width > min_sane_w || dx > 0) && (sibling->width > min_sane_w || dx < 0)) {
143 recursive_resize(parent, dx, WLC_RESIZE_EDGE_RIGHT);
144 recursive_resize(sibling, -1 * dx, WLC_RESIZE_EDGE_LEFT);
145 changed_tiling = true;
146 } else {
147 if (parent->width < min_sane_w) {
148 pointer_state.lock.temp_left = true;
149 pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20;
150 } else if (sibling->width < min_sane_w) {
151 pointer_state.lock.temp_right = true;
152 pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20;
153 }
154 }
155 }
156 }
157 } else if (!pointer_state.lock.left) {
158 while (parent->type != C_WORKSPACE) {
159 if (fabs(parent->parent->x - view->x) <= 1 && parent->parent) {
160 parent = parent->parent;
161 } else {
162 break;
163 }
164 }
165 if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) {
166 swayc_t *sibling = get_swayc_in_direction(parent, MOVE_LEFT);
167 if (sibling) {
168 if ((parent->width > min_sane_w || dx < 0) && (sibling->width > min_sane_w || dx > 0)) {
169 recursive_resize(parent, -1 * dx, WLC_RESIZE_EDGE_LEFT);
170 recursive_resize(sibling, dx, WLC_RESIZE_EDGE_RIGHT);
171 changed_tiling = true;
172 } else {
173 if (parent->width < min_sane_w) {
174 pointer_state.lock.temp_right = true;
175 pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20;
176 } else if (sibling->width < min_sane_w) {
177 pointer_state.lock.temp_left = true;
178 pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20;
179 }
180 }
181 }
182 }
183 }
184 arrange_windows(swayc_active_workspace(), -1, -1);
185 }
186 return changed_tiling;
187}
188
189bool resize_floating(struct wlc_origin prev_pos) {
190 bool changed = false;
191 swayc_t *view = container_under_pointer();
192 uint32_t edge = 0;
193 int dx = mouse_origin.x - prev_pos.x;
194 int dy = mouse_origin.y - prev_pos.y;
195
196 // Move and resize the view based on the dx/dy and mouse position
197 int midway_x = view->x + view->width/2;
198 int midway_y = view->y + view->height/2;
199 if (dx < 0) {
200 if (!pointer_state.lock.right) {
201 if (view->width > min_sane_w) {
202 changed = true;
203 view->width += dx;
204 edge += WLC_RESIZE_EDGE_RIGHT;
205 }
206 } else if (mouse_origin.x < midway_x && !pointer_state.lock.left) {
207 changed = true;
208 view->x += dx;
209 view->width -= dx;
210 edge += WLC_RESIZE_EDGE_LEFT;
211 }
212 } else if (dx > 0) {
213 if (mouse_origin.x > midway_x && !pointer_state.lock.right) {
214 changed = true;
215 view->width += dx;
216 edge += WLC_RESIZE_EDGE_RIGHT;
217 } else if (!pointer_state.lock.left) {
218 if (view->width > min_sane_w) {
219 changed = true;
220 view->x += dx;
221 view->width -= dx;
222 edge += WLC_RESIZE_EDGE_LEFT;
223 }
224 }
225 }
226
227 if (dy < 0) {
228 if (!pointer_state.lock.bottom) {
229 if (view->height > min_sane_h) {
230 changed = true;
231 view->height += dy;
232 edge += WLC_RESIZE_EDGE_BOTTOM;
233 }
234 } else if (mouse_origin.y < midway_y && !pointer_state.lock.top) {
235 changed = true;
236 view->y += dy;
237 view->height -= dy;
238 edge += WLC_RESIZE_EDGE_TOP;
239 }
240 } else if (dy > 0) {
241 if (mouse_origin.y > midway_y && !pointer_state.lock.bottom) {
242 changed = true;
243 view->height += dy;
244 edge += WLC_RESIZE_EDGE_BOTTOM;
245 } else if (!pointer_state.lock.top) {
246 if (view->height > min_sane_h) {
247 changed = true;
248 view->y += dy;
249 view->height -= dy;
250 edge += WLC_RESIZE_EDGE_TOP;
251 }
252 }
253 }
254 if (changed) {
255 struct wlc_geometry geometry = {
256 .origin = {
257 .x = view->x,
258 .y = view->y
259 },
260 .size = {
261 .w = view->width,
262 .h = view->height
263 }
264 };
265 wlc_view_set_geometry(view->handle, edge, &geometry);
266 }
267 return changed;
268}
269
270bool resize_tiled(int amount, bool use_width) {
271 swayc_t *parent = get_focused_view(swayc_active_workspace());
272 swayc_t *focused = parent;
273 swayc_t *sibling;
274 if (!parent) {
275 return true;
276 }
277 // Find the closest parent container which has siblings of the proper layout.
278 // Then apply the resize to all of them.
279 int i;
280 if (use_width) {
281 int lnumber = 0;
282 int rnumber = 0;
283 while (parent->parent) {
284 if (parent->parent->layout == L_HORIZ) {
285 for (i = 0; i < parent->parent->children->length; i++) {
286 sibling = parent->parent->children->items[i];
287 if (sibling->x != focused->x) {
288 if (sibling->x < parent->x) {
289 lnumber++;
290 } else if (sibling->x > parent->x) {
291 rnumber++;
292 }
293 }
294 }
295 if (rnumber || lnumber) {
296 break;
297 }
298 }
299 parent = parent->parent;
300 }
301 if (parent == &root_container) {
302 return true;
303 }
304 sway_log(L_DEBUG, "Found the proper parent: %p. It has %d l conts, and %d r conts", parent->parent, lnumber, rnumber);
305 //TODO: Ensure rounding is done in such a way that there are NO pixel leaks
306 bool valid = true;
307 for (i = 0; i < parent->parent->children->length; i++) {
308 sibling = parent->parent->children->items[i];
309 if (sibling->x != focused->x) {
310 if (sibling->x < parent->x) {
311 double pixels = -1 * amount;
312 pixels /= lnumber;
313 if (rnumber) {
314 if ((sibling->width + pixels/2) < min_sane_w) {
315 valid = false;
316 break;
317 }
318 } else {
319 if ((sibling->width + pixels) < min_sane_w) {
320 valid = false;
321 break;
322 }
323 }
324 } else if (sibling->x > parent->x) {
325 double pixels = -1 * amount;
326 pixels /= rnumber;
327 if (lnumber) {
328 if ((sibling->width + pixels/2) < min_sane_w) {
329 valid = false;
330 break;
331 }
332 } else {
333 if ((sibling->width + pixels) < min_sane_w) {
334 valid = false;
335 break;
336 }
337 }
338 }
339 } else {
340 double pixels = amount;
341 if (parent->width + pixels < min_sane_w) {
342 valid = false;
343 break;
344 }
345 }
346 }
347 if (valid) {
348 for (i = 0; i < parent->parent->children->length; i++) {
349 sibling = parent->parent->children->items[i];
350 if (sibling->x != focused->x) {
351 if (sibling->x < parent->x) {
352 double pixels = -1 * amount;
353 pixels /= lnumber;
354 if (rnumber) {
355 recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_RIGHT);
356 } else {
357 recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_RIGHT);
358 }
359 } else if (sibling->x > parent->x) {
360 double pixels = -1 * amount;
361 pixels /= rnumber;
362 if (lnumber) {
363 recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_LEFT);
364 } else {
365 recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_LEFT);
366 }
367 }
368 } else {
369 if (rnumber != 0 && lnumber != 0) {
370 double pixels = amount;
371 pixels /= 2;
372 recursive_resize(parent, pixels, WLC_RESIZE_EDGE_LEFT);
373 recursive_resize(parent, pixels, WLC_RESIZE_EDGE_RIGHT);
374 } else if (rnumber) {
375 recursive_resize(parent, amount, WLC_RESIZE_EDGE_RIGHT);
376 } else if (lnumber) {
377 recursive_resize(parent, amount, WLC_RESIZE_EDGE_LEFT);
378 }
379 }
380 }
381 // Recursive resize does not handle positions, let arrange_windows
382 // take care of that.
383 arrange_windows(swayc_active_workspace(), -1, -1);
384 }
385 return true;
386 } else {
387 int tnumber = 0;
388 int bnumber = 0;
389 while (parent->parent) {
390 if (parent->parent->layout == L_VERT) {
391 for (i = 0; i < parent->parent->children->length; i++) {
392 sibling = parent->parent->children->items[i];
393 if (sibling->y != focused->y) {
394 if (sibling->y < parent->y) {
395 bnumber++;
396 } else if (sibling->y > parent->y) {
397 tnumber++;
398 }
399 }
400 }
401 if (bnumber || tnumber) {
402 break;
403 }
404 }
405 parent = parent->parent;
406 }
407 if (parent == &root_container) {
408 return true;
409 }
410 sway_log(L_DEBUG, "Found the proper parent: %p. It has %d b conts, and %d t conts", parent->parent, bnumber, tnumber);
411 //TODO: Ensure rounding is done in such a way that there are NO pixel leaks
412 bool valid = true;
413 for (i = 0; i < parent->parent->children->length; i++) {
414 sibling = parent->parent->children->items[i];
415 if (sibling->y != focused->y) {
416 if (sibling->y < parent->y) {
417 double pixels = -1 * amount;
418 pixels /= bnumber;
419 if (tnumber) {
420 if ((sibling->height + pixels/2) < min_sane_h) {
421 valid = false;
422 break;
423 }
424 } else {
425 if ((sibling->height + pixels) < min_sane_h) {
426 valid = false;
427 break;
428 }
429 }
430 } else if (sibling->y > parent->y) {
431 double pixels = -1 * amount;
432 pixels /= tnumber;
433 if (bnumber) {
434 if ((sibling->height + pixels/2) < min_sane_h) {
435 valid = false;
436 break;
437 }
438 } else {
439 if ((sibling->height + pixels) < min_sane_h) {
440 valid = false;
441 break;
442 }
443 }
444 }
445 } else {
446 double pixels = amount;
447 if (parent->height + pixels < min_sane_h) {
448 valid = false;
449 break;
450 }
451 }
452 }
453 if (valid) {
454 for (i = 0; i < parent->parent->children->length; i++) {
455 sibling = parent->parent->children->items[i];
456 if (sibling->y != focused->y) {
457 if (sibling->y < parent->y) {
458 double pixels = -1 * amount;
459 pixels /= bnumber;
460 if (tnumber) {
461 recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_BOTTOM);
462 } else {
463 recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_BOTTOM);
464 }
465 } else if (sibling->x > parent->x) {
466 double pixels = -1 * amount;
467 pixels /= tnumber;
468 if (bnumber) {
469 recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_TOP);
470 } else {
471 recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_TOP);
472 }
473 }
474 } else {
475 if (bnumber != 0 && tnumber != 0) {
476 double pixels = amount/2;
477 recursive_resize(parent, pixels, WLC_RESIZE_EDGE_TOP);
478 recursive_resize(parent, pixels, WLC_RESIZE_EDGE_BOTTOM);
479 } else if (tnumber) {
480 recursive_resize(parent, amount, WLC_RESIZE_EDGE_TOP);
481 } else if (bnumber) {
482 recursive_resize(parent, amount, WLC_RESIZE_EDGE_BOTTOM);
483 }
484 }
485 }
486 arrange_windows(swayc_active_workspace(), -1, -1);
487 }
488 return true;
489 }
490 return true;
491}