1 #include <stdbool.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <wayland-server-core.h>
5 #include <wlr/types/wlr_box.h>
6 #include <wlr/types/wlr_layer_shell_v1.h>
7 #include <wlr/types/wlr_output_damage.h>
8 #include <wlr/types/wlr_output.h>
9 #include "log.h"
10 #include "sway/desktop/transaction.h"
11 #include "sway/input/cursor.h"
12 #include "sway/input/input-manager.h"
13 #include "sway/input/seat.h"
14 #include "sway/layers.h"
15 #include "sway/output.h"
16 #include "sway/server.h"
17 #include "sway/tree/arrange.h"
18 #include "sway/tree/workspace.h"
19
apply_exclusive(struct wlr_box * usable_area,uint32_t anchor,int32_t exclusive,int32_t margin_top,int32_t margin_right,int32_t margin_bottom,int32_t margin_left)20 static void apply_exclusive(struct wlr_box *usable_area,
21 uint32_t anchor, int32_t exclusive,
22 int32_t margin_top, int32_t margin_right,
23 int32_t margin_bottom, int32_t margin_left) {
24 if (exclusive <= 0) {
25 return;
26 }
27 struct {
28 uint32_t singular_anchor;
29 uint32_t anchor_triplet;
30 int *positive_axis;
31 int *negative_axis;
32 int margin;
33 } edges[] = {
34 // Top
35 {
36 .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP,
37 .anchor_triplet =
38 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
39 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
40 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP,
41 .positive_axis = &usable_area->y,
42 .negative_axis = &usable_area->height,
43 .margin = margin_top,
44 },
45 // Bottom
46 {
47 .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
48 .anchor_triplet =
49 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
50 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
51 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
52 .positive_axis = NULL,
53 .negative_axis = &usable_area->height,
54 .margin = margin_bottom,
55 },
56 // Left
57 {
58 .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT,
59 .anchor_triplet =
60 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
61 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
62 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
63 .positive_axis = &usable_area->x,
64 .negative_axis = &usable_area->width,
65 .margin = margin_left,
66 },
67 // Right
68 {
69 .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT,
70 .anchor_triplet =
71 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
72 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
73 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
74 .positive_axis = NULL,
75 .negative_axis = &usable_area->width,
76 .margin = margin_right,
77 },
78 };
79 for (size_t i = 0; i < sizeof(edges) / sizeof(edges[0]); ++i) {
80 if ((anchor == edges[i].singular_anchor || anchor == edges[i].anchor_triplet)
81 && exclusive + edges[i].margin > 0) {
82 if (edges[i].positive_axis) {
83 *edges[i].positive_axis += exclusive + edges[i].margin;
84 }
85 if (edges[i].negative_axis) {
86 *edges[i].negative_axis -= exclusive + edges[i].margin;
87 }
88 break;
89 }
90 }
91 }
92
arrange_layer(struct sway_output * output,struct wl_list * list,struct wlr_box * usable_area,bool exclusive)93 static void arrange_layer(struct sway_output *output, struct wl_list *list,
94 struct wlr_box *usable_area, bool exclusive) {
95 struct sway_layer_surface *sway_layer;
96 struct wlr_box full_area = { 0 };
97 wlr_output_effective_resolution(output->wlr_output,
98 &full_area.width, &full_area.height);
99 wl_list_for_each(sway_layer, list, link) {
100 struct wlr_layer_surface_v1 *layer = sway_layer->layer_surface;
101 struct wlr_layer_surface_v1_state *state = &layer->current;
102 if (exclusive != (state->exclusive_zone > 0)) {
103 continue;
104 }
105 struct wlr_box bounds;
106 if (state->exclusive_zone == -1) {
107 bounds = full_area;
108 } else {
109 bounds = *usable_area;
110 }
111 struct wlr_box box = {
112 .width = state->desired_width,
113 .height = state->desired_height
114 };
115 // Horizontal axis
116 const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
117 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
118 if ((state->anchor & both_horiz) && box.width == 0) {
119 box.x = bounds.x;
120 box.width = bounds.width;
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 ((state->anchor & both_vert) && box.height == 0) {
132 box.y = bounds.y;
133 box.height = bounds.height;
134 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
135 box.y = bounds.y;
136 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
137 box.y = bounds.y + (bounds.height - box.height);
138 } else {
139 box.y = bounds.y + ((bounds.height / 2) - (box.height / 2));
140 }
141 // Margin
142 if ((state->anchor & both_horiz) == both_horiz) {
143 box.x += state->margin.left;
144 box.width -= state->margin.left + state->margin.right;
145 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
146 box.x += state->margin.left;
147 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
148 box.x -= state->margin.right;
149 }
150 if ((state->anchor & both_vert) == both_vert) {
151 box.y += state->margin.top;
152 box.height -= state->margin.top + state->margin.bottom;
153 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
154 box.y += state->margin.top;
155 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
156 box.y -= state->margin.bottom;
157 }
158 if (box.width < 0 || box.height < 0) {
159 // TODO: Bubble up a protocol error?
160 wlr_layer_surface_v1_close(layer);
161 continue;
162 }
163 // Apply
164 sway_layer->geo = box;
165 apply_exclusive(usable_area, state->anchor, state->exclusive_zone,
166 state->margin.top, state->margin.right,
167 state->margin.bottom, state->margin.left);
168 wlr_layer_surface_v1_configure(layer, box.width, box.height);
169 }
170 }
171
arrange_layers(struct sway_output * output)172 void arrange_layers(struct sway_output *output) {
173 struct wlr_box usable_area = { 0 };
174 wlr_output_effective_resolution(output->wlr_output,
175 &usable_area.width, &usable_area.height);
176
177 // Arrange exclusive surfaces from top->bottom
178 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
179 &usable_area, true);
180 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
181 &usable_area, true);
182 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
183 &usable_area, true);
184 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
185 &usable_area, true);
186
187 if (memcmp(&usable_area, &output->usable_area,
188 sizeof(struct wlr_box)) != 0) {
189 sway_log(SWAY_DEBUG, "Usable area changed, rearranging output");
190 memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box));
191 arrange_output(output);
192 }
193
194 // Arrange non-exlusive surfaces from top->bottom
195 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
196 &usable_area, false);
197 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
198 &usable_area, false);
199 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
200 &usable_area, false);
201 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
202 &usable_area, false);
203
204 // Find topmost keyboard interactive layer, if such a layer exists
205 uint32_t layers_above_shell[] = {
206 ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY,
207 ZWLR_LAYER_SHELL_V1_LAYER_TOP,
208 };
209 size_t nlayers = sizeof(layers_above_shell) / sizeof(layers_above_shell[0]);
210 struct sway_layer_surface *layer, *topmost = NULL;
211 for (size_t i = 0; i < nlayers; ++i) {
212 wl_list_for_each_reverse(layer,
213 &output->layers[layers_above_shell[i]], link) {
214 if (layer->layer_surface->current.keyboard_interactive &&
215 layer->layer_surface->mapped) {
216 topmost = layer;
217 break;
218 }
219 }
220 if (topmost != NULL) {
221 break;
222 }
223 }
224
225 struct sway_seat *seat;
226 wl_list_for_each(seat, &server.input->seats, link) {
227 if (topmost != NULL) {
228 seat_set_focus_layer(seat, topmost->layer_surface);
229 } else if (seat->focused_layer &&
230 !seat->focused_layer->current.keyboard_interactive) {
231 seat_set_focus_layer(seat, NULL);
232 }
233 }
234 }
235
find_mapped_layer_by_client(struct wl_client * client,struct wlr_output * ignore_output)236 static struct sway_layer_surface *find_mapped_layer_by_client(
237 struct wl_client *client, struct wlr_output *ignore_output) {
238 for (int i = 0; i < root->outputs->length; ++i) {
239 struct sway_output *output = root->outputs->items[i];
240 if (output->wlr_output == ignore_output) {
241 continue;
242 }
243 // For now we'll only check the overlay layer
244 struct sway_layer_surface *lsurface;
245 wl_list_for_each(lsurface,
246 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], link) {
247 struct wl_resource *resource = lsurface->layer_surface->resource;
248 if (wl_resource_get_client(resource) == client
249 && lsurface->layer_surface->mapped) {
250 return lsurface;
251 }
252 }
253 }
254 return NULL;
255 }
256
handle_output_destroy(struct wl_listener * listener,void * data)257 static void handle_output_destroy(struct wl_listener *listener, void *data) {
258 struct sway_layer_surface *sway_layer =
259 wl_container_of(listener, sway_layer, output_destroy);
260 // Determine if this layer is being used by an exclusive client. If it is,
261 // try and find another layer owned by this client to pass focus to.
262 struct sway_seat *seat = input_manager_get_default_seat();
263 struct wl_client *client =
264 wl_resource_get_client(sway_layer->layer_surface->resource);
265 bool set_focus = seat->exclusive_client == client;
266
267 wl_list_remove(&sway_layer->output_destroy.link);
268 wl_list_remove(&sway_layer->link);
269 wl_list_init(&sway_layer->link);
270
271 if (set_focus) {
272 struct sway_layer_surface *layer =
273 find_mapped_layer_by_client(client, sway_layer->layer_surface->output);
274 if (layer) {
275 seat_set_focus_layer(seat, layer->layer_surface);
276 }
277 }
278
279 sway_layer->layer_surface->output = NULL;
280 wlr_layer_surface_v1_close(sway_layer->layer_surface);
281 }
282
handle_surface_commit(struct wl_listener * listener,void * data)283 static void handle_surface_commit(struct wl_listener *listener, void *data) {
284 struct sway_layer_surface *layer =
285 wl_container_of(listener, layer, surface_commit);
286 struct wlr_layer_surface_v1 *layer_surface = layer->layer_surface;
287 struct wlr_output *wlr_output = layer_surface->output;
288 if (wlr_output == NULL) {
289 return;
290 }
291
292 struct sway_output *output = wlr_output->data;
293 struct wlr_box old_geo = layer->geo;
294 arrange_layers(output);
295
296 bool geo_changed =
297 memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0;
298 bool layer_changed = layer->layer != layer_surface->current.layer;
299 if (layer_changed) {
300 wl_list_remove(&layer->link);
301 wl_list_insert(&output->layers[layer_surface->current.layer],
302 &layer->link);
303 layer->layer = layer_surface->current.layer;
304 }
305 if (geo_changed || layer_changed) {
306 output_damage_surface(output, old_geo.x, old_geo.y,
307 layer_surface->surface, true);
308 output_damage_surface(output, layer->geo.x, layer->geo.y,
309 layer_surface->surface, true);
310 } else {
311 output_damage_surface(output, layer->geo.x, layer->geo.y,
312 layer_surface->surface, false);
313 }
314
315 transaction_commit_dirty();
316 }
317
unmap(struct sway_layer_surface * sway_layer)318 static void unmap(struct sway_layer_surface *sway_layer) {
319 struct sway_seat *seat;
320 wl_list_for_each(seat, &server.input->seats, link) {
321 if (seat->focused_layer == sway_layer->layer_surface) {
322 seat_set_focus_layer(seat, NULL);
323 }
324 }
325
326 cursor_rebase_all();
327
328 struct wlr_output *wlr_output = sway_layer->layer_surface->output;
329 if (wlr_output == NULL) {
330 return;
331 }
332 struct sway_output *output = wlr_output->data;
333 if (output == NULL) {
334 return;
335 }
336 output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y,
337 sway_layer->layer_surface->surface, true);
338 }
339
handle_destroy(struct wl_listener * listener,void * data)340 static void handle_destroy(struct wl_listener *listener, void *data) {
341 struct sway_layer_surface *sway_layer =
342 wl_container_of(listener, sway_layer, destroy);
343 sway_log(SWAY_DEBUG, "Layer surface destroyed (%s)",
344 sway_layer->layer_surface->namespace);
345 if (sway_layer->layer_surface->mapped) {
346 unmap(sway_layer);
347 }
348 wl_list_remove(&sway_layer->link);
349 wl_list_remove(&sway_layer->destroy.link);
350 wl_list_remove(&sway_layer->map.link);
351 wl_list_remove(&sway_layer->unmap.link);
352 wl_list_remove(&sway_layer->surface_commit.link);
353 wl_list_remove(&sway_layer->new_popup.link);
354 if (sway_layer->layer_surface->output != NULL) {
355 struct sway_output *output = sway_layer->layer_surface->output->data;
356 if (output != NULL) {
357 arrange_layers(output);
358 transaction_commit_dirty();
359 }
360 wl_list_remove(&sway_layer->output_destroy.link);
361 sway_layer->layer_surface->output = NULL;
362 }
363 free(sway_layer);
364 }
365
handle_map(struct wl_listener * listener,void * data)366 static void handle_map(struct wl_listener *listener, void *data) {
367 struct sway_layer_surface *sway_layer = wl_container_of(listener,
368 sway_layer, map);
369 struct sway_output *output = sway_layer->layer_surface->output->data;
370 output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y,
371 sway_layer->layer_surface->surface, true);
372 wlr_surface_send_enter(sway_layer->layer_surface->surface,
373 sway_layer->layer_surface->output);
374 cursor_rebase_all();
375 }
376
handle_unmap(struct wl_listener * listener,void * data)377 static void handle_unmap(struct wl_listener *listener, void *data) {
378 struct sway_layer_surface *sway_layer = wl_container_of(
379 listener, sway_layer, unmap);
380 unmap(sway_layer);
381 }
382
popup_get_layer(struct sway_layer_popup * popup)383 static struct sway_layer_surface *popup_get_layer(
384 struct sway_layer_popup *popup) {
385 while (popup->parent_type == LAYER_PARENT_POPUP) {
386 popup = popup->parent_popup;
387 }
388 return popup->parent_layer;
389 }
390
popup_damage(struct sway_layer_popup * layer_popup,bool whole)391 static void popup_damage(struct sway_layer_popup *layer_popup, bool whole) {
392 struct wlr_xdg_popup *popup = layer_popup->wlr_popup;
393 struct wlr_surface *surface = popup->base->surface;
394 int popup_sx = popup->geometry.x - popup->base->geometry.x;
395 int popup_sy = popup->geometry.y - popup->base->geometry.y;
396 int ox = popup_sx, oy = popup_sy;
397 struct sway_layer_surface *layer;
398 while (true) {
399 if (layer_popup->parent_type == LAYER_PARENT_POPUP) {
400 layer_popup = layer_popup->parent_popup;
401 ox += layer_popup->wlr_popup->geometry.x;
402 oy += layer_popup->wlr_popup->geometry.y;
403 } else {
404 layer = layer_popup->parent_layer;
405 ox += layer->geo.x;
406 oy += layer->geo.y;
407 break;
408 }
409 }
410 struct wlr_output *wlr_output = layer->layer_surface->output;
411 struct sway_output *output = wlr_output->data;
412 output_damage_surface(output, ox, oy, surface, whole);
413 }
414
popup_handle_map(struct wl_listener * listener,void * data)415 static void popup_handle_map(struct wl_listener *listener, void *data) {
416 struct sway_layer_popup *popup = wl_container_of(listener, popup, map);
417 struct sway_layer_surface *layer = popup_get_layer(popup);
418 struct wlr_output *wlr_output = layer->layer_surface->output;
419 wlr_surface_send_enter(popup->wlr_popup->base->surface, wlr_output);
420 popup_damage(popup, true);
421 }
422
popup_handle_unmap(struct wl_listener * listener,void * data)423 static void popup_handle_unmap(struct wl_listener *listener, void *data) {
424 struct sway_layer_popup *popup = wl_container_of(listener, popup, unmap);
425 popup_damage(popup, true);
426 }
427
popup_handle_commit(struct wl_listener * listener,void * data)428 static void popup_handle_commit(struct wl_listener *listener, void *data) {
429 struct sway_layer_popup *popup = wl_container_of(listener, popup, commit);
430 popup_damage(popup, false);
431 }
432
popup_handle_destroy(struct wl_listener * listener,void * data)433 static void popup_handle_destroy(struct wl_listener *listener, void *data) {
434 struct sway_layer_popup *popup =
435 wl_container_of(listener, popup, destroy);
436
437 wl_list_remove(&popup->map.link);
438 wl_list_remove(&popup->unmap.link);
439 wl_list_remove(&popup->destroy.link);
440 wl_list_remove(&popup->commit.link);
441 free(popup);
442 }
443
popup_unconstrain(struct sway_layer_popup * popup)444 static void popup_unconstrain(struct sway_layer_popup *popup) {
445 struct sway_layer_surface *layer = popup_get_layer(popup);
446 struct wlr_xdg_popup *wlr_popup = popup->wlr_popup;
447
448 struct sway_output *output = layer->layer_surface->output->data;
449
450 // the output box expressed in the coordinate system of the toplevel parent
451 // of the popup
452 struct wlr_box output_toplevel_sx_box = {
453 .x = -layer->geo.x,
454 .y = -layer->geo.y,
455 .width = output->width,
456 .height = output->height,
457 };
458
459 wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box);
460 }
461
462 static void popup_handle_new_popup(struct wl_listener *listener, void *data);
463
create_popup(struct wlr_xdg_popup * wlr_popup,enum layer_parent parent_type,void * parent)464 static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup,
465 enum layer_parent parent_type, void *parent) {
466 struct sway_layer_popup *popup =
467 calloc(1, sizeof(struct sway_layer_popup));
468 if (popup == NULL) {
469 return NULL;
470 }
471
472 popup->wlr_popup = wlr_popup;
473 popup->parent_type = parent_type;
474 popup->parent_layer = parent;
475
476 popup->map.notify = popup_handle_map;
477 wl_signal_add(&wlr_popup->base->events.map, &popup->map);
478 popup->unmap.notify = popup_handle_unmap;
479 wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap);
480 popup->destroy.notify = popup_handle_destroy;
481 wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
482 popup->commit.notify = popup_handle_commit;
483 wl_signal_add(&wlr_popup->base->surface->events.commit, &popup->commit);
484 popup->new_popup.notify = popup_handle_new_popup;
485 wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
486
487 popup_unconstrain(popup);
488
489 return popup;
490 }
491
popup_handle_new_popup(struct wl_listener * listener,void * data)492 static void popup_handle_new_popup(struct wl_listener *listener, void *data) {
493 struct sway_layer_popup *sway_layer_popup =
494 wl_container_of(listener, sway_layer_popup, new_popup);
495 struct wlr_xdg_popup *wlr_popup = data;
496 create_popup(wlr_popup, LAYER_PARENT_POPUP, sway_layer_popup);
497 }
498
handle_new_popup(struct wl_listener * listener,void * data)499 static void handle_new_popup(struct wl_listener *listener, void *data) {
500 struct sway_layer_surface *sway_layer_surface =
501 wl_container_of(listener, sway_layer_surface, new_popup);
502 struct wlr_xdg_popup *wlr_popup = data;
503 create_popup(wlr_popup, LAYER_PARENT_LAYER, sway_layer_surface);
504 }
505
layer_from_wlr_layer_surface_v1(struct wlr_layer_surface_v1 * layer_surface)506 struct sway_layer_surface *layer_from_wlr_layer_surface_v1(
507 struct wlr_layer_surface_v1 *layer_surface) {
508 return layer_surface->data;
509 }
510
handle_layer_shell_surface(struct wl_listener * listener,void * data)511 void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
512 struct wlr_layer_surface_v1 *layer_surface = data;
513 sway_log(SWAY_DEBUG, "new layer surface: namespace %s layer %d anchor %d "
514 "size %dx%d margin %d,%d,%d,%d",
515 layer_surface->namespace,
516 layer_surface->client_pending.layer,
517 layer_surface->client_pending.layer,
518 layer_surface->client_pending.desired_width,
519 layer_surface->client_pending.desired_height,
520 layer_surface->client_pending.margin.top,
521 layer_surface->client_pending.margin.right,
522 layer_surface->client_pending.margin.bottom,
523 layer_surface->client_pending.margin.left);
524
525 if (!layer_surface->output) {
526 // Assign last active output
527 struct sway_output *output = NULL;
528 struct sway_seat *seat = input_manager_get_default_seat();
529 if (seat) {
530 struct sway_workspace *ws = seat_get_focused_workspace(seat);
531 if (ws != NULL) {
532 output = ws->output;
533 }
534 }
535 if (!output || output == root->noop_output) {
536 if (!root->outputs->length) {
537 sway_log(SWAY_ERROR,
538 "no output to auto-assign layer surface '%s' to",
539 layer_surface->namespace);
540 wlr_layer_surface_v1_close(layer_surface);
541 return;
542 }
543 output = root->outputs->items[0];
544 }
545 layer_surface->output = output->wlr_output;
546 }
547
548 struct sway_layer_surface *sway_layer =
549 calloc(1, sizeof(struct sway_layer_surface));
550 if (!sway_layer) {
551 return;
552 }
553
554 sway_layer->surface_commit.notify = handle_surface_commit;
555 wl_signal_add(&layer_surface->surface->events.commit,
556 &sway_layer->surface_commit);
557
558 sway_layer->destroy.notify = handle_destroy;
559 wl_signal_add(&layer_surface->events.destroy, &sway_layer->destroy);
560 sway_layer->map.notify = handle_map;
561 wl_signal_add(&layer_surface->events.map, &sway_layer->map);
562 sway_layer->unmap.notify = handle_unmap;
563 wl_signal_add(&layer_surface->events.unmap, &sway_layer->unmap);
564 sway_layer->new_popup.notify = handle_new_popup;
565 wl_signal_add(&layer_surface->events.new_popup, &sway_layer->new_popup);
566
567 sway_layer->layer_surface = layer_surface;
568 layer_surface->data = sway_layer;
569
570 struct sway_output *output = layer_surface->output->data;
571 sway_layer->output_destroy.notify = handle_output_destroy;
572 wl_signal_add(&output->events.destroy, &sway_layer->output_destroy);
573
574 wl_list_insert(&output->layers[layer_surface->client_pending.layer],
575 &sway_layer->link);
576
577 // Temporarily set the layer's current state to client_pending
578 // So that we can easily arrange it
579 struct wlr_layer_surface_v1_state old_state = layer_surface->current;
580 layer_surface->current = layer_surface->client_pending;
581 arrange_layers(output);
582 layer_surface->current = old_state;
583 }
584