diff options
author | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-04-28 11:26:14 +1000 |
---|---|---|
committer | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-04-28 11:26:14 +1000 |
commit | 167c2e1aa99aa8011e169b0fb61c47953cc9a5f6 (patch) | |
tree | f312cac40cd542964f62d8b7ed53d44bb13dea37 /sway/tree/layout.c | |
parent | Merge pull request #1866 from ggreer/swaybar-cmd-sh (diff) | |
download | sway-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.c | 279 |
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 | ||
22 | static void output_layout_handle_change(struct wl_listener *listener, | 23 | static 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 | ||
36 | void layout_init(void) { | 28 | void 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 | ||
103 | void container_insert_child(struct sway_container *parent, | 97 | void 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 | ||
305 | void container_move(struct sway_container *container, | 300 | void 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 | ||
556 | static 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 | |||
561 | static 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 | |||
566 | void 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 | |||
670 | static 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 | |||
727 | void 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 | ||