From ee8489e3a1a385811f8d89ae64fdfd16a6e07e38 Mon Sep 17 00:00:00 2001 From: lkn Date: Sat, 23 May 2026 13:50:00 +0200 Subject: [PATCH] fix: WINGs widget clicks on Wayland (child view hit-testing) On Wayland, all WINGs child widgets composite into a single scene_buf for the toplevel dialog. Clicks always arrived with the toplevel window ID, so WMHandleEvent delivered them to the toplevel view which has no ButtonPressMask handler. Child widget handlers never fired. Fix: add W_FindViewAtPoint() to walk the view tree and find the deepest mapped child at click coordinates. In handle_pointer_button, resolve the child view for WINGs surfaces and pass it as the direct target to W_WL_EnqueueEvent. WMHandleEvent then delivers directly to the widget. --- WINGs/wview_wl.c | 19 +++++++++++++++++++ src/backend/wayland/wl_backend.c | 15 ++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/WINGs/wview_wl.c b/WINGs/wview_wl.c index 8380dcf..b80caff 100644 --- a/WINGs/wview_wl.c +++ b/WINGs/wview_wl.c @@ -328,6 +328,25 @@ static void wl_redisplay(void *vctx, W_View *view) W_ViewCommitBackingFn((unsigned long)top->window); } +/* Find the deepest child view at (x, y) relative to the given view. */ +W_View *W_FindViewAtPoint(W_View *parent, int x, int y) +{ + if (!parent) return NULL; + W_View *child = parent->childrenList; + while (child) { + if (child->flags.mapped && child->flags.realized && + x >= child->pos.x && x < child->pos.x + child->size.width && + y >= child->pos.y && y < child->pos.y + child->size.height) { + /* Recurse into this child with local coordinates */ + W_View *deeper = W_FindViewAtPoint(child, + x - child->pos.x, y - child->pos.y); + return deeper ? deeper : child; + } + child = child->nextSister; + } + return NULL; +} + static WMPoint wl_get_screen_position(void *vctx, W_View *view) { W_Screen *scr = (W_Screen *)vctx; diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 21c5341..abc1366 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -5248,7 +5248,20 @@ handle_pointer_button(struct wl_listener *listener, void *data) case 0x112: wev.u.button.button = 2; break; default: wev.u.button.button = (ev->button - 0x110) + 1; break; } - W_WL_EnqueueEvent(wmscr, &wev, NULL); + /* For WINGs views, resolve the child widget at click coordinates */ + struct W_View *target = NULL; + if (fb && fb->id >= 0x20000000) { + extern W_View *W_GetViewForWindow(unsigned long id); + extern struct W_View *W_FindViewAtPoint(struct W_View *parent, int x, int y); + W_View *toplevel = W_GetViewForWindow((unsigned long)fb->id); + if (toplevel) { + target = W_FindViewAtPoint(toplevel, + wev.u.button.x, wev.u.button.y); + if (!target) + target = toplevel; + } + } + W_WL_EnqueueEvent(wmscr, &wev, target); } wlr_seat_pointer_notify_button(wl_state.seat, ev->time_msec,