From 2240cac022befa8fb45deb11214a2f42311d0da3 Mon Sep 17 00:00:00 2001 From: Stanislav Aleksandrov Date: Mon, 22 Dec 2025 13:09:23 +0000 Subject: [PATCH] xwayland: Fix XYToWindow to return focused window The Wayland protocol already tells us which window is focused, so let's use that instead of trying to find a window at the global pointer coordinates. This solves the problem when a window receives wayland pointer events but actual X11 Enter/Leave/Motion events are delivered to another window at provided coordinates (the other window might be above the focused window). --- hw/xwayland/xwayland-input.c | 18 +++++++++++++----- hw/xwayland/xwayland-screen.c | 5 ++--- hw/xwayland/xwayland-screen.h | 2 +- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c index 447627dc6..e5ef5faa5 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -3279,14 +3279,23 @@ static WindowPtr xwl_xy_to_window(ScreenPtr screen, SpritePtr sprite, int x, int y) { struct xwl_screen *xwl_screen; + struct xwl_seat *seat; WindowPtr ret; xwl_screen = xwl_screen_get(screen); - screen->XYToWindow = xwl_screen->XYToWindow; - ret = screen->XYToWindow(screen, sprite, x, y); - xwl_screen->XYToWindow = screen->XYToWindow; - screen->XYToWindow = xwl_xy_to_window; + /* root window should be already there */ + sprite->spriteTraceGood = 1; + ret = DeepestSpriteWin(sprite); + + seat = xwl_screen_get_default_seat(xwl_screen); + if (seat && seat->focus_window) { + ret = seat->focus_window->toplevel; + sprite->spriteTrace[sprite->spriteTraceGood++] = ret; + + /* Continue to look deeper to find a child window if any */ + ret = miSpriteTrace(sprite, x, y); + } /* If the device controlling the sprite has left the Wayland surface but * the DIX still finds the pointer within the X11 window, it means that @@ -3658,7 +3667,6 @@ InitInput(int argc, char *argv[]) wl_registry_add_listener(xwl_screen->input_registry, &input_listener, xwl_screen); - xwl_screen->XYToWindow = pScreen->XYToWindow; pScreen->XYToWindow = xwl_xy_to_window; xwl_screen_roundtrip(xwl_screen); diff --git a/hw/xwayland/xwayland-screen.c b/hw/xwayland/xwayland-screen.c index 22c500801..e78e1d6ff 100644 --- a/hw/xwayland/xwayland-screen.c +++ b/hw/xwayland/xwayland-screen.c @@ -283,9 +283,8 @@ xwl_close_screen(ScreenPtr screen) return screen->CloseScreen(screen); } -static struct xwl_seat * -xwl_screen_get_default_seat(struct xwl_screen *xwl_screen) -{ +struct xwl_seat * +xwl_screen_get_default_seat(struct xwl_screen *xwl_screen) { if (xorg_list_is_empty(&xwl_screen->seat_list)) return NULL; diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h index ffbaa09e7..36e312809 100644 --- a/hw/xwayland/xwayland-screen.h +++ b/hw/xwayland/xwayland-screen.h @@ -75,7 +75,6 @@ struct xwl_screen { RealizeWindowProcPtr RealizeWindow; UnrealizeWindowProcPtr UnrealizeWindow; DestroyWindowProcPtr DestroyWindow; - XYToWindowProcPtr XYToWindow; SetWindowPixmapProcPtr SetWindowPixmap; ChangeWindowAttributesProcPtr ChangeWindowAttributes; ReparentWindowProcPtr ReparentWindow; @@ -183,5 +182,6 @@ int xwl_screen_get_next_output_serial(struct xwl_screen * xwl_screen); void xwl_screen_lost_focus(struct xwl_screen *xwl_screen); Bool xwl_screen_update_global_surface_scale(struct xwl_screen *xwl_screen); Bool xwl_screen_should_use_fractional_scale(struct xwl_screen *xwl_screen); +struct xwl_seat *xwl_screen_get_default_seat(struct xwl_screen *xwl_screen); #endif /* XWAYLAND_SCREEN_H */