[PATCH xwayland v3 5/7] xwayland: Lock the pointer if it is confined and has no cursor

Carlos Garnacho carlosg at gnome.org
Sun May 28 13:56:20 UTC 2017


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 at gnome.org>
---
 hw/xwayland/xwayland-input.c | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
index 557aac8ed..02fdf6eef 100644
--- a/hw/xwayland/xwayland-input.c
+++ b/hw/xwayland/xwayland-input.c
@@ -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,
-- 
2.13.0



More information about the xorg-devel mailing list