summaryrefslogtreecommitdiff
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.c78
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;