diff options
author | Carlos Garnacho <carlosg@gnome.org> | 2017-05-28 15:56:20 +0200 |
---|---|---|
committer | Adam Jackson <ajax@redhat.com> | 2017-09-25 15:34:10 -0400 |
commit | c6df0d03de22b57d5faa77b19ac1ec0311f4f3a5 (patch) | |
tree | a378675f88d6a1ace39d590c3625fb1ccaa9acb9 /hw | |
parent | 2ccea152c091e25474a83588e18475567471e7c8 (diff) |
xwayland: Lock the pointer if it is confined and has no cursor
In the typical pattern in games of "hide cursor, grab with a confineTo,
warp constantly the pointer to the middle of the window" the last warping
step is actually rather optional. Some games may choose to just set up a
grab with confineTo argument, and trust that they'll get correct relative
X/Y axis values despite the hidden cursor hitting the confinement window
edge.
To cater for these cases, lock the pointer whenever there is a pointer
confinement and the cursor is hidden. This ensures the pointer position
is in sync with the compositor's when it's next shown again, and more
importantly resorts to the relative pointer for event delivery.
Signed-off-by: Carlos Garnacho <carlosg@gnome.org>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit ca17f3e9fd3b59fdc5ffd0e5d78e4db6ddc87aa1)
Diffstat (limited to 'hw')
-rw-r--r-- | hw/xwayland/xwayland-input.c | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c index f06e88aa5..add76f547 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -1524,11 +1524,35 @@ xwl_seat_emulate_pointer_warp(struct xwl_seat *xwl_seat, x, y); } +static Bool +xwl_seat_maybe_lock_on_hidden_cursor(struct xwl_seat *xwl_seat) +{ + /* Some clients use hidden cursor+confineTo+relative motion + * to implement infinite panning (eg. 3D views), lock the + * pointer for so the relative pointer is used. + */ + if (xwl_seat->x_cursor || + !xwl_seat->cursor_confinement_window) + return FALSE; + + if (xwl_seat->confined_pointer) + xwl_seat_destroy_confined_pointer(xwl_seat); + + xwl_seat_create_pointer_warp_emulator(xwl_seat); + xwl_pointer_warp_emulator_lock(xwl_seat->pointer_warp_emulator); + return TRUE; +} + void xwl_seat_cursor_visibility_changed(struct xwl_seat *xwl_seat) { - if (xwl_seat->pointer_warp_emulator && xwl_seat->x_cursor != NULL) + if (xwl_seat->pointer_warp_emulator && xwl_seat->x_cursor != NULL) { xwl_seat_destroy_pointer_warp_emulator(xwl_seat); + } else if (!xwl_seat->x_cursor && xwl_seat->cursor_confinement_window) { + /* If the cursor goes hidden as is confined, lock it for + * relative motion to work. */ + xwl_seat_maybe_lock_on_hidden_cursor(xwl_seat); + } } void @@ -1567,6 +1591,9 @@ xwl_seat_confine_pointer(struct xwl_seat *xwl_seat, if (xwl_seat->pointer_warp_emulator) return; + if (xwl_seat_maybe_lock_on_hidden_cursor(xwl_seat)) + return; + xwl_seat->confined_pointer = zwp_pointer_constraints_v1_confine_pointer(pointer_constraints, xwl_window->surface, |