From 1d1f5bdc71cedc326c406cd14457ffd9fa9b045d Mon Sep 17 00:00:00 2001 From: Window Maker Date: Sun, 24 May 2026 16:04:25 +0200 Subject: [PATCH] wl_backend: forward pointer events to client surface in client area frame_buf_at() matches the entire window frame tree including the client content area. This caused wl_update_pointer_focus to never set seat pointer focus on the client surface, so Wayland clients (like WPrefs) never received pointer enter/motion/button events. Fix: when frame_buf_at returns a hit, also check view_surface_at. If a client surface is found at the pointer position, use it instead of treating the area as WM-internal decorations. --- src/backend/wayland/wl_backend.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 6fae10e..73db25a 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -5846,11 +5846,26 @@ wl_update_pointer_focus(uint32_t time_msec) struct wlr_surface *surface = NULL; /* If pointer is over an internal frame_buf (menu, titlebar, etc.), - * don't send pointer events to any client surface. */ + * don't send pointer events to any client surface — UNLESS the + * pointer is actually over the client content area within the frame. */ struct wl_frame_buf *fb = frame_buf_at(wl_state.pointer_x, wl_state.pointer_y); - if (!fb) + if (fb) { + /* Check if this frame_buf has a client surface (toplevel view) + * and the pointer is over the client area, not the decorations. */ + double sx, sy; + struct wl_toplevel_view *v = NULL; + struct wlr_surface *cs = view_surface_at( + wl_state.pointer_x, wl_state.pointer_y, &sx, &sy, &v); + if (cs) { + surface = cs; + view = v; + fb = NULL; /* not over decorations */ + } + } + if (!fb && !surface) { surface = view_surface_at( wl_state.pointer_x, wl_state.pointer_y, &sx, &sy, &view); + } static struct wlr_surface *last_focused_surface = NULL; if (surface) {