diff options
author | Mikkel Oscar Lyderik <mikkeloscar@gmail.com> | 2016-04-20 00:22:15 +0200 |
---|---|---|
committer | Mikkel Oscar Lyderik <mikkeloscar@gmail.com> | 2016-04-25 00:00:49 +0200 |
commit | 3e1f78ab26e8bc6b6cefd53ee137e97533c2695e (patch) | |
tree | f158bcae9fce9af29a35bd3ec0e32b81bff87662 /sway/layout.c | |
parent | Use tabs for indentation (diff) | |
download | sway-3e1f78ab26e8bc6b6cefd53ee137e97533c2695e.tar.gz sway-3e1f78ab26e8bc6b6cefd53ee137e97533c2695e.tar.zst sway-3e1f78ab26e8bc6b6cefd53ee137e97533c2695e.zip |
Add support for nested tabbed/stacked containers
Diffstat (limited to 'sway/layout.c')
-rw-r--r-- | sway/layout.c | 115 |
1 files changed, 93 insertions, 22 deletions
diff --git a/sway/layout.c b/sway/layout.c index 65ca2402..801f6f6b 100644 --- a/sway/layout.c +++ b/sway/layout.c | |||
@@ -3,7 +3,6 @@ | |||
3 | #include <math.h> | 3 | #include <math.h> |
4 | #include <wlc/wlc.h> | 4 | #include <wlc/wlc.h> |
5 | #include "extensions.h" | 5 | #include "extensions.h" |
6 | #include "layout.h" | ||
7 | #include "log.h" | 6 | #include "log.h" |
8 | #include "list.h" | 7 | #include "list.h" |
9 | #include "config.h" | 8 | #include "config.h" |
@@ -13,6 +12,7 @@ | |||
13 | #include "output.h" | 12 | #include "output.h" |
14 | #include "ipc-server.h" | 13 | #include "ipc-server.h" |
15 | #include "border.h" | 14 | #include "border.h" |
15 | #include "layout.h" | ||
16 | 16 | ||
17 | swayc_t root_container; | 17 | swayc_t root_container; |
18 | list_t *scratchpad; | 18 | list_t *scratchpad; |
@@ -442,12 +442,49 @@ static void update_border_geometry_floating(swayc_t *c, struct wlc_geometry *geo | |||
442 | update_view_border(c); | 442 | update_view_border(c); |
443 | } | 443 | } |
444 | 444 | ||
445 | void update_layout_geometry(swayc_t *parent, enum swayc_layouts prev_layout) { | ||
446 | switch (parent->layout) { | ||
447 | case L_TABBED: | ||
448 | case L_STACKED: | ||
449 | if (prev_layout != L_TABBED && prev_layout != L_STACKED) { | ||
450 | // cache current geometry for all non-float children | ||
451 | int i; | ||
452 | for (i = 0; i < parent->children->length; ++i) { | ||
453 | swayc_t *child = parent->children->items[i]; | ||
454 | child->cached_geometry.origin.x = child->x; | ||
455 | child->cached_geometry.origin.y = child->y; | ||
456 | child->cached_geometry.size.w = child->width; | ||
457 | child->cached_geometry.size.h = child->height; | ||
458 | } | ||
459 | } | ||
460 | break; | ||
461 | default: | ||
462 | if (prev_layout == L_TABBED || prev_layout == L_STACKED) { | ||
463 | // recover cached geometry for all non-float children | ||
464 | int i; | ||
465 | for (i = 0; i < parent->children->length; ++i) { | ||
466 | swayc_t *child = parent->children->items[i]; | ||
467 | // only recoverer cached geometry if non-zero | ||
468 | if (!wlc_geometry_equals(&child->cached_geometry, &wlc_geometry_zero)) { | ||
469 | child->x = child->cached_geometry.origin.x; | ||
470 | child->y = child->cached_geometry.origin.y; | ||
471 | child->width = child->cached_geometry.size.w; | ||
472 | child->height = child->cached_geometry.size.h; | ||
473 | } | ||
474 | } | ||
475 | } | ||
476 | break; | ||
477 | } | ||
478 | } | ||
479 | |||
445 | void update_geometry(swayc_t *container) { | 480 | void update_geometry(swayc_t *container) { |
446 | if (container->type != C_VIEW) { | 481 | if (container->type != C_VIEW && container->type != C_CONTAINER) { |
447 | return; | 482 | return; |
448 | } | 483 | } |
484 | |||
449 | swayc_t *ws = swayc_parent_by_type(container, C_WORKSPACE); | 485 | swayc_t *ws = swayc_parent_by_type(container, C_WORKSPACE); |
450 | swayc_t *op = ws->parent; | 486 | swayc_t *op = ws->parent; |
487 | swayc_t *parent = container->parent; | ||
451 | int gap = container->is_floating ? 0 : swayc_gap(container); | 488 | int gap = container->is_floating ? 0 : swayc_gap(container); |
452 | if (gap % 2 != 0) { | 489 | if (gap % 2 != 0) { |
453 | // because gaps are implemented as "half sized margins" it's currently | 490 | // because gaps are implemented as "half sized margins" it's currently |
@@ -455,24 +492,14 @@ void update_geometry(swayc_t *container) { | |||
455 | gap -= 1; | 492 | gap -= 1; |
456 | } | 493 | } |
457 | 494 | ||
458 | int width = container->width; | ||
459 | int height = container->height; | ||
460 | |||
461 | // use parent size if window is in a stacked/tabbed layout | ||
462 | swayc_t *parent = container->parent; | ||
463 | if (swayc_is_tabbed_stacked(container)) { | ||
464 | width = parent->width; | ||
465 | height = parent->height; | ||
466 | } | ||
467 | |||
468 | struct wlc_geometry geometry = { | 495 | struct wlc_geometry geometry = { |
469 | .origin = { | 496 | .origin = { |
470 | .x = container->x + gap/2 < op->width ? container->x + gap/2 : op->width-1, | 497 | .x = container->x + gap/2 < op->width ? container->x + gap/2 : op->width-1, |
471 | .y = container->y + gap/2 < op->height ? container->y + gap/2 : op->height-1 | 498 | .y = container->y + gap/2 < op->height ? container->y + gap/2 : op->height-1 |
472 | }, | 499 | }, |
473 | .size = { | 500 | .size = { |
474 | .w = width > gap ? width - gap : 1, | 501 | .w = container->width > gap ? container->width - gap : 1, |
475 | .h = height > gap ? height - gap : 1, | 502 | .h = container->height > gap ? container->height - gap : 1, |
476 | } | 503 | } |
477 | }; | 504 | }; |
478 | if (swayc_is_fullscreen(container)) { | 505 | if (swayc_is_fullscreen(container)) { |
@@ -492,16 +519,16 @@ void update_geometry(swayc_t *container) { | |||
492 | // with gap, and align correctly). | 519 | // with gap, and align correctly). |
493 | if (container->x - gap <= ws->x) { | 520 | if (container->x - gap <= ws->x) { |
494 | geometry.origin.x = ws->x; | 521 | geometry.origin.x = ws->x; |
495 | geometry.size.w = width - gap/2; | 522 | geometry.size.w = container->width - gap/2; |
496 | } | 523 | } |
497 | if (container->y - gap <= ws->y) { | 524 | if (container->y - gap <= ws->y) { |
498 | geometry.origin.y = ws->y; | 525 | geometry.origin.y = ws->y; |
499 | geometry.size.h = height - gap/2; | 526 | geometry.size.h = container->height - gap/2; |
500 | } | 527 | } |
501 | if (container->x + width + gap >= ws->x + ws->width) { | 528 | if (container->x + container->width + gap >= ws->x + ws->width) { |
502 | geometry.size.w = ws->x + ws->width - geometry.origin.x; | 529 | geometry.size.w = ws->x + ws->width - geometry.origin.x; |
503 | } | 530 | } |
504 | if (container->y + height + gap >= ws->y + ws->height) { | 531 | if (container->y + container->height + gap >= ws->y + ws->height) { |
505 | geometry.size.h = ws->y + ws->height - geometry.origin.y; | 532 | geometry.size.h = ws->y + ws->height - geometry.origin.y; |
506 | } | 533 | } |
507 | } | 534 | } |
@@ -637,10 +664,14 @@ void update_geometry(swayc_t *container) { | |||
637 | 664 | ||
638 | container->actual_geometry = geometry; | 665 | container->actual_geometry = geometry; |
639 | 666 | ||
640 | update_view_border(container); | 667 | if (container->type == C_VIEW) { |
668 | update_view_border(container); | ||
669 | } | ||
641 | } | 670 | } |
642 | 671 | ||
643 | wlc_view_set_geometry(container->handle, 0, &geometry); | 672 | if (container->type == C_VIEW) { |
673 | wlc_view_set_geometry(container->handle, 0, &geometry); | ||
674 | } | ||
644 | } | 675 | } |
645 | 676 | ||
646 | static void arrange_windows_r(swayc_t *container, double width, double height) { | 677 | static void arrange_windows_r(swayc_t *container, double width, double height) { |
@@ -736,6 +767,22 @@ static void arrange_windows_r(swayc_t *container, double width, double height) { | |||
736 | container->height = height; | 767 | container->height = height; |
737 | x = container->x; | 768 | x = container->x; |
738 | y = container->y; | 769 | y = container->y; |
770 | |||
771 | // update container size if it's a child in a tabbed/stacked layout | ||
772 | if (swayc_is_tabbed_stacked(container)) { | ||
773 | // Use parent geometry as a base for calculating | ||
774 | // container geometry | ||
775 | container->width = container->parent->width; | ||
776 | container->height = container->parent->height; | ||
777 | container->x = container->parent->x; | ||
778 | container->y = container->parent->y; | ||
779 | update_geometry(container); | ||
780 | width = container->width = container->actual_geometry.size.w; | ||
781 | height = container->height = container->actual_geometry.size.h; | ||
782 | x = container->x = container->actual_geometry.origin.x; | ||
783 | y = container->y = container->actual_geometry.origin.y; | ||
784 | } | ||
785 | |||
739 | break; | 786 | break; |
740 | } | 787 | } |
741 | 788 | ||
@@ -760,11 +807,17 @@ static void arrange_windows_r(swayc_t *container, double width, double height) { | |||
760 | if (scale > 0.1) { | 807 | if (scale > 0.1) { |
761 | scale = width / scale; | 808 | scale = width / scale; |
762 | sway_log(L_DEBUG, "Arranging %p horizontally", container); | 809 | sway_log(L_DEBUG, "Arranging %p horizontally", container); |
810 | swayc_t *focused = NULL; | ||
763 | for (i = 0; i < container->children->length; ++i) { | 811 | for (i = 0; i < container->children->length; ++i) { |
764 | swayc_t *child = container->children->items[i]; | 812 | swayc_t *child = container->children->items[i]; |
765 | sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, width, scale); | 813 | sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, width, scale); |
766 | child->x = x; | 814 | child->x = x; |
767 | child->y = y; | 815 | child->y = y; |
816 | |||
817 | if (child == container->focused) { | ||
818 | focused = child; | ||
819 | } | ||
820 | |||
768 | if (i == container->children->length - 1) { | 821 | if (i == container->children->length - 1) { |
769 | double remaining_width = container->x + width - x; | 822 | double remaining_width = container->x + width - x; |
770 | arrange_windows_r(child, remaining_width, height); | 823 | arrange_windows_r(child, remaining_width, height); |
@@ -773,6 +826,12 @@ static void arrange_windows_r(swayc_t *container, double width, double height) { | |||
773 | } | 826 | } |
774 | x += child->width; | 827 | x += child->width; |
775 | } | 828 | } |
829 | |||
830 | // update focused view border last because it may | ||
831 | // depend on the title bar geometry of its siblings. | ||
832 | if (focused && container->children->length > 1) { | ||
833 | update_view_border(focused); | ||
834 | } | ||
776 | } | 835 | } |
777 | break; | 836 | break; |
778 | case L_VERT: | 837 | case L_VERT: |
@@ -792,11 +851,17 @@ static void arrange_windows_r(swayc_t *container, double width, double height) { | |||
792 | if (scale > 0.1) { | 851 | if (scale > 0.1) { |
793 | scale = height / scale; | 852 | scale = height / scale; |
794 | sway_log(L_DEBUG, "Arranging %p vertically", container); | 853 | sway_log(L_DEBUG, "Arranging %p vertically", container); |
854 | swayc_t *focused = NULL; | ||
795 | for (i = 0; i < container->children->length; ++i) { | 855 | for (i = 0; i < container->children->length; ++i) { |
796 | swayc_t *child = container->children->items[i]; | 856 | swayc_t *child = container->children->items[i]; |
797 | sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, height, scale); | 857 | sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, height, scale); |
798 | child->x = x; | 858 | child->x = x; |
799 | child->y = y; | 859 | child->y = y; |
860 | |||
861 | if (child == container->focused) { | ||
862 | focused = child; | ||
863 | } | ||
864 | |||
800 | if (i == container->children->length - 1) { | 865 | if (i == container->children->length - 1) { |
801 | double remaining_height = container->y + height - y; | 866 | double remaining_height = container->y + height - y; |
802 | arrange_windows_r(child, width, remaining_height); | 867 | arrange_windows_r(child, width, remaining_height); |
@@ -805,6 +870,12 @@ static void arrange_windows_r(swayc_t *container, double width, double height) { | |||
805 | } | 870 | } |
806 | y += child->height; | 871 | y += child->height; |
807 | } | 872 | } |
873 | |||
874 | // update focused view border last because it may | ||
875 | // depend on the title bar geometry of its siblings. | ||
876 | if (focused && container->children->length > 1) { | ||
877 | update_view_border(focused); | ||
878 | } | ||
808 | } | 879 | } |
809 | break; | 880 | break; |
810 | case L_TABBED: | 881 | case L_TABBED: |
@@ -818,12 +889,12 @@ static void arrange_windows_r(swayc_t *container, double width, double height) { | |||
818 | if (child == container->focused) { | 889 | if (child == container->focused) { |
819 | focused = child; | 890 | focused = child; |
820 | } else { | 891 | } else { |
821 | arrange_windows_r(child, -1, -1); | 892 | arrange_windows_r(child, width, height); |
822 | } | 893 | } |
823 | } | 894 | } |
824 | 895 | ||
825 | if (focused) { | 896 | if (focused) { |
826 | arrange_windows_r(focused, -1, -1); | 897 | arrange_windows_r(focused, width, height); |
827 | } | 898 | } |
828 | break; | 899 | break; |
829 | } | 900 | } |