aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree/container.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/tree/container.c')
-rw-r--r--sway/tree/container.c518
1 files changed, 291 insertions, 227 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 6a9ce1c4..b928d069 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -1,12 +1,13 @@
1#define _POSIX_C_SOURCE 200809L 1#define _POSIX_C_SOURCE 200809L
2#include <assert.h> 2#include <assert.h>
3#include <drm_fourcc.h>
3#include <stdint.h> 4#include <stdint.h>
4#include <stdlib.h> 5#include <stdlib.h>
5#include <string.h> 6#include <string.h>
6#include <strings.h> 7#include <strings.h>
7#include <wayland-server-core.h> 8#include <wayland-server-core.h>
8#include <wlr/types/wlr_output_layout.h> 9#include <wlr/types/wlr_output_layout.h>
9#include "cairo.h" 10#include "cairo_util.h"
10#include "pango.h" 11#include "pango.h"
11#include "sway/config.h" 12#include "sway/config.h"
12#include "sway/desktop.h" 13#include "sway/desktop.h"
@@ -30,12 +31,12 @@ struct sway_container *container_create(struct sway_view *view) {
30 return NULL; 31 return NULL;
31 } 32 }
32 node_init(&c->node, N_CONTAINER, c); 33 node_init(&c->node, N_CONTAINER, c);
33 c->layout = L_NONE; 34 c->pending.layout = L_NONE;
34 c->view = view; 35 c->view = view;
35 c->alpha = 1.0f; 36 c->alpha = 1.0f;
36 37
37 if (!view) { 38 if (!view) {
38 c->children = create_list(); 39 c->pending.children = create_list();
39 c->current.children = create_list(); 40 c->current.children = create_list();
40 } 41 }
41 c->marks = create_list(); 42 c->marks = create_list();
@@ -62,7 +63,7 @@ void container_destroy(struct sway_container *con) {
62 wlr_texture_destroy(con->title_focused_inactive); 63 wlr_texture_destroy(con->title_focused_inactive);
63 wlr_texture_destroy(con->title_unfocused); 64 wlr_texture_destroy(con->title_unfocused);
64 wlr_texture_destroy(con->title_urgent); 65 wlr_texture_destroy(con->title_urgent);
65 list_free(con->children); 66 list_free(con->pending.children);
66 list_free(con->current.children); 67 list_free(con->current.children);
67 list_free(con->outputs); 68 list_free(con->outputs);
68 69
@@ -90,10 +91,10 @@ void container_begin_destroy(struct sway_container *con) {
90 } 91 }
91 // The workspace must have the fullscreen pointer cleared so that the 92 // The workspace must have the fullscreen pointer cleared so that the
92 // seat code can find an appropriate new focus. 93 // seat code can find an appropriate new focus.
93 if (con->fullscreen_mode == FULLSCREEN_WORKSPACE && con->workspace) { 94 if (con->pending.fullscreen_mode == FULLSCREEN_WORKSPACE && con->pending.workspace) {
94 con->workspace->fullscreen = NULL; 95 con->pending.workspace->fullscreen = NULL;
95 } 96 }
96 if (con->scratchpad && con->fullscreen_mode == FULLSCREEN_GLOBAL) { 97 if (con->scratchpad && con->pending.fullscreen_mode == FULLSCREEN_GLOBAL) {
97 container_fullscreen_disable(con); 98 container_fullscreen_disable(con);
98 } 99 }
99 100
@@ -108,11 +109,11 @@ void container_begin_destroy(struct sway_container *con) {
108 root_scratchpad_remove_container(con); 109 root_scratchpad_remove_container(con);
109 } 110 }
110 111
111 if (con->fullscreen_mode == FULLSCREEN_GLOBAL) { 112 if (con->pending.fullscreen_mode == FULLSCREEN_GLOBAL) {
112 container_fullscreen_disable(con); 113 container_fullscreen_disable(con);
113 } 114 }
114 115
115 if (con->parent || con->workspace) { 116 if (con->pending.parent || con->pending.workspace) {
116 container_detach(con); 117 container_detach(con);
117 } 118 }
118} 119}
@@ -121,12 +122,12 @@ void container_reap_empty(struct sway_container *con) {
121 if (con->view) { 122 if (con->view) {
122 return; 123 return;
123 } 124 }
124 struct sway_workspace *ws = con->workspace; 125 struct sway_workspace *ws = con->pending.workspace;
125 while (con) { 126 while (con) {
126 if (con->children->length) { 127 if (con->pending.children->length) {
127 return; 128 return;
128 } 129 }
129 struct sway_container *parent = con->parent; 130 struct sway_container *parent = con->pending.parent;
130 container_begin_destroy(con); 131 container_begin_destroy(con);
131 con = parent; 132 con = parent;
132 } 133 }
@@ -139,9 +140,9 @@ struct sway_container *container_flatten(struct sway_container *container) {
139 if (container->view) { 140 if (container->view) {
140 return NULL; 141 return NULL;
141 } 142 }
142 while (container && container->children->length == 1) { 143 while (container && container->pending.children->length == 1) {
143 struct sway_container *child = container->children->items[0]; 144 struct sway_container *child = container->pending.children->items[0];
144 struct sway_container *parent = container->parent; 145 struct sway_container *parent = container->pending.parent;
145 container_replace(container, child); 146 container_replace(container, child);
146 container_begin_destroy(container); 147 container_begin_destroy(container);
147 container = parent; 148 container = parent;
@@ -151,11 +152,11 @@ struct sway_container *container_flatten(struct sway_container *container) {
151 152
152struct sway_container *container_find_child(struct sway_container *container, 153struct sway_container *container_find_child(struct sway_container *container,
153 bool (*test)(struct sway_container *con, void *data), void *data) { 154 bool (*test)(struct sway_container *con, void *data), void *data) {
154 if (!container->children) { 155 if (!container->pending.children) {
155 return NULL; 156 return NULL;
156 } 157 }
157 for (int i = 0; i < container->children->length; ++i) { 158 for (int i = 0; i < container->pending.children->length; ++i) {
158 struct sway_container *child = container->children->items[i]; 159 struct sway_container *child = container->pending.children->items[i];
159 if (test(child, data)) { 160 if (test(child, data)) {
160 return child; 161 return child;
161 } 162 }
@@ -310,7 +311,7 @@ static struct sway_container *floating_container_at(double lx, double ly,
310 return NULL; 311 return NULL;
311} 312}
312 313
313struct sway_container *view_container_at(struct sway_node *parent, 314static struct sway_container *view_container_content_at(struct sway_node *parent,
314 double lx, double ly, 315 double lx, double ly,
315 struct wlr_surface **surface, double *sx, double *sy) { 316 struct wlr_surface **surface, double *sx, double *sy) {
316 if (!sway_assert(node_is_view(parent), "Expected a view")) { 317 if (!sway_assert(node_is_view(parent), "Expected a view")) {
@@ -319,10 +320,33 @@ struct sway_container *view_container_at(struct sway_node *parent,
319 320
320 struct sway_container *container = parent->sway_container; 321 struct sway_container *container = parent->sway_container;
321 struct wlr_box box = { 322 struct wlr_box box = {
322 .x = container->x, 323 .x = container->pending.content_x,
323 .y = container->y, 324 .y = container->pending.content_y,
324 .width = container->width, 325 .width = container->pending.content_width,
325 .height = container->height, 326 .height = container->pending.content_height,
327 };
328
329 if (wlr_box_contains_point(&box, lx, ly)) {
330 surface_at_view(parent->sway_container, lx, ly, surface, sx, sy);
331 return container;
332 }
333
334 return NULL;
335}
336
337static struct sway_container *view_container_at(struct sway_node *parent,
338 double lx, double ly,
339 struct wlr_surface **surface, double *sx, double *sy) {
340 if (!sway_assert(node_is_view(parent), "Expected a view")) {
341 return NULL;
342 }
343
344 struct sway_container *container = parent->sway_container;
345 struct wlr_box box = {
346 .x = container->pending.x,
347 .y = container->pending.y,
348 .width = container->pending.width,
349 .height = container->pending.height,
326 }; 350 };
327 351
328 if (wlr_box_contains_point(&box, lx, ly)) { 352 if (wlr_box_contains_point(&box, lx, ly)) {
@@ -394,7 +418,7 @@ struct sway_container *container_at(struct sway_workspace *workspace,
394 } 418 }
395 // Tiling (focused) 419 // Tiling (focused)
396 if (focus && focus->view && !is_floating) { 420 if (focus && focus->view && !is_floating) {
397 if ((c = surface_at_view(focus, lx, ly, surface, sx, sy))) { 421 if ((c = view_container_content_at(&focus->node, lx, ly, surface, sx, sy))) {
398 return c; 422 return c;
399 } 423 }
400 } 424 }
@@ -408,19 +432,41 @@ struct sway_container *container_at(struct sway_workspace *workspace,
408void container_for_each_child(struct sway_container *container, 432void container_for_each_child(struct sway_container *container,
409 void (*f)(struct sway_container *container, void *data), 433 void (*f)(struct sway_container *container, void *data),
410 void *data) { 434 void *data) {
411 if (container->children) { 435 if (container->pending.children) {
412 for (int i = 0; i < container->children->length; ++i) { 436 for (int i = 0; i < container->pending.children->length; ++i) {
413 struct sway_container *child = container->children->items[i]; 437 struct sway_container *child = container->pending.children->items[i];
414 f(child, data); 438 f(child, data);
415 container_for_each_child(child, f, data); 439 container_for_each_child(child, f, data);
416 } 440 }
417 } 441 }
418} 442}
419 443
444struct sway_container *container_obstructing_fullscreen_container(struct sway_container *container)
445{
446 struct sway_workspace *workspace = container->pending.workspace;
447
448 if (workspace && workspace->fullscreen && !container_is_fullscreen_or_child(container)) {
449 if (container_is_transient_for(container, workspace->fullscreen)) {
450 return NULL;
451 }
452 return workspace->fullscreen;
453 }
454
455 struct sway_container *fullscreen_global = root->fullscreen_global;
456 if (fullscreen_global && container != fullscreen_global && !container_has_ancestor(container, fullscreen_global)) {
457 if (container_is_transient_for(container, fullscreen_global)) {
458 return NULL;
459 }
460 return fullscreen_global;
461 }
462
463 return NULL;
464}
465
420bool container_has_ancestor(struct sway_container *descendant, 466bool container_has_ancestor(struct sway_container *descendant,
421 struct sway_container *ancestor) { 467 struct sway_container *ancestor) {
422 while (descendant) { 468 while (descendant) {
423 descendant = descendant->parent; 469 descendant = descendant->pending.parent;
424 if (descendant == ancestor) { 470 if (descendant == ancestor) {
425 return true; 471 return true;
426 } 472 }
@@ -485,6 +531,10 @@ static void update_title_texture(struct sway_container *con,
485 cairo_surface_destroy(dummy_surface); 531 cairo_surface_destroy(dummy_surface);
486 cairo_destroy(c); 532 cairo_destroy(c);
487 533
534 if (width == 0 || height == 0) {
535 return;
536 }
537
488 cairo_surface_t *surface = cairo_image_surface_create( 538 cairo_surface_t *surface = cairo_image_surface_create(
489 CAIRO_FORMAT_ARGB32, width, height); 539 CAIRO_FORMAT_ARGB32, width, height);
490 cairo_t *cairo = cairo_create(surface); 540 cairo_t *cairo = cairo_create(surface);
@@ -504,11 +554,11 @@ static void update_title_texture(struct sway_container *con,
504 554
505 cairo_surface_flush(surface); 555 cairo_surface_flush(surface);
506 unsigned char *data = cairo_image_surface_get_data(surface); 556 unsigned char *data = cairo_image_surface_get_data(surface);
507 int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); 557 int stride = cairo_image_surface_get_stride(surface);
508 struct wlr_renderer *renderer = wlr_backend_get_renderer( 558 struct wlr_renderer *renderer = wlr_backend_get_renderer(
509 output->wlr_output->backend); 559 output->wlr_output->backend);
510 *texture = wlr_texture_from_pixels( 560 *texture = wlr_texture_from_pixels(
511 renderer, WL_SHM_FORMAT_ARGB8888, stride, width, height, data); 561 renderer, DRM_FORMAT_ARGB8888, stride, width, height, data);
512 cairo_surface_destroy(surface); 562 cairo_surface_destroy(surface);
513 g_object_unref(pango); 563 g_object_unref(pango);
514 cairo_destroy(cairo); 564 cairo_destroy(cairo);
@@ -596,23 +646,23 @@ size_t container_build_representation(enum sway_container_layout layout,
596 646
597void container_update_representation(struct sway_container *con) { 647void container_update_representation(struct sway_container *con) {
598 if (!con->view) { 648 if (!con->view) {
599 size_t len = container_build_representation(con->layout, 649 size_t len = container_build_representation(con->pending.layout,
600 con->children, NULL); 650 con->pending.children, NULL);
601 free(con->formatted_title); 651 free(con->formatted_title);
602 con->formatted_title = calloc(len + 1, sizeof(char)); 652 con->formatted_title = calloc(len + 1, sizeof(char));
603 if (!sway_assert(con->formatted_title, 653 if (!sway_assert(con->formatted_title,
604 "Unable to allocate title string")) { 654 "Unable to allocate title string")) {
605 return; 655 return;
606 } 656 }
607 container_build_representation(con->layout, con->children, 657 container_build_representation(con->pending.layout, con->pending.children,
608 con->formatted_title); 658 con->formatted_title);
609 container_calculate_title_height(con); 659 container_calculate_title_height(con);
610 container_update_title_textures(con); 660 container_update_title_textures(con);
611 } 661 }
612 if (con->parent) { 662 if (con->pending.parent) {
613 container_update_representation(con->parent); 663 container_update_representation(con->pending.parent);
614 } else if (con->workspace) { 664 } else if (con->pending.workspace) {
615 workspace_update_representation(con->workspace); 665 workspace_update_representation(con->pending.workspace);
616 } 666 }
617} 667}
618 668
@@ -663,20 +713,20 @@ static void floating_natural_resize(struct sway_container *con) {
663 floating_calculate_constraints(&min_width, &max_width, 713 floating_calculate_constraints(&min_width, &max_width,
664 &min_height, &max_height); 714 &min_height, &max_height);
665 if (!con->view) { 715 if (!con->view) {
666 con->width = fmax(min_width, fmin(con->width, max_width)); 716 con->pending.width = fmax(min_width, fmin(con->pending.width, max_width));
667 con->height = fmax(min_height, fmin(con->height, max_height)); 717 con->pending.height = fmax(min_height, fmin(con->pending.height, max_height));
668 } else { 718 } else {
669 struct sway_view *view = con->view; 719 struct sway_view *view = con->view;
670 con->content_width = 720 con->pending.content_width =
671 fmax(min_width, fmin(view->natural_width, max_width)); 721 fmax(min_width, fmin(view->natural_width, max_width));
672 con->content_height = 722 con->pending.content_height =
673 fmax(min_height, fmin(view->natural_height, max_height)); 723 fmax(min_height, fmin(view->natural_height, max_height));
674 container_set_geometry_from_content(con); 724 container_set_geometry_from_content(con);
675 } 725 }
676} 726}
677 727
678void container_floating_resize_and_center(struct sway_container *con) { 728void container_floating_resize_and_center(struct sway_container *con) {
679 struct sway_workspace *ws = con->workspace; 729 struct sway_workspace *ws = con->pending.workspace;
680 if (!ws) { 730 if (!ws) {
681 // On scratchpad, just resize 731 // On scratchpad, just resize
682 floating_natural_resize(con); 732 floating_natural_resize(con);
@@ -687,42 +737,42 @@ void container_floating_resize_and_center(struct sway_container *con) {
687 ws->output->wlr_output); 737 ws->output->wlr_output);
688 if (!ob) { 738 if (!ob) {
689 // On NOOP output. Will be called again when moved to an output 739 // On NOOP output. Will be called again when moved to an output
690 con->x = 0; 740 con->pending.x = 0;
691 con->y = 0; 741 con->pending.y = 0;
692 con->width = 0; 742 con->pending.width = 0;
693 con->height = 0; 743 con->pending.height = 0;
694 return; 744 return;
695 } 745 }
696 746
697 floating_natural_resize(con); 747 floating_natural_resize(con);
698 if (!con->view) { 748 if (!con->view) {
699 if (con->width > ws->width || con->height > ws->height) { 749 if (con->pending.width > ws->width || con->pending.height > ws->height) {
700 con->x = ob->x + (ob->width - con->width) / 2; 750 con->pending.x = ob->x + (ob->width - con->pending.width) / 2;
701 con->y = ob->y + (ob->height - con->height) / 2; 751 con->pending.y = ob->y + (ob->height - con->pending.height) / 2;
702 } else { 752 } else {
703 con->x = ws->x + (ws->width - con->width) / 2; 753 con->pending.x = ws->x + (ws->width - con->pending.width) / 2;
704 con->y = ws->y + (ws->height - con->height) / 2; 754 con->pending.y = ws->y + (ws->height - con->pending.height) / 2;
705 } 755 }
706 } else { 756 } else {
707 if (con->content_width > ws->width 757 if (con->pending.content_width > ws->width
708 || con->content_height > ws->height) { 758 || con->pending.content_height > ws->height) {
709 con->content_x = ob->x + (ob->width - con->content_width) / 2; 759 con->pending.content_x = ob->x + (ob->width - con->pending.content_width) / 2;
710 con->content_y = ob->y + (ob->height - con->content_height) / 2; 760 con->pending.content_y = ob->y + (ob->height - con->pending.content_height) / 2;
711 } else { 761 } else {
712 con->content_x = ws->x + (ws->width - con->content_width) / 2; 762 con->pending.content_x = ws->x + (ws->width - con->pending.content_width) / 2;
713 con->content_y = ws->y + (ws->height - con->content_height) / 2; 763 con->pending.content_y = ws->y + (ws->height - con->pending.content_height) / 2;
714 } 764 }
715 765
716 // If the view's border is B_NONE then these properties are ignored. 766 // If the view's border is B_NONE then these properties are ignored.
717 con->border_top = con->border_bottom = true; 767 con->pending.border_top = con->pending.border_bottom = true;
718 con->border_left = con->border_right = true; 768 con->pending.border_left = con->pending.border_right = true;
719 769
720 container_set_geometry_from_content(con); 770 container_set_geometry_from_content(con);
721 } 771 }
722} 772}
723 773
724void container_floating_set_default_size(struct sway_container *con) { 774void container_floating_set_default_size(struct sway_container *con) {
725 if (!sway_assert(con->workspace, "Expected a container on a workspace")) { 775 if (!sway_assert(con->pending.workspace, "Expected a container on a workspace")) {
726 return; 776 return;
727 } 777 }
728 778
@@ -730,16 +780,16 @@ void container_floating_set_default_size(struct sway_container *con) {
730 floating_calculate_constraints(&min_width, &max_width, 780 floating_calculate_constraints(&min_width, &max_width,
731 &min_height, &max_height); 781 &min_height, &max_height);
732 struct wlr_box *box = calloc(1, sizeof(struct wlr_box)); 782 struct wlr_box *box = calloc(1, sizeof(struct wlr_box));
733 workspace_get_box(con->workspace, box); 783 workspace_get_box(con->pending.workspace, box);
734 784
735 double width = fmax(min_width, fmin(box->width * 0.5, max_width)); 785 double width = fmax(min_width, fmin(box->width * 0.5, max_width));
736 double height = fmax(min_height, fmin(box->height * 0.75, max_height)); 786 double height = fmax(min_height, fmin(box->height * 0.75, max_height));
737 if (!con->view) { 787 if (!con->view) {
738 con->width = width; 788 con->pending.width = width;
739 con->height = height; 789 con->pending.height = height;
740 } else { 790 } else {
741 con->content_width = width; 791 con->pending.content_width = width;
742 con->content_height = height; 792 con->pending.content_height = height;
743 container_set_geometry_from_content(con); 793 container_set_geometry_from_content(con);
744 } 794 }
745 795
@@ -761,8 +811,8 @@ void container_set_resizing(struct sway_container *con, bool resizing) {
761 con->view->impl->set_resizing(con->view, resizing); 811 con->view->impl->set_resizing(con->view, resizing);
762 } 812 }
763 } else { 813 } else {
764 for (int i = 0; i < con->children->length; ++i ) { 814 for (int i = 0; i < con->pending.children->length; ++i ) {
765 struct sway_container *child = con->children->items[i]; 815 struct sway_container *child = con->pending.children->items[i];
766 container_set_resizing(child, resizing); 816 container_set_resizing(child, resizing);
767 } 817 }
768 } 818 }
@@ -774,21 +824,27 @@ void container_set_floating(struct sway_container *container, bool enable) {
774 } 824 }
775 825
776 struct sway_seat *seat = input_manager_current_seat(); 826 struct sway_seat *seat = input_manager_current_seat();
777 struct sway_workspace *workspace = container->workspace; 827 struct sway_workspace *workspace = container->pending.workspace;
828 struct sway_container *focus = seat_get_focused_container(seat);
829 bool set_focus = focus == container;
778 830
779 if (enable) { 831 if (enable) {
780 struct sway_container *old_parent = container->parent; 832 struct sway_container *old_parent = container->pending.parent;
781 container_detach(container); 833 container_detach(container);
782 workspace_add_floating(workspace, container); 834 workspace_add_floating(workspace, container);
783 if (container->view) { 835 if (container->view) {
784 view_set_tiled(container->view, false); 836 view_set_tiled(container->view, false);
785 if (container->view->using_csd) { 837 if (container->view->using_csd) {
786 container->border = B_CSD; 838 container->pending.border = B_CSD;
787 } 839 }
788 } 840 }
789 container_floating_set_default_size(container); 841 container_floating_set_default_size(container);
790 container_floating_resize_and_center(container); 842 container_floating_resize_and_center(container);
791 if (old_parent) { 843 if (old_parent) {
844 if (set_focus) {
845 seat_set_raw_focus(seat, &old_parent->node);
846 seat_set_raw_focus(seat, &container->node);
847 }
792 container_reap_empty(old_parent); 848 container_reap_empty(old_parent);
793 } 849 }
794 } else { 850 } else {
@@ -800,19 +856,23 @@ void container_set_floating(struct sway_container *container, bool enable) {
800 struct sway_container *reference = 856 struct sway_container *reference =
801 seat_get_focus_inactive_tiling(seat, workspace); 857 seat_get_focus_inactive_tiling(seat, workspace);
802 if (reference) { 858 if (reference) {
803 container_add_sibling(reference, container, 1); 859 if (reference->view) {
804 container->width = reference->width; 860 container_add_sibling(reference, container, 1);
805 container->height = reference->height; 861 } else {
862 container_add_child(reference, container);
863 }
864 container->pending.width = reference->pending.width;
865 container->pending.height = reference->pending.height;
806 } else { 866 } else {
807 struct sway_container *other = 867 struct sway_container *other =
808 workspace_add_tiling(workspace, container); 868 workspace_add_tiling(workspace, container);
809 other->width = workspace->width; 869 other->pending.width = workspace->width;
810 other->height = workspace->height; 870 other->pending.height = workspace->height;
811 } 871 }
812 if (container->view) { 872 if (container->view) {
813 view_set_tiled(container->view, true); 873 view_set_tiled(container->view, true);
814 if (container->view->using_csd) { 874 if (container->view->using_csd) {
815 container->border = container->saved_border; 875 container->pending.border = container->saved_border;
816 } 876 }
817 } 877 }
818 container->width_fraction = 0; 878 container->width_fraction = 0;
@@ -834,22 +894,33 @@ void container_set_geometry_from_content(struct sway_container *con) {
834 size_t border_width = 0; 894 size_t border_width = 0;
835 size_t top = 0; 895 size_t top = 0;
836 896
837 if (con->border != B_CSD) { 897 if (con->pending.border != B_CSD) {
838 border_width = con->border_thickness * (con->border != B_NONE); 898 border_width = con->pending.border_thickness * (con->pending.border != B_NONE);
839 top = con->border == B_NORMAL ? 899 top = con->pending.border == B_NORMAL ?
840 container_titlebar_height() : border_width; 900 container_titlebar_height() : border_width;
841 } 901 }
842 902
843 con->x = con->content_x - border_width; 903 con->pending.x = con->pending.content_x - border_width;
844 con->y = con->content_y - top; 904 con->pending.y = con->pending.content_y - top;
845 con->width = con->content_width + border_width * 2; 905 con->pending.width = con->pending.content_width + border_width * 2;
846 con->height = top + con->content_height + border_width; 906 con->pending.height = top + con->pending.content_height + border_width;
847 node_set_dirty(&con->node); 907 node_set_dirty(&con->node);
848} 908}
849 909
850bool container_is_floating(struct sway_container *container) { 910bool container_is_floating(struct sway_container *container) {
851 if (!container->parent && container->workspace && 911 if (!container->pending.parent && container->pending.workspace &&
852 list_find(container->workspace->floating, container) != -1) { 912 list_find(container->pending.workspace->floating, container) != -1) {
913 return true;
914 }
915 if (container->scratchpad) {
916 return true;
917 }
918 return false;
919}
920
921bool container_is_current_floating(struct sway_container *container) {
922 if (!container->current.parent && container->current.workspace &&
923 list_find(container->current.workspace->floating, container) != -1) {
853 return true; 924 return true;
854 } 925 }
855 if (container->scratchpad) { 926 if (container->scratchpad) {
@@ -859,10 +930,10 @@ bool container_is_floating(struct sway_container *container) {
859} 930}
860 931
861void container_get_box(struct sway_container *container, struct wlr_box *box) { 932void container_get_box(struct sway_container *container, struct wlr_box *box) {
862 box->x = container->x; 933 box->x = container->pending.x;
863 box->y = container->y; 934 box->y = container->pending.y;
864 box->width = container->width; 935 box->width = container->pending.width;
865 box->height = container->height; 936 box->height = container->pending.height;
866} 937}
867 938
868/** 939/**
@@ -870,14 +941,14 @@ void container_get_box(struct sway_container *container, struct wlr_box *box) {
870 */ 941 */
871void container_floating_translate(struct sway_container *con, 942void container_floating_translate(struct sway_container *con,
872 double x_amount, double y_amount) { 943 double x_amount, double y_amount) {
873 con->x += x_amount; 944 con->pending.x += x_amount;
874 con->y += y_amount; 945 con->pending.y += y_amount;
875 con->content_x += x_amount; 946 con->pending.content_x += x_amount;
876 con->content_y += y_amount; 947 con->pending.content_y += y_amount;
877 948
878 if (con->children) { 949 if (con->pending.children) {
879 for (int i = 0; i < con->children->length; ++i) { 950 for (int i = 0; i < con->pending.children->length; ++i) {
880 struct sway_container *child = con->children->items[i]; 951 struct sway_container *child = con->pending.children->items[i];
881 container_floating_translate(child, x_amount, y_amount); 952 container_floating_translate(child, x_amount, y_amount);
882 } 953 }
883 } 954 }
@@ -893,8 +964,8 @@ void container_floating_translate(struct sway_container *con,
893 * center. 964 * center.
894 */ 965 */
895struct sway_output *container_floating_find_output(struct sway_container *con) { 966struct sway_output *container_floating_find_output(struct sway_container *con) {
896 double center_x = con->x + con->width / 2; 967 double center_x = con->pending.x + con->pending.width / 2;
897 double center_y = con->y + con->height / 2; 968 double center_y = con->pending.y + con->pending.height / 2;
898 struct sway_output *closest_output = NULL; 969 struct sway_output *closest_output = NULL;
899 double closest_distance = DBL_MAX; 970 double closest_distance = DBL_MAX;
900 for (int i = 0; i < root->outputs->length; ++i) { 971 for (int i = 0; i < root->outputs->length; ++i) {
@@ -925,11 +996,11 @@ void container_floating_move_to(struct sway_container *con,
925 "Expected a floating container")) { 996 "Expected a floating container")) {
926 return; 997 return;
927 } 998 }
928 container_floating_translate(con, lx - con->x, ly - con->y); 999 container_floating_translate(con, lx - con->pending.x, ly - con->pending.y);
929 if (container_is_scratchpad_hidden(con)) { 1000 if (container_is_scratchpad_hidden(con)) {
930 return; 1001 return;
931 } 1002 }
932 struct sway_workspace *old_workspace = con->workspace; 1003 struct sway_workspace *old_workspace = con->pending.workspace;
933 struct sway_output *new_output = container_floating_find_output(con); 1004 struct sway_output *new_output = container_floating_find_output(con);
934 if (!sway_assert(new_output, "Unable to find any output")) { 1005 if (!sway_assert(new_output, "Unable to find any output")) {
935 return; 1006 return;
@@ -951,10 +1022,10 @@ void container_floating_move_to_center(struct sway_container *con) {
951 "Expected a floating container")) { 1022 "Expected a floating container")) {
952 return; 1023 return;
953 } 1024 }
954 struct sway_workspace *ws = con->workspace; 1025 struct sway_workspace *ws = con->pending.workspace;
955 double new_lx = ws->x + (ws->width - con->width) / 2; 1026 double new_lx = ws->x + (ws->width - con->pending.width) / 2;
956 double new_ly = ws->y + (ws->height - con->height) / 2; 1027 double new_ly = ws->y + (ws->height - con->pending.height) / 2;
957 container_floating_translate(con, new_lx - con->x, new_ly - con->y); 1028 container_floating_translate(con, new_lx - con->pending.x, new_ly - con->pending.y);
958} 1029}
959 1030
960static bool find_urgent_iterator(struct sway_container *con, void *data) { 1031static bool find_urgent_iterator(struct sway_container *con, void *data) {
@@ -972,42 +1043,39 @@ void container_end_mouse_operation(struct sway_container *container) {
972 } 1043 }
973} 1044}
974 1045
975static void set_fullscreen_iterator(struct sway_container *con, void *data) { 1046static void set_fullscreen(struct sway_container *con, bool enable) {
976 if (!con->view) { 1047 if (!con->view) {
977 return; 1048 return;
978 } 1049 }
979 if (con->view->impl->set_fullscreen) { 1050 if (con->view->impl->set_fullscreen) {
980 bool *enable = data; 1051 con->view->impl->set_fullscreen(con->view, enable);
981 con->view->impl->set_fullscreen(con->view, *enable);
982 if (con->view->foreign_toplevel) { 1052 if (con->view->foreign_toplevel) {
983 wlr_foreign_toplevel_handle_v1_set_fullscreen( 1053 wlr_foreign_toplevel_handle_v1_set_fullscreen(
984 con->view->foreign_toplevel, *enable); 1054 con->view->foreign_toplevel, enable);
985 } 1055 }
986 } 1056 }
987} 1057}
988 1058
989static void container_fullscreen_workspace(struct sway_container *con) { 1059static void container_fullscreen_workspace(struct sway_container *con) {
990 if (!sway_assert(con->fullscreen_mode == FULLSCREEN_NONE, 1060 if (!sway_assert(con->pending.fullscreen_mode == FULLSCREEN_NONE,
991 "Expected a non-fullscreen container")) { 1061 "Expected a non-fullscreen container")) {
992 return; 1062 return;
993 } 1063 }
994 bool enable = true; 1064 set_fullscreen(con, true);
995 set_fullscreen_iterator(con, &enable); 1065 con->pending.fullscreen_mode = FULLSCREEN_WORKSPACE;
996 container_for_each_child(con, set_fullscreen_iterator, &enable);
997 con->fullscreen_mode = FULLSCREEN_WORKSPACE;
998 1066
999 con->saved_x = con->x; 1067 con->saved_x = con->pending.x;
1000 con->saved_y = con->y; 1068 con->saved_y = con->pending.y;
1001 con->saved_width = con->width; 1069 con->saved_width = con->pending.width;
1002 con->saved_height = con->height; 1070 con->saved_height = con->pending.height;
1003 1071
1004 if (con->workspace) { 1072 if (con->pending.workspace) {
1005 con->workspace->fullscreen = con; 1073 con->pending.workspace->fullscreen = con;
1006 struct sway_seat *seat; 1074 struct sway_seat *seat;
1007 struct sway_workspace *focus_ws; 1075 struct sway_workspace *focus_ws;
1008 wl_list_for_each(seat, &server.input->seats, link) { 1076 wl_list_for_each(seat, &server.input->seats, link) {
1009 focus_ws = seat_get_focused_workspace(seat); 1077 focus_ws = seat_get_focused_workspace(seat);
1010 if (focus_ws == con->workspace) { 1078 if (focus_ws == con->pending.workspace) {
1011 seat_set_focus_container(seat, con); 1079 seat_set_focus_container(seat, con);
1012 } else { 1080 } else {
1013 struct sway_node *focus = 1081 struct sway_node *focus =
@@ -1023,19 +1091,17 @@ static void container_fullscreen_workspace(struct sway_container *con) {
1023} 1091}
1024 1092
1025static void container_fullscreen_global(struct sway_container *con) { 1093static void container_fullscreen_global(struct sway_container *con) {
1026 if (!sway_assert(con->fullscreen_mode == FULLSCREEN_NONE, 1094 if (!sway_assert(con->pending.fullscreen_mode == FULLSCREEN_NONE,
1027 "Expected a non-fullscreen container")) { 1095 "Expected a non-fullscreen container")) {
1028 return; 1096 return;
1029 } 1097 }
1030 bool enable = true; 1098 set_fullscreen(con, true);
1031 set_fullscreen_iterator(con, &enable);
1032 container_for_each_child(con, set_fullscreen_iterator, &enable);
1033 1099
1034 root->fullscreen_global = con; 1100 root->fullscreen_global = con;
1035 con->saved_x = con->x; 1101 con->saved_x = con->pending.x;
1036 con->saved_y = con->y; 1102 con->saved_y = con->pending.y;
1037 con->saved_width = con->width; 1103 con->saved_width = con->pending.width;
1038 con->saved_height = con->height; 1104 con->saved_height = con->pending.height;
1039 1105
1040 struct sway_seat *seat; 1106 struct sway_seat *seat;
1041 wl_list_for_each(seat, &server.input->seats, link) { 1107 wl_list_for_each(seat, &server.input->seats, link) {
@@ -1045,34 +1111,32 @@ static void container_fullscreen_global(struct sway_container *con) {
1045 } 1111 }
1046 } 1112 }
1047 1113
1048 con->fullscreen_mode = FULLSCREEN_GLOBAL; 1114 con->pending.fullscreen_mode = FULLSCREEN_GLOBAL;
1049 container_end_mouse_operation(con); 1115 container_end_mouse_operation(con);
1050 ipc_event_window(con, "fullscreen_mode"); 1116 ipc_event_window(con, "fullscreen_mode");
1051} 1117}
1052 1118
1053void container_fullscreen_disable(struct sway_container *con) { 1119void container_fullscreen_disable(struct sway_container *con) {
1054 if (!sway_assert(con->fullscreen_mode != FULLSCREEN_NONE, 1120 if (!sway_assert(con->pending.fullscreen_mode != FULLSCREEN_NONE,
1055 "Expected a fullscreen container")) { 1121 "Expected a fullscreen container")) {
1056 return; 1122 return;
1057 } 1123 }
1058 bool enable = false; 1124 set_fullscreen(con, false);
1059 set_fullscreen_iterator(con, &enable);
1060 container_for_each_child(con, set_fullscreen_iterator, &enable);
1061 1125
1062 if (container_is_floating(con)) { 1126 if (container_is_floating(con)) {
1063 con->x = con->saved_x; 1127 con->pending.x = con->saved_x;
1064 con->y = con->saved_y; 1128 con->pending.y = con->saved_y;
1065 con->width = con->saved_width; 1129 con->pending.width = con->saved_width;
1066 con->height = con->saved_height; 1130 con->pending.height = con->saved_height;
1067 } 1131 }
1068 1132
1069 if (con->fullscreen_mode == FULLSCREEN_WORKSPACE) { 1133 if (con->pending.fullscreen_mode == FULLSCREEN_WORKSPACE) {
1070 if (con->workspace) { 1134 if (con->pending.workspace) {
1071 con->workspace->fullscreen = NULL; 1135 con->pending.workspace->fullscreen = NULL;
1072 if (container_is_floating(con)) { 1136 if (container_is_floating(con)) {
1073 struct sway_output *output = 1137 struct sway_output *output =
1074 container_floating_find_output(con); 1138 container_floating_find_output(con);
1075 if (con->workspace->output != output) { 1139 if (con->pending.workspace->output != output) {
1076 container_floating_move_to_center(con); 1140 container_floating_move_to_center(con);
1077 } 1141 }
1078 } 1142 }
@@ -1084,11 +1148,11 @@ void container_fullscreen_disable(struct sway_container *con) {
1084 // If the container was mapped as fullscreen and set as floating by 1148 // If the container was mapped as fullscreen and set as floating by
1085 // criteria, it needs to be reinitialized as floating to get the proper 1149 // criteria, it needs to be reinitialized as floating to get the proper
1086 // size and location 1150 // size and location
1087 if (container_is_floating(con) && (con->width == 0 || con->height == 0)) { 1151 if (container_is_floating(con) && (con->pending.width == 0 || con->pending.height == 0)) {
1088 container_floating_resize_and_center(con); 1152 container_floating_resize_and_center(con);
1089 } 1153 }
1090 1154
1091 con->fullscreen_mode = FULLSCREEN_NONE; 1155 con->pending.fullscreen_mode = FULLSCREEN_NONE;
1092 container_end_mouse_operation(con); 1156 container_end_mouse_operation(con);
1093 ipc_event_window(con, "fullscreen_mode"); 1157 ipc_event_window(con, "fullscreen_mode");
1094 1158
@@ -1106,7 +1170,7 @@ void container_fullscreen_disable(struct sway_container *con) {
1106 1170
1107void container_set_fullscreen(struct sway_container *con, 1171void container_set_fullscreen(struct sway_container *con,
1108 enum sway_fullscreen_mode mode) { 1172 enum sway_fullscreen_mode mode) {
1109 if (con->fullscreen_mode == mode) { 1173 if (con->pending.fullscreen_mode == mode) {
1110 return; 1174 return;
1111 } 1175 }
1112 1176
@@ -1118,8 +1182,8 @@ void container_set_fullscreen(struct sway_container *con,
1118 if (root->fullscreen_global) { 1182 if (root->fullscreen_global) {
1119 container_fullscreen_disable(root->fullscreen_global); 1183 container_fullscreen_disable(root->fullscreen_global);
1120 } 1184 }
1121 if (con->workspace && con->workspace->fullscreen) { 1185 if (con->pending.workspace && con->pending.workspace->fullscreen) {
1122 container_fullscreen_disable(con->workspace->fullscreen); 1186 container_fullscreen_disable(con->pending.workspace->fullscreen);
1123 } 1187 }
1124 container_fullscreen_workspace(con); 1188 container_fullscreen_workspace(con);
1125 break; 1189 break;
@@ -1127,7 +1191,7 @@ void container_set_fullscreen(struct sway_container *con,
1127 if (root->fullscreen_global) { 1191 if (root->fullscreen_global) {
1128 container_fullscreen_disable(root->fullscreen_global); 1192 container_fullscreen_disable(root->fullscreen_global);
1129 } 1193 }
1130 if (con->fullscreen_mode == FULLSCREEN_WORKSPACE) { 1194 if (con->pending.fullscreen_mode == FULLSCREEN_WORKSPACE) {
1131 container_fullscreen_disable(con); 1195 container_fullscreen_disable(con);
1132 } 1196 }
1133 container_fullscreen_global(con); 1197 container_fullscreen_global(con);
@@ -1137,8 +1201,8 @@ void container_set_fullscreen(struct sway_container *con,
1137 1201
1138struct sway_container *container_toplevel_ancestor( 1202struct sway_container *container_toplevel_ancestor(
1139 struct sway_container *container) { 1203 struct sway_container *container) {
1140 while (container->parent) { 1204 while (container->pending.parent) {
1141 container = container->parent; 1205 container = container->pending.parent;
1142 } 1206 }
1143 1207
1144 return container; 1208 return container;
@@ -1150,10 +1214,10 @@ bool container_is_floating_or_child(struct sway_container *container) {
1150 1214
1151bool container_is_fullscreen_or_child(struct sway_container *container) { 1215bool container_is_fullscreen_or_child(struct sway_container *container) {
1152 do { 1216 do {
1153 if (container->fullscreen_mode) { 1217 if (container->pending.fullscreen_mode) {
1154 return true; 1218 return true;
1155 } 1219 }
1156 container = container->parent; 1220 container = container->pending.parent;
1157 } while (container); 1221 } while (container);
1158 1222
1159 return false; 1223 return false;
@@ -1226,11 +1290,11 @@ void container_discover_outputs(struct sway_container *con) {
1226} 1290}
1227 1291
1228enum sway_container_layout container_parent_layout(struct sway_container *con) { 1292enum sway_container_layout container_parent_layout(struct sway_container *con) {
1229 if (con->parent) { 1293 if (con->pending.parent) {
1230 return con->parent->layout; 1294 return con->pending.parent->pending.layout;
1231 } 1295 }
1232 if (con->workspace) { 1296 if (con->pending.workspace) {
1233 return con->workspace->layout; 1297 return con->pending.workspace->layout;
1234 } 1298 }
1235 return L_NONE; 1299 return L_NONE;
1236} 1300}
@@ -1244,16 +1308,16 @@ enum sway_container_layout container_current_parent_layout(
1244} 1308}
1245 1309
1246list_t *container_get_siblings(struct sway_container *container) { 1310list_t *container_get_siblings(struct sway_container *container) {
1247 if (container->parent) { 1311 if (container->pending.parent) {
1248 return container->parent->children; 1312 return container->pending.parent->pending.children;
1249 } 1313 }
1250 if (container_is_scratchpad_hidden(container)) { 1314 if (container_is_scratchpad_hidden(container)) {
1251 return NULL; 1315 return NULL;
1252 } 1316 }
1253 if (list_find(container->workspace->tiling, container) != -1) { 1317 if (list_find(container->pending.workspace->tiling, container) != -1) {
1254 return container->workspace->tiling; 1318 return container->pending.workspace->tiling;
1255 } 1319 }
1256 return container->workspace->floating; 1320 return container->pending.workspace->floating;
1257} 1321}
1258 1322
1259int container_sibling_index(struct sway_container *child) { 1323int container_sibling_index(struct sway_container *child) {
@@ -1268,30 +1332,30 @@ list_t *container_get_current_siblings(struct sway_container *container) {
1268} 1332}
1269 1333
1270void container_handle_fullscreen_reparent(struct sway_container *con) { 1334void container_handle_fullscreen_reparent(struct sway_container *con) {
1271 if (con->fullscreen_mode != FULLSCREEN_WORKSPACE || !con->workspace || 1335 if (con->pending.fullscreen_mode != FULLSCREEN_WORKSPACE || !con->pending.workspace ||
1272 con->workspace->fullscreen == con) { 1336 con->pending.workspace->fullscreen == con) {
1273 return; 1337 return;
1274 } 1338 }
1275 if (con->workspace->fullscreen) { 1339 if (con->pending.workspace->fullscreen) {
1276 container_fullscreen_disable(con->workspace->fullscreen); 1340 container_fullscreen_disable(con->pending.workspace->fullscreen);
1277 } 1341 }
1278 con->workspace->fullscreen = con; 1342 con->pending.workspace->fullscreen = con;
1279 1343
1280 arrange_workspace(con->workspace); 1344 arrange_workspace(con->pending.workspace);
1281} 1345}
1282 1346
1283static void set_workspace(struct sway_container *container, void *data) { 1347static void set_workspace(struct sway_container *container, void *data) {
1284 container->workspace = container->parent->workspace; 1348 container->pending.workspace = container->pending.parent->pending.workspace;
1285} 1349}
1286 1350
1287void container_insert_child(struct sway_container *parent, 1351void container_insert_child(struct sway_container *parent,
1288 struct sway_container *child, int i) { 1352 struct sway_container *child, int i) {
1289 if (child->workspace) { 1353 if (child->pending.workspace) {
1290 container_detach(child); 1354 container_detach(child);
1291 } 1355 }
1292 list_insert(parent->children, i, child); 1356 list_insert(parent->pending.children, i, child);
1293 child->parent = parent; 1357 child->pending.parent = parent;
1294 child->workspace = parent->workspace; 1358 child->pending.workspace = parent->pending.workspace;
1295 container_for_each_child(child, set_workspace, NULL); 1359 container_for_each_child(child, set_workspace, NULL);
1296 container_handle_fullscreen_reparent(child); 1360 container_handle_fullscreen_reparent(child);
1297 container_update_representation(parent); 1361 container_update_representation(parent);
@@ -1299,14 +1363,14 @@ void container_insert_child(struct sway_container *parent,
1299 1363
1300void container_add_sibling(struct sway_container *fixed, 1364void container_add_sibling(struct sway_container *fixed,
1301 struct sway_container *active, bool after) { 1365 struct sway_container *active, bool after) {
1302 if (active->workspace) { 1366 if (active->pending.workspace) {
1303 container_detach(active); 1367 container_detach(active);
1304 } 1368 }
1305 list_t *siblings = container_get_siblings(fixed); 1369 list_t *siblings = container_get_siblings(fixed);
1306 int index = list_find(siblings, fixed); 1370 int index = list_find(siblings, fixed);
1307 list_insert(siblings, index + after, active); 1371 list_insert(siblings, index + after, active);
1308 active->parent = fixed->parent; 1372 active->pending.parent = fixed->pending.parent;
1309 active->workspace = fixed->workspace; 1373 active->pending.workspace = fixed->pending.workspace;
1310 container_for_each_child(active, set_workspace, NULL); 1374 container_for_each_child(active, set_workspace, NULL);
1311 container_handle_fullscreen_reparent(active); 1375 container_handle_fullscreen_reparent(active);
1312 container_update_representation(active); 1376 container_update_representation(active);
@@ -1314,17 +1378,13 @@ void container_add_sibling(struct sway_container *fixed,
1314 1378
1315void container_add_child(struct sway_container *parent, 1379void container_add_child(struct sway_container *parent,
1316 struct sway_container *child) { 1380 struct sway_container *child) {
1317 if (child->workspace) { 1381 if (child->pending.workspace) {
1318 container_detach(child); 1382 container_detach(child);
1319 } 1383 }
1320 list_add(parent->children, child); 1384 list_add(parent->pending.children, child);
1321 child->parent = parent; 1385 child->pending.parent = parent;
1322 child->workspace = parent->workspace; 1386 child->pending.workspace = parent->pending.workspace;
1323 container_for_each_child(child, set_workspace, NULL); 1387 container_for_each_child(child, set_workspace, NULL);
1324 bool fullscreen = child->fullscreen_mode != FULLSCREEN_NONE ||
1325 parent->fullscreen_mode != FULLSCREEN_NONE;
1326 set_fullscreen_iterator(child, &fullscreen);
1327 container_for_each_child(child, set_fullscreen_iterator, &fullscreen);
1328 container_handle_fullscreen_reparent(child); 1388 container_handle_fullscreen_reparent(child);
1329 container_update_representation(parent); 1389 container_update_representation(parent);
1330 node_set_dirty(&child->node); 1390 node_set_dirty(&child->node);
@@ -1332,15 +1392,15 @@ void container_add_child(struct sway_container *parent,
1332} 1392}
1333 1393
1334void container_detach(struct sway_container *child) { 1394void container_detach(struct sway_container *child) {
1335 if (child->fullscreen_mode == FULLSCREEN_WORKSPACE) { 1395 if (child->pending.fullscreen_mode == FULLSCREEN_WORKSPACE) {
1336 child->workspace->fullscreen = NULL; 1396 child->pending.workspace->fullscreen = NULL;
1337 } 1397 }
1338 if (child->fullscreen_mode == FULLSCREEN_GLOBAL) { 1398 if (child->pending.fullscreen_mode == FULLSCREEN_GLOBAL) {
1339 root->fullscreen_global = NULL; 1399 root->fullscreen_global = NULL;
1340 } 1400 }
1341 1401
1342 struct sway_container *old_parent = child->parent; 1402 struct sway_container *old_parent = child->pending.parent;
1343 struct sway_workspace *old_workspace = child->workspace; 1403 struct sway_workspace *old_workspace = child->pending.workspace;
1344 list_t *siblings = container_get_siblings(child); 1404 list_t *siblings = container_get_siblings(child);
1345 if (siblings) { 1405 if (siblings) {
1346 int index = list_find(siblings, child); 1406 int index = list_find(siblings, child);
@@ -1348,8 +1408,8 @@ void container_detach(struct sway_container *child) {
1348 list_del(siblings, index); 1408 list_del(siblings, index);
1349 } 1409 }
1350 } 1410 }
1351 child->parent = NULL; 1411 child->pending.parent = NULL;
1352 child->workspace = NULL; 1412 child->pending.workspace = NULL;
1353 container_for_each_child(child, set_workspace, NULL); 1413 container_for_each_child(child, set_workspace, NULL);
1354 1414
1355 if (old_parent) { 1415 if (old_parent) {
@@ -1364,18 +1424,18 @@ void container_detach(struct sway_container *child) {
1364 1424
1365void container_replace(struct sway_container *container, 1425void container_replace(struct sway_container *container,
1366 struct sway_container *replacement) { 1426 struct sway_container *replacement) {
1367 enum sway_fullscreen_mode fullscreen = container->fullscreen_mode; 1427 enum sway_fullscreen_mode fullscreen = container->pending.fullscreen_mode;
1368 bool scratchpad = container->scratchpad; 1428 bool scratchpad = container->scratchpad;
1369 struct sway_workspace *ws = NULL; 1429 struct sway_workspace *ws = NULL;
1370 if (fullscreen != FULLSCREEN_NONE) { 1430 if (fullscreen != FULLSCREEN_NONE) {
1371 container_fullscreen_disable(container); 1431 container_fullscreen_disable(container);
1372 } 1432 }
1373 if (scratchpad) { 1433 if (scratchpad) {
1374 ws = container->workspace; 1434 ws = container->pending.workspace;
1375 root_scratchpad_show(container); 1435 root_scratchpad_show(container);
1376 root_scratchpad_remove_container(container); 1436 root_scratchpad_remove_container(container);
1377 } 1437 }
1378 if (container->parent || container->workspace) { 1438 if (container->pending.parent || container->pending.workspace) {
1379 float width_fraction = container->width_fraction; 1439 float width_fraction = container->width_fraction;
1380 float height_fraction = container->height_fraction; 1440 float height_fraction = container->height_fraction;
1381 container_add_sibling(container, replacement, 1); 1441 container_add_sibling(container, replacement, 1);
@@ -1403,7 +1463,7 @@ struct sway_container *container_split(struct sway_container *child,
1403 enum sway_container_layout layout) { 1463 enum sway_container_layout layout) {
1404 // i3 doesn't split singleton H/V containers 1464 // i3 doesn't split singleton H/V containers
1405 // https://github.com/i3/i3/blob/3cd1c45eba6de073bc4300eebb4e1cc1a0c4479a/src/tree.c#L354 1465 // https://github.com/i3/i3/blob/3cd1c45eba6de073bc4300eebb4e1cc1a0c4479a/src/tree.c#L354
1406 if (child->parent || child->workspace) { 1466 if (child->pending.parent || child->pending.workspace) {
1407 list_t *siblings = container_get_siblings(child); 1467 list_t *siblings = container_get_siblings(child);
1408 if (siblings->length == 1) { 1468 if (siblings->length == 1) {
1409 enum sway_container_layout current = container_parent_layout(child); 1469 enum sway_container_layout current = container_parent_layout(child);
@@ -1411,12 +1471,12 @@ struct sway_container *container_split(struct sway_container *child,
1411 current = L_NONE; 1471 current = L_NONE;
1412 } 1472 }
1413 if (current == L_HORIZ || current == L_VERT) { 1473 if (current == L_HORIZ || current == L_VERT) {
1414 if (child->parent) { 1474 if (child->pending.parent) {
1415 child->parent->layout = layout; 1475 child->pending.parent->pending.layout = layout;
1416 container_update_representation(child->parent); 1476 container_update_representation(child->pending.parent);
1417 } else { 1477 } else {
1418 child->workspace->layout = layout; 1478 child->pending.workspace->layout = layout;
1419 workspace_update_representation(child->workspace); 1479 workspace_update_representation(child->pending.workspace);
1420 } 1480 }
1421 return child; 1481 return child;
1422 } 1482 }
@@ -1429,25 +1489,25 @@ struct sway_container *container_split(struct sway_container *child,
1429 if (container_is_floating(child) && child->view) { 1489 if (container_is_floating(child) && child->view) {
1430 view_set_tiled(child->view, true); 1490 view_set_tiled(child->view, true);
1431 if (child->view->using_csd) { 1491 if (child->view->using_csd) {
1432 child->border = child->saved_border; 1492 child->pending.border = child->saved_border;
1433 } 1493 }
1434 } 1494 }
1435 1495
1436 struct sway_container *cont = container_create(NULL); 1496 struct sway_container *cont = container_create(NULL);
1437 cont->width = child->width; 1497 cont->pending.width = child->pending.width;
1438 cont->height = child->height; 1498 cont->pending.height = child->pending.height;
1439 cont->width_fraction = child->width_fraction; 1499 cont->width_fraction = child->width_fraction;
1440 cont->height_fraction = child->height_fraction; 1500 cont->height_fraction = child->height_fraction;
1441 cont->x = child->x; 1501 cont->pending.x = child->pending.x;
1442 cont->y = child->y; 1502 cont->pending.y = child->pending.y;
1443 cont->layout = layout; 1503 cont->pending.layout = layout;
1444 1504
1445 container_replace(child, cont); 1505 container_replace(child, cont);
1446 container_add_child(cont, child); 1506 container_add_child(cont, child);
1447 1507
1448 if (set_focus) { 1508 if (set_focus) {
1449 seat_set_raw_focus(seat, &cont->node); 1509 seat_set_raw_focus(seat, &cont->node);
1450 if (cont->fullscreen_mode == FULLSCREEN_GLOBAL) { 1510 if (cont->pending.fullscreen_mode == FULLSCREEN_GLOBAL) {
1451 seat_set_focus(seat, &child->node); 1511 seat_set_focus(seat, &child->node);
1452 } else { 1512 } else {
1453 seat_set_raw_focus(seat, &child->node); 1513 seat_set_raw_focus(seat, &child->node);
@@ -1563,6 +1623,10 @@ static void update_marks_texture(struct sway_container *con,
1563 "%s", buffer); 1623 "%s", buffer);
1564 cairo_destroy(c); 1624 cairo_destroy(c);
1565 1625
1626 if (width == 0 || height == 0) {
1627 return;
1628 }
1629
1566 cairo_surface_t *surface = cairo_image_surface_create( 1630 cairo_surface_t *surface = cairo_image_surface_create(
1567 CAIRO_FORMAT_ARGB32, width, height); 1631 CAIRO_FORMAT_ARGB32, width, height);
1568 cairo_t *cairo = cairo_create(surface); 1632 cairo_t *cairo = cairo_create(surface);
@@ -1579,11 +1643,11 @@ static void update_marks_texture(struct sway_container *con,
1579 1643
1580 cairo_surface_flush(surface); 1644 cairo_surface_flush(surface);
1581 unsigned char *data = cairo_image_surface_get_data(surface); 1645 unsigned char *data = cairo_image_surface_get_data(surface);
1582 int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); 1646 int stride = cairo_image_surface_get_stride(surface);
1583 struct wlr_renderer *renderer = wlr_backend_get_renderer( 1647 struct wlr_renderer *renderer = wlr_backend_get_renderer(
1584 output->wlr_output->backend); 1648 output->wlr_output->backend);
1585 *texture = wlr_texture_from_pixels( 1649 *texture = wlr_texture_from_pixels(
1586 renderer, WL_SHM_FORMAT_ARGB8888, stride, width, height, data); 1650 renderer, DRM_FORMAT_ARGB8888, stride, width, height, data);
1587 cairo_surface_destroy(surface); 1651 cairo_surface_destroy(surface);
1588 g_object_unref(pango); 1652 g_object_unref(pango);
1589 cairo_destroy(cairo); 1653 cairo_destroy(cairo);
@@ -1608,19 +1672,19 @@ void container_update_marks_textures(struct sway_container *con) {
1608void container_raise_floating(struct sway_container *con) { 1672void container_raise_floating(struct sway_container *con) {
1609 // Bring container to front by putting it at the end of the floating list. 1673 // Bring container to front by putting it at the end of the floating list.
1610 struct sway_container *floater = container_toplevel_ancestor(con); 1674 struct sway_container *floater = container_toplevel_ancestor(con);
1611 if (container_is_floating(floater) && floater->workspace) { 1675 if (container_is_floating(floater) && floater->pending.workspace) {
1612 list_move_to_end(floater->workspace->floating, floater); 1676 list_move_to_end(floater->pending.workspace->floating, floater);
1613 node_set_dirty(&floater->workspace->node); 1677 node_set_dirty(&floater->pending.workspace->node);
1614 } 1678 }
1615} 1679}
1616 1680
1617bool container_is_scratchpad_hidden(struct sway_container *con) { 1681bool container_is_scratchpad_hidden(struct sway_container *con) {
1618 return con->scratchpad && !con->workspace; 1682 return con->scratchpad && !con->pending.workspace;
1619} 1683}
1620 1684
1621bool container_is_scratchpad_hidden_or_child(struct sway_container *con) { 1685bool container_is_scratchpad_hidden_or_child(struct sway_container *con) {
1622 con = container_toplevel_ancestor(con); 1686 con = container_toplevel_ancestor(con);
1623 return con->scratchpad && !con->workspace; 1687 return con->scratchpad && !con->pending.workspace;
1624} 1688}
1625 1689
1626bool container_is_sticky(struct sway_container *con) { 1690bool container_is_sticky(struct sway_container *con) {
@@ -1648,39 +1712,39 @@ static bool is_parallel(enum sway_container_layout first,
1648static bool container_is_squashable(struct sway_container *con, 1712static bool container_is_squashable(struct sway_container *con,
1649 struct sway_container *child) { 1713 struct sway_container *child) {
1650 enum sway_container_layout gp_layout = container_parent_layout(con); 1714 enum sway_container_layout gp_layout = container_parent_layout(con);
1651 return (con->layout == L_HORIZ || con->layout == L_VERT) && 1715 return (con->pending.layout == L_HORIZ || con->pending.layout == L_VERT) &&
1652 (child->layout == L_HORIZ || child->layout == L_VERT) && 1716 (child->pending.layout == L_HORIZ || child->pending.layout == L_VERT) &&
1653 !is_parallel(con->layout, child->layout) && 1717 !is_parallel(con->pending.layout, child->pending.layout) &&
1654 is_parallel(gp_layout, child->layout); 1718 is_parallel(gp_layout, child->pending.layout);
1655} 1719}
1656 1720
1657static void container_squash_children(struct sway_container *con) { 1721static void container_squash_children(struct sway_container *con) {
1658 for (int i = 0; i < con->children->length; i++) { 1722 for (int i = 0; i < con->pending.children->length; i++) {
1659 struct sway_container *child = con->children->items[i]; 1723 struct sway_container *child = con->pending.children->items[i];
1660 i += container_squash(child); 1724 i += container_squash(child);
1661 } 1725 }
1662} 1726}
1663 1727
1664int container_squash(struct sway_container *con) { 1728int container_squash(struct sway_container *con) {
1665 if (!con->children) { 1729 if (!con->pending.children) {
1666 return 0; 1730 return 0;
1667 } 1731 }
1668 if (con->children->length != 1) { 1732 if (con->pending.children->length != 1) {
1669 container_squash_children(con); 1733 container_squash_children(con);
1670 return 0; 1734 return 0;
1671 } 1735 }
1672 struct sway_container *child = con->children->items[0]; 1736 struct sway_container *child = con->pending.children->items[0];
1673 int idx = container_sibling_index(con); 1737 int idx = container_sibling_index(con);
1674 int change = 0; 1738 int change = 0;
1675 if (container_is_squashable(con, child)) { 1739 if (container_is_squashable(con, child)) {
1676 // con and child are a redundant H/V pair. Destroy them. 1740 // con and child are a redundant H/V pair. Destroy them.
1677 while (child->children->length) { 1741 while (child->pending.children->length) {
1678 struct sway_container *current = child->children->items[0]; 1742 struct sway_container *current = child->pending.children->items[0];
1679 container_detach(current); 1743 container_detach(current);
1680 if (con->parent) { 1744 if (con->pending.parent) {
1681 container_insert_child(con->parent, current, idx); 1745 container_insert_child(con->pending.parent, current, idx);
1682 } else { 1746 } else {
1683 workspace_insert_tiling_direct(con->workspace, current, idx); 1747 workspace_insert_tiling_direct(con->pending.workspace, current, idx);
1684 } 1748 }
1685 change++; 1749 change++;
1686 } 1750 }