aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Alexander Orzechowski <alex@ozal.ski>2024-01-18 10:04:51 -0500
committerLibravatar Kirill Primak <vyivel@eclair.cafe>2024-01-18 18:36:54 +0300
commit188811f80861caacd016b857b0d07f6d2d62d15a (patch)
treedc68ea00b707b25ce398c71fe1ad996f0eb820ea
parentinput: Query scene graph for relevant surface/node intersections (diff)
downloadsway-188811f80861caacd016b857b0d07f6d2d62d15a.tar.gz
sway-188811f80861caacd016b857b0d07f6d2d62d15a.tar.zst
sway-188811f80861caacd016b857b0d07f6d2d62d15a.zip
scene_graph: Port layer_shell
-rw-r--r--include/sway/layers.h44
-rw-r--r--include/sway/output.h19
-rw-r--r--include/sway/scene_descriptor.h1
-rw-r--r--include/sway/tree/root.h5
-rw-r--r--sway/desktop/layer_shell.c720
-rw-r--r--sway/desktop/output.c85
-rw-r--r--sway/input/cursor.c6
-rw-r--r--sway/tree/output.c13
-rw-r--r--sway/tree/root.c5
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
7enum layer_parent {
8 LAYER_PARENT_LAYER,
9 LAYER_PARENT_POPUP,
10};
11
12struct sway_layer_surface { 7struct 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
32struct sway_layer_popup { 24struct 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
46struct 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
62void arrange_layers(struct sway_output *output); 39void arrange_layers(struct sway_output *output);
63 40
64struct 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
125void output_disable(struct sway_output *output); 128void output_disable(struct sway_output *output);
126 129
127bool output_has_opaque_overlay_layer_surface(struct sway_output *output);
128
129struct sway_workspace *output_get_active_workspace(struct sway_output *output); 130struct sway_workspace *output_get_active_workspace(struct sway_output *output);
130 131
131void output_surface_for_each_surface(struct sway_output *output, 132void 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
143void 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
147void 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
151void 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
156void output_unmanaged_for_each_surface(struct sway_output *output, 145void 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
20struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface( 22struct 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
53static void apply_exclusive(struct wlr_box *usable_area, 55static 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
126static 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 92static 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); 109static 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
281static struct sway_layer_surface *find_mapped_layer_by_client( 132static 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
302static void handle_output_destroy(struct wl_listener *listener, void *data) { 156static 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
164static 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
322static void handle_surface_commit(struct wl_listener *listener, void *data) { 201static 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
372static void layer_subsurface_destroy(struct sway_layer_subsurface *subsurface); 229static void handle_map(struct wl_listener *listener, void *data) {
373 230 struct sway_layer_surface *surface = wl_container_of(listener,
374static 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
404static 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
415static void handle_unmap(struct wl_listener *listener, void *data) { 254static 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
434static 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
446static void subsurface_handle_unmap(struct wl_listener *listener, void *data) { 267static 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
452static 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
458static 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
464static 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
473static 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
480static 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
505static 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
513static 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
521static 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
546static void popup_unconstrain(struct sway_layer_popup *popup) { 277static 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
566static 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
575static 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
580static void popup_handle_commit(struct wl_listener *listener, void *data) { 302static 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
588static 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
599static void popup_handle_new_popup(struct wl_listener *listener, void *data); 309static void popup_handle_new_popup(struct wl_listener *listener, void *data);
600 310
601static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup, 311static 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
634static void handle_new_popup(struct wl_listener *listener, void *data) { 345static 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
641struct 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
646void handle_layer_shell_surface(struct wl_listener *listener, void *data) { 352void 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
185void 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
208void 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
222void 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
246void output_unmanaged_for_each_surface(struct sway_output *output, 186void 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
285bool 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
310struct send_frame_done_data { 225struct 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