From c244148e31e64b80e0dcc71ae31072d29317388a Mon Sep 17 00:00:00 2001 From: lkn Date: Mon, 22 Jun 2026 00:33:08 +0200 Subject: [PATCH] wayland: route pointer events to layer surfaces Screenshot tools (slurp) use layer-shell overlay surfaces that need pointer input. Check if the pointer is over a layer surface before falling through to the toplevel/frame_buf focus logic. --- src/backend/wayland/wl_pointer_focus.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/backend/wayland/wl_pointer_focus.c b/src/backend/wayland/wl_pointer_focus.c index 0197584..e17dfcd 100644 --- a/src/backend/wayland/wl_pointer_focus.c +++ b/src/backend/wayland/wl_pointer_focus.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "../../screen.h" #include "wl_types.h" @@ -127,6 +128,30 @@ wl_update_pointer_focus(uint32_t time_msec) struct wl_toplevel_view *view = NULL; struct wlr_surface *surface = NULL; + /* Check if pointer is over a layer surface (overlays, screenshot tools). */ + { + double lsx, lsy; + struct wlr_scene_node *node = wlr_scene_node_at( + &wl_state.scene->tree.node, + (double)wl_state.pointer_x, (double)wl_state.pointer_y, + &lsx, &lsy); + if (node && node->type == WLR_SCENE_NODE_BUFFER) { + struct wlr_scene_buffer *sbuf = wlr_scene_buffer_from_node(node); + struct wlr_scene_surface *ssurf = wlr_scene_surface_try_from_buffer(sbuf); + if (ssurf) { + struct wl_layer_view *lv; + wl_list_for_each(lv, &wl_state.layer_list, link) { + if (lv->layer_surface && lv->layer_surface->surface == ssurf->surface) { + surface = ssurf->surface; + sx = lsx; + sy = lsy; + goto deliver; + } + } + } + } + } + /* If pointer is over an internal frame_buf (menu, titlebar, etc.), * don't send pointer events to any client surface — UNLESS the * pointer is actually over the client content area within the frame. */ @@ -148,6 +173,7 @@ wl_update_pointer_focus(uint32_t time_msec) wl_state.pointer_x, wl_state.pointer_y, &sx, &sy, &view); } +deliver: static struct wlr_surface *last_focused_surface = NULL; if (surface) { if (surface != last_focused_surface) {