aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree/layout.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/tree/layout.c')
-rw-r--r--sway/tree/layout.c133
1 files changed, 55 insertions, 78 deletions
diff --git a/sway/tree/layout.c b/sway/tree/layout.c
index dc0ee5b4..de9e7b58 100644
--- a/sway/tree/layout.c
+++ b/sway/tree/layout.c
@@ -6,26 +6,24 @@
6#include <string.h> 6#include <string.h>
7#include <wlr/types/wlr_output.h> 7#include <wlr/types/wlr_output.h>
8#include <wlr/types/wlr_output_layout.h> 8#include <wlr/types/wlr_output_layout.h>
9#include "sway/tree/container.h" 9#include "sway/container.h"
10#include "sway/tree/layout.h" 10#include "sway/layout.h"
11#include "sway/output.h" 11#include "sway/output.h"
12#include "sway/tree/view.h" 12#include "sway/view.h"
13#include "sway/input/seat.h" 13#include "sway/input/seat.h"
14#include "list.h" 14#include "list.h"
15#include "log.h" 15#include "log.h"
16 16
17struct sway_container root_container; 17swayc_t root_container;
18 18
19static void output_layout_change_notify(struct wl_listener *listener, 19static void output_layout_change_notify(struct wl_listener *listener, void *data) {
20 void *data) {
21 struct wlr_box *layout_box = wlr_output_layout_get_box( 20 struct wlr_box *layout_box = wlr_output_layout_get_box(
22 root_container.sway_root->output_layout, NULL); 21 root_container.sway_root->output_layout, NULL);
23 root_container.width = layout_box->width; 22 root_container.width = layout_box->width;
24 root_container.height = layout_box->height; 23 root_container.height = layout_box->height;
25 24
26 for (int i = 0 ; i < root_container.children->length; ++i) { 25 for (int i = 0 ; i < root_container.children->length; ++i) {
27 struct sway_container *output_container = 26 swayc_t *output_container = root_container.children->items[i];
28 root_container.children->items[i];
29 if (output_container->type != C_OUTPUT) { 27 if (output_container->type != C_OUTPUT) {
30 continue; 28 continue;
31 } 29 }
@@ -45,7 +43,7 @@ static void output_layout_change_notify(struct wl_listener *listener,
45 arrange_windows(&root_container, -1, -1); 43 arrange_windows(&root_container, -1, -1);
46} 44}
47 45
48void layout_init(void) { 46void init_layout(void) {
49 root_container.id = 0; // normally assigned in new_swayc() 47 root_container.id = 0; // normally assigned in new_swayc()
50 root_container.type = C_ROOT; 48 root_container.type = C_ROOT;
51 root_container.layout = L_NONE; 49 root_container.layout = L_NONE;
@@ -64,9 +62,9 @@ void layout_init(void) {
64 &root_container.sway_root->output_layout_change); 62 &root_container.sway_root->output_layout_change);
65} 63}
66 64
67static int index_child(const struct sway_container *child) { 65static int index_child(const swayc_t *child) {
68 // TODO handle floating 66 // TODO handle floating
69 struct sway_container *parent = child->parent; 67 swayc_t *parent = child->parent;
70 int i, len; 68 int i, len;
71 len = parent->children->length; 69 len = parent->children->length;
72 for (i = 0; i < len; ++i) { 70 for (i = 0; i < len; ++i) {
@@ -81,18 +79,16 @@ static int index_child(const struct sway_container *child) {
81 return i; 79 return i;
82} 80}
83 81
84struct sway_container *container_add_sibling(struct sway_container *fixed, 82swayc_t *add_sibling(swayc_t *fixed, swayc_t *active) {
85 struct sway_container *active) {
86 // TODO handle floating 83 // TODO handle floating
87 struct sway_container *parent = fixed->parent; 84 swayc_t *parent = fixed->parent;
88 int i = index_child(fixed); 85 int i = index_child(fixed);
89 list_insert(parent->children, i + 1, active); 86 list_insert(parent->children, i + 1, active);
90 active->parent = parent; 87 active->parent = parent;
91 return active->parent; 88 return active->parent;
92} 89}
93 90
94void container_add_child(struct sway_container *parent, 91void add_child(swayc_t *parent, swayc_t *child) {
95 struct sway_container *child) {
96 wlr_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", 92 wlr_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)",
97 child, child->type, child->width, child->height, 93 child, child->type, child->width, child->height,
98 parent, parent->type, parent->width, parent->height); 94 parent, parent->type, parent->width, parent->height);
@@ -100,17 +96,15 @@ void container_add_child(struct sway_container *parent,
100 child->parent = parent; 96 child->parent = parent;
101 // set focus for this container 97 // set focus for this container
102 /* TODO WLR 98 /* TODO WLR
103 if (parent->type == C_WORKSPACE && child->type == C_VIEW && 99 if (parent->type == C_WORKSPACE && child->type == C_VIEW && (parent->workspace_layout == L_TABBED || parent->workspace_layout == L_STACKED)) {
104 (parent->workspace_layout == L_TABBED || parent->workspace_layout ==
105 L_STACKED)) {
106 child = new_container(child, parent->workspace_layout); 100 child = new_container(child, parent->workspace_layout);
107 } 101 }
108 */ 102 */
109} 103}
110 104
111struct sway_container *container_remove_child(struct sway_container *child) { 105swayc_t *remove_child(swayc_t *child) {
112 int i; 106 int i;
113 struct sway_container *parent = child->parent; 107 swayc_t *parent = child->parent;
114 for (i = 0; i < parent->children->length; ++i) { 108 for (i = 0; i < parent->children->length; ++i) {
115 if (parent->children->items[i] == child) { 109 if (parent->children->items[i] == child) {
116 list_del(parent->children, i); 110 list_del(parent->children, i);
@@ -121,8 +115,7 @@ struct sway_container *container_remove_child(struct sway_container *child) {
121 return parent; 115 return parent;
122} 116}
123 117
124enum sway_container_layout container_get_default_layout( 118enum swayc_layouts default_layout(swayc_t *output) {
125 struct sway_container *output) {
126 /* TODO WLR 119 /* TODO WLR
127 if (config->default_layout != L_NONE) { 120 if (config->default_layout != L_NONE) {
128 //return config->default_layout; 121 //return config->default_layout;
@@ -136,8 +129,8 @@ enum sway_container_layout container_get_default_layout(
136} 129}
137 130
138static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { 131static int sort_workspace_cmp_qsort(const void *_a, const void *_b) {
139 struct sway_container *a = *(void **)_a; 132 swayc_t *a = *(void **)_a;
140 struct sway_container *b = *(void **)_b; 133 swayc_t *b = *(void **)_b;
141 int retval = 0; 134 int retval = 0;
142 135
143 if (isdigit(a->name[0]) && isdigit(b->name[0])) { 136 if (isdigit(a->name[0]) && isdigit(b->name[0])) {
@@ -153,22 +146,21 @@ static int sort_workspace_cmp_qsort(const void *_a, const void *_b) {
153 return retval; 146 return retval;
154} 147}
155 148
156void container_sort_workspaces(struct sway_container *output) { 149void sort_workspaces(swayc_t *output) {
157 list_stable_sort(output->children, sort_workspace_cmp_qsort); 150 list_stable_sort(output->children, sort_workspace_cmp_qsort);
158} 151}
159 152
160static void apply_horiz_layout(struct sway_container *container, const double x, 153static void apply_horiz_layout(swayc_t *container, const double x,
161 const double y, const double width, 154 const double y, const double width,
162 const double height, const int start, 155 const double height, const int start,
163 const int end); 156 const int end);
164 157
165static void apply_vert_layout(struct sway_container *container, const double x, 158static void apply_vert_layout(swayc_t *container, const double x,
166 const double y, const double width, 159 const double y, const double width,
167 const double height, const int start, 160 const double height, const int start,
168 const int end); 161 const int end);
169 162
170void arrange_windows(struct sway_container *container, 163void arrange_windows(swayc_t *container, double width, double height) {
171 double width, double height) {
172 int i; 164 int i;
173 if (width == -1 || height == -1) { 165 if (width == -1 || height == -1) {
174 width = container->width; 166 width = container->width;
@@ -189,7 +181,7 @@ void arrange_windows(struct sway_container *container,
189 case C_ROOT: 181 case C_ROOT:
190 // TODO: wlr_output_layout probably 182 // TODO: wlr_output_layout probably
191 for (i = 0; i < container->children->length; ++i) { 183 for (i = 0; i < container->children->length; ++i) {
192 struct sway_container *output = container->children->items[i]; 184 swayc_t *output = container->children->items[i];
193 wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f", 185 wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f",
194 output->name, output->x, output->y); 186 output->name, output->x, output->y);
195 arrange_windows(output, -1, -1); 187 arrange_windows(output, -1, -1);
@@ -205,14 +197,13 @@ void arrange_windows(struct sway_container *container,
205 } 197 }
206 // arrange all workspaces: 198 // arrange all workspaces:
207 for (i = 0; i < container->children->length; ++i) { 199 for (i = 0; i < container->children->length; ++i) {
208 struct sway_container *child = container->children->items[i]; 200 swayc_t *child = container->children->items[i];
209 arrange_windows(child, -1, -1); 201 arrange_windows(child, -1, -1);
210 } 202 }
211 return; 203 return;
212 case C_WORKSPACE: 204 case C_WORKSPACE:
213 { 205 {
214 struct sway_container *output = 206 swayc_t *output = swayc_parent_by_type(container, C_OUTPUT);
215 container_parent(container, C_OUTPUT);
216 struct wlr_box *area = &output->sway_output->usable_area; 207 struct wlr_box *area = &output->sway_output->usable_area;
217 wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d", 208 wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d",
218 area->width, area->height, area->x, area->y); 209 area->width, area->height, area->x, area->y);
@@ -261,15 +252,14 @@ void arrange_windows(struct sway_container *container,
261 } 252 }
262} 253}
263 254
264static void apply_horiz_layout(struct sway_container *container, 255static void apply_horiz_layout(swayc_t *container,
265 const double x, const double y, 256 const double x, const double y,
266 const double width, const double height, 257 const double width, const double height,
267 const int start, const int end) { 258 const int start, const int end) {
268 double scale = 0; 259 double scale = 0;
269 // Calculate total width 260 // Calculate total width
270 for (int i = start; i < end; ++i) { 261 for (int i = start; i < end; ++i) {
271 double *old_width = 262 double *old_width = &((swayc_t *)container->children->items[i])->width;
272 &((struct sway_container *)container->children->items[i])->width;
273 if (*old_width <= 0) { 263 if (*old_width <= 0) {
274 if (end - start > 1) { 264 if (end - start > 1) {
275 *old_width = width / (end - start - 1); 265 *old_width = width / (end - start - 1);
@@ -286,7 +276,7 @@ static void apply_horiz_layout(struct sway_container *container,
286 if (scale > 0.1) { 276 if (scale > 0.1) {
287 wlr_log(L_DEBUG, "Arranging %p horizontally", container); 277 wlr_log(L_DEBUG, "Arranging %p horizontally", container);
288 for (int i = start; i < end; ++i) { 278 for (int i = start; i < end; ++i) {
289 struct sway_container *child = container->children->items[i]; 279 swayc_t *child = container->children->items[i];
290 wlr_log(L_DEBUG, 280 wlr_log(L_DEBUG,
291 "Calculating arrangement for %p:%d (will scale %f by %f)", 281 "Calculating arrangement for %p:%d (will scale %f by %f)",
292 child, child->type, width, scale); 282 child, child->type, width, scale);
@@ -311,7 +301,7 @@ static void apply_horiz_layout(struct sway_container *container,
311 } 301 }
312} 302}
313 303
314void apply_vert_layout(struct sway_container *container, 304void apply_vert_layout(swayc_t *container,
315 const double x, const double y, 305 const double x, const double y,
316 const double width, const double height, const int start, 306 const double width, const double height, const int start,
317 const int end) { 307 const int end) {
@@ -319,8 +309,7 @@ void apply_vert_layout(struct sway_container *container,
319 double scale = 0; 309 double scale = 0;
320 // Calculate total height 310 // Calculate total height
321 for (i = start; i < end; ++i) { 311 for (i = start; i < end; ++i) {
322 double *old_height = 312 double *old_height = &((swayc_t *)container->children->items[i])->height;
323 &((struct sway_container *)container->children->items[i])->height;
324 if (*old_height <= 0) { 313 if (*old_height <= 0) {
325 if (end - start > 1) { 314 if (end - start > 1) {
326 *old_height = height / (end - start - 1); 315 *old_height = height / (end - start - 1);
@@ -337,7 +326,7 @@ void apply_vert_layout(struct sway_container *container,
337 if (scale > 0.1) { 326 if (scale > 0.1) {
338 wlr_log(L_DEBUG, "Arranging %p vertically", container); 327 wlr_log(L_DEBUG, "Arranging %p vertically", container);
339 for (i = start; i < end; ++i) { 328 for (i = start; i < end; ++i) {
340 struct sway_container *child = container->children->items[i]; 329 swayc_t *child = container->children->items[i];
341 wlr_log(L_DEBUG, 330 wlr_log(L_DEBUG,
342 "Calculating arrangement for %p:%d (will scale %f by %f)", 331 "Calculating arrangement for %p:%d (will scale %f by %f)",
343 child, child->type, height, scale); 332 child, child->type, height, scale);
@@ -365,16 +354,15 @@ void apply_vert_layout(struct sway_container *container,
365/** 354/**
366 * Get swayc in the direction of newly entered output. 355 * Get swayc in the direction of newly entered output.
367 */ 356 */
368static struct sway_container *get_swayc_in_output_direction( 357static swayc_t *get_swayc_in_output_direction(swayc_t *output,
369 struct sway_container *output, enum movement_direction dir, 358 enum movement_direction dir, struct sway_seat *seat) {
370 struct sway_seat *seat) {
371 if (!output) { 359 if (!output) {
372 return NULL; 360 return NULL;
373 } 361 }
374 362
375 struct sway_container *ws = sway_seat_get_focus_inactive(seat, output); 363 swayc_t *ws = sway_seat_get_focus_inactive(seat, output);
376 if (ws->type != C_WORKSPACE) { 364 if (ws->type != C_WORKSPACE) {
377 ws = container_parent(ws, C_WORKSPACE); 365 ws = swayc_parent_by_type(ws, C_WORKSPACE);
378 } 366 }
379 367
380 if (ws == NULL) { 368 if (ws == NULL) {
@@ -392,15 +380,13 @@ static struct sway_container *get_swayc_in_output_direction(
392 return ws->children->items[0]; 380 return ws->children->items[0];
393 case MOVE_UP: 381 case MOVE_UP:
394 case MOVE_DOWN: { 382 case MOVE_DOWN: {
395 struct sway_container *focused = 383 swayc_t *focused = sway_seat_get_focus_inactive(seat, ws);
396 sway_seat_get_focus_inactive(seat, ws);
397 if (focused && focused->parent) { 384 if (focused && focused->parent) {
398 struct sway_container *parent = focused->parent; 385 swayc_t *parent = focused->parent;
399 if (parent->layout == L_VERT) { 386 if (parent->layout == L_VERT) {
400 if (dir == MOVE_UP) { 387 if (dir == MOVE_UP) {
401 // get child furthest down on new output 388 // get child furthest down on new output
402 int idx = parent->children->length - 1; 389 return parent->children->items[parent->children->length-1];
403 return parent->children->items[idx];
404 } else if (dir == MOVE_DOWN) { 390 } else if (dir == MOVE_DOWN) {
405 // get child furthest up on new output 391 // get child furthest up on new output
406 return parent->children->items[0]; 392 return parent->children->items[0];
@@ -418,14 +404,13 @@ static struct sway_container *get_swayc_in_output_direction(
418 return ws; 404 return ws;
419} 405}
420 406
421static void get_layout_center_position(struct sway_container *container, 407static void get_layout_center_position(swayc_t *container, int *x, int *y) {
422 int *x, int *y) {
423 // FIXME view coords are inconsistently referred to in layout/output systems 408 // FIXME view coords are inconsistently referred to in layout/output systems
424 if (container->type == C_OUTPUT) { 409 if (container->type == C_OUTPUT) {
425 *x = container->x + container->width/2; 410 *x = container->x + container->width/2;
426 *y = container->y + container->height/2; 411 *y = container->y + container->height/2;
427 } else { 412 } else {
428 struct sway_container *output = container_parent(container, C_OUTPUT); 413 swayc_t *output = swayc_parent_by_type(container, C_OUTPUT);
429 if (container->type == C_WORKSPACE) { 414 if (container->type == C_WORKSPACE) {
430 // Workspace coordinates are actually wrong/arbitrary, but should 415 // Workspace coordinates are actually wrong/arbitrary, but should
431 // be same as output. 416 // be same as output.
@@ -438,8 +423,7 @@ static void get_layout_center_position(struct sway_container *container,
438 } 423 }
439} 424}
440 425
441static bool sway_dir_to_wlr(enum movement_direction dir, 426static bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out) {
442 enum wlr_direction *out) {
443 switch (dir) { 427 switch (dir) {
444 case MOVE_UP: 428 case MOVE_UP:
445 *out = WLR_DIRECTION_UP; 429 *out = WLR_DIRECTION_UP;
@@ -460,12 +444,12 @@ static bool sway_dir_to_wlr(enum movement_direction dir,
460 return true; 444 return true;
461} 445}
462 446
463static struct sway_container *sway_output_from_wlr(struct wlr_output *output) { 447static swayc_t *sway_output_from_wlr(struct wlr_output *output) {
464 if (output == NULL) { 448 if (output == NULL) {
465 return NULL; 449 return NULL;
466 } 450 }
467 for (int i = 0; i < root_container.children->length; ++i) { 451 for (int i = 0; i < root_container.children->length; ++i) {
468 struct sway_container *o = root_container.children->items[i]; 452 swayc_t *o = root_container.children->items[i];
469 if (o->type == C_OUTPUT && o->sway_output->wlr_output == output) { 453 if (o->type == C_OUTPUT && o->sway_output->wlr_output == output) {
470 return o; 454 return o;
471 } 455 }
@@ -473,14 +457,13 @@ static struct sway_container *sway_output_from_wlr(struct wlr_output *output) {
473 return NULL; 457 return NULL;
474} 458}
475 459
476static struct sway_container *get_swayc_in_direction_under( 460static swayc_t *get_swayc_in_direction_under(swayc_t *container,
477 struct sway_container *container, enum movement_direction dir, 461 enum movement_direction dir, struct sway_seat *seat, swayc_t *limit) {
478 struct sway_seat *seat, struct sway_container *limit) {
479 if (dir == MOVE_CHILD) { 462 if (dir == MOVE_CHILD) {
480 return sway_seat_get_focus_inactive(seat, container); 463 return sway_seat_get_focus_inactive(seat, container);
481 } 464 }
482 465
483 struct sway_container *parent = container->parent; 466 swayc_t *parent = container->parent;
484 if (dir == MOVE_PARENT) { 467 if (dir == MOVE_PARENT) {
485 if (parent->type == C_OUTPUT) { 468 if (parent->type == C_OUTPUT) {
486 return NULL; 469 return NULL;
@@ -513,10 +496,9 @@ static struct sway_container *get_swayc_in_direction_under(
513 /* 496 /*
514 if (container->type == C_VIEW && swayc_is_fullscreen(container)) { 497 if (container->type == C_VIEW && swayc_is_fullscreen(container)) {
515 wlr_log(L_DEBUG, "Moving from fullscreen view, skipping to output"); 498 wlr_log(L_DEBUG, "Moving from fullscreen view, skipping to output");
516 container = container_parent(container, C_OUTPUT); 499 container = swayc_parent_by_type(container, C_OUTPUT);
517 get_layout_center_position(container, &abs_pos); 500 get_layout_center_position(container, &abs_pos);
518 struct sway_container *output = 501 swayc_t *output = swayc_adjacent_output(container, dir, &abs_pos, true);
519 swayc_adjacent_output(container, dir, &abs_pos, true);
520 return get_swayc_in_output_direction(output, dir); 502 return get_swayc_in_output_direction(output, dir);
521 } 503 }
522 if (container->type == C_WORKSPACE && container->fullscreen) { 504 if (container->type == C_WORKSPACE && container->fullscreen) {
@@ -525,7 +507,7 @@ static struct sway_container *get_swayc_in_direction_under(
525 } 507 }
526 */ 508 */
527 509
528 struct sway_container *wrap_candidate = NULL; 510 swayc_t *wrap_candidate = NULL;
529 while (true) { 511 while (true) {
530 // Test if we can even make a difference here 512 // Test if we can even make a difference here
531 bool can_move = false; 513 bool can_move = false;
@@ -539,19 +521,16 @@ static struct sway_container *get_swayc_in_direction_under(
539 } 521 }
540 int lx, ly; 522 int lx, ly;
541 get_layout_center_position(container, &lx, &ly); 523 get_layout_center_position(container, &lx, &ly);
542 struct wlr_output_layout *layout = 524 struct wlr_output_layout *layout = root_container.sway_root->output_layout;
543 root_container.sway_root->output_layout;
544 struct wlr_output *wlr_adjacent = 525 struct wlr_output *wlr_adjacent =
545 wlr_output_layout_adjacent_output(layout, wlr_dir, 526 wlr_output_layout_adjacent_output(layout, wlr_dir,
546 container->sway_output->wlr_output, lx, ly); 527 container->sway_output->wlr_output, lx, ly);
547 struct sway_container *adjacent = 528 swayc_t *adjacent = sway_output_from_wlr(wlr_adjacent);
548 sway_output_from_wlr(wlr_adjacent);
549 529
550 if (!adjacent || adjacent == container) { 530 if (!adjacent || adjacent == container) {
551 return wrap_candidate; 531 return wrap_candidate;
552 } 532 }
553 struct sway_container *next = 533 swayc_t *next = get_swayc_in_output_direction(adjacent, dir, seat);
554 get_swayc_in_output_direction(adjacent, dir, seat);
555 if (next == NULL) { 534 if (next == NULL) {
556 return NULL; 535 return NULL;
557 } 536 }
@@ -591,9 +570,8 @@ static struct sway_container *get_swayc_in_direction_under(
591 } 570 }
592 } 571 }
593 } else { 572 } else {
594 wlr_log(L_DEBUG, 573 wlr_log(L_DEBUG, "%s cont %d-%p dir %i sibling %d: %p", __func__,
595 "cont %d-%p dir %i sibling %d: %p", idx, 574 idx, container, dir, desired, parent->children->items[desired]);
596 container, dir, desired, parent->children->items[desired]);
597 return parent->children->items[desired]; 575 return parent->children->items[desired];
598 } 576 }
599 } 577 }
@@ -609,8 +587,7 @@ static struct sway_container *get_swayc_in_direction_under(
609 } 587 }
610} 588}
611 589
612struct sway_container *container_get_in_direction( 590swayc_t *get_swayc_in_direction(swayc_t *container, struct sway_seat *seat,
613 struct sway_container *container, struct sway_seat *seat,
614 enum movement_direction dir) { 591 enum movement_direction dir) {
615 return get_swayc_in_direction_under(container, dir, seat, NULL); 592 return get_swayc_in_direction_under(container, dir, seat, NULL);
616} 593}