diff options
Diffstat (limited to 'sway/desktop/layer_shell.c')
-rw-r--r-- | sway/desktop/layer_shell.c | 186 |
1 files changed, 106 insertions, 80 deletions
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index d4ca4fb4..d44d6338 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c | |||
@@ -2,10 +2,10 @@ | |||
2 | #include <stdlib.h> | 2 | #include <stdlib.h> |
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_box.h> | ||
6 | #include <wlr/types/wlr_layer_shell_v1.h> | 5 | #include <wlr/types/wlr_layer_shell_v1.h> |
7 | #include <wlr/types/wlr_output_damage.h> | 6 | #include <wlr/types/wlr_output_damage.h> |
8 | #include <wlr/types/wlr_output.h> | 7 | #include <wlr/types/wlr_output.h> |
8 | #include <wlr/types/wlr_subcompositor.h> | ||
9 | #include "log.h" | 9 | #include "log.h" |
10 | #include "sway/desktop/transaction.h" | 10 | #include "sway/desktop/transaction.h" |
11 | #include "sway/input/cursor.h" | 11 | #include "sway/input/cursor.h" |
@@ -115,9 +115,10 @@ static void arrange_layer(struct sway_output *output, struct wl_list *list, | |||
115 | // Horizontal axis | 115 | // Horizontal axis |
116 | const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | 116 | const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
117 | | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; | 117 | | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; |
118 | if ((state->anchor & both_horiz) && box.width == 0) { | 118 | if (box.width == 0) { |
119 | box.x = bounds.x; | 119 | box.x = bounds.x; |
120 | box.width = bounds.width; | 120 | } else if ((state->anchor & both_horiz) == both_horiz) { |
121 | box.x = bounds.x + ((bounds.width / 2) - (box.width / 2)); | ||
121 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { | 122 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { |
122 | box.x = bounds.x; | 123 | box.x = bounds.x; |
123 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { | 124 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { |
@@ -128,9 +129,10 @@ static void arrange_layer(struct sway_output *output, struct wl_list *list, | |||
128 | // Vertical axis | 129 | // Vertical axis |
129 | const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | 130 | const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
130 | | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; | 131 | | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; |
131 | if ((state->anchor & both_vert) && box.height == 0) { | 132 | if (box.height == 0) { |
132 | box.y = bounds.y; | 133 | box.y = bounds.y; |
133 | box.height = bounds.height; | 134 | } else if ((state->anchor & both_vert) == both_vert) { |
135 | box.y = bounds.y + ((bounds.height / 2) - (box.height / 2)); | ||
134 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { | 136 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { |
135 | box.y = bounds.y; | 137 | box.y = bounds.y; |
136 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { | 138 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { |
@@ -139,25 +141,30 @@ static void arrange_layer(struct sway_output *output, struct wl_list *list, | |||
139 | box.y = bounds.y + ((bounds.height / 2) - (box.height / 2)); | 141 | box.y = bounds.y + ((bounds.height / 2) - (box.height / 2)); |
140 | } | 142 | } |
141 | // Margin | 143 | // Margin |
142 | if ((state->anchor & both_horiz) == both_horiz) { | 144 | if (box.width == 0) { |
143 | box.x += state->margin.left; | 145 | box.x += state->margin.left; |
144 | box.width -= state->margin.left + state->margin.right; | 146 | box.width = bounds.width - |
147 | (state->margin.left + state->margin.right); | ||
148 | } else if ((state->anchor & both_horiz) == both_horiz) { | ||
149 | // don't apply margins | ||
145 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { | 150 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { |
146 | box.x += state->margin.left; | 151 | box.x += state->margin.left; |
147 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { | 152 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { |
148 | box.x -= state->margin.right; | 153 | box.x -= state->margin.right; |
149 | } | 154 | } |
150 | if ((state->anchor & both_vert) == both_vert) { | 155 | if (box.height == 0) { |
151 | box.y += state->margin.top; | 156 | box.y += state->margin.top; |
152 | box.height -= state->margin.top + state->margin.bottom; | 157 | box.height = bounds.height - |
158 | (state->margin.top + state->margin.bottom); | ||
159 | } else if ((state->anchor & both_vert) == both_vert) { | ||
160 | // don't apply margins | ||
153 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { | 161 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { |
154 | box.y += state->margin.top; | 162 | box.y += state->margin.top; |
155 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { | 163 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { |
156 | box.y -= state->margin.bottom; | 164 | box.y -= state->margin.bottom; |
157 | } | 165 | } |
158 | if (box.width < 0 || box.height < 0) { | 166 | if (!sway_assert(box.width >= 0 && box.height >= 0, |
159 | // TODO: Bubble up a protocol error? | 167 | "Expected layer surface to have positive size")) { |
160 | wlr_layer_surface_v1_close(layer); | ||
161 | continue; | 168 | continue; |
162 | } | 169 | } |
163 | // Apply | 170 | // Apply |
@@ -191,7 +198,7 @@ void arrange_layers(struct sway_output *output) { | |||
191 | arrange_output(output); | 198 | arrange_output(output); |
192 | } | 199 | } |
193 | 200 | ||
194 | // Arrange non-exlusive surfaces from top->bottom | 201 | // Arrange non-exclusive surfaces from top->bottom |
195 | arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], | 202 | arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], |
196 | &usable_area, false); | 203 | &usable_area, false); |
197 | arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], | 204 | arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], |
@@ -264,10 +271,6 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) { | |||
264 | wl_resource_get_client(sway_layer->layer_surface->resource); | 271 | wl_resource_get_client(sway_layer->layer_surface->resource); |
265 | bool set_focus = seat->exclusive_client == client; | 272 | bool set_focus = seat->exclusive_client == client; |
266 | 273 | ||
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) { | 274 | if (set_focus) { |
272 | struct sway_layer_surface *layer = | 275 | struct sway_layer_surface *layer = |
273 | find_mapped_layer_by_client(client, sway_layer->layer_surface->output); | 276 | find_mapped_layer_by_client(client, sway_layer->layer_surface->output); |
@@ -276,8 +279,7 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) { | |||
276 | } | 279 | } |
277 | } | 280 | } |
278 | 281 | ||
279 | sway_layer->layer_surface->output = NULL; | 282 | wlr_layer_surface_v1_destroy(sway_layer->layer_surface); |
280 | wlr_layer_surface_v1_close(sway_layer->layer_surface); | ||
281 | } | 283 | } |
282 | 284 | ||
283 | static void handle_surface_commit(struct wl_listener *listener, void *data) { | 285 | static void handle_surface_commit(struct wl_listener *listener, void *data) { |
@@ -285,26 +287,32 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { | |||
285 | wl_container_of(listener, layer, surface_commit); | 287 | wl_container_of(listener, layer, surface_commit); |
286 | struct wlr_layer_surface_v1 *layer_surface = layer->layer_surface; | 288 | struct wlr_layer_surface_v1 *layer_surface = layer->layer_surface; |
287 | struct wlr_output *wlr_output = layer_surface->output; | 289 | struct wlr_output *wlr_output = layer_surface->output; |
288 | if (wlr_output == NULL) { | 290 | sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); |
289 | return; | 291 | struct sway_output *output = wlr_output->data; |
292 | struct wlr_box old_extent = layer->extent; | ||
293 | |||
294 | bool layer_changed = false; | ||
295 | if (layer_surface->current.committed != 0 | ||
296 | || layer->mapped != layer_surface->mapped) { | ||
297 | layer->mapped = layer_surface->mapped; | ||
298 | 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 | arrange_layers(output); | ||
290 | } | 306 | } |
291 | 307 | ||
292 | struct sway_output *output = wlr_output->data; | 308 | wlr_surface_get_extends(layer_surface->surface, &layer->extent); |
293 | struct wlr_box old_geo = layer->geo; | 309 | layer->extent.x += layer->geo.x; |
294 | arrange_layers(output); | 310 | layer->extent.y += layer->geo.y; |
295 | 311 | ||
296 | bool geo_changed = | 312 | bool extent_changed = |
297 | memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0; | 313 | memcmp(&old_extent, &layer->extent, sizeof(struct wlr_box)) != 0; |
298 | bool layer_changed = layer->layer != layer_surface->current.layer; | 314 | if (extent_changed || layer_changed) { |
299 | if (layer_changed) { | 315 | output_damage_box(output, &old_extent); |
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, | 316 | output_damage_surface(output, layer->geo.x, layer->geo.y, |
309 | layer_surface->surface, true); | 317 | layer_surface->surface, true); |
310 | } else { | 318 | } else { |
@@ -326,17 +334,14 @@ static void unmap(struct sway_layer_surface *sway_layer) { | |||
326 | cursor_rebase_all(); | 334 | cursor_rebase_all(); |
327 | 335 | ||
328 | struct wlr_output *wlr_output = sway_layer->layer_surface->output; | 336 | struct wlr_output *wlr_output = sway_layer->layer_surface->output; |
329 | if (wlr_output == NULL) { | 337 | sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); |
330 | return; | ||
331 | } | ||
332 | struct sway_output *output = wlr_output->data; | 338 | 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, | 339 | output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y, |
337 | sway_layer->layer_surface->surface, true); | 340 | sway_layer->layer_surface->surface, true); |
338 | } | 341 | } |
339 | 342 | ||
343 | static void layer_subsurface_destroy(struct sway_layer_subsurface *subsurface); | ||
344 | |||
340 | static void handle_destroy(struct wl_listener *listener, void *data) { | 345 | static void handle_destroy(struct wl_listener *listener, void *data) { |
341 | struct sway_layer_surface *sway_layer = | 346 | struct sway_layer_surface *sway_layer = |
342 | wl_container_of(listener, sway_layer, destroy); | 347 | wl_container_of(listener, sway_layer, destroy); |
@@ -345,6 +350,12 @@ static void handle_destroy(struct wl_listener *listener, void *data) { | |||
345 | if (sway_layer->layer_surface->mapped) { | 350 | if (sway_layer->layer_surface->mapped) { |
346 | unmap(sway_layer); | 351 | unmap(sway_layer); |
347 | } | 352 | } |
353 | |||
354 | struct sway_layer_subsurface *subsurface, *subsurface_tmp; | ||
355 | wl_list_for_each_safe(subsurface, subsurface_tmp, &sway_layer->subsurfaces, link) { | ||
356 | layer_subsurface_destroy(subsurface); | ||
357 | } | ||
358 | |||
348 | wl_list_remove(&sway_layer->link); | 359 | wl_list_remove(&sway_layer->link); |
349 | wl_list_remove(&sway_layer->destroy.link); | 360 | wl_list_remove(&sway_layer->destroy.link); |
350 | wl_list_remove(&sway_layer->map.link); | 361 | wl_list_remove(&sway_layer->map.link); |
@@ -352,22 +363,24 @@ static void handle_destroy(struct wl_listener *listener, void *data) { | |||
352 | wl_list_remove(&sway_layer->surface_commit.link); | 363 | wl_list_remove(&sway_layer->surface_commit.link); |
353 | wl_list_remove(&sway_layer->new_popup.link); | 364 | wl_list_remove(&sway_layer->new_popup.link); |
354 | wl_list_remove(&sway_layer->new_subsurface.link); | 365 | wl_list_remove(&sway_layer->new_subsurface.link); |
355 | if (sway_layer->layer_surface->output != NULL) { | 366 | |
356 | struct sway_output *output = sway_layer->layer_surface->output->data; | 367 | struct wlr_output *wlr_output = sway_layer->layer_surface->output; |
357 | if (output != NULL) { | 368 | sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); |
358 | arrange_layers(output); | 369 | struct sway_output *output = wlr_output->data; |
359 | transaction_commit_dirty(); | 370 | arrange_layers(output); |
360 | } | 371 | transaction_commit_dirty(); |
361 | wl_list_remove(&sway_layer->output_destroy.link); | 372 | wl_list_remove(&sway_layer->output_destroy.link); |
362 | sway_layer->layer_surface->output = NULL; | 373 | sway_layer->layer_surface->output = NULL; |
363 | } | 374 | |
364 | free(sway_layer); | 375 | free(sway_layer); |
365 | } | 376 | } |
366 | 377 | ||
367 | static void handle_map(struct wl_listener *listener, void *data) { | 378 | static void handle_map(struct wl_listener *listener, void *data) { |
368 | struct sway_layer_surface *sway_layer = wl_container_of(listener, | 379 | struct sway_layer_surface *sway_layer = wl_container_of(listener, |
369 | sway_layer, map); | 380 | sway_layer, map); |
370 | struct sway_output *output = sway_layer->layer_surface->output->data; | 381 | struct wlr_output *wlr_output = sway_layer->layer_surface->output; |
382 | sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); | ||
383 | struct sway_output *output = wlr_output->data; | ||
371 | output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y, | 384 | output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y, |
372 | sway_layer->layer_surface->surface, true); | 385 | sway_layer->layer_surface->surface, true); |
373 | wlr_surface_send_enter(sway_layer->layer_surface->surface, | 386 | wlr_surface_send_enter(sway_layer->layer_surface->surface, |
@@ -385,9 +398,7 @@ static void subsurface_damage(struct sway_layer_subsurface *subsurface, | |||
385 | bool whole) { | 398 | bool whole) { |
386 | struct sway_layer_surface *layer = subsurface->layer_surface; | 399 | struct sway_layer_surface *layer = subsurface->layer_surface; |
387 | struct wlr_output *wlr_output = layer->layer_surface->output; | 400 | struct wlr_output *wlr_output = layer->layer_surface->output; |
388 | if (!wlr_output) { | 401 | sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); |
389 | return; | ||
390 | } | ||
391 | struct sway_output *output = wlr_output->data; | 402 | struct sway_output *output = wlr_output->data; |
392 | int ox = subsurface->wlr_subsurface->current.x + layer->geo.x; | 403 | int ox = subsurface->wlr_subsurface->current.x + layer->geo.x; |
393 | int oy = subsurface->wlr_subsurface->current.y + layer->geo.y; | 404 | int oy = subsurface->wlr_subsurface->current.y + layer->geo.y; |
@@ -413,11 +424,8 @@ static void subsurface_handle_commit(struct wl_listener *listener, void *data) { | |||
413 | subsurface_damage(subsurface, false); | 424 | subsurface_damage(subsurface, false); |
414 | } | 425 | } |
415 | 426 | ||
416 | static void subsurface_handle_destroy(struct wl_listener *listener, | 427 | static void layer_subsurface_destroy(struct sway_layer_subsurface *subsurface) { |
417 | void *data) { | 428 | wl_list_remove(&subsurface->link); |
418 | struct sway_layer_subsurface *subsurface = | ||
419 | wl_container_of(listener, subsurface, destroy); | ||
420 | |||
421 | wl_list_remove(&subsurface->map.link); | 429 | wl_list_remove(&subsurface->map.link); |
422 | wl_list_remove(&subsurface->unmap.link); | 430 | wl_list_remove(&subsurface->unmap.link); |
423 | wl_list_remove(&subsurface->destroy.link); | 431 | wl_list_remove(&subsurface->destroy.link); |
@@ -425,17 +433,25 @@ static void subsurface_handle_destroy(struct wl_listener *listener, | |||
425 | free(subsurface); | 433 | free(subsurface); |
426 | } | 434 | } |
427 | 435 | ||
436 | static void subsurface_handle_destroy(struct wl_listener *listener, | ||
437 | void *data) { | ||
438 | struct sway_layer_subsurface *subsurface = | ||
439 | wl_container_of(listener, subsurface, destroy); | ||
440 | layer_subsurface_destroy(subsurface); | ||
441 | } | ||
442 | |||
428 | static struct sway_layer_subsurface *create_subsurface( | 443 | static struct sway_layer_subsurface *create_subsurface( |
429 | struct wlr_subsurface *wlr_subsurface, | 444 | struct wlr_subsurface *wlr_subsurface, |
430 | struct sway_layer_surface *layer_surface) { | 445 | struct sway_layer_surface *layer_surface) { |
431 | struct sway_layer_subsurface *subsurface = | 446 | struct sway_layer_subsurface *subsurface = |
432 | calloc(1, sizeof(struct sway_layer_surface)); | 447 | calloc(1, sizeof(struct sway_layer_subsurface)); |
433 | if (subsurface == NULL) { | 448 | if (subsurface == NULL) { |
434 | return NULL; | 449 | return NULL; |
435 | } | 450 | } |
436 | 451 | ||
437 | subsurface->wlr_subsurface = wlr_subsurface; | 452 | subsurface->wlr_subsurface = wlr_subsurface; |
438 | subsurface->layer_surface = layer_surface; | 453 | subsurface->layer_surface = layer_surface; |
454 | wl_list_insert(&layer_surface->subsurfaces, &subsurface->link); | ||
439 | 455 | ||
440 | subsurface->map.notify = subsurface_handle_map; | 456 | subsurface->map.notify = subsurface_handle_map; |
441 | wl_signal_add(&wlr_subsurface->events.map, &subsurface->map); | 457 | wl_signal_add(&wlr_subsurface->events.map, &subsurface->map); |
@@ -468,15 +484,15 @@ static struct sway_layer_surface *popup_get_layer( | |||
468 | static void popup_damage(struct sway_layer_popup *layer_popup, bool whole) { | 484 | static void popup_damage(struct sway_layer_popup *layer_popup, bool whole) { |
469 | struct wlr_xdg_popup *popup = layer_popup->wlr_popup; | 485 | struct wlr_xdg_popup *popup = layer_popup->wlr_popup; |
470 | struct wlr_surface *surface = popup->base->surface; | 486 | struct wlr_surface *surface = popup->base->surface; |
471 | int popup_sx = popup->geometry.x - popup->base->geometry.x; | 487 | int popup_sx = popup->current.geometry.x - popup->base->current.geometry.x; |
472 | int popup_sy = popup->geometry.y - popup->base->geometry.y; | 488 | int popup_sy = popup->current.geometry.y - popup->base->current.geometry.y; |
473 | int ox = popup_sx, oy = popup_sy; | 489 | int ox = popup_sx, oy = popup_sy; |
474 | struct sway_layer_surface *layer; | 490 | struct sway_layer_surface *layer; |
475 | while (true) { | 491 | while (true) { |
476 | if (layer_popup->parent_type == LAYER_PARENT_POPUP) { | 492 | if (layer_popup->parent_type == LAYER_PARENT_POPUP) { |
477 | layer_popup = layer_popup->parent_popup; | 493 | layer_popup = layer_popup->parent_popup; |
478 | ox += layer_popup->wlr_popup->geometry.x; | 494 | ox += layer_popup->wlr_popup->current.geometry.x; |
479 | oy += layer_popup->wlr_popup->geometry.y; | 495 | oy += layer_popup->wlr_popup->current.geometry.y; |
480 | } else { | 496 | } else { |
481 | layer = layer_popup->parent_layer; | 497 | layer = layer_popup->parent_layer; |
482 | ox += layer->geo.x; | 498 | ox += layer->geo.x; |
@@ -485,6 +501,7 @@ static void popup_damage(struct sway_layer_popup *layer_popup, bool whole) { | |||
485 | } | 501 | } |
486 | } | 502 | } |
487 | struct wlr_output *wlr_output = layer->layer_surface->output; | 503 | struct wlr_output *wlr_output = layer->layer_surface->output; |
504 | sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); | ||
488 | struct sway_output *output = wlr_output->data; | 505 | struct sway_output *output = wlr_output->data; |
489 | output_damage_surface(output, ox, oy, surface, whole); | 506 | output_damage_surface(output, ox, oy, surface, whole); |
490 | } | 507 | } |
@@ -493,6 +510,7 @@ static void popup_handle_map(struct wl_listener *listener, void *data) { | |||
493 | struct sway_layer_popup *popup = wl_container_of(listener, popup, map); | 510 | struct sway_layer_popup *popup = wl_container_of(listener, popup, map); |
494 | struct sway_layer_surface *layer = popup_get_layer(popup); | 511 | struct sway_layer_surface *layer = popup_get_layer(popup); |
495 | struct wlr_output *wlr_output = layer->layer_surface->output; | 512 | struct wlr_output *wlr_output = layer->layer_surface->output; |
513 | sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); | ||
496 | wlr_surface_send_enter(popup->wlr_popup->base->surface, wlr_output); | 514 | wlr_surface_send_enter(popup->wlr_popup->base->surface, wlr_output); |
497 | popup_damage(popup, true); | 515 | popup_damage(popup, true); |
498 | } | 516 | } |
@@ -522,7 +540,9 @@ static void popup_unconstrain(struct sway_layer_popup *popup) { | |||
522 | struct sway_layer_surface *layer = popup_get_layer(popup); | 540 | struct sway_layer_surface *layer = popup_get_layer(popup); |
523 | struct wlr_xdg_popup *wlr_popup = popup->wlr_popup; | 541 | struct wlr_xdg_popup *wlr_popup = popup->wlr_popup; |
524 | 542 | ||
525 | struct sway_output *output = layer->layer_surface->output->data; | 543 | struct wlr_output *wlr_output = layer->layer_surface->output; |
544 | sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); | ||
545 | struct sway_output *output = wlr_output->data; | ||
526 | 546 | ||
527 | // the output box expressed in the coordinate system of the toplevel parent | 547 | // the output box expressed in the coordinate system of the toplevel parent |
528 | // of the popup | 548 | // of the popup |
@@ -590,14 +610,14 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { | |||
590 | sway_log(SWAY_DEBUG, "new layer surface: namespace %s layer %d anchor %" PRIu32 | 610 | sway_log(SWAY_DEBUG, "new layer surface: namespace %s layer %d anchor %" PRIu32 |
591 | " size %" PRIu32 "x%" PRIu32 " margin %" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",", | 611 | " size %" PRIu32 "x%" PRIu32 " margin %" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",", |
592 | layer_surface->namespace, | 612 | layer_surface->namespace, |
593 | layer_surface->client_pending.layer, | 613 | layer_surface->pending.layer, |
594 | layer_surface->client_pending.anchor, | 614 | layer_surface->pending.anchor, |
595 | layer_surface->client_pending.desired_width, | 615 | layer_surface->pending.desired_width, |
596 | layer_surface->client_pending.desired_height, | 616 | layer_surface->pending.desired_height, |
597 | layer_surface->client_pending.margin.top, | 617 | layer_surface->pending.margin.top, |
598 | layer_surface->client_pending.margin.right, | 618 | layer_surface->pending.margin.right, |
599 | layer_surface->client_pending.margin.bottom, | 619 | layer_surface->pending.margin.bottom, |
600 | layer_surface->client_pending.margin.left); | 620 | layer_surface->pending.margin.left); |
601 | 621 | ||
602 | if (!layer_surface->output) { | 622 | if (!layer_surface->output) { |
603 | // Assign last active output | 623 | // Assign last active output |
@@ -609,12 +629,16 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { | |||
609 | output = ws->output; | 629 | output = ws->output; |
610 | } | 630 | } |
611 | } | 631 | } |
612 | if (!output || output == root->noop_output) { | 632 | if (!output || output == root->fallback_output) { |
613 | if (!root->outputs->length) { | 633 | if (!root->outputs->length) { |
614 | sway_log(SWAY_ERROR, | 634 | sway_log(SWAY_ERROR, |
615 | "no output to auto-assign layer surface '%s' to", | 635 | "no output to auto-assign layer surface '%s' to", |
616 | layer_surface->namespace); | 636 | layer_surface->namespace); |
617 | wlr_layer_surface_v1_close(layer_surface); | 637 | // Note that layer_surface->output can be NULL |
638 | // here, but none of our destroy callbacks are | ||
639 | // registered yet so we don't have to make them | ||
640 | // handle that case. | ||
641 | wlr_layer_surface_v1_destroy(layer_surface); | ||
618 | return; | 642 | return; |
619 | } | 643 | } |
620 | output = root->outputs->items[0]; | 644 | output = root->outputs->items[0]; |
@@ -628,6 +652,8 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { | |||
628 | return; | 652 | return; |
629 | } | 653 | } |
630 | 654 | ||
655 | wl_list_init(&sway_layer->subsurfaces); | ||
656 | |||
631 | sway_layer->surface_commit.notify = handle_surface_commit; | 657 | sway_layer->surface_commit.notify = handle_surface_commit; |
632 | wl_signal_add(&layer_surface->surface->events.commit, | 658 | wl_signal_add(&layer_surface->surface->events.commit, |
633 | &sway_layer->surface_commit); | 659 | &sway_layer->surface_commit); |
@@ -649,15 +675,15 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { | |||
649 | 675 | ||
650 | struct sway_output *output = layer_surface->output->data; | 676 | struct sway_output *output = layer_surface->output->data; |
651 | sway_layer->output_destroy.notify = handle_output_destroy; | 677 | sway_layer->output_destroy.notify = handle_output_destroy; |
652 | wl_signal_add(&output->events.destroy, &sway_layer->output_destroy); | 678 | wl_signal_add(&output->events.disable, &sway_layer->output_destroy); |
653 | 679 | ||
654 | wl_list_insert(&output->layers[layer_surface->client_pending.layer], | 680 | wl_list_insert(&output->layers[layer_surface->pending.layer], |
655 | &sway_layer->link); | 681 | &sway_layer->link); |
656 | 682 | ||
657 | // Temporarily set the layer's current state to client_pending | 683 | // Temporarily set the layer's current state to pending |
658 | // So that we can easily arrange it | 684 | // So that we can easily arrange it |
659 | struct wlr_layer_surface_v1_state old_state = layer_surface->current; | 685 | struct wlr_layer_surface_v1_state old_state = layer_surface->current; |
660 | layer_surface->current = layer_surface->client_pending; | 686 | layer_surface->current = layer_surface->pending; |
661 | arrange_layers(output); | 687 | arrange_layers(output); |
662 | layer_surface->current = old_state; | 688 | layer_surface->current = old_state; |
663 | } | 689 | } |