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.
This commit is contained in:
lkn 2026-06-22 00:33:08 +02:00
parent c1927f0948
commit c244148e31
1 changed files with 26 additions and 0 deletions

View File

@ -10,6 +10,7 @@
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_seat.h>
#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/util/log.h>
#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) {