summaryrefslogtreecommitdiffstats
path: root/sway/layout.c
diff options
context:
space:
mode:
authorLibravatar Mikkel Oscar Lyderik <mikkeloscar@gmail.com>2016-04-20 00:22:15 +0200
committerLibravatar Mikkel Oscar Lyderik <mikkeloscar@gmail.com>2016-04-25 00:00:49 +0200
commit3e1f78ab26e8bc6b6cefd53ee137e97533c2695e (patch)
treef158bcae9fce9af29a35bd3ec0e32b81bff87662 /sway/layout.c
parentUse tabs for indentation (diff)
downloadsway-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.c115
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
17swayc_t root_container; 17swayc_t root_container;
18list_t *scratchpad; 18list_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
445void 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
445void update_geometry(swayc_t *container) { 480void 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
646static void arrange_windows_r(swayc_t *container, double width, double height) { 677static 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 }