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.c130
1 files changed, 128 insertions, 2 deletions
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c
index 34ba5592..f1f79c1b 100644
--- a/sway/desktop/layer_shell.c
+++ b/sway/desktop/layer_shell.c
@@ -320,6 +320,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
320 wl_list_remove(&sway_layer->map.link); 320 wl_list_remove(&sway_layer->map.link);
321 wl_list_remove(&sway_layer->unmap.link); 321 wl_list_remove(&sway_layer->unmap.link);
322 wl_list_remove(&sway_layer->surface_commit.link); 322 wl_list_remove(&sway_layer->surface_commit.link);
323 wl_list_remove(&sway_layer->new_popup.link);
323 if (sway_layer->layer_surface->output != NULL) { 324 if (sway_layer->layer_surface->output != NULL) {
324 struct sway_output *output = sway_layer->layer_surface->output->data; 325 struct sway_output *output = sway_layer->layer_surface->output->data;
325 if (output != NULL) { 326 if (output != NULL) {
@@ -338,7 +339,6 @@ static void handle_map(struct wl_listener *listener, void *data) {
338 struct sway_output *output = sway_layer->layer_surface->output->data; 339 struct sway_output *output = sway_layer->layer_surface->output->data;
339 output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y, 340 output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y,
340 sway_layer->layer_surface->surface, true); 341 sway_layer->layer_surface->surface, true);
341 // TODO: send enter to subsurfaces and popups
342 wlr_surface_send_enter(sway_layer->layer_surface->surface, 342 wlr_surface_send_enter(sway_layer->layer_surface->surface,
343 sway_layer->layer_surface->output); 343 sway_layer->layer_surface->output);
344 cursor_rebase_all(); 344 cursor_rebase_all();
@@ -350,6 +350,131 @@ static void handle_unmap(struct wl_listener *listener, void *data) {
350 unmap(sway_layer); 350 unmap(sway_layer);
351} 351}
352 352
353static struct sway_layer_surface *popup_get_layer(
354 struct sway_layer_popup *popup) {
355 while (popup->parent_type == LAYER_PARENT_POPUP) {
356 popup = popup->parent_popup;
357 }
358 return popup->parent_layer;
359}
360
361static void popup_damage(struct sway_layer_popup *layer_popup, bool whole) {
362 struct wlr_xdg_popup *popup = layer_popup->wlr_popup;
363 struct wlr_surface *surface = popup->base->surface;
364 int popup_sx = popup->geometry.x - popup->base->geometry.x;
365 int popup_sy = popup->geometry.y - popup->base->geometry.y;
366 int ox = popup_sx, oy = popup_sy;
367 struct sway_layer_surface *layer;
368 while (true) {
369 if (layer_popup->parent_type == LAYER_PARENT_POPUP) {
370 layer_popup = layer_popup->parent_popup;
371 ox += layer_popup->wlr_popup->base->geometry.x +
372 layer_popup->wlr_popup->geometry.x;
373 oy += layer_popup->wlr_popup->base->geometry.y +
374 layer_popup->wlr_popup->geometry.y;
375 } else {
376 layer = layer_popup->parent_layer;
377 ox += layer->geo.x;
378 oy += layer->geo.y;
379 break;
380 }
381 }
382 struct wlr_output *wlr_output = layer->layer_surface->output;
383 struct sway_output *output = wlr_output->data;
384 output_damage_surface(output, ox, oy, surface, whole);
385}
386
387static void popup_handle_map(struct wl_listener *listener, void *data) {
388 struct sway_layer_popup *popup = wl_container_of(listener, popup, map);
389 struct sway_layer_surface *layer = popup_get_layer(popup);
390 struct wlr_output *wlr_output = layer->layer_surface->output;
391 wlr_surface_send_enter(popup->wlr_popup->base->surface, wlr_output);
392 popup_damage(popup, true);
393}
394
395static void popup_handle_unmap(struct wl_listener *listener, void *data) {
396 struct sway_layer_popup *popup = wl_container_of(listener, popup, unmap);
397 popup_damage(popup, true);
398}
399
400static void popup_handle_commit(struct wl_listener *listener, void *data) {
401 struct sway_layer_popup *popup = wl_container_of(listener, popup, commit);
402 popup_damage(popup, false);
403}
404
405static void popup_handle_destroy(struct wl_listener *listener, void *data) {
406 struct sway_layer_popup *popup =
407 wl_container_of(listener, popup, destroy);
408
409 wl_list_remove(&popup->map.link);
410 wl_list_remove(&popup->unmap.link);
411 wl_list_remove(&popup->destroy.link);
412 wl_list_remove(&popup->commit.link);
413 free(popup);
414}
415
416static void popup_unconstrain(struct sway_layer_popup *popup) {
417 struct sway_layer_surface *layer = popup_get_layer(popup);
418 struct wlr_xdg_popup *wlr_popup = popup->wlr_popup;
419
420 struct sway_output *output = layer->layer_surface->output->data;
421
422 // the output box expressed in the coordinate system of the toplevel parent
423 // of the popup
424 struct wlr_box output_toplevel_sx_box = {
425 .x = -layer->geo.x,
426 .y = -layer->geo.y,
427 .width = output->width,
428 .height = output->height,
429 };
430
431 wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box);
432}
433
434static void popup_handle_new_popup(struct wl_listener *listener, void *data);
435
436static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup,
437 enum layer_parent parent_type, void *parent) {
438 struct sway_layer_popup *popup =
439 calloc(1, sizeof(struct sway_layer_popup));
440 if (popup == NULL) {
441 return NULL;
442 }
443
444 popup->wlr_popup = wlr_popup;
445 popup->parent_type = parent_type;
446 popup->parent_layer = parent;
447
448 popup->map.notify = popup_handle_map;
449 wl_signal_add(&wlr_popup->base->events.map, &popup->map);
450 popup->unmap.notify = popup_handle_unmap;
451 wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap);
452 popup->destroy.notify = popup_handle_destroy;
453 wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
454 popup->commit.notify = popup_handle_commit;
455 wl_signal_add(&wlr_popup->base->surface->events.commit, &popup->commit);
456 popup->new_popup.notify = popup_handle_new_popup;
457 wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
458
459 popup_unconstrain(popup);
460
461 return popup;
462}
463
464static void popup_handle_new_popup(struct wl_listener *listener, void *data) {
465 struct sway_layer_popup *sway_layer_popup =
466 wl_container_of(listener, sway_layer_popup, new_popup);
467 struct wlr_xdg_popup *wlr_popup = data;
468 create_popup(wlr_popup, LAYER_PARENT_POPUP, sway_layer_popup);
469}
470
471static void handle_new_popup(struct wl_listener *listener, void *data) {
472 struct sway_layer_surface *sway_layer_surface =
473 wl_container_of(listener, sway_layer_surface, new_popup);
474 struct wlr_xdg_popup *wlr_popup = data;
475 create_popup(wlr_popup, LAYER_PARENT_LAYER, sway_layer_surface);
476}
477
353struct sway_layer_surface *layer_from_wlr_layer_surface_v1( 478struct sway_layer_surface *layer_from_wlr_layer_surface_v1(
354 struct wlr_layer_surface_v1 *layer_surface) { 479 struct wlr_layer_surface_v1 *layer_surface) {
355 return layer_surface->data; 480 return layer_surface->data;
@@ -406,7 +531,8 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
406 wl_signal_add(&layer_surface->events.map, &sway_layer->map); 531 wl_signal_add(&layer_surface->events.map, &sway_layer->map);
407 sway_layer->unmap.notify = handle_unmap; 532 sway_layer->unmap.notify = handle_unmap;
408 wl_signal_add(&layer_surface->events.unmap, &sway_layer->unmap); 533 wl_signal_add(&layer_surface->events.unmap, &sway_layer->unmap);
409 // TODO: Listen for subsurfaces 534 sway_layer->new_popup.notify = handle_new_popup;
535 wl_signal_add(&layer_surface->events.new_popup, &sway_layer->new_popup);
410 536
411 sway_layer->layer_surface = layer_surface; 537 sway_layer->layer_surface = layer_surface;
412 layer_surface->data = sway_layer; 538 layer_surface->data = sway_layer;