diff options
author | Alexander Orzechowski <alex@ozal.ski> | 2024-01-18 10:04:51 -0500 |
---|---|---|
committer | Kirill Primak <vyivel@eclair.cafe> | 2024-01-18 18:36:54 +0300 |
commit | 188811f80861caacd016b857b0d07f6d2d62d15a (patch) | |
tree | dc68ea00b707b25ce398c71fe1ad996f0eb820ea | |
parent | input: Query scene graph for relevant surface/node intersections (diff) | |
download | sway-188811f80861caacd016b857b0d07f6d2d62d15a.tar.gz sway-188811f80861caacd016b857b0d07f6d2d62d15a.tar.zst sway-188811f80861caacd016b857b0d07f6d2d62d15a.zip |
scene_graph: Port layer_shell
-rw-r--r-- | include/sway/layers.h | 44 | ||||
-rw-r--r-- | include/sway/output.h | 19 | ||||
-rw-r--r-- | include/sway/scene_descriptor.h | 1 | ||||
-rw-r--r-- | include/sway/tree/root.h | 5 | ||||
-rw-r--r-- | sway/desktop/layer_shell.c | 720 | ||||
-rw-r--r-- | sway/desktop/output.c | 85 | ||||
-rw-r--r-- | sway/input/cursor.c | 6 | ||||
-rw-r--r-- | sway/tree/output.c | 13 | ||||
-rw-r--r-- | sway/tree/root.c | 5 |
9 files changed, 256 insertions, 642 deletions
diff --git a/include/sway/layers.h b/include/sway/layers.h index 9220bdb5..a7afb900 100644 --- a/include/sway/layers.h +++ b/include/sway/layers.h | |||
@@ -4,53 +4,30 @@ | |||
4 | #include <wlr/types/wlr_compositor.h> | 4 | #include <wlr/types/wlr_compositor.h> |
5 | #include <wlr/types/wlr_layer_shell_v1.h> | 5 | #include <wlr/types/wlr_layer_shell_v1.h> |
6 | 6 | ||
7 | enum layer_parent { | ||
8 | LAYER_PARENT_LAYER, | ||
9 | LAYER_PARENT_POPUP, | ||
10 | }; | ||
11 | |||
12 | struct sway_layer_surface { | 7 | struct sway_layer_surface { |
13 | struct wlr_layer_surface_v1 *layer_surface; | ||
14 | struct wl_list link; | ||
15 | |||
16 | struct wl_listener destroy; | ||
17 | struct wl_listener map; | 8 | struct wl_listener map; |
18 | struct wl_listener unmap; | 9 | struct wl_listener unmap; |
19 | struct wl_listener surface_commit; | 10 | struct wl_listener surface_commit; |
20 | struct wl_listener output_destroy; | 11 | struct wl_listener output_destroy; |
12 | struct wl_listener node_destroy; | ||
21 | struct wl_listener new_popup; | 13 | struct wl_listener new_popup; |
22 | struct wl_listener new_subsurface; | ||
23 | 14 | ||
24 | struct wlr_box geo; | ||
25 | bool mapped; | 15 | bool mapped; |
26 | struct wlr_box extent; | ||
27 | enum zwlr_layer_shell_v1_layer layer; | ||
28 | 16 | ||
29 | struct wl_list subsurfaces; | 17 | struct sway_output *output; |
18 | struct wlr_scene_layer_surface_v1 *scene; | ||
19 | struct wlr_scene_tree *tree; | ||
20 | struct wlr_scene_tree *popups; | ||
21 | struct wlr_layer_surface_v1 *layer_surface; | ||
30 | }; | 22 | }; |
31 | 23 | ||
32 | struct sway_layer_popup { | 24 | struct sway_layer_popup { |
33 | struct wlr_xdg_popup *wlr_popup; | 25 | struct wlr_xdg_popup *wlr_popup; |
34 | enum layer_parent parent_type; | 26 | struct wlr_scene_tree *scene; |
35 | union { | 27 | struct sway_layer_surface *toplevel; |
36 | struct sway_layer_surface *parent_layer; | ||
37 | struct sway_layer_popup *parent_popup; | ||
38 | }; | ||
39 | struct wl_listener map; | ||
40 | struct wl_listener unmap; | ||
41 | struct wl_listener destroy; | ||
42 | struct wl_listener commit; | ||
43 | struct wl_listener new_popup; | ||
44 | }; | ||
45 | |||
46 | struct sway_layer_subsurface { | ||
47 | struct wlr_subsurface *wlr_subsurface; | ||
48 | struct sway_layer_surface *layer_surface; | ||
49 | struct wl_list link; | ||
50 | 28 | ||
51 | struct wl_listener map; | ||
52 | struct wl_listener unmap; | ||
53 | struct wl_listener destroy; | 29 | struct wl_listener destroy; |
30 | struct wl_listener new_popup; | ||
54 | struct wl_listener commit; | 31 | struct wl_listener commit; |
55 | }; | 32 | }; |
56 | 33 | ||
@@ -61,7 +38,4 @@ struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface( | |||
61 | 38 | ||
62 | void arrange_layers(struct sway_output *output); | 39 | void arrange_layers(struct sway_output *output); |
63 | 40 | ||
64 | struct sway_layer_surface *layer_from_wlr_layer_surface_v1( | ||
65 | struct wlr_layer_surface_v1 *layer_surface); | ||
66 | |||
67 | #endif | 41 | #endif |
diff --git a/include/sway/output.h b/include/sway/output.h index d353ce61..ea5d8f47 100644 --- a/include/sway/output.h +++ b/include/sway/output.h | |||
@@ -22,8 +22,12 @@ struct sway_output { | |||
22 | struct sway_node node; | 22 | struct sway_node node; |
23 | 23 | ||
24 | struct { | 24 | struct { |
25 | struct wlr_scene_tree *shell_background; | ||
26 | struct wlr_scene_tree *shell_bottom; | ||
25 | struct wlr_scene_tree *tiling; | 27 | struct wlr_scene_tree *tiling; |
26 | struct wlr_scene_tree *fullscreen; | 28 | struct wlr_scene_tree *fullscreen; |
29 | struct wlr_scene_tree *shell_top; | ||
30 | struct wlr_scene_tree *shell_overlay; | ||
27 | struct wlr_scene_tree *session_lock; | 31 | struct wlr_scene_tree *session_lock; |
28 | } layers; | 32 | } layers; |
29 | 33 | ||
@@ -39,7 +43,6 @@ struct sway_output { | |||
39 | struct sway_server *server; | 43 | struct sway_server *server; |
40 | struct wl_list link; | 44 | struct wl_list link; |
41 | 45 | ||
42 | struct wl_list shell_layers[4]; // sway_layer_surface::link | ||
43 | struct wlr_box usable_area; | 46 | struct wlr_box usable_area; |
44 | 47 | ||
45 | struct wlr_damage_ring damage_ring; | 48 | struct wlr_damage_ring damage_ring; |
@@ -124,8 +127,6 @@ void output_enable(struct sway_output *output); | |||
124 | 127 | ||
125 | void output_disable(struct sway_output *output); | 128 | void output_disable(struct sway_output *output); |
126 | 129 | ||
127 | bool output_has_opaque_overlay_layer_surface(struct sway_output *output); | ||
128 | |||
129 | struct sway_workspace *output_get_active_workspace(struct sway_output *output); | 130 | struct sway_workspace *output_get_active_workspace(struct sway_output *output); |
130 | 131 | ||
131 | void output_surface_for_each_surface(struct sway_output *output, | 132 | void output_surface_for_each_surface(struct sway_output *output, |
@@ -140,18 +141,6 @@ void output_view_for_each_popup_surface(struct sway_output *output, | |||
140 | struct sway_view *view, sway_surface_iterator_func_t iterator, | 141 | struct sway_view *view, sway_surface_iterator_func_t iterator, |
141 | void *user_data); | 142 | void *user_data); |
142 | 143 | ||
143 | void output_layer_for_each_surface(struct sway_output *output, | ||
144 | struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, | ||
145 | void *user_data); | ||
146 | |||
147 | void output_layer_for_each_toplevel_surface(struct sway_output *output, | ||
148 | struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, | ||
149 | void *user_data); | ||
150 | |||
151 | void output_layer_for_each_popup_surface(struct sway_output *output, | ||
152 | struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, | ||
153 | void *user_data); | ||
154 | |||
155 | #if HAVE_XWAYLAND | 144 | #if HAVE_XWAYLAND |
156 | void output_unmanaged_for_each_surface(struct sway_output *output, | 145 | void output_unmanaged_for_each_surface(struct sway_output *output, |
157 | struct wl_list *unmanaged, sway_surface_iterator_func_t iterator, | 146 | struct wl_list *unmanaged, sway_surface_iterator_func_t iterator, |
diff --git a/include/sway/scene_descriptor.h b/include/sway/scene_descriptor.h index 8af81219..970adaa5 100644 --- a/include/sway/scene_descriptor.h +++ b/include/sway/scene_descriptor.h | |||
@@ -15,6 +15,7 @@ enum sway_scene_descriptor_type { | |||
15 | SWAY_SCENE_DESC_NON_INTERACTIVE, | 15 | SWAY_SCENE_DESC_NON_INTERACTIVE, |
16 | SWAY_SCENE_DESC_CONTAINER, | 16 | SWAY_SCENE_DESC_CONTAINER, |
17 | SWAY_SCENE_DESC_VIEW, | 17 | SWAY_SCENE_DESC_VIEW, |
18 | SWAY_SCENE_DESC_LAYER_SHELL, | ||
18 | SWAY_SCENE_DESC_DRAG_ICON, | 19 | SWAY_SCENE_DESC_DRAG_ICON, |
19 | }; | 20 | }; |
20 | 21 | ||
diff --git a/include/sway/tree/root.h b/include/sway/tree/root.h index 003606aa..2f717bae 100644 --- a/include/sway/tree/root.h +++ b/include/sway/tree/root.h | |||
@@ -40,10 +40,15 @@ struct sway_root { | |||
40 | struct wlr_scene_tree *layer_tree; | 40 | struct wlr_scene_tree *layer_tree; |
41 | 41 | ||
42 | struct { | 42 | struct { |
43 | struct wlr_scene_tree *shell_background; | ||
44 | struct wlr_scene_tree *shell_bottom; | ||
43 | struct wlr_scene_tree *tiling; | 45 | struct wlr_scene_tree *tiling; |
44 | struct wlr_scene_tree *floating; | 46 | struct wlr_scene_tree *floating; |
47 | struct wlr_scene_tree *shell_top; | ||
45 | struct wlr_scene_tree *fullscreen; | 48 | struct wlr_scene_tree *fullscreen; |
46 | struct wlr_scene_tree *fullscreen_global; | 49 | struct wlr_scene_tree *fullscreen_global; |
50 | struct wlr_scene_tree *shell_overlay; | ||
51 | struct wlr_scene_tree *popup; | ||
47 | struct wlr_scene_tree *seat; | 52 | struct wlr_scene_tree *seat; |
48 | struct wlr_scene_tree *session_lock; | 53 | struct wlr_scene_tree *session_lock; |
49 | } layers; | 54 | } layers; |
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 6480d7ce..a52d27fa 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <wlr/types/wlr_output.h> | 6 | #include <wlr/types/wlr_output.h> |
7 | #include <wlr/types/wlr_subcompositor.h> | 7 | #include <wlr/types/wlr_subcompositor.h> |
8 | #include "log.h" | 8 | #include "log.h" |
9 | #include "sway/scene_descriptor.h" | ||
9 | #include "sway/desktop/transaction.h" | 10 | #include "sway/desktop/transaction.h" |
10 | #include "sway/input/cursor.h" | 11 | #include "sway/input/cursor.h" |
11 | #include "sway/input/input-manager.h" | 12 | #include "sway/input/input-manager.h" |
@@ -16,6 +17,7 @@ | |||
16 | #include "sway/surface.h" | 17 | #include "sway/surface.h" |
17 | #include "sway/tree/arrange.h" | 18 | #include "sway/tree/arrange.h" |
18 | #include "sway/tree/workspace.h" | 19 | #include "sway/tree/workspace.h" |
20 | #include <wlr/types/wlr_scene.h> | ||
19 | 21 | ||
20 | struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface( | 22 | struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface( |
21 | struct wlr_surface *surface) { | 23 | struct wlr_surface *surface) { |
@@ -50,165 +52,22 @@ struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface( | |||
50 | } while (true); | 52 | } while (true); |
51 | } | 53 | } |
52 | 54 | ||
53 | static void apply_exclusive(struct wlr_box *usable_area, | 55 | static void arrange_surface(struct sway_output *output, const struct wlr_box *full_area, |
54 | uint32_t anchor, int32_t exclusive, | 56 | struct wlr_box *usable_area, struct wlr_scene_tree *tree) { |
55 | int32_t margin_top, int32_t margin_right, | 57 | struct wlr_scene_node *node; |
56 | int32_t margin_bottom, int32_t margin_left) { | 58 | wl_list_for_each(node, &tree->children, link) { |
57 | if (exclusive <= 0) { | 59 | struct sway_layer_surface *surface = scene_descriptor_try_get(node, |
58 | return; | 60 | SWAY_SCENE_DESC_LAYER_SHELL); |
59 | } | 61 | // surface could be null during destruction |
60 | struct { | 62 | if (!surface) { |
61 | uint32_t singular_anchor; | 63 | continue; |
62 | uint32_t anchor_triplet; | ||
63 | int *positive_axis; | ||
64 | int *negative_axis; | ||
65 | int margin; | ||
66 | } edges[] = { | ||
67 | // Top | ||
68 | { | ||
69 | .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP, | ||
70 | .anchor_triplet = | ||
71 | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | | ||
72 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | | ||
73 | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP, | ||
74 | .positive_axis = &usable_area->y, | ||
75 | .negative_axis = &usable_area->height, | ||
76 | .margin = margin_top, | ||
77 | }, | ||
78 | // Bottom | ||
79 | { | ||
80 | .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, | ||
81 | .anchor_triplet = | ||
82 | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | | ||
83 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | | ||
84 | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, | ||
85 | .positive_axis = NULL, | ||
86 | .negative_axis = &usable_area->height, | ||
87 | .margin = margin_bottom, | ||
88 | }, | ||
89 | // Left | ||
90 | { | ||
91 | .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT, | ||
92 | .anchor_triplet = | ||
93 | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | | ||
94 | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | | ||
95 | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, | ||
96 | .positive_axis = &usable_area->x, | ||
97 | .negative_axis = &usable_area->width, | ||
98 | .margin = margin_left, | ||
99 | }, | ||
100 | // Right | ||
101 | { | ||
102 | .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT, | ||
103 | .anchor_triplet = | ||
104 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | | ||
105 | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | | ||
106 | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, | ||
107 | .positive_axis = NULL, | ||
108 | .negative_axis = &usable_area->width, | ||
109 | .margin = margin_right, | ||
110 | }, | ||
111 | }; | ||
112 | for (size_t i = 0; i < sizeof(edges) / sizeof(edges[0]); ++i) { | ||
113 | if ((anchor == edges[i].singular_anchor || anchor == edges[i].anchor_triplet) | ||
114 | && exclusive + edges[i].margin > 0) { | ||
115 | if (edges[i].positive_axis) { | ||
116 | *edges[i].positive_axis += exclusive + edges[i].margin; | ||
117 | } | ||
118 | if (edges[i].negative_axis) { | ||
119 | *edges[i].negative_axis -= exclusive + edges[i].margin; | ||
120 | } | ||
121 | break; | ||
122 | } | 64 | } |
123 | } | ||
124 | } | ||
125 | 65 | ||
126 | static void arrange_layer(struct sway_output *output, struct wl_list *list, | 66 | if (!surface->scene->layer_surface->initialized) { |
127 | struct wlr_box *usable_area, bool exclusive) { | ||
128 | struct sway_layer_surface *sway_layer; | ||
129 | struct wlr_box full_area = { 0 }; | ||
130 | wlr_output_effective_resolution(output->wlr_output, | ||
131 | &full_area.width, &full_area.height); | ||
132 | wl_list_for_each(sway_layer, list, link) { | ||
133 | struct wlr_layer_surface_v1 *layer = sway_layer->layer_surface; | ||
134 | if (!layer->initialized) { | ||
135 | return; | 67 | return; |
136 | } | 68 | } |
137 | struct wlr_layer_surface_v1_state *state = &layer->current; | 69 | |
138 | if (exclusive != (state->exclusive_zone > 0)) { | 70 | wlr_scene_layer_surface_v1_configure(surface->scene, full_area, usable_area); |
139 | continue; | ||
140 | } | ||
141 | struct wlr_box bounds; | ||
142 | if (state->exclusive_zone == -1) { | ||
143 | bounds = full_area; | ||
144 | } else { | ||
145 | bounds = *usable_area; | ||
146 | } | ||
147 | struct wlr_box box = { | ||
148 | .width = state->desired_width, | ||
149 | .height = state->desired_height | ||
150 | }; | ||
151 | // Horizontal axis | ||
152 | const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ||
153 | | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; | ||
154 | if (box.width == 0) { | ||
155 | box.x = bounds.x; | ||
156 | } else if ((state->anchor & both_horiz) == both_horiz) { | ||
157 | box.x = bounds.x + ((bounds.width / 2) - (box.width / 2)); | ||
158 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { | ||
159 | box.x = bounds.x; | ||
160 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { | ||
161 | box.x = bounds.x + (bounds.width - box.width); | ||
162 | } else { | ||
163 | box.x = bounds.x + ((bounds.width / 2) - (box.width / 2)); | ||
164 | } | ||
165 | // Vertical axis | ||
166 | const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ||
167 | | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; | ||
168 | if (box.height == 0) { | ||
169 | box.y = bounds.y; | ||
170 | } else if ((state->anchor & both_vert) == both_vert) { | ||
171 | box.y = bounds.y + ((bounds.height / 2) - (box.height / 2)); | ||
172 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { | ||
173 | box.y = bounds.y; | ||
174 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { | ||
175 | box.y = bounds.y + (bounds.height - box.height); | ||
176 | } else { | ||
177 | box.y = bounds.y + ((bounds.height / 2) - (box.height / 2)); | ||
178 | } | ||
179 | // Margin | ||
180 | if (box.width == 0) { | ||
181 | box.x += state->margin.left; | ||
182 | box.width = bounds.width - | ||
183 | (state->margin.left + state->margin.right); | ||
184 | } else if ((state->anchor & both_horiz) == both_horiz) { | ||
185 | // don't apply margins | ||
186 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { | ||
187 | box.x += state->margin.left; | ||
188 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { | ||
189 | box.x -= state->margin.right; | ||
190 | } | ||
191 | if (box.height == 0) { | ||
192 | box.y += state->margin.top; | ||
193 | box.height = bounds.height - | ||
194 | (state->margin.top + state->margin.bottom); | ||
195 | } else if ((state->anchor & both_vert) == both_vert) { | ||
196 | // don't apply margins | ||
197 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { | ||
198 | box.y += state->margin.top; | ||
199 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { | ||
200 | box.y -= state->margin.bottom; | ||
201 | } | ||
202 | if (!sway_assert(box.width >= 0 && box.height >= 0, | ||
203 | "Expected layer surface to have positive size")) { | ||
204 | continue; | ||
205 | } | ||
206 | // Apply | ||
207 | sway_layer->geo = box; | ||
208 | apply_exclusive(usable_area, state->anchor, state->exclusive_zone, | ||
209 | state->margin.top, state->margin.right, | ||
210 | state->margin.bottom, state->margin.left); | ||
211 | wlr_layer_surface_v1_configure(layer, box.width, box.height); | ||
212 | } | 71 | } |
213 | } | 72 | } |
214 | 73 | ||
@@ -216,83 +75,78 @@ void arrange_layers(struct sway_output *output) { | |||
216 | struct wlr_box usable_area = { 0 }; | 75 | struct wlr_box usable_area = { 0 }; |
217 | wlr_output_effective_resolution(output->wlr_output, | 76 | wlr_output_effective_resolution(output->wlr_output, |
218 | &usable_area.width, &usable_area.height); | 77 | &usable_area.width, &usable_area.height); |
78 | const struct wlr_box full_area = usable_area; | ||
219 | 79 | ||
220 | // Arrange exclusive surfaces from top->bottom | 80 | arrange_surface(output, &full_area, &usable_area, output->layers.shell_background); |
221 | arrange_layer(output, &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], | 81 | arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom); |
222 | &usable_area, true); | 82 | arrange_surface(output, &full_area, &usable_area, output->layers.shell_top); |
223 | arrange_layer(output, &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], | 83 | arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay); |
224 | &usable_area, true); | 84 | |
225 | arrange_layer(output, &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], | 85 | if (!wlr_box_equal(&usable_area, &output->usable_area)) { |
226 | &usable_area, true); | ||
227 | arrange_layer(output, &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], | ||
228 | &usable_area, true); | ||
229 | |||
230 | if (memcmp(&usable_area, &output->usable_area, | ||
231 | sizeof(struct wlr_box)) != 0) { | ||
232 | sway_log(SWAY_DEBUG, "Usable area changed, rearranging output"); | 86 | sway_log(SWAY_DEBUG, "Usable area changed, rearranging output"); |
233 | memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); | 87 | output->usable_area = usable_area; |
234 | arrange_output(output); | 88 | arrange_output(output); |
235 | } | 89 | } |
90 | } | ||
236 | 91 | ||
237 | // Arrange non-exclusive surfaces from top->bottom | 92 | static struct wlr_scene_tree *sway_layer_get_scene(struct sway_output *output, |
238 | arrange_layer(output, &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], | 93 | enum zwlr_layer_shell_v1_layer type) { |
239 | &usable_area, false); | 94 | switch (type) { |
240 | arrange_layer(output, &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], | 95 | case ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND: |
241 | &usable_area, false); | 96 | return output->layers.shell_background; |
242 | arrange_layer(output, &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], | 97 | case ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM: |
243 | &usable_area, false); | 98 | return output->layers.shell_bottom; |
244 | arrange_layer(output, &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], | 99 | case ZWLR_LAYER_SHELL_V1_LAYER_TOP: |
245 | &usable_area, false); | 100 | return output->layers.shell_top; |
246 | 101 | case ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY: | |
247 | // Find topmost keyboard interactive layer, if such a layer exists | 102 | return output->layers.shell_overlay; |
248 | uint32_t layers_above_shell[] = { | ||
249 | ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, | ||
250 | ZWLR_LAYER_SHELL_V1_LAYER_TOP, | ||
251 | }; | ||
252 | size_t nlayers = sizeof(layers_above_shell) / sizeof(layers_above_shell[0]); | ||
253 | struct sway_layer_surface *layer, *topmost = NULL; | ||
254 | for (size_t i = 0; i < nlayers; ++i) { | ||
255 | wl_list_for_each_reverse(layer, | ||
256 | &output->shell_layers[layers_above_shell[i]], link) { | ||
257 | if (layer->layer_surface->current.keyboard_interactive && | ||
258 | layer->layer_surface->surface->mapped) { | ||
259 | topmost = layer; | ||
260 | break; | ||
261 | } | ||
262 | } | ||
263 | if (topmost != NULL) { | ||
264 | break; | ||
265 | } | ||
266 | } | 103 | } |
267 | 104 | ||
268 | struct sway_seat *seat; | 105 | sway_assert(false, "unreachable"); |
269 | wl_list_for_each(seat, &server.input->seats, link) { | 106 | return NULL; |
270 | seat->has_exclusive_layer = false; | 107 | } |
271 | if (topmost != NULL) { | 108 | |
272 | seat_set_focus_layer(seat, topmost->layer_surface); | 109 | static struct sway_layer_surface *sway_layer_surface_create( |
273 | } else if (seat->focused_layer && | 110 | struct wlr_scene_layer_surface_v1 *scene) { |
274 | seat->focused_layer->current.keyboard_interactive | 111 | struct sway_layer_surface *surface = calloc(1, sizeof(*surface)); |
275 | != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) { | 112 | if (!surface) { |
276 | seat_set_focus_layer(seat, NULL); | 113 | sway_log(SWAY_ERROR, "Could not allocate a scene_layer surface"); |
277 | } | 114 | return NULL; |
278 | } | 115 | } |
116 | |||
117 | struct wlr_scene_tree *popups = wlr_scene_tree_create(root->layers.popup); | ||
118 | if (!popups) { | ||
119 | sway_log(SWAY_ERROR, "Could not allocate a scene_layer popup node"); | ||
120 | free(surface); | ||
121 | return NULL; | ||
122 | } | ||
123 | |||
124 | surface->tree = scene->tree; | ||
125 | surface->scene = scene; | ||
126 | surface->layer_surface = scene->layer_surface; | ||
127 | surface->popups = popups; | ||
128 | |||
129 | return surface; | ||
279 | } | 130 | } |
280 | 131 | ||
281 | static struct sway_layer_surface *find_mapped_layer_by_client( | 132 | static struct sway_layer_surface *find_mapped_layer_by_client( |
282 | struct wl_client *client, struct wlr_output *ignore_output) { | 133 | struct wl_client *client, struct sway_output *ignore_output) { |
283 | for (int i = 0; i < root->outputs->length; ++i) { | 134 | for (int i = 0; i < root->outputs->length; ++i) { |
284 | struct sway_output *output = root->outputs->items[i]; | 135 | struct sway_output *output = root->outputs->items[i]; |
285 | if (output->wlr_output == ignore_output) { | 136 | if (output == ignore_output) { |
286 | continue; | 137 | continue; |
287 | } | 138 | } |
288 | // For now we'll only check the overlay layer | 139 | // For now we'll only check the overlay layer |
289 | struct sway_layer_surface *lsurface; | 140 | struct wlr_scene_node *node; |
290 | wl_list_for_each(lsurface, | 141 | wl_list_for_each (node, &output->layers.shell_overlay->children, link) { |
291 | &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], link) { | 142 | struct sway_layer_surface *surface = scene_descriptor_try_get(node, |
292 | struct wl_resource *resource = lsurface->layer_surface->resource; | 143 | SWAY_SCENE_DESC_LAYER_SHELL); |
144 | |||
145 | struct wlr_layer_surface_v1 *layer_surface = surface->layer_surface; | ||
146 | struct wl_resource *resource = layer_surface->resource; | ||
293 | if (wl_resource_get_client(resource) == client | 147 | if (wl_resource_get_client(resource) == client |
294 | && lsurface->layer_surface->surface->mapped) { | 148 | && layer_surface->surface->mapped) { |
295 | return lsurface; | 149 | return surface; |
296 | } | 150 | } |
297 | } | 151 | } |
298 | } | 152 | } |
@@ -300,262 +154,144 @@ static struct sway_layer_surface *find_mapped_layer_by_client( | |||
300 | } | 154 | } |
301 | 155 | ||
302 | static void handle_output_destroy(struct wl_listener *listener, void *data) { | 156 | static void handle_output_destroy(struct wl_listener *listener, void *data) { |
303 | struct sway_layer_surface *sway_layer = | 157 | struct sway_layer_surface *layer = |
304 | wl_container_of(listener, sway_layer, output_destroy); | 158 | wl_container_of(listener, layer, output_destroy); |
159 | |||
160 | layer->output = NULL; | ||
161 | wlr_scene_node_destroy(&layer->scene->tree->node); | ||
162 | } | ||
163 | |||
164 | static void handle_node_destroy(struct wl_listener *listener, void *data) { | ||
165 | struct sway_layer_surface *layer = | ||
166 | wl_container_of(listener, layer, node_destroy); | ||
167 | |||
168 | // destroy the scene descriptor straight away if it exists, otherwise | ||
169 | // we will try to reflow still considering the destroyed node. | ||
170 | scene_descriptor_destroy(&layer->tree->node, SWAY_SCENE_DESC_LAYER_SHELL); | ||
171 | |||
305 | // Determine if this layer is being used by an exclusive client. If it is, | 172 | // Determine if this layer is being used by an exclusive client. If it is, |
306 | // try and find another layer owned by this client to pass focus to. | 173 | // try and find another layer owned by this client to pass focus to. |
307 | struct sway_seat *seat = input_manager_get_default_seat(); | 174 | struct sway_seat *seat = input_manager_get_default_seat(); |
308 | struct wl_client *client = | 175 | struct wl_client *client = |
309 | wl_resource_get_client(sway_layer->layer_surface->resource); | 176 | wl_resource_get_client(layer->layer_surface->resource); |
310 | 177 | if (!server.session_lock.lock) { | |
311 | if (!server.session_lock.locked) { | 178 | struct sway_layer_surface *consider_layer = |
312 | struct sway_layer_surface *layer = | 179 | find_mapped_layer_by_client(client, layer->output); |
313 | find_mapped_layer_by_client(client, sway_layer->layer_surface->output); | 180 | if (consider_layer) { |
314 | if (layer) { | 181 | seat_set_focus_layer(seat, consider_layer->layer_surface); |
315 | seat_set_focus_layer(seat, layer->layer_surface); | ||
316 | } | 182 | } |
317 | } | 183 | } |
318 | 184 | ||
319 | wlr_layer_surface_v1_destroy(sway_layer->layer_surface); | 185 | if (layer->output) { |
186 | arrange_layers(layer->output); | ||
187 | transaction_commit_dirty(); | ||
188 | } | ||
189 | |||
190 | wlr_scene_node_destroy(&layer->popups->node); | ||
191 | |||
192 | wl_list_remove(&layer->map.link); | ||
193 | wl_list_remove(&layer->unmap.link); | ||
194 | wl_list_remove(&layer->surface_commit.link); | ||
195 | wl_list_remove(&layer->node_destroy.link); | ||
196 | wl_list_remove(&layer->output_destroy.link); | ||
197 | |||
198 | free(layer); | ||
320 | } | 199 | } |
321 | 200 | ||
322 | static void handle_surface_commit(struct wl_listener *listener, void *data) { | 201 | static void handle_surface_commit(struct wl_listener *listener, void *data) { |
323 | struct sway_layer_surface *layer = | 202 | struct sway_layer_surface *surface = |
324 | wl_container_of(listener, layer, surface_commit); | 203 | wl_container_of(listener, surface, surface_commit); |
325 | struct wlr_layer_surface_v1 *layer_surface = layer->layer_surface; | 204 | |
326 | struct wlr_output *wlr_output = layer_surface->output; | 205 | struct wlr_layer_surface_v1 *layer_surface = surface->layer_surface; |
327 | sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); | 206 | if (!layer_surface->initialized) { |
328 | struct sway_output *output = wlr_output->data; | ||
329 | |||
330 | if (layer_surface->initial_commit) { | ||
331 | surface_enter_output(layer_surface->surface, output); | ||
332 | } else if (!layer_surface->initialized) { | ||
333 | return; | 207 | return; |
334 | } | 208 | } |
335 | 209 | ||
336 | struct wlr_box old_extent = layer->extent; | 210 | uint32_t committed = layer_surface->current.committed; |
337 | 211 | if (committed & WLR_LAYER_SURFACE_V1_STATE_LAYER) { | |
338 | bool layer_changed = false; | 212 | enum zwlr_layer_shell_v1_layer layer_type = layer_surface->current.layer; |
339 | if (layer_surface->initial_commit || layer_surface->current.committed != 0 | 213 | struct wlr_scene_tree *output_layer = sway_layer_get_scene( |
340 | || layer->mapped != layer_surface->surface->mapped) { | 214 | surface->output, layer_type); |
341 | layer->mapped = layer_surface->surface->mapped; | 215 | wlr_scene_node_reparent(&surface->scene->tree->node, output_layer); |
342 | layer_changed = layer->layer != layer_surface->current.layer; | ||
343 | if (layer_changed) { | ||
344 | wl_list_remove(&layer->link); | ||
345 | wl_list_insert(&output->shell_layers[layer_surface->current.layer], | ||
346 | &layer->link); | ||
347 | layer->layer = layer_surface->current.layer; | ||
348 | } | ||
349 | arrange_layers(output); | ||
350 | } | 216 | } |
351 | 217 | ||
352 | wlr_surface_get_extends(layer_surface->surface, &layer->extent); | 218 | if (layer_surface->initial_commit || committed || layer_surface->surface->mapped != surface->mapped) { |
353 | layer->extent.x += layer->geo.x; | 219 | surface->mapped = layer_surface->surface->mapped; |
354 | layer->extent.y += layer->geo.y; | 220 | arrange_layers(surface->output); |
355 | 221 | transaction_commit_dirty(); | |
356 | bool extent_changed = | ||
357 | memcmp(&old_extent, &layer->extent, sizeof(struct wlr_box)) != 0; | ||
358 | if (extent_changed || layer_changed) { | ||
359 | old_extent.x += output->lx; | ||
360 | old_extent.y += output->ly; | ||
361 | output_damage_box(output, &old_extent); | ||
362 | output_damage_surface(output, layer->geo.x, layer->geo.y, | ||
363 | layer_surface->surface, true); | ||
364 | } else { | ||
365 | output_damage_surface(output, layer->geo.x, layer->geo.y, | ||
366 | layer_surface->surface, false); | ||
367 | } | 222 | } |
368 | 223 | ||
369 | transaction_commit_dirty(); | 224 | int lx, ly; |
225 | wlr_scene_node_coords(&surface->scene->tree->node, &lx, &ly); | ||
226 | wlr_scene_node_set_position(&surface->popups->node, lx, ly); | ||
370 | } | 227 | } |
371 | 228 | ||
372 | static void layer_subsurface_destroy(struct sway_layer_subsurface *subsurface); | 229 | static void handle_map(struct wl_listener *listener, void *data) { |
373 | 230 | struct sway_layer_surface *surface = wl_container_of(listener, | |
374 | static void handle_destroy(struct wl_listener *listener, void *data) { | 231 | surface, map); |
375 | struct sway_layer_surface *sway_layer = | 232 | |
376 | wl_container_of(listener, sway_layer, destroy); | 233 | struct wlr_layer_surface_v1 *layer_surface = |
377 | sway_log(SWAY_DEBUG, "Layer surface destroyed (%s)", | 234 | surface->scene->layer_surface; |
378 | sway_layer->layer_surface->namespace); | 235 | |
379 | 236 | // focus on new surface | |
380 | struct sway_layer_subsurface *subsurface, *subsurface_tmp; | 237 | if (layer_surface->current.keyboard_interactive && |
381 | wl_list_for_each_safe(subsurface, subsurface_tmp, &sway_layer->subsurfaces, link) { | 238 | (layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY || |
382 | layer_subsurface_destroy(subsurface); | 239 | layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP)) { |
240 | struct sway_seat *seat; | ||
241 | wl_list_for_each(seat, &server.input->seats, link) { | ||
242 | // but only if the currently focused layer has a lower precedence | ||
243 | if (!seat->focused_layer || | ||
244 | seat->focused_layer->current.layer >= layer_surface->current.layer) { | ||
245 | seat_set_focus_layer(seat, layer_surface); | ||
246 | } | ||
247 | } | ||
248 | arrange_layers(surface->output); | ||
383 | } | 249 | } |
384 | 250 | ||
385 | wl_list_remove(&sway_layer->link); | ||
386 | wl_list_remove(&sway_layer->destroy.link); | ||
387 | wl_list_remove(&sway_layer->map.link); | ||
388 | wl_list_remove(&sway_layer->unmap.link); | ||
389 | wl_list_remove(&sway_layer->surface_commit.link); | ||
390 | wl_list_remove(&sway_layer->new_popup.link); | ||
391 | wl_list_remove(&sway_layer->new_subsurface.link); | ||
392 | |||
393 | struct wlr_output *wlr_output = sway_layer->layer_surface->output; | ||
394 | sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); | ||
395 | struct sway_output *output = wlr_output->data; | ||
396 | arrange_layers(output); | ||
397 | transaction_commit_dirty(); | ||
398 | wl_list_remove(&sway_layer->output_destroy.link); | ||
399 | sway_layer->layer_surface->output = NULL; | ||
400 | |||
401 | free(sway_layer); | ||
402 | } | ||
403 | |||
404 | static void handle_map(struct wl_listener *listener, void *data) { | ||
405 | struct sway_layer_surface *sway_layer = wl_container_of(listener, | ||
406 | sway_layer, map); | ||
407 | struct wlr_output *wlr_output = sway_layer->layer_surface->output; | ||
408 | sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); | ||
409 | struct sway_output *output = wlr_output->data; | ||
410 | output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y, | ||
411 | sway_layer->layer_surface->surface, true); | ||
412 | cursor_rebase_all(); | 251 | cursor_rebase_all(); |
413 | } | 252 | } |
414 | 253 | ||
415 | static void handle_unmap(struct wl_listener *listener, void *data) { | 254 | static void handle_unmap(struct wl_listener *listener, void *data) { |
416 | struct sway_layer_surface *sway_layer = wl_container_of( | 255 | struct sway_layer_surface *surface = wl_container_of( |
417 | listener, sway_layer, unmap); | 256 | listener, surface, unmap); |
418 | struct sway_seat *seat; | 257 | struct sway_seat *seat; |
419 | wl_list_for_each(seat, &server.input->seats, link) { | 258 | wl_list_for_each(seat, &server.input->seats, link) { |
420 | if (seat->focused_layer == sway_layer->layer_surface) { | 259 | if (seat->focused_layer == surface->layer_surface) { |
421 | seat_set_focus_layer(seat, NULL); | 260 | seat_set_focus_layer(seat, NULL); |
422 | } | 261 | } |
423 | } | 262 | } |
424 | 263 | ||
425 | cursor_rebase_all(); | 264 | cursor_rebase_all(); |
426 | |||
427 | struct wlr_output *wlr_output = sway_layer->layer_surface->output; | ||
428 | sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); | ||
429 | struct sway_output *output = wlr_output->data; | ||
430 | output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y, | ||
431 | sway_layer->layer_surface->surface, true); | ||
432 | } | ||
433 | |||
434 | static void subsurface_damage(struct sway_layer_subsurface *subsurface, | ||
435 | bool whole) { | ||
436 | struct sway_layer_surface *layer = subsurface->layer_surface; | ||
437 | struct wlr_output *wlr_output = layer->layer_surface->output; | ||
438 | sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); | ||
439 | struct sway_output *output = wlr_output->data; | ||
440 | int ox = subsurface->wlr_subsurface->current.x + layer->geo.x; | ||
441 | int oy = subsurface->wlr_subsurface->current.y + layer->geo.y; | ||
442 | output_damage_surface( | ||
443 | output, ox, oy, subsurface->wlr_subsurface->surface, whole); | ||
444 | } | 265 | } |
445 | 266 | ||
446 | static void subsurface_handle_unmap(struct wl_listener *listener, void *data) { | 267 | static void popup_handle_destroy(struct wl_listener *listener, void *data) { |
447 | struct sway_layer_subsurface *subsurface = | 268 | struct sway_layer_popup *popup = |
448 | wl_container_of(listener, subsurface, unmap); | 269 | wl_container_of(listener, popup, destroy); |
449 | subsurface_damage(subsurface, true); | ||
450 | } | ||
451 | |||
452 | static void subsurface_handle_map(struct wl_listener *listener, void *data) { | ||
453 | struct sway_layer_subsurface *subsurface = | ||
454 | wl_container_of(listener, subsurface, map); | ||
455 | subsurface_damage(subsurface, true); | ||
456 | } | ||
457 | |||
458 | static void subsurface_handle_commit(struct wl_listener *listener, void *data) { | ||
459 | struct sway_layer_subsurface *subsurface = | ||
460 | wl_container_of(listener, subsurface, commit); | ||
461 | subsurface_damage(subsurface, false); | ||
462 | } | ||
463 | |||
464 | static void layer_subsurface_destroy(struct sway_layer_subsurface *subsurface) { | ||
465 | wl_list_remove(&subsurface->link); | ||
466 | wl_list_remove(&subsurface->map.link); | ||
467 | wl_list_remove(&subsurface->unmap.link); | ||
468 | wl_list_remove(&subsurface->destroy.link); | ||
469 | wl_list_remove(&subsurface->commit.link); | ||
470 | free(subsurface); | ||
471 | } | ||
472 | |||
473 | static void subsurface_handle_destroy(struct wl_listener *listener, | ||
474 | void *data) { | ||
475 | struct sway_layer_subsurface *subsurface = | ||
476 | wl_container_of(listener, subsurface, destroy); | ||
477 | layer_subsurface_destroy(subsurface); | ||
478 | } | ||
479 | |||
480 | static struct sway_layer_subsurface *create_subsurface( | ||
481 | struct wlr_subsurface *wlr_subsurface, | ||
482 | struct sway_layer_surface *layer_surface) { | ||
483 | struct sway_layer_subsurface *subsurface = | ||
484 | calloc(1, sizeof(struct sway_layer_subsurface)); | ||
485 | if (subsurface == NULL) { | ||
486 | return NULL; | ||
487 | } | ||
488 | |||
489 | subsurface->wlr_subsurface = wlr_subsurface; | ||
490 | subsurface->layer_surface = layer_surface; | ||
491 | wl_list_insert(&layer_surface->subsurfaces, &subsurface->link); | ||
492 | |||
493 | subsurface->map.notify = subsurface_handle_map; | ||
494 | wl_signal_add(&wlr_subsurface->surface->events.map, &subsurface->map); | ||
495 | subsurface->unmap.notify = subsurface_handle_unmap; | ||
496 | wl_signal_add(&wlr_subsurface->surface->events.unmap, &subsurface->unmap); | ||
497 | subsurface->destroy.notify = subsurface_handle_destroy; | ||
498 | wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy); | ||
499 | subsurface->commit.notify = subsurface_handle_commit; | ||
500 | wl_signal_add(&wlr_subsurface->surface->events.commit, &subsurface->commit); | ||
501 | |||
502 | return subsurface; | ||
503 | } | ||
504 | |||
505 | static void handle_new_subsurface(struct wl_listener *listener, void *data) { | ||
506 | struct sway_layer_surface *sway_layer_surface = | ||
507 | wl_container_of(listener, sway_layer_surface, new_subsurface); | ||
508 | struct wlr_subsurface *wlr_subsurface = data; | ||
509 | create_subsurface(wlr_subsurface, sway_layer_surface); | ||
510 | } | ||
511 | |||
512 | |||
513 | static struct sway_layer_surface *popup_get_layer( | ||
514 | struct sway_layer_popup *popup) { | ||
515 | while (popup->parent_type == LAYER_PARENT_POPUP) { | ||
516 | popup = popup->parent_popup; | ||
517 | } | ||
518 | return popup->parent_layer; | ||
519 | } | ||
520 | 270 | ||
521 | static void popup_damage(struct sway_layer_popup *layer_popup, bool whole) { | 271 | wl_list_remove(&popup->destroy.link); |
522 | struct wlr_xdg_popup *popup = layer_popup->wlr_popup; | 272 | wl_list_remove(&popup->new_popup.link); |
523 | struct wlr_surface *surface = popup->base->surface; | 273 | wl_list_remove(&popup->commit.link); |
524 | int popup_sx = popup->current.geometry.x - popup->base->current.geometry.x; | 274 | free(popup); |
525 | int popup_sy = popup->current.geometry.y - popup->base->current.geometry.y; | ||
526 | int ox = popup_sx, oy = popup_sy; | ||
527 | struct sway_layer_surface *layer; | ||
528 | while (true) { | ||
529 | if (layer_popup->parent_type == LAYER_PARENT_POPUP) { | ||
530 | layer_popup = layer_popup->parent_popup; | ||
531 | ox += layer_popup->wlr_popup->current.geometry.x; | ||
532 | oy += layer_popup->wlr_popup->current.geometry.y; | ||
533 | } else { | ||
534 | layer = layer_popup->parent_layer; | ||
535 | ox += layer->geo.x; | ||
536 | oy += layer->geo.y; | ||
537 | break; | ||
538 | } | ||
539 | } | ||
540 | struct wlr_output *wlr_output = layer->layer_surface->output; | ||
541 | sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); | ||
542 | struct sway_output *output = wlr_output->data; | ||
543 | output_damage_surface(output, ox, oy, surface, whole); | ||
544 | } | 275 | } |
545 | 276 | ||
546 | static void popup_unconstrain(struct sway_layer_popup *popup) { | 277 | static void popup_unconstrain(struct sway_layer_popup *popup) { |
547 | struct sway_layer_surface *layer = popup_get_layer(popup); | ||
548 | struct wlr_xdg_popup *wlr_popup = popup->wlr_popup; | 278 | struct wlr_xdg_popup *wlr_popup = popup->wlr_popup; |
279 | struct sway_output *output = popup->toplevel->output; | ||
280 | |||
281 | // if a client tries to create a popup while we are in the process of destroying | ||
282 | // its output, don't crash. | ||
283 | if (!output) { | ||
284 | return; | ||
285 | } | ||
549 | 286 | ||
550 | struct wlr_output *wlr_output = layer->layer_surface->output; | 287 | int lx, ly; |
551 | sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); | 288 | wlr_scene_node_coords(&popup->toplevel->scene->tree->node, &lx, &ly); |
552 | struct sway_output *output = wlr_output->data; | ||
553 | 289 | ||
554 | // the output box expressed in the coordinate system of the toplevel parent | 290 | // the output box expressed in the coordinate system of the toplevel parent |
555 | // of the popup | 291 | // of the popup |
556 | struct wlr_box output_toplevel_sx_box = { | 292 | struct wlr_box output_toplevel_sx_box = { |
557 | .x = -layer->geo.x, | 293 | .x = output->lx - lx, |
558 | .y = -layer->geo.y, | 294 | .y = output->ly - ly, |
559 | .width = output->width, | 295 | .width = output->width, |
560 | .height = output->height, | 296 | .height = output->height, |
561 | }; | 297 | }; |
@@ -563,63 +299,38 @@ static void popup_unconstrain(struct sway_layer_popup *popup) { | |||
563 | wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); | 299 | wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); |
564 | } | 300 | } |
565 | 301 | ||
566 | static void popup_handle_map(struct wl_listener *listener, void *data) { | ||
567 | struct sway_layer_popup *popup = wl_container_of(listener, popup, map); | ||
568 | struct sway_layer_surface *layer = popup_get_layer(popup); | ||
569 | struct wlr_output *wlr_output = layer->layer_surface->output; | ||
570 | sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); | ||
571 | surface_enter_output(popup->wlr_popup->base->surface, wlr_output->data); | ||
572 | popup_damage(popup, true); | ||
573 | } | ||
574 | |||
575 | static void popup_handle_unmap(struct wl_listener *listener, void *data) { | ||
576 | struct sway_layer_popup *popup = wl_container_of(listener, popup, unmap); | ||
577 | popup_damage(popup, true); | ||
578 | } | ||
579 | |||
580 | static void popup_handle_commit(struct wl_listener *listener, void *data) { | 302 | static void popup_handle_commit(struct wl_listener *listener, void *data) { |
581 | struct sway_layer_popup *popup = wl_container_of(listener, popup, commit); | 303 | struct sway_layer_popup *popup = wl_container_of(listener, popup, commit); |
582 | if (popup->wlr_popup->base->initial_commit) { | 304 | if (popup->wlr_popup->base->initial_commit) { |
583 | popup_unconstrain(popup); | 305 | popup_unconstrain(popup); |
584 | } | 306 | } |
585 | popup_damage(popup, false); | ||
586 | } | ||
587 | |||
588 | static void popup_handle_destroy(struct wl_listener *listener, void *data) { | ||
589 | struct sway_layer_popup *popup = | ||
590 | wl_container_of(listener, popup, destroy); | ||
591 | |||
592 | wl_list_remove(&popup->map.link); | ||
593 | wl_list_remove(&popup->unmap.link); | ||
594 | wl_list_remove(&popup->destroy.link); | ||
595 | wl_list_remove(&popup->commit.link); | ||
596 | free(popup); | ||
597 | } | 307 | } |
598 | 308 | ||
599 | static void popup_handle_new_popup(struct wl_listener *listener, void *data); | 309 | static void popup_handle_new_popup(struct wl_listener *listener, void *data); |
600 | 310 | ||
601 | static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup, | 311 | static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup, |
602 | enum layer_parent parent_type, void *parent) { | 312 | struct sway_layer_surface *toplevel, struct wlr_scene_tree *parent) { |
603 | struct sway_layer_popup *popup = | 313 | struct sway_layer_popup *popup = calloc(1, sizeof(*popup)); |
604 | calloc(1, sizeof(struct sway_layer_popup)); | ||
605 | if (popup == NULL) { | 314 | if (popup == NULL) { |
606 | return NULL; | 315 | return NULL; |
607 | } | 316 | } |
608 | 317 | ||
318 | popup->toplevel = toplevel; | ||
609 | popup->wlr_popup = wlr_popup; | 319 | popup->wlr_popup = wlr_popup; |
610 | popup->parent_type = parent_type; | 320 | popup->scene = wlr_scene_xdg_surface_create(parent, |
611 | popup->parent_layer = parent; | 321 | wlr_popup->base); |
322 | |||
323 | if (!popup->scene) { | ||
324 | free(popup); | ||
325 | return NULL; | ||
326 | } | ||
612 | 327 | ||
613 | popup->map.notify = popup_handle_map; | ||
614 | wl_signal_add(&wlr_popup->base->surface->events.map, &popup->map); | ||
615 | popup->unmap.notify = popup_handle_unmap; | ||
616 | wl_signal_add(&wlr_popup->base->surface->events.unmap, &popup->unmap); | ||
617 | popup->destroy.notify = popup_handle_destroy; | 328 | popup->destroy.notify = popup_handle_destroy; |
618 | wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy); | 329 | wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy); |
619 | popup->commit.notify = popup_handle_commit; | ||
620 | wl_signal_add(&wlr_popup->base->surface->events.commit, &popup->commit); | ||
621 | popup->new_popup.notify = popup_handle_new_popup; | 330 | popup->new_popup.notify = popup_handle_new_popup; |
622 | wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup); | 331 | wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup); |
332 | popup->commit.notify = popup_handle_commit; | ||
333 | wl_signal_add(&wlr_popup->base->surface->events.commit, &popup->commit); | ||
623 | 334 | ||
624 | return popup; | 335 | return popup; |
625 | } | 336 | } |
@@ -628,19 +339,14 @@ static void popup_handle_new_popup(struct wl_listener *listener, void *data) { | |||
628 | struct sway_layer_popup *sway_layer_popup = | 339 | struct sway_layer_popup *sway_layer_popup = |
629 | wl_container_of(listener, sway_layer_popup, new_popup); | 340 | wl_container_of(listener, sway_layer_popup, new_popup); |
630 | struct wlr_xdg_popup *wlr_popup = data; | 341 | struct wlr_xdg_popup *wlr_popup = data; |
631 | create_popup(wlr_popup, LAYER_PARENT_POPUP, sway_layer_popup); | 342 | create_popup(wlr_popup, sway_layer_popup->toplevel, sway_layer_popup->scene); |
632 | } | 343 | } |
633 | 344 | ||
634 | static void handle_new_popup(struct wl_listener *listener, void *data) { | 345 | static void handle_new_popup(struct wl_listener *listener, void *data) { |
635 | struct sway_layer_surface *sway_layer_surface = | 346 | struct sway_layer_surface *sway_layer_surface = |
636 | wl_container_of(listener, sway_layer_surface, new_popup); | 347 | wl_container_of(listener, sway_layer_surface, new_popup); |
637 | struct wlr_xdg_popup *wlr_popup = data; | 348 | struct wlr_xdg_popup *wlr_popup = data; |
638 | create_popup(wlr_popup, LAYER_PARENT_LAYER, sway_layer_surface); | 349 | create_popup(wlr_popup, sway_layer_surface, sway_layer_surface->popups); |
639 | } | ||
640 | |||
641 | struct sway_layer_surface *layer_from_wlr_layer_surface_v1( | ||
642 | struct wlr_layer_surface_v1 *layer_surface) { | ||
643 | return layer_surface->data; | ||
644 | } | 350 | } |
645 | 351 | ||
646 | void handle_layer_shell_surface(struct wl_listener *listener, void *data) { | 352 | void handle_layer_shell_surface(struct wl_listener *listener, void *data) { |
@@ -672,10 +378,6 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { | |||
672 | sway_log(SWAY_ERROR, | 378 | sway_log(SWAY_ERROR, |
673 | "no output to auto-assign layer surface '%s' to", | 379 | "no output to auto-assign layer surface '%s' to", |
674 | layer_surface->namespace); | 380 | layer_surface->namespace); |
675 | // Note that layer_surface->output can be NULL | ||
676 | // here, but none of our destroy callbacks are | ||
677 | // registered yet so we don't have to make them | ||
678 | // handle that case. | ||
679 | wlr_layer_surface_v1_destroy(layer_surface); | 381 | wlr_layer_surface_v1_destroy(layer_surface); |
680 | return; | 382 | return; |
681 | } | 383 | } |
@@ -684,37 +386,51 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { | |||
684 | layer_surface->output = output->wlr_output; | 386 | layer_surface->output = output->wlr_output; |
685 | } | 387 | } |
686 | 388 | ||
687 | struct sway_layer_surface *sway_layer = | 389 | struct sway_output *output = layer_surface->output->data; |
688 | calloc(1, sizeof(struct sway_layer_surface)); | 390 | |
689 | if (!sway_layer) { | 391 | enum zwlr_layer_shell_v1_layer layer_type = layer_surface->pending.layer; |
392 | struct wlr_scene_tree *output_layer = sway_layer_get_scene( | ||
393 | output, layer_type); | ||
394 | struct wlr_scene_layer_surface_v1 *scene_surface = | ||
395 | wlr_scene_layer_surface_v1_create(output_layer, layer_surface); | ||
396 | if (!scene_surface) { | ||
397 | sway_log(SWAY_ERROR, "Could not allocate a layer_surface_v1"); | ||
690 | return; | 398 | return; |
691 | } | 399 | } |
692 | 400 | ||
693 | wl_list_init(&sway_layer->subsurfaces); | 401 | struct sway_layer_surface *surface = |
402 | sway_layer_surface_create(scene_surface); | ||
403 | if (!surface) { | ||
404 | wlr_layer_surface_v1_destroy(layer_surface); | ||
694 | 405 | ||
695 | sway_layer->surface_commit.notify = handle_surface_commit; | 406 | sway_log(SWAY_ERROR, "Could not allocate a sway_layer_surface"); |
696 | wl_signal_add(&layer_surface->surface->events.commit, | 407 | return; |
697 | &sway_layer->surface_commit); | 408 | } |
698 | |||
699 | sway_layer->destroy.notify = handle_destroy; | ||
700 | wl_signal_add(&layer_surface->events.destroy, &sway_layer->destroy); | ||
701 | sway_layer->map.notify = handle_map; | ||
702 | wl_signal_add(&layer_surface->surface->events.map, &sway_layer->map); | ||
703 | sway_layer->unmap.notify = handle_unmap; | ||
704 | wl_signal_add(&layer_surface->surface->events.unmap, &sway_layer->unmap); | ||
705 | sway_layer->new_popup.notify = handle_new_popup; | ||
706 | wl_signal_add(&layer_surface->events.new_popup, &sway_layer->new_popup); | ||
707 | sway_layer->new_subsurface.notify = handle_new_subsurface; | ||
708 | wl_signal_add(&layer_surface->surface->events.new_subsurface, | ||
709 | &sway_layer->new_subsurface); | ||
710 | |||
711 | sway_layer->layer_surface = layer_surface; | ||
712 | layer_surface->data = sway_layer; | ||
713 | 409 | ||
714 | struct sway_output *output = layer_surface->output->data; | 410 | if (!scene_descriptor_assign(&scene_surface->tree->node, |
715 | sway_layer->output_destroy.notify = handle_output_destroy; | 411 | SWAY_SCENE_DESC_LAYER_SHELL, surface)) { |
716 | wl_signal_add(&output->events.disable, &sway_layer->output_destroy); | 412 | sway_log(SWAY_ERROR, "Failed to allocate a layer surface descriptor"); |
413 | // destroying the layer_surface will also destroy its corresponding | ||
414 | // scene node | ||
415 | wlr_layer_surface_v1_destroy(layer_surface); | ||
416 | return; | ||
417 | } | ||
717 | 418 | ||
718 | wl_list_insert(&output->shell_layers[layer_surface->pending.layer], | 419 | surface->output = output; |
719 | &sway_layer->link); | 420 | |
421 | surface->surface_commit.notify = handle_surface_commit; | ||
422 | wl_signal_add(&layer_surface->surface->events.commit, | ||
423 | &surface->surface_commit); | ||
424 | surface->map.notify = handle_map; | ||
425 | wl_signal_add(&layer_surface->surface->events.map, &surface->map); | ||
426 | surface->unmap.notify = handle_unmap; | ||
427 | wl_signal_add(&layer_surface->surface->events.unmap, &surface->unmap); | ||
428 | surface->new_popup.notify = handle_new_popup; | ||
429 | wl_signal_add(&layer_surface->events.new_popup, &surface->new_popup); | ||
430 | |||
431 | surface->output_destroy.notify = handle_output_destroy; | ||
432 | wl_signal_add(&output->events.disable, &surface->output_destroy); | ||
433 | |||
434 | surface->node_destroy.notify = handle_node_destroy; | ||
435 | wl_signal_add(&scene_surface->tree->node.events.destroy, &surface->node_destroy); | ||
720 | } | 436 | } |
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 1e4474ce..942bc780 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -182,66 +182,6 @@ void output_view_for_each_popup_surface(struct sway_output *output, | |||
182 | view_for_each_popup_surface(view, output_for_each_surface_iterator, &data); | 182 | view_for_each_popup_surface(view, output_for_each_surface_iterator, &data); |
183 | } | 183 | } |
184 | 184 | ||
185 | void output_layer_for_each_surface(struct sway_output *output, | ||
186 | struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, | ||
187 | void *user_data) { | ||
188 | struct sway_layer_surface *layer_surface; | ||
189 | wl_list_for_each(layer_surface, layer_surfaces, link) { | ||
190 | struct wlr_layer_surface_v1 *wlr_layer_surface_v1 = | ||
191 | layer_surface->layer_surface; | ||
192 | struct wlr_surface *surface = wlr_layer_surface_v1->surface; | ||
193 | struct surface_iterator_data data = { | ||
194 | .user_iterator = iterator, | ||
195 | .user_data = user_data, | ||
196 | .output = output, | ||
197 | .view = NULL, | ||
198 | .ox = layer_surface->geo.x, | ||
199 | .oy = layer_surface->geo.y, | ||
200 | .width = surface->current.width, | ||
201 | .height = surface->current.height, | ||
202 | }; | ||
203 | wlr_layer_surface_v1_for_each_surface(wlr_layer_surface_v1, | ||
204 | output_for_each_surface_iterator, &data); | ||
205 | } | ||
206 | } | ||
207 | |||
208 | void output_layer_for_each_toplevel_surface(struct sway_output *output, | ||
209 | struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, | ||
210 | void *user_data) { | ||
211 | struct sway_layer_surface *layer_surface; | ||
212 | wl_list_for_each(layer_surface, layer_surfaces, link) { | ||
213 | struct wlr_layer_surface_v1 *wlr_layer_surface_v1 = | ||
214 | layer_surface->layer_surface; | ||
215 | output_surface_for_each_surface(output, wlr_layer_surface_v1->surface, | ||
216 | layer_surface->geo.x, layer_surface->geo.y, iterator, | ||
217 | user_data); | ||
218 | } | ||
219 | } | ||
220 | |||
221 | |||
222 | void output_layer_for_each_popup_surface(struct sway_output *output, | ||
223 | struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, | ||
224 | void *user_data) { | ||
225 | struct sway_layer_surface *layer_surface; | ||
226 | wl_list_for_each(layer_surface, layer_surfaces, link) { | ||
227 | struct wlr_layer_surface_v1 *wlr_layer_surface_v1 = | ||
228 | layer_surface->layer_surface; | ||
229 | struct wlr_surface *surface = wlr_layer_surface_v1->surface; | ||
230 | struct surface_iterator_data data = { | ||
231 | .user_iterator = iterator, | ||
232 | .user_data = user_data, | ||
233 | .output = output, | ||
234 | .view = NULL, | ||
235 | .ox = layer_surface->geo.x, | ||
236 | .oy = layer_surface->geo.y, | ||
237 | .width = surface->current.width, | ||
238 | .height = surface->current.height, | ||
239 | }; | ||
240 | wlr_layer_surface_v1_for_each_popup_surface(wlr_layer_surface_v1, | ||
241 | output_for_each_surface_iterator, &data); | ||
242 | } | ||
243 | } | ||
244 | |||
245 | #if HAVE_XWAYLAND | 185 | #if HAVE_XWAYLAND |
246 | void output_unmanaged_for_each_surface(struct sway_output *output, | 186 | void output_unmanaged_for_each_surface(struct sway_output *output, |
247 | struct wl_list *unmanaged, sway_surface_iterator_func_t iterator, | 187 | struct wl_list *unmanaged, sway_surface_iterator_func_t iterator, |
@@ -282,31 +222,6 @@ struct sway_workspace *output_get_active_workspace(struct sway_output *output) { | |||
282 | return focus->sway_workspace; | 222 | return focus->sway_workspace; |
283 | } | 223 | } |
284 | 224 | ||
285 | bool output_has_opaque_overlay_layer_surface(struct sway_output *output) { | ||
286 | struct sway_layer_surface *sway_layer_surface; | ||
287 | wl_list_for_each(sway_layer_surface, | ||
288 | &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], link) { | ||
289 | struct wlr_surface *wlr_surface = sway_layer_surface->layer_surface->surface; | ||
290 | pixman_box32_t output_box = { | ||
291 | .x2 = output->width, | ||
292 | .y2 = output->height, | ||
293 | }; | ||
294 | pixman_region32_t surface_opaque_box; | ||
295 | pixman_region32_init(&surface_opaque_box); | ||
296 | pixman_region32_copy(&surface_opaque_box, &wlr_surface->opaque_region); | ||
297 | pixman_region32_translate(&surface_opaque_box, | ||
298 | sway_layer_surface->geo.x, sway_layer_surface->geo.y); | ||
299 | pixman_region_overlap_t contains = | ||
300 | pixman_region32_contains_rectangle(&surface_opaque_box, &output_box); | ||
301 | pixman_region32_fini(&surface_opaque_box); | ||
302 | |||
303 | if (contains == PIXMAN_REGION_IN) { | ||
304 | return true; | ||
305 | } | ||
306 | } | ||
307 | return false; | ||
308 | } | ||
309 | |||
310 | struct send_frame_done_data { | 225 | struct send_frame_done_data { |
311 | struct timespec when; | 226 | struct timespec when; |
312 | int msec_until_refresh; | 227 | int msec_until_refresh; |
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 79373e40..30df76f4 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -94,6 +94,12 @@ struct sway_node *node_at_coords( | |||
94 | } | 94 | } |
95 | } | 95 | } |
96 | 96 | ||
97 | if (scene_descriptor_try_get(current, SWAY_SCENE_DESC_LAYER_SHELL)) { | ||
98 | // We don't want to feed through the current workspace on | ||
99 | // layer shells | ||
100 | return NULL; | ||
101 | } | ||
102 | |||
97 | if (!current->parent) { | 103 | if (!current->parent) { |
98 | break; | 104 | break; |
99 | } | 105 | } |
diff --git a/sway/tree/output.c b/sway/tree/output.c index 64ca3d75..3c8823dc 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c | |||
@@ -93,8 +93,12 @@ static void destroy_scene_layers(struct sway_output *output) { | |||
93 | scene_node_disown_children(output->layers.tiling); | 93 | scene_node_disown_children(output->layers.tiling); |
94 | scene_node_disown_children(output->layers.fullscreen); | 94 | scene_node_disown_children(output->layers.fullscreen); |
95 | 95 | ||
96 | wlr_scene_node_destroy(&output->layers.shell_background->node); | ||
97 | wlr_scene_node_destroy(&output->layers.shell_bottom->node); | ||
96 | wlr_scene_node_destroy(&output->layers.tiling->node); | 98 | wlr_scene_node_destroy(&output->layers.tiling->node); |
97 | wlr_scene_node_destroy(&output->layers.fullscreen->node); | 99 | wlr_scene_node_destroy(&output->layers.fullscreen->node); |
100 | wlr_scene_node_destroy(&output->layers.shell_top->node); | ||
101 | wlr_scene_node_destroy(&output->layers.shell_overlay->node); | ||
98 | wlr_scene_node_destroy(&output->layers.session_lock->node); | 102 | wlr_scene_node_destroy(&output->layers.session_lock->node); |
99 | } | 103 | } |
100 | 104 | ||
@@ -103,8 +107,12 @@ struct sway_output *output_create(struct wlr_output *wlr_output) { | |||
103 | node_init(&output->node, N_OUTPUT, output); | 107 | node_init(&output->node, N_OUTPUT, output); |
104 | 108 | ||
105 | bool failed = false; | 109 | bool failed = false; |
110 | output->layers.shell_background = alloc_scene_tree(root->staging, &failed); | ||
111 | output->layers.shell_bottom = alloc_scene_tree(root->staging, &failed); | ||
106 | output->layers.tiling = alloc_scene_tree(root->staging, &failed); | 112 | output->layers.tiling = alloc_scene_tree(root->staging, &failed); |
107 | output->layers.fullscreen = alloc_scene_tree(root->staging, &failed); | 113 | output->layers.fullscreen = alloc_scene_tree(root->staging, &failed); |
114 | output->layers.shell_top = alloc_scene_tree(root->staging, &failed); | ||
115 | output->layers.shell_overlay = alloc_scene_tree(root->staging, &failed); | ||
108 | output->layers.session_lock = alloc_scene_tree(root->staging, &failed); | 116 | output->layers.session_lock = alloc_scene_tree(root->staging, &failed); |
109 | 117 | ||
110 | if (!failed) { | 118 | if (!failed) { |
@@ -136,11 +144,6 @@ struct sway_output *output_create(struct wlr_output *wlr_output) { | |||
136 | output->workspaces = create_list(); | 144 | output->workspaces = create_list(); |
137 | output->current.workspaces = create_list(); | 145 | output->current.workspaces = create_list(); |
138 | 146 | ||
139 | size_t len = sizeof(output->shell_layers) / sizeof(output->shell_layers[0]); | ||
140 | for (size_t i = 0; i < len; ++i) { | ||
141 | wl_list_init(&output->shell_layers[i]); | ||
142 | } | ||
143 | |||
144 | return output; | 147 | return output; |
145 | } | 148 | } |
146 | 149 | ||
diff --git a/sway/tree/root.c b/sway/tree/root.c index fbdd9a96..7c8f9ea6 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c | |||
@@ -47,10 +47,15 @@ struct sway_root *root_create(struct wl_display *wl_display) { | |||
47 | root->staging = alloc_scene_tree(&root_scene->tree, &failed); | 47 | root->staging = alloc_scene_tree(&root_scene->tree, &failed); |
48 | root->layer_tree = alloc_scene_tree(&root_scene->tree, &failed); | 48 | root->layer_tree = alloc_scene_tree(&root_scene->tree, &failed); |
49 | 49 | ||
50 | root->layers.shell_background = alloc_scene_tree(root->layer_tree, &failed); | ||
51 | root->layers.shell_bottom = alloc_scene_tree(root->layer_tree, &failed); | ||
50 | root->layers.tiling = alloc_scene_tree(root->layer_tree, &failed); | 52 | root->layers.tiling = alloc_scene_tree(root->layer_tree, &failed); |
51 | root->layers.floating = alloc_scene_tree(root->layer_tree, &failed); | 53 | root->layers.floating = alloc_scene_tree(root->layer_tree, &failed); |
54 | root->layers.shell_top = alloc_scene_tree(root->layer_tree, &failed); | ||
52 | root->layers.fullscreen = alloc_scene_tree(root->layer_tree, &failed); | 55 | root->layers.fullscreen = alloc_scene_tree(root->layer_tree, &failed); |
53 | root->layers.fullscreen_global = alloc_scene_tree(root->layer_tree, &failed); | 56 | root->layers.fullscreen_global = alloc_scene_tree(root->layer_tree, &failed); |
57 | root->layers.shell_overlay = alloc_scene_tree(root->layer_tree, &failed); | ||
58 | root->layers.popup = alloc_scene_tree(root->layer_tree, &failed); | ||
54 | root->layers.seat = alloc_scene_tree(root->layer_tree, &failed); | 59 | root->layers.seat = alloc_scene_tree(root->layer_tree, &failed); |
55 | root->layers.session_lock = alloc_scene_tree(root->layer_tree, &failed); | 60 | root->layers.session_lock = alloc_scene_tree(root->layer_tree, &failed); |
56 | 61 | ||