From 6d3de364f57d5d980a34c9837e40a1d0f05bd9d8 Mon Sep 17 00:00:00 2001 From: lkn Date: Tue, 23 Jun 2026 23:40:44 +0200 Subject: [PATCH] text fields: synthesize ENTER/LEAVE for WINGs child views When the pointer moves between WINGs child views (e.g. into a text field), synthesize WME_ENTER/LEAVE events. This triggers the i-beam cursor change in wtextfield.c which fires on WME_ENTER. --- src/backend/wayland/wl_pointer_motion.c | 22 ++++++++++++++++++++++ src/backend/wayland/wl_types.h | 1 + 2 files changed, 23 insertions(+) diff --git a/src/backend/wayland/wl_pointer_motion.c b/src/backend/wayland/wl_pointer_motion.c index b99f700..5b22c16 100644 --- a/src/backend/wayland/wl_pointer_motion.c +++ b/src/backend/wayland/wl_pointer_motion.c @@ -116,6 +116,28 @@ handle_pointer_motion(struct wl_listener *listener, void *data) } } W_WL_EnqueueEvent(wmscr, &wev, mtarget); + /* Synthesize ENTER/LEAVE for WINGs child view transitions. */ + if (mtarget != wl_state.last_hovered_view) { + WMEvent cev; + memset(&cev, 0, sizeof(cev)); + if (wl_state.last_hovered_view) { + cev.type = WME_LEAVE; + cev.window = wl_state.last_hovered_view->window; + cev.u.crossing.window = cev.window; + cev.u.crossing.mode = WM_NOTIFY_NORMAL; + cev.u.crossing.detail = WM_NOTIFY_ANCESTOR; + W_WL_EnqueueEvent(wmscr, &cev, wl_state.last_hovered_view); + } + if (mtarget) { + cev.type = WME_ENTER; + cev.window = mtarget->window; + cev.u.crossing.window = cev.window; + cev.u.crossing.mode = WM_NOTIFY_NORMAL; + cev.u.crossing.detail = WM_NOTIFY_ANCESTOR; + W_WL_EnqueueEvent(wmscr, &cev, mtarget); + } + wl_state.last_hovered_view = mtarget; + } /* Emit synthetic LEAVE/ENTER when pointer crosses WM sub-window * boundaries (titlebar ↔ button, etc.). These feed the inner * press-track loop in framewin.c:buttonMouseDown so the cancel- diff --git a/src/backend/wayland/wl_types.h b/src/backend/wayland/wl_types.h index 83a94d5..280f9e1 100644 --- a/src/backend/wayland/wl_types.h +++ b/src/backend/wayland/wl_types.h @@ -400,6 +400,7 @@ struct wl_compositor_state { * the pointer crosses between WM frame sub-windows (titlebar, resizebar, * buttons). buttonMouseDown's inner press-track loop depends on these. */ WNativeWindow last_hovered_id; + struct W_View *last_hovered_view; /* WINGs child view */ /* Focus guard: when true, the next focus-follows-pointer event is suppressed. * Set by switchpanel_send_enter (called twice in wSwitchPanelDestroy) to prevent * spurious focus changes when the Alt-Tab overlay is destroyed and the pointer