diff options
Diffstat (limited to 'sway/desktop/layer_shell.c')
-rw-r--r-- | sway/desktop/layer_shell.c | 78 |
1 files changed, 60 insertions, 18 deletions
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index d0d56755..81429053 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -1,3 +1,4 @@ +#include <scenefx/render/fx_renderer/fx_effect_framebuffers.h> #include <stdbool.h> #include <stdlib.h> #include <string.h> @@ -14,10 +15,44 @@ #include "sway/layers.h" #include "sway/output.h" #include "sway/server.h" +#include "sway/surface.h" #include "sway/tree/arrange.h" #include "sway/tree/workspace.h" #include "wlr-layer-shell-unstable-v1-protocol.h" +struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface( + struct wlr_surface *surface) { + struct wlr_layer_surface_v1 *layer; + do { + if (!surface) { + return NULL; + } + // Topmost layer surface + if ((layer = wlr_layer_surface_v1_try_from_wlr_surface(surface))) { + return layer; + } + // Layer subsurface + if (wlr_subsurface_try_from_wlr_surface(surface)) { + surface = wlr_surface_get_root_surface(surface); + continue; + } + + // Layer surface popup + struct wlr_xdg_surface *xdg_surface = NULL; + if ((xdg_surface = wlr_xdg_surface_try_from_wlr_surface(surface)) && + xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP && xdg_surface->popup != NULL) { + if (!xdg_surface->popup->parent) { + return NULL; + } + surface = wlr_surface_get_root_surface(xdg_surface->popup->parent); + continue; + } + + // Return early if the surface is not a layer/xdg_popup/sub surface + return NULL; + } while (true); +} + static void layer_parse_criteria(struct sway_layer_surface *sway_layer) { enum zwlr_layer_shell_v1_layer layer = sway_layer->layer; if (layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND) { @@ -233,8 +268,9 @@ void arrange_layers(struct sway_output *output) { for (size_t i = 0; i < nlayers; ++i) { wl_list_for_each_reverse(layer, &output->layers[layers_above_shell[i]], link) { - if (layer->layer_surface->current.keyboard_interactive && - layer->layer_surface->mapped) { + if (layer->layer_surface->current.keyboard_interactive + == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE && + layer->layer_surface->surface->mapped) { topmost = layer; break; } @@ -246,10 +282,12 @@ void arrange_layers(struct sway_output *output) { struct sway_seat *seat; wl_list_for_each(seat, &server.input->seats, link) { + seat->has_exclusive_layer = false; if (topmost != NULL) { seat_set_focus_layer(seat, topmost->layer_surface); } else if (seat->focused_layer && - !seat->focused_layer->current.keyboard_interactive) { + seat->focused_layer->current.keyboard_interactive + != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) { seat_set_focus_layer(seat, NULL); } } @@ -268,7 +306,7 @@ static struct sway_layer_surface *find_mapped_layer_by_client( &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], link) { struct wl_resource *resource = lsurface->layer_surface->resource; if (wl_resource_get_client(resource) == client - && lsurface->layer_surface->mapped) { + && lsurface->layer_surface->surface->mapped) { return lsurface; } } @@ -309,13 +347,15 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { // Rerender the static blur on change if (layer->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || layer->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM) { - output->renderer->blur_buffer_dirty = true; + struct fx_effect_framebuffers *effect_fbos = + fx_effect_framebuffers_try_get(output->wlr_output); + effect_fbos->blur_buffer_dirty = true; } bool layer_changed = false; if (layer_surface->current.committed != 0 - || layer->mapped != layer_surface->mapped) { - layer->mapped = layer_surface->mapped; + || layer->mapped != layer_surface->surface->mapped) { + layer->mapped = layer_surface->surface->mapped; layer_changed = layer->layer != layer_surface->current.layer; if (layer_changed) { wl_list_remove(&layer->link); @@ -376,7 +416,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_container_of(listener, sway_layer, destroy); sway_log(SWAY_DEBUG, "Layer surface destroyed (%s)", sway_layer->layer_surface->namespace); - if (sway_layer->layer_surface->mapped) { + if (sway_layer->layer_surface->surface->mapped) { unmap(sway_layer); } @@ -400,7 +440,9 @@ static void handle_destroy(struct wl_listener *listener, void *data) { // Rerender the static blur if (sway_layer->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || sway_layer->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM) { - output->renderer->blur_buffer_dirty = true; + struct fx_effect_framebuffers *effect_fbos = + fx_effect_framebuffers_try_get(output->wlr_output); + effect_fbos->blur_buffer_dirty = true; } arrange_layers(output); @@ -420,8 +462,6 @@ static void handle_map(struct wl_listener *listener, void *data) { layer_parse_criteria(sway_layer); output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y, sway_layer->layer_surface->surface, true); - wlr_surface_send_enter(sway_layer->layer_surface->surface, - sway_layer->layer_surface->output); cursor_rebase_all(); } @@ -491,9 +531,9 @@ static struct sway_layer_subsurface *create_subsurface( wl_list_insert(&layer_surface->subsurfaces, &subsurface->link); subsurface->map.notify = subsurface_handle_map; - wl_signal_add(&wlr_subsurface->events.map, &subsurface->map); + wl_signal_add(&wlr_subsurface->surface->events.map, &subsurface->map); subsurface->unmap.notify = subsurface_handle_unmap; - wl_signal_add(&wlr_subsurface->events.unmap, &subsurface->unmap); + wl_signal_add(&wlr_subsurface->surface->events.unmap, &subsurface->unmap); subsurface->destroy.notify = subsurface_handle_destroy; wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy); subsurface->commit.notify = subsurface_handle_commit; @@ -548,7 +588,7 @@ static void popup_handle_map(struct wl_listener *listener, void *data) { struct sway_layer_surface *layer = popup_get_layer(popup); struct wlr_output *wlr_output = layer->layer_surface->output; sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); - wlr_surface_send_enter(popup->wlr_popup->base->surface, wlr_output); + surface_enter_output(popup->wlr_popup->base->surface, wlr_output->data); popup_damage(popup, true); } @@ -608,9 +648,9 @@ static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup, popup->parent_layer = parent; popup->map.notify = popup_handle_map; - wl_signal_add(&wlr_popup->base->events.map, &popup->map); + wl_signal_add(&wlr_popup->base->surface->events.map, &popup->map); popup->unmap.notify = popup_handle_unmap; - wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap); + wl_signal_add(&wlr_popup->base->surface->events.unmap, &popup->unmap); popup->destroy.notify = popup_handle_destroy; wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy); popup->commit.notify = popup_handle_commit; @@ -698,9 +738,9 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { sway_layer->destroy.notify = handle_destroy; wl_signal_add(&layer_surface->events.destroy, &sway_layer->destroy); sway_layer->map.notify = handle_map; - wl_signal_add(&layer_surface->events.map, &sway_layer->map); + wl_signal_add(&layer_surface->surface->events.map, &sway_layer->map); sway_layer->unmap.notify = handle_unmap; - wl_signal_add(&layer_surface->events.unmap, &sway_layer->unmap); + wl_signal_add(&layer_surface->surface->events.unmap, &sway_layer->unmap); sway_layer->new_popup.notify = handle_new_popup; wl_signal_add(&layer_surface->events.new_popup, &sway_layer->new_popup); sway_layer->new_subsurface.notify = handle_new_subsurface; @@ -722,6 +762,8 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { wl_list_insert(&output->layers[layer_surface->pending.layer], &sway_layer->link); + surface_enter_output(layer_surface->surface, output); + // Temporarily set the layer's current state to pending // So that we can easily arrange it struct wlr_layer_surface_v1_state old_state = layer_surface->current; |