aboutsummaryrefslogtreecommitdiffstats
path: root/sway/desktop/layer_shell.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/desktop/layer_shell.c')
-rw-r--r--sway/desktop/layer_shell.c778
1 files changed, 279 insertions, 499 deletions
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c
index cadc702a..4b2584b6 100644
--- a/sway/desktop/layer_shell.c
+++ b/sway/desktop/layer_shell.c
@@ -3,9 +3,12 @@
3#include <string.h> 3#include <string.h>
4#include <wayland-server-core.h> 4#include <wayland-server-core.h>
5#include <wlr/types/wlr_layer_shell_v1.h> 5#include <wlr/types/wlr_layer_shell_v1.h>
6#include <wlr/types/wlr_output_damage.h>
7#include <wlr/types/wlr_output.h> 6#include <wlr/types/wlr_output.h>
7#include <wlr/types/wlr_scene.h>
8#include <wlr/types/wlr_subcompositor.h>
9#include <wlr/types/wlr_xdg_shell.h>
8#include "log.h" 10#include "log.h"
11#include "sway/scene_descriptor.h"
9#include "sway/desktop/transaction.h" 12#include "sway/desktop/transaction.h"
10#include "sway/input/cursor.h" 13#include "sway/input/cursor.h"
11#include "sway/input/input-manager.h" 14#include "sway/input/input-manager.h"
@@ -16,163 +19,55 @@
16#include "sway/tree/arrange.h" 19#include "sway/tree/arrange.h"
17#include "sway/tree/workspace.h" 20#include "sway/tree/workspace.h"
18 21
19static void apply_exclusive(struct wlr_box *usable_area, 22struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface(
20 uint32_t anchor, int32_t exclusive, 23 struct wlr_surface *surface) {
21 int32_t margin_top, int32_t margin_right, 24 struct wlr_layer_surface_v1 *layer;
22 int32_t margin_bottom, int32_t margin_left) { 25 do {
23 if (exclusive <= 0) { 26 if (!surface) {
24 return; 27 return NULL;
25 } 28 }
26 struct { 29 // Topmost layer surface
27 uint32_t singular_anchor; 30 if ((layer = wlr_layer_surface_v1_try_from_wlr_surface(surface))) {
28 uint32_t anchor_triplet; 31 return layer;
29 int *positive_axis; 32 }
30 int *negative_axis; 33 // Layer subsurface
31 int margin; 34 if (wlr_subsurface_try_from_wlr_surface(surface)) {
32 } edges[] = { 35 surface = wlr_surface_get_root_surface(surface);
33 // Top 36 continue;
34 { 37 }
35 .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP, 38
36 .anchor_triplet = 39 // Layer surface popup
37 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | 40 struct wlr_xdg_surface *xdg_surface = NULL;
38 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | 41 if ((xdg_surface = wlr_xdg_surface_try_from_wlr_surface(surface)) &&
39 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP, 42 xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP && xdg_surface->popup != NULL) {
40 .positive_axis = &usable_area->y, 43 if (!xdg_surface->popup->parent) {
41 .negative_axis = &usable_area->height, 44 return NULL;
42 .margin = margin_top,
43 },
44 // Bottom
45 {
46 .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
47 .anchor_triplet =
48 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
49 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
50 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
51 .positive_axis = NULL,
52 .negative_axis = &usable_area->height,
53 .margin = margin_bottom,
54 },
55 // Left
56 {
57 .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT,
58 .anchor_triplet =
59 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
60 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
61 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
62 .positive_axis = &usable_area->x,
63 .negative_axis = &usable_area->width,
64 .margin = margin_left,
65 },
66 // Right
67 {
68 .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT,
69 .anchor_triplet =
70 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
71 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
72 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
73 .positive_axis = NULL,
74 .negative_axis = &usable_area->width,
75 .margin = margin_right,
76 },
77 };
78 for (size_t i = 0; i < sizeof(edges) / sizeof(edges[0]); ++i) {
79 if ((anchor == edges[i].singular_anchor || anchor == edges[i].anchor_triplet)
80 && exclusive + edges[i].margin > 0) {
81 if (edges[i].positive_axis) {
82 *edges[i].positive_axis += exclusive + edges[i].margin;
83 }
84 if (edges[i].negative_axis) {
85 *edges[i].negative_axis -= exclusive + edges[i].margin;
86 } 45 }
87 break; 46 surface = wlr_surface_get_root_surface(xdg_surface->popup->parent);
47 continue;
88 } 48 }
89 } 49
50 // Return early if the surface is not a layer/xdg_popup/sub surface
51 return NULL;
52 } while (true);
90} 53}
91 54
92static void arrange_layer(struct sway_output *output, struct wl_list *list, 55static void arrange_surface(struct sway_output *output, const struct wlr_box *full_area,
93 struct wlr_box *usable_area, bool exclusive) { 56 struct wlr_box *usable_area, struct wlr_scene_tree *tree) {
94 struct sway_layer_surface *sway_layer; 57 struct wlr_scene_node *node;
95 struct wlr_box full_area = { 0 }; 58 wl_list_for_each(node, &tree->children, link) {
96 wlr_output_effective_resolution(output->wlr_output, 59 struct sway_layer_surface *surface = scene_descriptor_try_get(node,
97 &full_area.width, &full_area.height); 60 SWAY_SCENE_DESC_LAYER_SHELL);
98 wl_list_for_each(sway_layer, list, link) { 61 // surface could be null during destruction
99 struct wlr_layer_surface_v1 *layer = sway_layer->layer_surface; 62 if (!surface) {
100 struct wlr_layer_surface_v1_state *state = &layer->current;
101 if (exclusive != (state->exclusive_zone > 0)) {
102 continue; 63 continue;
103 } 64 }
104 struct wlr_box bounds; 65
105 if (state->exclusive_zone == -1) { 66 if (!surface->scene->layer_surface->initialized) {
106 bounds = full_area;
107 } else {
108 bounds = *usable_area;
109 }
110 struct wlr_box box = {
111 .width = state->desired_width,
112 .height = state->desired_height
113 };
114 // Horizontal axis
115 const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
116 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
117 if (box.width == 0) {
118 box.x = bounds.x;
119 } else if ((state->anchor & both_horiz) == both_horiz) {
120 box.x = bounds.x + ((bounds.width / 2) - (box.width / 2));
121 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
122 box.x = bounds.x;
123 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
124 box.x = bounds.x + (bounds.width - box.width);
125 } else {
126 box.x = bounds.x + ((bounds.width / 2) - (box.width / 2));
127 }
128 // Vertical axis
129 const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP
130 | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
131 if (box.height == 0) {
132 box.y = bounds.y;
133 } else if ((state->anchor & both_vert) == both_vert) {
134 box.y = bounds.y + ((bounds.height / 2) - (box.height / 2));
135 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
136 box.y = bounds.y;
137 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
138 box.y = bounds.y + (bounds.height - box.height);
139 } else {
140 box.y = bounds.y + ((bounds.height / 2) - (box.height / 2));
141 }
142 // Margin
143 if (box.width == 0) {
144 box.x += state->margin.left;
145 box.width = bounds.width -
146 (state->margin.left + state->margin.right);
147 } else if ((state->anchor & both_horiz) == both_horiz) {
148 // don't apply margins
149 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
150 box.x += state->margin.left;
151 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
152 box.x -= state->margin.right;
153 }
154 if (box.height == 0) {
155 box.y += state->margin.top;
156 box.height = bounds.height -
157 (state->margin.top + state->margin.bottom);
158 } else if ((state->anchor & both_vert) == both_vert) {
159 // don't apply margins
160 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
161 box.y += state->margin.top;
162 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
163 box.y -= state->margin.bottom;
164 }
165 if (box.width < 0 || box.height < 0) {
166 // TODO: Bubble up a protocol error?
167 wlr_layer_surface_v1_close(layer);
168 continue; 67 continue;
169 } 68 }
170 // Apply 69
171 sway_layer->geo = box; 70 wlr_scene_layer_surface_v1_configure(surface->scene, full_area, usable_area);
172 apply_exclusive(usable_area, state->anchor, state->exclusive_zone,
173 state->margin.top, state->margin.right,
174 state->margin.bottom, state->margin.left);
175 wlr_layer_surface_v1_configure(layer, box.width, box.height);
176 } 71 }
177} 72}
178 73
@@ -180,81 +75,94 @@ void arrange_layers(struct sway_output *output) {
180 struct wlr_box usable_area = { 0 }; 75 struct wlr_box usable_area = { 0 };
181 wlr_output_effective_resolution(output->wlr_output, 76 wlr_output_effective_resolution(output->wlr_output,
182 &usable_area.width, &usable_area.height); 77 &usable_area.width, &usable_area.height);
78 const struct wlr_box full_area = usable_area;
79
80 arrange_surface(output, &full_area, &usable_area, output->layers.shell_background);
81 arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom);
82 arrange_surface(output, &full_area, &usable_area, output->layers.shell_top);
83 arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay);
183 84
184 // Arrange exclusive surfaces from top->bottom 85 if (!wlr_box_equal(&usable_area, &output->usable_area)) {
185 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
186 &usable_area, true);
187 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
188 &usable_area, true);
189 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
190 &usable_area, true);
191 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
192 &usable_area, true);
193
194 if (memcmp(&usable_area, &output->usable_area,
195 sizeof(struct wlr_box)) != 0) {
196 sway_log(SWAY_DEBUG, "Usable area changed, rearranging output"); 86 sway_log(SWAY_DEBUG, "Usable area changed, rearranging output");
197 memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); 87 output->usable_area = usable_area;
198 arrange_output(output); 88 arrange_output(output);
89 } else {
90 arrange_popups(root->layers.popup);
199 } 91 }
92}
200 93
201 // Arrange non-exclusive surfaces from top->bottom 94static struct wlr_scene_tree *sway_layer_get_scene(struct sway_output *output,
202 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], 95 enum zwlr_layer_shell_v1_layer type) {
203 &usable_area, false); 96 switch (type) {
204 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], 97 case ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND:
205 &usable_area, false); 98 return output->layers.shell_background;
206 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], 99 case ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM:
207 &usable_area, false); 100 return output->layers.shell_bottom;
208 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], 101 case ZWLR_LAYER_SHELL_V1_LAYER_TOP:
209 &usable_area, false); 102 return output->layers.shell_top;
210 103 case ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY:
211 // Find topmost keyboard interactive layer, if such a layer exists 104 return output->layers.shell_overlay;
212 uint32_t layers_above_shell[] = {
213 ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY,
214 ZWLR_LAYER_SHELL_V1_LAYER_TOP,
215 };
216 size_t nlayers = sizeof(layers_above_shell) / sizeof(layers_above_shell[0]);
217 struct sway_layer_surface *layer, *topmost = NULL;
218 for (size_t i = 0; i < nlayers; ++i) {
219 wl_list_for_each_reverse(layer,
220 &output->layers[layers_above_shell[i]], link) {
221 if (layer->layer_surface->current.keyboard_interactive &&
222 layer->layer_surface->mapped) {
223 topmost = layer;
224 break;
225 }
226 }
227 if (topmost != NULL) {
228 break;
229 }
230 } 105 }
231 106
232 struct sway_seat *seat; 107 sway_assert(false, "unreachable");
233 wl_list_for_each(seat, &server.input->seats, link) { 108 return NULL;
234 if (topmost != NULL) { 109}
235 seat_set_focus_layer(seat, topmost->layer_surface); 110
236 } else if (seat->focused_layer && 111static struct sway_layer_surface *sway_layer_surface_create(
237 !seat->focused_layer->current.keyboard_interactive) { 112 struct wlr_scene_layer_surface_v1 *scene) {
238 seat_set_focus_layer(seat, NULL); 113 struct sway_layer_surface *surface = calloc(1, sizeof(*surface));
239 } 114 if (!surface) {
115 sway_log(SWAY_ERROR, "Could not allocate a scene_layer surface");
116 return NULL;
240 } 117 }
118
119 struct wlr_scene_tree *popups = wlr_scene_tree_create(root->layers.popup);
120 if (!popups) {
121 sway_log(SWAY_ERROR, "Could not allocate a scene_layer popup node");
122 free(surface);
123 return NULL;
124 }
125
126 surface->desc.relative = &scene->tree->node;
127
128 if (!scene_descriptor_assign(&popups->node,
129 SWAY_SCENE_DESC_POPUP, &surface->desc)) {
130 sway_log(SWAY_ERROR, "Failed to allocate a popup scene descriptor");
131 wlr_scene_node_destroy(&popups->node);
132 free(surface);
133 return NULL;
134 }
135
136 surface->tree = scene->tree;
137 surface->scene = scene;
138 surface->layer_surface = scene->layer_surface;
139 surface->popups = popups;
140 surface->layer_surface->data = surface;
141
142 return surface;
241} 143}
242 144
243static struct sway_layer_surface *find_mapped_layer_by_client( 145static struct sway_layer_surface *find_mapped_layer_by_client(
244 struct wl_client *client, struct wlr_output *ignore_output) { 146 struct wl_client *client, struct sway_output *ignore_output) {
245 for (int i = 0; i < root->outputs->length; ++i) { 147 for (int i = 0; i < root->outputs->length; ++i) {
246 struct sway_output *output = root->outputs->items[i]; 148 struct sway_output *output = root->outputs->items[i];
247 if (output->wlr_output == ignore_output) { 149 if (output == ignore_output) {
248 continue; 150 continue;
249 } 151 }
250 // For now we'll only check the overlay layer 152 // For now we'll only check the overlay layer
251 struct sway_layer_surface *lsurface; 153 struct wlr_scene_node *node;
252 wl_list_for_each(lsurface, 154 wl_list_for_each (node, &output->layers.shell_overlay->children, link) {
253 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], link) { 155 struct sway_layer_surface *surface = scene_descriptor_try_get(node,
254 struct wl_resource *resource = lsurface->layer_surface->resource; 156 SWAY_SCENE_DESC_LAYER_SHELL);
157 if (!surface) {
158 continue;
159 }
160
161 struct wlr_layer_surface_v1 *layer_surface = surface->layer_surface;
162 struct wl_resource *resource = layer_surface->resource;
255 if (wl_resource_get_client(resource) == client 163 if (wl_resource_get_client(resource) == client
256 && lsurface->layer_surface->mapped) { 164 && layer_surface->surface->mapped) {
257 return lsurface; 165 return surface;
258 } 166 }
259 } 167 }
260 } 168 }
@@ -262,280 +170,142 @@ static struct sway_layer_surface *find_mapped_layer_by_client(
262} 170}
263 171
264static void handle_output_destroy(struct wl_listener *listener, void *data) { 172static void handle_output_destroy(struct wl_listener *listener, void *data) {
265 struct sway_layer_surface *sway_layer = 173 struct sway_layer_surface *layer =
266 wl_container_of(listener, sway_layer, output_destroy); 174 wl_container_of(listener, layer, output_destroy);
267 // Determine if this layer is being used by an exclusive client. If it is,
268 // try and find another layer owned by this client to pass focus to.
269 struct sway_seat *seat = input_manager_get_default_seat();
270 struct wl_client *client =
271 wl_resource_get_client(sway_layer->layer_surface->resource);
272 bool set_focus = seat->exclusive_client == client;
273
274 wl_list_remove(&sway_layer->output_destroy.link);
275 wl_list_remove(&sway_layer->link);
276 wl_list_init(&sway_layer->link);
277
278 if (set_focus) {
279 struct sway_layer_surface *layer =
280 find_mapped_layer_by_client(client, sway_layer->layer_surface->output);
281 if (layer) {
282 seat_set_focus_layer(seat, layer->layer_surface);
283 }
284 }
285 175
286 sway_layer->layer_surface->output = NULL; 176 layer->output = NULL;
287 wlr_layer_surface_v1_close(sway_layer->layer_surface); 177 wlr_scene_node_destroy(&layer->scene->tree->node);
288} 178}
289 179
290static void handle_surface_commit(struct wl_listener *listener, void *data) { 180static void handle_node_destroy(struct wl_listener *listener, void *data) {
291 struct sway_layer_surface *layer = 181 struct sway_layer_surface *layer =
292 wl_container_of(listener, layer, surface_commit); 182 wl_container_of(listener, layer, node_destroy);
293 struct wlr_layer_surface_v1 *layer_surface = layer->layer_surface;
294 struct wlr_output *wlr_output = layer_surface->output;
295 if (wlr_output == NULL) {
296 return;
297 }
298 183
299 struct sway_output *output = wlr_output->data; 184 // destroy the scene descriptor straight away if it exists, otherwise
300 struct wlr_box old_geo = layer->geo; 185 // we will try to reflow still considering the destroyed node.
301 arrange_layers(output); 186 scene_descriptor_destroy(&layer->tree->node, SWAY_SCENE_DESC_LAYER_SHELL);
302
303 bool geo_changed =
304 memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0;
305 bool layer_changed = layer->layer != layer_surface->current.layer;
306 if (layer_changed) {
307 wl_list_remove(&layer->link);
308 wl_list_insert(&output->layers[layer_surface->current.layer],
309 &layer->link);
310 layer->layer = layer_surface->current.layer;
311 }
312 if (geo_changed || layer_changed) {
313 output_damage_surface(output, old_geo.x, old_geo.y,
314 layer_surface->surface, true);
315 output_damage_surface(output, layer->geo.x, layer->geo.y,
316 layer_surface->surface, true);
317 } else {
318 output_damage_surface(output, layer->geo.x, layer->geo.y,
319 layer_surface->surface, false);
320 }
321
322 transaction_commit_dirty();
323}
324 187
325static void unmap(struct sway_layer_surface *sway_layer) { 188 // Determine if this layer is being used by an exclusive client. If it is,
326 struct sway_seat *seat; 189 // try and find another layer owned by this client to pass focus to.
327 wl_list_for_each(seat, &server.input->seats, link) { 190 struct sway_seat *seat = input_manager_get_default_seat();
328 if (seat->focused_layer == sway_layer->layer_surface) { 191 struct wl_client *client =
329 seat_set_focus_layer(seat, NULL); 192 wl_resource_get_client(layer->layer_surface->resource);
193 if (!server.session_lock.lock) {
194 struct sway_layer_surface *consider_layer =
195 find_mapped_layer_by_client(client, layer->output);
196 if (consider_layer) {
197 seat_set_focus_layer(seat, consider_layer->layer_surface);
330 } 198 }
331 } 199 }
332 200
333 cursor_rebase_all(); 201 if (layer->output) {
334 202 arrange_layers(layer->output);
335 struct wlr_output *wlr_output = sway_layer->layer_surface->output; 203 transaction_commit_dirty();
336 if (wlr_output == NULL) {
337 return;
338 }
339 struct sway_output *output = wlr_output->data;
340 if (output == NULL) {
341 return;
342 }
343 output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y,
344 sway_layer->layer_surface->surface, true);
345}
346
347static void handle_destroy(struct wl_listener *listener, void *data) {
348 struct sway_layer_surface *sway_layer =
349 wl_container_of(listener, sway_layer, destroy);
350 sway_log(SWAY_DEBUG, "Layer surface destroyed (%s)",
351 sway_layer->layer_surface->namespace);
352 if (sway_layer->layer_surface->mapped) {
353 unmap(sway_layer);
354 } 204 }
355 wl_list_remove(&sway_layer->link);
356 wl_list_remove(&sway_layer->destroy.link);
357 wl_list_remove(&sway_layer->map.link);
358 wl_list_remove(&sway_layer->unmap.link);
359 wl_list_remove(&sway_layer->surface_commit.link);
360 wl_list_remove(&sway_layer->new_popup.link);
361 wl_list_remove(&sway_layer->new_subsurface.link);
362 if (sway_layer->layer_surface->output != NULL) {
363 struct sway_output *output = sway_layer->layer_surface->output->data;
364 if (output != NULL) {
365 arrange_layers(output);
366 transaction_commit_dirty();
367 }
368 wl_list_remove(&sway_layer->output_destroy.link);
369 sway_layer->layer_surface->output = NULL;
370 }
371 free(sway_layer);
372}
373 205
374static void handle_map(struct wl_listener *listener, void *data) { 206 wlr_scene_node_destroy(&layer->popups->node);
375 struct sway_layer_surface *sway_layer = wl_container_of(listener,
376 sway_layer, map);
377 struct sway_output *output = sway_layer->layer_surface->output->data;
378 output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y,
379 sway_layer->layer_surface->surface, true);
380 wlr_surface_send_enter(sway_layer->layer_surface->surface,
381 sway_layer->layer_surface->output);
382 cursor_rebase_all();
383}
384 207
385static void handle_unmap(struct wl_listener *listener, void *data) { 208 wl_list_remove(&layer->map.link);
386 struct sway_layer_surface *sway_layer = wl_container_of( 209 wl_list_remove(&layer->unmap.link);
387 listener, sway_layer, unmap); 210 wl_list_remove(&layer->surface_commit.link);
388 unmap(sway_layer); 211 wl_list_remove(&layer->node_destroy.link);
389} 212 wl_list_remove(&layer->output_destroy.link);
390 213
391static void subsurface_damage(struct sway_layer_subsurface *subsurface, 214 layer->layer_surface->data = NULL;
392 bool whole) {
393 struct sway_layer_surface *layer = subsurface->layer_surface;
394 struct wlr_output *wlr_output = layer->layer_surface->output;
395 if (!wlr_output) {
396 return;
397 }
398 struct sway_output *output = wlr_output->data;
399 int ox = subsurface->wlr_subsurface->current.x + layer->geo.x;
400 int oy = subsurface->wlr_subsurface->current.y + layer->geo.y;
401 output_damage_surface(
402 output, ox, oy, subsurface->wlr_subsurface->surface, whole);
403}
404
405static void subsurface_handle_unmap(struct wl_listener *listener, void *data) {
406 struct sway_layer_subsurface *subsurface =
407 wl_container_of(listener, subsurface, unmap);
408 subsurface_damage(subsurface, true);
409}
410 215
411static void subsurface_handle_map(struct wl_listener *listener, void *data) { 216 free(layer);
412 struct sway_layer_subsurface *subsurface =
413 wl_container_of(listener, subsurface, map);
414 subsurface_damage(subsurface, true);
415} 217}
416 218
417static void subsurface_handle_commit(struct wl_listener *listener, void *data) { 219static void handle_surface_commit(struct wl_listener *listener, void *data) {
418 struct sway_layer_subsurface *subsurface = 220 struct sway_layer_surface *surface =
419 wl_container_of(listener, subsurface, commit); 221 wl_container_of(listener, surface, surface_commit);
420 subsurface_damage(subsurface, false);
421}
422
423static void subsurface_handle_destroy(struct wl_listener *listener,
424 void *data) {
425 struct sway_layer_subsurface *subsurface =
426 wl_container_of(listener, subsurface, destroy);
427
428 wl_list_remove(&subsurface->map.link);
429 wl_list_remove(&subsurface->unmap.link);
430 wl_list_remove(&subsurface->destroy.link);
431 wl_list_remove(&subsurface->commit.link);
432 free(subsurface);
433}
434 222
435static struct sway_layer_subsurface *create_subsurface( 223 struct wlr_layer_surface_v1 *layer_surface = surface->layer_surface;
436 struct wlr_subsurface *wlr_subsurface, 224 if (!layer_surface->initialized) {
437 struct sway_layer_surface *layer_surface) { 225 return;
438 struct sway_layer_subsurface *subsurface =
439 calloc(1, sizeof(struct sway_layer_subsurface));
440 if (subsurface == NULL) {
441 return NULL;
442 } 226 }
443 227
444 subsurface->wlr_subsurface = wlr_subsurface; 228 uint32_t committed = layer_surface->current.committed;
445 subsurface->layer_surface = layer_surface; 229 if (committed & WLR_LAYER_SURFACE_V1_STATE_LAYER) {
446 230 enum zwlr_layer_shell_v1_layer layer_type = layer_surface->current.layer;
447 subsurface->map.notify = subsurface_handle_map; 231 struct wlr_scene_tree *output_layer = sway_layer_get_scene(
448 wl_signal_add(&wlr_subsurface->events.map, &subsurface->map); 232 surface->output, layer_type);
449 subsurface->unmap.notify = subsurface_handle_unmap; 233 wlr_scene_node_reparent(&surface->scene->tree->node, output_layer);
450 wl_signal_add(&wlr_subsurface->events.unmap, &subsurface->unmap); 234 }
451 subsurface->destroy.notify = subsurface_handle_destroy;
452 wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy);
453 subsurface->commit.notify = subsurface_handle_commit;
454 wl_signal_add(&wlr_subsurface->surface->events.commit, &subsurface->commit);
455
456 return subsurface;
457}
458
459static void handle_new_subsurface(struct wl_listener *listener, void *data) {
460 struct sway_layer_surface *sway_layer_surface =
461 wl_container_of(listener, sway_layer_surface, new_subsurface);
462 struct wlr_subsurface *wlr_subsurface = data;
463 create_subsurface(wlr_subsurface, sway_layer_surface);
464}
465
466 235
467static struct sway_layer_surface *popup_get_layer( 236 if (layer_surface->initial_commit || committed || layer_surface->surface->mapped != surface->mapped) {
468 struct sway_layer_popup *popup) { 237 surface->mapped = layer_surface->surface->mapped;
469 while (popup->parent_type == LAYER_PARENT_POPUP) { 238 arrange_layers(surface->output);
470 popup = popup->parent_popup; 239 transaction_commit_dirty();
471 } 240 }
472 return popup->parent_layer;
473} 241}
474 242
475static void popup_damage(struct sway_layer_popup *layer_popup, bool whole) { 243static void handle_map(struct wl_listener *listener, void *data) {
476 struct wlr_xdg_popup *popup = layer_popup->wlr_popup; 244 struct sway_layer_surface *surface = wl_container_of(listener,
477 struct wlr_surface *surface = popup->base->surface; 245 surface, map);
478 int popup_sx = popup->geometry.x - popup->base->geometry.x; 246
479 int popup_sy = popup->geometry.y - popup->base->geometry.y; 247 struct wlr_layer_surface_v1 *layer_surface =
480 int ox = popup_sx, oy = popup_sy; 248 surface->scene->layer_surface;
481 struct sway_layer_surface *layer; 249
482 while (true) { 250 // focus on new surface
483 if (layer_popup->parent_type == LAYER_PARENT_POPUP) { 251 if (layer_surface->current.keyboard_interactive &&
484 layer_popup = layer_popup->parent_popup; 252 (layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY ||
485 ox += layer_popup->wlr_popup->geometry.x; 253 layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP)) {
486 oy += layer_popup->wlr_popup->geometry.y; 254 struct sway_seat *seat;
487 } else { 255 wl_list_for_each(seat, &server.input->seats, link) {
488 layer = layer_popup->parent_layer; 256 // but only if the currently focused layer has a lower precedence
489 ox += layer->geo.x; 257 if (!seat->focused_layer ||
490 oy += layer->geo.y; 258 seat->focused_layer->current.layer >= layer_surface->current.layer) {
491 break; 259 seat_set_focus_layer(seat, layer_surface);
260 }
492 } 261 }
262 arrange_layers(surface->output);
493 } 263 }
494 struct wlr_output *wlr_output = layer->layer_surface->output;
495 struct sway_output *output = wlr_output->data;
496 output_damage_surface(output, ox, oy, surface, whole);
497}
498 264
499static void popup_handle_map(struct wl_listener *listener, void *data) { 265 cursor_rebase_all();
500 struct sway_layer_popup *popup = wl_container_of(listener, popup, map);
501 struct sway_layer_surface *layer = popup_get_layer(popup);
502 struct wlr_output *wlr_output = layer->layer_surface->output;
503 wlr_surface_send_enter(popup->wlr_popup->base->surface, wlr_output);
504 popup_damage(popup, true);
505} 266}
506 267
507static void popup_handle_unmap(struct wl_listener *listener, void *data) { 268static void handle_unmap(struct wl_listener *listener, void *data) {
508 struct sway_layer_popup *popup = wl_container_of(listener, popup, unmap); 269 struct sway_layer_surface *surface = wl_container_of(
509 popup_damage(popup, true); 270 listener, surface, unmap);
510} 271 struct sway_seat *seat;
272 wl_list_for_each(seat, &server.input->seats, link) {
273 if (seat->focused_layer == surface->layer_surface) {
274 seat_set_focus_layer(seat, NULL);
275 }
276 }
511 277
512static void popup_handle_commit(struct wl_listener *listener, void *data) { 278 cursor_rebase_all();
513 struct sway_layer_popup *popup = wl_container_of(listener, popup, commit);
514 popup_damage(popup, false);
515} 279}
516 280
517static void popup_handle_destroy(struct wl_listener *listener, void *data) { 281static void popup_handle_destroy(struct wl_listener *listener, void *data) {
518 struct sway_layer_popup *popup = 282 struct sway_layer_popup *popup =
519 wl_container_of(listener, popup, destroy); 283 wl_container_of(listener, popup, destroy);
520 284
521 wl_list_remove(&popup->map.link);
522 wl_list_remove(&popup->unmap.link);
523 wl_list_remove(&popup->destroy.link); 285 wl_list_remove(&popup->destroy.link);
286 wl_list_remove(&popup->new_popup.link);
524 wl_list_remove(&popup->commit.link); 287 wl_list_remove(&popup->commit.link);
525 free(popup); 288 free(popup);
526} 289}
527 290
528static void popup_unconstrain(struct sway_layer_popup *popup) { 291static void popup_unconstrain(struct sway_layer_popup *popup) {
529 struct sway_layer_surface *layer = popup_get_layer(popup);
530 struct wlr_xdg_popup *wlr_popup = popup->wlr_popup; 292 struct wlr_xdg_popup *wlr_popup = popup->wlr_popup;
293 struct sway_output *output = popup->toplevel->output;
531 294
532 struct sway_output *output = layer->layer_surface->output->data; 295 // if a client tries to create a popup while we are in the process of destroying
296 // its output, don't crash.
297 if (!output) {
298 return;
299 }
300
301 int lx, ly;
302 wlr_scene_node_coords(&popup->toplevel->scene->tree->node, &lx, &ly);
533 303
534 // the output box expressed in the coordinate system of the toplevel parent 304 // the output box expressed in the coordinate system of the toplevel parent
535 // of the popup 305 // of the popup
536 struct wlr_box output_toplevel_sx_box = { 306 struct wlr_box output_toplevel_sx_box = {
537 .x = -layer->geo.x, 307 .x = output->lx - lx,
538 .y = -layer->geo.y, 308 .y = output->ly - ly,
539 .width = output->width, 309 .width = output->width,
540 .height = output->height, 310 .height = output->height,
541 }; 311 };
@@ -543,32 +313,38 @@ static void popup_unconstrain(struct sway_layer_popup *popup) {
543 wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); 313 wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box);
544} 314}
545 315
316static void popup_handle_commit(struct wl_listener *listener, void *data) {
317 struct sway_layer_popup *popup = wl_container_of(listener, popup, commit);
318 if (popup->wlr_popup->base->initial_commit) {
319 popup_unconstrain(popup);
320 }
321}
322
546static void popup_handle_new_popup(struct wl_listener *listener, void *data); 323static void popup_handle_new_popup(struct wl_listener *listener, void *data);
547 324
548static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup, 325static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup,
549 enum layer_parent parent_type, void *parent) { 326 struct sway_layer_surface *toplevel, struct wlr_scene_tree *parent) {
550 struct sway_layer_popup *popup = 327 struct sway_layer_popup *popup = calloc(1, sizeof(*popup));
551 calloc(1, sizeof(struct sway_layer_popup));
552 if (popup == NULL) { 328 if (popup == NULL) {
553 return NULL; 329 return NULL;
554 } 330 }
555 331
332 popup->toplevel = toplevel;
556 popup->wlr_popup = wlr_popup; 333 popup->wlr_popup = wlr_popup;
557 popup->parent_type = parent_type; 334 popup->scene = wlr_scene_xdg_surface_create(parent,
558 popup->parent_layer = parent; 335 wlr_popup->base);
336
337 if (!popup->scene) {
338 free(popup);
339 return NULL;
340 }
559 341
560 popup->map.notify = popup_handle_map;
561 wl_signal_add(&wlr_popup->base->events.map, &popup->map);
562 popup->unmap.notify = popup_handle_unmap;
563 wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap);
564 popup->destroy.notify = popup_handle_destroy; 342 popup->destroy.notify = popup_handle_destroy;
565 wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy); 343 wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
566 popup->commit.notify = popup_handle_commit;
567 wl_signal_add(&wlr_popup->base->surface->events.commit, &popup->commit);
568 popup->new_popup.notify = popup_handle_new_popup; 344 popup->new_popup.notify = popup_handle_new_popup;
569 wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup); 345 wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
570 346 popup->commit.notify = popup_handle_commit;
571 popup_unconstrain(popup); 347 wl_signal_add(&wlr_popup->base->surface->events.commit, &popup->commit);
572 348
573 return popup; 349 return popup;
574} 350}
@@ -577,19 +353,14 @@ static void popup_handle_new_popup(struct wl_listener *listener, void *data) {
577 struct sway_layer_popup *sway_layer_popup = 353 struct sway_layer_popup *sway_layer_popup =
578 wl_container_of(listener, sway_layer_popup, new_popup); 354 wl_container_of(listener, sway_layer_popup, new_popup);
579 struct wlr_xdg_popup *wlr_popup = data; 355 struct wlr_xdg_popup *wlr_popup = data;
580 create_popup(wlr_popup, LAYER_PARENT_POPUP, sway_layer_popup); 356 create_popup(wlr_popup, sway_layer_popup->toplevel, sway_layer_popup->scene);
581} 357}
582 358
583static void handle_new_popup(struct wl_listener *listener, void *data) { 359static void handle_new_popup(struct wl_listener *listener, void *data) {
584 struct sway_layer_surface *sway_layer_surface = 360 struct sway_layer_surface *sway_layer_surface =
585 wl_container_of(listener, sway_layer_surface, new_popup); 361 wl_container_of(listener, sway_layer_surface, new_popup);
586 struct wlr_xdg_popup *wlr_popup = data; 362 struct wlr_xdg_popup *wlr_popup = data;
587 create_popup(wlr_popup, LAYER_PARENT_LAYER, sway_layer_surface); 363 create_popup(wlr_popup, sway_layer_surface, sway_layer_surface->popups);
588}
589
590struct sway_layer_surface *layer_from_wlr_layer_surface_v1(
591 struct wlr_layer_surface_v1 *layer_surface) {
592 return layer_surface->data;
593} 364}
594 365
595void handle_layer_shell_surface(struct wl_listener *listener, void *data) { 366void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
@@ -597,14 +368,14 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
597 sway_log(SWAY_DEBUG, "new layer surface: namespace %s layer %d anchor %" PRIu32 368 sway_log(SWAY_DEBUG, "new layer surface: namespace %s layer %d anchor %" PRIu32
598 " size %" PRIu32 "x%" PRIu32 " margin %" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",", 369 " size %" PRIu32 "x%" PRIu32 " margin %" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",",
599 layer_surface->namespace, 370 layer_surface->namespace,
600 layer_surface->client_pending.layer, 371 layer_surface->pending.layer,
601 layer_surface->client_pending.anchor, 372 layer_surface->pending.anchor,
602 layer_surface->client_pending.desired_width, 373 layer_surface->pending.desired_width,
603 layer_surface->client_pending.desired_height, 374 layer_surface->pending.desired_height,
604 layer_surface->client_pending.margin.top, 375 layer_surface->pending.margin.top,
605 layer_surface->client_pending.margin.right, 376 layer_surface->pending.margin.right,
606 layer_surface->client_pending.margin.bottom, 377 layer_surface->pending.margin.bottom,
607 layer_surface->client_pending.margin.left); 378 layer_surface->pending.margin.left);
608 379
609 if (!layer_surface->output) { 380 if (!layer_surface->output) {
610 // Assign last active output 381 // Assign last active output
@@ -616,12 +387,12 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
616 output = ws->output; 387 output = ws->output;
617 } 388 }
618 } 389 }
619 if (!output || output == root->noop_output) { 390 if (!output || output == root->fallback_output) {
620 if (!root->outputs->length) { 391 if (!root->outputs->length) {
621 sway_log(SWAY_ERROR, 392 sway_log(SWAY_ERROR,
622 "no output to auto-assign layer surface '%s' to", 393 "no output to auto-assign layer surface '%s' to",
623 layer_surface->namespace); 394 layer_surface->namespace);
624 wlr_layer_surface_v1_close(layer_surface); 395 wlr_layer_surface_v1_destroy(layer_surface);
625 return; 396 return;
626 } 397 }
627 output = root->outputs->items[0]; 398 output = root->outputs->items[0];
@@ -629,42 +400,51 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
629 layer_surface->output = output->wlr_output; 400 layer_surface->output = output->wlr_output;
630 } 401 }
631 402
632 struct sway_layer_surface *sway_layer = 403 struct sway_output *output = layer_surface->output->data;
633 calloc(1, sizeof(struct sway_layer_surface)); 404
634 if (!sway_layer) { 405 enum zwlr_layer_shell_v1_layer layer_type = layer_surface->pending.layer;
406 struct wlr_scene_tree *output_layer = sway_layer_get_scene(
407 output, layer_type);
408 struct wlr_scene_layer_surface_v1 *scene_surface =
409 wlr_scene_layer_surface_v1_create(output_layer, layer_surface);
410 if (!scene_surface) {
411 sway_log(SWAY_ERROR, "Could not allocate a layer_surface_v1");
635 return; 412 return;
636 } 413 }
637 414
638 sway_layer->surface_commit.notify = handle_surface_commit; 415 struct sway_layer_surface *surface =
639 wl_signal_add(&layer_surface->surface->events.commit, 416 sway_layer_surface_create(scene_surface);
640 &sway_layer->surface_commit); 417 if (!surface) {
641 418 wlr_layer_surface_v1_destroy(layer_surface);
642 sway_layer->destroy.notify = handle_destroy;
643 wl_signal_add(&layer_surface->events.destroy, &sway_layer->destroy);
644 sway_layer->map.notify = handle_map;
645 wl_signal_add(&layer_surface->events.map, &sway_layer->map);
646 sway_layer->unmap.notify = handle_unmap;
647 wl_signal_add(&layer_surface->events.unmap, &sway_layer->unmap);
648 sway_layer->new_popup.notify = handle_new_popup;
649 wl_signal_add(&layer_surface->events.new_popup, &sway_layer->new_popup);
650 sway_layer->new_subsurface.notify = handle_new_subsurface;
651 wl_signal_add(&layer_surface->surface->events.new_subsurface,
652 &sway_layer->new_subsurface);
653
654 sway_layer->layer_surface = layer_surface;
655 layer_surface->data = sway_layer;
656 419
657 struct sway_output *output = layer_surface->output->data; 420 sway_log(SWAY_ERROR, "Could not allocate a sway_layer_surface");
658 sway_layer->output_destroy.notify = handle_output_destroy; 421 return;
659 wl_signal_add(&output->events.destroy, &sway_layer->output_destroy); 422 }
660 423
661 wl_list_insert(&output->layers[layer_surface->client_pending.layer], 424 if (!scene_descriptor_assign(&scene_surface->tree->node,
662 &sway_layer->link); 425 SWAY_SCENE_DESC_LAYER_SHELL, surface)) {
663 426 sway_log(SWAY_ERROR, "Failed to allocate a layer surface descriptor");
664 // Temporarily set the layer's current state to client_pending 427 // destroying the layer_surface will also destroy its corresponding
665 // So that we can easily arrange it 428 // scene node
666 struct wlr_layer_surface_v1_state old_state = layer_surface->current; 429 wlr_layer_surface_v1_destroy(layer_surface);
667 layer_surface->current = layer_surface->client_pending; 430 return;
668 arrange_layers(output); 431 }
669 layer_surface->current = old_state; 432
433 surface->output = output;
434
435 surface->surface_commit.notify = handle_surface_commit;
436 wl_signal_add(&layer_surface->surface->events.commit,
437 &surface->surface_commit);
438 surface->map.notify = handle_map;
439 wl_signal_add(&layer_surface->surface->events.map, &surface->map);
440 surface->unmap.notify = handle_unmap;
441 wl_signal_add(&layer_surface->surface->events.unmap, &surface->unmap);
442 surface->new_popup.notify = handle_new_popup;
443 wl_signal_add(&layer_surface->events.new_popup, &surface->new_popup);
444
445 surface->output_destroy.notify = handle_output_destroy;
446 wl_signal_add(&output->events.disable, &surface->output_destroy);
447
448 surface->node_destroy.notify = handle_node_destroy;
449 wl_signal_add(&scene_surface->tree->node.events.destroy, &surface->node_destroy);
670} 450}