From 53399164db2aeb8f7c250afa6625e737b4020113 Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Fri, 20 Mar 2026 10:54:37 +0100 Subject: [PATCH] xwayland: Use viewport scale for warping coordinates When Xwayland is used rootful with hidpi, a viewport is in effect and a scale applied. This is however "transparent" to the Xserver which uses unscaled coordinates, so to set the fake cursor position with a viewport and a scale applied, we need to factor the scale to the coordinates before passing the coordinate to the Wayland compositor through the method zwp_locked_pointer_v1_set_cursor_position_hint(). Failing to do that will introduce a shift when warping the cursor position. v2: Use an xwl_window instead of an xwl_seat to improve readability (Michel) Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1875 Signed-off-by: Olivier Fourdan (cherry picked from commit 0e580872b03d7d7684551c21a4858ce35b53d52b) Part-of: --- hw/xwayland/xwayland-input.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c index d3fcc185c..b1fe0be1f 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -24,6 +24,7 @@ * SOFTWARE. */ +#include #include #include @@ -3293,26 +3294,30 @@ xwl_pointer_warp_emulator_set_fake_pos(struct xwl_pointer_warp_emulator *warp_em { struct zwp_locked_pointer_v1 *locked_pointer = warp_emulator->locked_pointer; + struct xwl_window *focus_window; WindowPtr window; int sx, sy; if (!warp_emulator->locked_pointer) return; - if (!warp_emulator->xwl_seat->focus_window) + focus_window = warp_emulator->xwl_seat->focus_window; + if (!focus_window) return; - window = warp_emulator->xwl_seat->focus_window->toplevel; + window = focus_window->toplevel; if (x >= window->drawable.x || y >= window->drawable.y || x < (window->drawable.x + window->drawable.width) || y < (window->drawable.y + window->drawable.height)) { - sx = x - window->drawable.x; - sy = y - window->drawable.y; + sx = round((double) (x - window->drawable.x) / + focus_window->viewport_scale_x); + sy = round((double) (y - window->drawable.y) / + focus_window->viewport_scale_y); zwp_locked_pointer_v1_set_cursor_position_hint(locked_pointer, wl_fixed_from_int(sx), wl_fixed_from_int(sy)); - wl_surface_commit(warp_emulator->xwl_seat->focus_window->surface); + wl_surface_commit(focus_window->surface); } }