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>
This commit is contained in:
Carlos Garnacho 2017-05-28 15:56:20 +02:00 committed by Peter Hutterer
parent 513e3bd387
commit ca17f3e9fd
1 changed files with 28 additions and 1 deletions

View File

@ -2615,11 +2615,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
@ -2658,6 +2682,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,