diff options
Diffstat (limited to 'sway/tree/container.c')
-rw-r--r-- | sway/tree/container.c | 518 |
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 | ||
152 | struct sway_container *container_find_child(struct sway_container *container, | 153 | struct 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 | ||
313 | struct sway_container *view_container_at(struct sway_node *parent, | 314 | static 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 | |||
337 | static 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, | |||
408 | void container_for_each_child(struct sway_container *container, | 432 | void 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 | ||
444 | struct 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 | |||
420 | bool container_has_ancestor(struct sway_container *descendant, | 466 | bool 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 | ||
597 | void container_update_representation(struct sway_container *con) { | 647 | void 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 | ||
678 | void container_floating_resize_and_center(struct sway_container *con) { | 728 | void 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 | ||
724 | void container_floating_set_default_size(struct sway_container *con) { | 774 | void 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 | ||
850 | bool container_is_floating(struct sway_container *container) { | 910 | bool 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 | |||
921 | bool 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 | ||
861 | void container_get_box(struct sway_container *container, struct wlr_box *box) { | 932 | void 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 | */ |
871 | void container_floating_translate(struct sway_container *con, | 942 | void 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 | */ |
895 | struct sway_output *container_floating_find_output(struct sway_container *con) { | 966 | struct 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 | ||
960 | static bool find_urgent_iterator(struct sway_container *con, void *data) { | 1031 | static 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 | ||
975 | static void set_fullscreen_iterator(struct sway_container *con, void *data) { | 1046 | static 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 | ||
989 | static void container_fullscreen_workspace(struct sway_container *con) { | 1059 | static 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 | ||
1025 | static void container_fullscreen_global(struct sway_container *con) { | 1093 | static 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 | ||
1053 | void container_fullscreen_disable(struct sway_container *con) { | 1119 | void 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 | ||
1107 | void container_set_fullscreen(struct sway_container *con, | 1171 | void 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 | ||
1138 | struct sway_container *container_toplevel_ancestor( | 1202 | struct 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 | ||
1151 | bool container_is_fullscreen_or_child(struct sway_container *container) { | 1215 | bool 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 | ||
1228 | enum sway_container_layout container_parent_layout(struct sway_container *con) { | 1292 | enum 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 | ||
1246 | list_t *container_get_siblings(struct sway_container *container) { | 1310 | list_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 | ||
1259 | int container_sibling_index(struct sway_container *child) { | 1323 | int 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 | ||
1270 | void container_handle_fullscreen_reparent(struct sway_container *con) { | 1334 | void 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 | ||
1283 | static void set_workspace(struct sway_container *container, void *data) { | 1347 | static 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 | ||
1287 | void container_insert_child(struct sway_container *parent, | 1351 | void 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 | ||
1300 | void container_add_sibling(struct sway_container *fixed, | 1364 | void 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 | ||
1315 | void container_add_child(struct sway_container *parent, | 1379 | void 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 | ||
1334 | void container_detach(struct sway_container *child) { | 1394 | void 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 | ||
1365 | void container_replace(struct sway_container *container, | 1425 | void 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) { | |||
1608 | void container_raise_floating(struct sway_container *con) { | 1672 | void 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 | ||
1617 | bool container_is_scratchpad_hidden(struct sway_container *con) { | 1681 | bool 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 | ||
1621 | bool container_is_scratchpad_hidden_or_child(struct sway_container *con) { | 1685 | bool 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 | ||
1626 | bool container_is_sticky(struct sway_container *con) { | 1690 | bool container_is_sticky(struct sway_container *con) { |
@@ -1648,39 +1712,39 @@ static bool is_parallel(enum sway_container_layout first, | |||
1648 | static bool container_is_squashable(struct sway_container *con, | 1712 | static 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 | ||
1657 | static void container_squash_children(struct sway_container *con) { | 1721 | static 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 | ||
1664 | int container_squash(struct sway_container *con) { | 1728 | int 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 | } |