aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree/layout.c
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-04-28 11:26:14 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-04-28 11:26:14 +1000
commit167c2e1aa99aa8011e169b0fb61c47953cc9a5f6 (patch)
treef312cac40cd542964f62d8b7ed53d44bb13dea37 /sway/tree/layout.c
parentMerge pull request #1866 from ggreer/swaybar-cmd-sh (diff)
downloadsway-167c2e1aa99aa8011e169b0fb61c47953cc9a5f6.tar.gz
sway-167c2e1aa99aa8011e169b0fb61c47953cc9a5f6.tar.zst
sway-167c2e1aa99aa8011e169b0fb61c47953cc9a5f6.zip
Refactor arrange_windows()
Replaces arrange_windows() with arrange_root(), arrange_output(), arrange_workspace() and arrange_children_of(). Also makes fullscreen views save and restore their dimensions, which allows it to preserve any custom resize and is also a requirement for floating views once they are implemented.
Diffstat (limited to 'sway/tree/layout.c')
-rw-r--r--sway/tree/layout.c279
1 files changed, 23 insertions, 256 deletions
diff --git a/sway/tree/layout.c b/sway/tree/layout.c
index a64cc9a9..ec1c6fe5 100644
--- a/sway/tree/layout.c
+++ b/sway/tree/layout.c
@@ -7,6 +7,7 @@
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/debug.h" 9#include "sway/debug.h"
10#include "sway/tree/arrange.h"
10#include "sway/tree/container.h" 11#include "sway/tree/container.h"
11#include "sway/tree/layout.h" 12#include "sway/tree/layout.h"
12#include "sway/output.h" 13#include "sway/output.h"
@@ -21,16 +22,7 @@ struct sway_container root_container;
21 22
22static void output_layout_handle_change(struct wl_listener *listener, 23static void output_layout_handle_change(struct wl_listener *listener,
23 void *data) { 24 void *data) {
24 struct wlr_output_layout *output_layout = 25 arrange_root();
25 root_container.sway_root->output_layout;
26 const struct wlr_box *layout_box =
27 wlr_output_layout_get_box(output_layout, NULL);
28 root_container.x = layout_box->x;
29 root_container.y = layout_box->y;
30 root_container.width = layout_box->width;
31 root_container.height = layout_box->height;
32
33 arrange_windows(&root_container, layout_box->width, layout_box->height);
34} 26}
35 27
36void layout_init(void) { 28void layout_init(void) {
@@ -91,13 +83,15 @@ static void container_handle_fullscreen_reparent(struct sway_container *viewcon,
91 83
92 // Mark the new workspace as fullscreen 84 // Mark the new workspace as fullscreen
93 if (new_workspace->sway_workspace->fullscreen) { 85 if (new_workspace->sway_workspace->fullscreen) {
94 view_set_fullscreen(new_workspace->sway_workspace->fullscreen, false); 86 view_set_fullscreen_raw(
87 new_workspace->sway_workspace->fullscreen, false);
95 } 88 }
96 new_workspace->sway_workspace->fullscreen = view; 89 new_workspace->sway_workspace->fullscreen = view;
97 // Resize view to new output dimensions 90 // Resize view to new output dimensions
98 struct sway_output *output = new_workspace->parent->sway_output; 91 struct sway_container *output = new_workspace->parent;
99 view_configure(view, 0, 0, 92 view_configure(view, 0, 0, output->width, output->height);
100 output->wlr_output->width, output->wlr_output->height); 93 view->swayc->width = output->width;
94 view->swayc->height = output->height;
101} 95}
102 96
103void container_insert_child(struct sway_container *parent, 97void container_insert_child(struct sway_container *parent,
@@ -166,6 +160,7 @@ void container_move_to(struct sway_container *container,
166 } 160 }
167 struct sway_container *old_parent = container_remove_child(container); 161 struct sway_container *old_parent = container_remove_child(container);
168 container->width = container->height = 0; 162 container->width = container->height = 0;
163 container->saved_width = container->saved_height = 0;
169 struct sway_container *new_parent; 164 struct sway_container *new_parent;
170 if (destination->type == C_VIEW) { 165 if (destination->type == C_VIEW) {
171 new_parent = container_add_sibling(destination, container); 166 new_parent = container_add_sibling(destination, container);
@@ -188,9 +183,9 @@ void container_move_to(struct sway_container *container,
188 seat_set_focus(seat, new_parent); 183 seat_set_focus(seat, new_parent);
189 } 184 }
190 if (old_parent) { 185 if (old_parent) {
191 arrange_windows(old_parent, -1, -1); 186 arrange_children_of(old_parent);
192 } 187 }
193 arrange_windows(new_parent, -1, -1); 188 arrange_children_of(new_parent);
194 // If view was moved to a fullscreen workspace, refocus the fullscreen view 189 // If view was moved to a fullscreen workspace, refocus the fullscreen view
195 struct sway_container *new_workspace = container; 190 struct sway_container *new_workspace = container;
196 if (new_workspace->type != C_WORKSPACE) { 191 if (new_workspace->type != C_WORKSPACE) {
@@ -299,7 +294,7 @@ static void workspace_rejigger(struct sway_container *ws,
299 container_reap_empty_recursive(original_parent); 294 container_reap_empty_recursive(original_parent);
300 wl_signal_emit(&child->events.reparent, original_parent); 295 wl_signal_emit(&child->events.reparent, original_parent);
301 container_create_notify(new_parent); 296 container_create_notify(new_parent);
302 arrange_windows(ws, -1, -1); 297 arrange_workspace(ws);
303} 298}
304 299
305void container_move(struct sway_container *container, 300void container_move(struct sway_container *container,
@@ -378,7 +373,7 @@ void container_move(struct sway_container *container,
378 move_dir == MOVE_LEFT || move_dir == MOVE_RIGHT ? 373 move_dir == MOVE_LEFT || move_dir == MOVE_RIGHT ?
379 L_HORIZ : L_VERT; 374 L_HORIZ : L_VERT;
380 container_insert_child(current, container, offs < 0 ? 0 : 1); 375 container_insert_child(current, container, offs < 0 ? 0 : 1);
381 arrange_windows(current, -1, -1); 376 arrange_workspace(current);
382 } 377 }
383 return; 378 return;
384 } else { 379 } else {
@@ -402,8 +397,8 @@ void container_move(struct sway_container *container,
402 container_insert_child(current->parent, container, 397 container_insert_child(current->parent, container,
403 index + (offs < 0 ? 0 : 1)); 398 index + (offs < 0 ? 0 : 1));
404 container->width = container->height = 0; 399 container->width = container->height = 0;
405 arrange_windows(current->parent, -1, -1); 400 arrange_children_of(current->parent);
406 arrange_windows(old_parent, -1, -1); 401 arrange_children_of(old_parent);
407 return; 402 return;
408 } 403 }
409 } else { 404 } else {
@@ -433,14 +428,14 @@ void container_move(struct sway_container *container,
433 wlr_log(L_DEBUG, "Swapping siblings"); 428 wlr_log(L_DEBUG, "Swapping siblings");
434 sibling->parent->children->items[index + offs] = container; 429 sibling->parent->children->items[index + offs] = container;
435 sibling->parent->children->items[index] = sibling; 430 sibling->parent->children->items[index] = sibling;
436 arrange_windows(sibling->parent, -1, -1); 431 arrange_children_of(sibling->parent);
437 } else { 432 } else {
438 wlr_log(L_DEBUG, "Promoting to sibling of cousin"); 433 wlr_log(L_DEBUG, "Promoting to sibling of cousin");
439 container_insert_child(sibling->parent, container, 434 container_insert_child(sibling->parent, container,
440 index_child(sibling) + (offs > 0 ? 0 : 1)); 435 index_child(sibling) + (offs > 0 ? 0 : 1));
441 container->width = container->height = 0; 436 container->width = container->height = 0;
442 arrange_windows(sibling->parent, -1, -1); 437 arrange_children_of(sibling->parent);
443 arrange_windows(old_parent, -1, -1); 438 arrange_children_of(old_parent);
444 } 439 }
445 sibling = NULL; 440 sibling = NULL;
446 break; 441 break;
@@ -454,8 +449,8 @@ void container_move(struct sway_container *container,
454 "(move dir: %d)", limit, move_dir); 449 "(move dir: %d)", limit, move_dir);
455 container_insert_child(sibling, container, limit); 450 container_insert_child(sibling, container, limit);
456 container->width = container->height = 0; 451 container->width = container->height = 0;
457 arrange_windows(sibling, -1, -1); 452 arrange_children_of(sibling);
458 arrange_windows(old_parent, -1, -1); 453 arrange_children_of(old_parent);
459 sibling = NULL; 454 sibling = NULL;
460 } else { 455 } else {
461 wlr_log(L_DEBUG, "Reparenting container (perpendicular)"); 456 wlr_log(L_DEBUG, "Reparenting container (perpendicular)");
@@ -478,8 +473,8 @@ void container_move(struct sway_container *container,
478 container_add_child(sibling, container); 473 container_add_child(sibling, container);
479 } 474 }
480 container->width = container->height = 0; 475 container->width = container->height = 0;
481 arrange_windows(sibling, -1, -1); 476 arrange_children_of(sibling);
482 arrange_windows(old_parent, -1, -1); 477 arrange_children_of(old_parent);
483 sibling = NULL; 478 sibling = NULL;
484 } 479 }
485 break; 480 break;
@@ -553,234 +548,6 @@ void container_sort_workspaces(struct sway_container *output) {
553 list_stable_sort(output->children, sort_workspace_cmp_qsort); 548 list_stable_sort(output->children, sort_workspace_cmp_qsort);
554} 549}
555 550
556static void apply_horiz_layout(struct sway_container *container, const double x,
557 const double y, const double width,
558 const double height, const int start,
559 const int end);
560
561static void apply_vert_layout(struct sway_container *container, const double x,
562 const double y, const double width,
563 const double height, const int start,
564 const int end);
565
566void arrange_windows(struct sway_container *container,
567 double width, double height) {
568 if (config->reloading) {
569 return;
570 }
571 int i;
572 if (width == -1 || height == -1) {
573 width = container->width;
574 height = container->height;
575 }
576 // pixels are indivisible. if we don't round the pixels, then the view
577 // calculations will be off (e.g. 50.5 + 50.5 = 101, but in reality it's
578 // 50 + 50 = 100). doing it here cascades properly to all width/height/x/y.
579 width = floor(width);
580 height = floor(height);
581
582 wlr_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", container,
583 container->name, container->width, container->height, container->x,
584 container->y);
585
586 double x = 0, y = 0;
587 switch (container->type) {
588 case C_ROOT:
589 for (i = 0; i < container->children->length; ++i) {
590 struct sway_container *output = container->children->items[i];
591 const struct wlr_box *output_box = wlr_output_layout_get_box(
592 container->sway_root->output_layout,
593 output->sway_output->wlr_output);
594 output->x = output_box->x;
595 output->y = output_box->y;
596 output->width = output_box->width;
597 output->height = output_box->height;
598 wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f",
599 output->name, output->x, output->y);
600 arrange_windows(output, output_box->width, output_box->height);
601 }
602 return;
603 case C_OUTPUT:
604 // arrange all workspaces:
605 for (i = 0; i < container->children->length; ++i) {
606 struct sway_container *child = container->children->items[i];
607 arrange_windows(child, -1, -1);
608 }
609 return;
610 case C_WORKSPACE:
611 {
612 struct sway_container *output =
613 container_parent(container, C_OUTPUT);
614 struct wlr_box *area = &output->sway_output->usable_area;
615 wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d",
616 area->width, area->height, area->x, area->y);
617 container->width = width = area->width;
618 container->height = height = area->height;
619 container->x = x = area->x;
620 container->y = y = area->y;
621 wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f",
622 container->name, container->x, container->y);
623 if (container->sway_workspace->fullscreen) {
624 view_configure(container->sway_workspace->fullscreen, 0, 0,
625 output->width, output->height);
626 return;
627 }
628 }
629 // children are properly handled below
630 break;
631 case C_VIEW:
632 {
633 container->width = width;
634 container->height = height;
635 view_configure(container->sway_view, container->x, container->y,
636 container->width, container->height);
637 wlr_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f",
638 container->width, container->height,
639 container->x, container->y);
640 }
641 return;
642 default:
643 container->width = width;
644 container->height = height;
645 x = container->x;
646 y = container->y;
647 break;
648 }
649
650 switch (container->layout) {
651 case L_HORIZ:
652 apply_horiz_layout(container, x, y, width, height, 0,
653 container->children->length);
654 break;
655 case L_VERT:
656 apply_vert_layout(container, x, y, width, height, 0,
657 container->children->length);
658 break;
659 default:
660 wlr_log(L_DEBUG, "TODO: arrange layout type %d", container->layout);
661 apply_horiz_layout(container, x, y, width, height, 0,
662 container->children->length);
663 break;
664 }
665 container_damage_whole(container);
666 // TODO: Make this less shitty
667 update_debug_tree();
668}
669
670static void apply_horiz_layout(struct sway_container *container,
671 const double x, const double y,
672 const double width, const double height,
673 const int start, const int end) {
674 double scale = 0;
675 // Calculate total width
676 for (int i = start; i < end; ++i) {
677 double *old_width =
678 &((struct sway_container *)container->children->items[i])->width;
679 if (*old_width <= 0) {
680 if (end - start > 1) {
681 *old_width = width / (end - start - 1);
682 } else {
683 *old_width = width;
684 }
685 }
686 scale += *old_width;
687 }
688 scale = width / scale;
689
690 // Resize windows
691 double child_x = x;
692 if (scale > 0.1) {
693 wlr_log(L_DEBUG, "Arranging %p horizontally", container);
694 for (int i = start; i < end; ++i) {
695 struct sway_container *child = container->children->items[i];
696 wlr_log(L_DEBUG,
697 "Calculating arrangement for %p:%d (will scale %f by %f)",
698 child, child->type, width, scale);
699
700 if (child->type == C_VIEW) {
701 view_configure(child->sway_view, child_x, y, child->width,
702 child->height);
703 } else {
704 child->x = child_x;
705 child->y = y;
706 }
707
708 if (i == end - 1) {
709 double remaining_width = x + width - child_x;
710 arrange_windows(child, remaining_width, height);
711 } else {
712 arrange_windows(child, child->width * scale, height);
713 }
714 child_x += child->width;
715 }
716
717 // update focused view border last because it may
718 // depend on the title bar geometry of its siblings.
719 /* TODO WLR
720 if (focused && container->children->length > 1) {
721 update_container_border(focused);
722 }
723 */
724 }
725}
726
727void apply_vert_layout(struct sway_container *container,
728 const double x, const double y,
729 const double width, const double height, const int start,
730 const int end) {
731 int i;
732 double scale = 0;
733 // Calculate total height
734 for (i = start; i < end; ++i) {
735 double *old_height =
736 &((struct sway_container *)container->children->items[i])->height;
737 if (*old_height <= 0) {
738 if (end - start > 1) {
739 *old_height = height / (end - start - 1);
740 } else {
741 *old_height = height;
742 }
743 }
744 scale += *old_height;
745 }
746 scale = height / scale;
747
748 // Resize
749 double child_y = y;
750 if (scale > 0.1) {
751 wlr_log(L_DEBUG, "Arranging %p vertically", container);
752 for (i = start; i < end; ++i) {
753 struct sway_container *child = container->children->items[i];
754 wlr_log(L_DEBUG,
755 "Calculating arrangement for %p:%d (will scale %f by %f)",
756 child, child->type, height, scale);
757 if (child->type == C_VIEW) {
758 view_configure(child->sway_view, x, child_y, child->width,
759 child->height);
760 } else {
761 child->x = x;
762 child->y = child_y;
763 }
764
765 if (i == end - 1) {
766 double remaining_height = y + height - child_y;
767 arrange_windows(child, width, remaining_height);
768 } else {
769 arrange_windows(child, width, child->height * scale);
770 }
771 child_y += child->height;
772 }
773
774 // update focused view border last because it may
775 // depend on the title bar geometry of its siblings.
776 /* TODO WLR
777 if (focused && container->children->length > 1) {
778 update_container_border(focused);
779 }
780 */
781 }
782}
783
784/** 551/**
785 * Get swayc in the direction of newly entered output. 552 * Get swayc in the direction of newly entered output.
786 */ 553 */
@@ -1026,7 +793,7 @@ struct sway_container *container_split(struct sway_container *child,
1026 // Special case: this just behaves like splitt 793 // Special case: this just behaves like splitt
1027 child->prev_layout = child->layout; 794 child->prev_layout = child->layout;
1028 child->layout = layout; 795 child->layout = layout;
1029 arrange_windows(child, -1, -1); 796 arrange_children_of(child);
1030 return child; 797 return child;
1031 } 798 }
1032 799