[PATCH xserver 08/12] xwayland: Set unaccelerated pointer motion delta if available

Jonas Ådahl jadahl at gmail.com
Thu Sep 8 10:46:37 UTC 2016


If there was an relative pointer motion within the same frame as an
absolute pointer motion, provide both the absolute coordinate and the
unaccelerated delta when setting the valuator mask.

If a frame contained only a relative motion, queue an absolute motion
with an unchanged position, but still pass the unaccelerated motion
event.

If the wl_seat advertised by the compositor is not new enough, assume
each relative and absolute pointer motion arrives within their own
separate frames.

Signed-off-by: Jonas Ådahl <jadahl at gmail.com>
---
 hw/xwayland/xwayland-input.c | 90 ++++++++++++++++++++++++++++++++++++--------
 hw/xwayland/xwayland.h       |  7 ++++
 2 files changed, 82 insertions(+), 15 deletions(-)

diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
index 19cfd93..e1d751c 100644
--- a/hw/xwayland/xwayland-input.c
+++ b/hw/xwayland/xwayland-input.c
@@ -336,30 +336,47 @@ pointer_handle_leave(void *data, struct wl_pointer *pointer,
 }
 
 static void
-dispatch_pointer_event(struct xwl_seat *xwl_seat)
+dispatch_pointer_motion_event(struct xwl_seat *xwl_seat)
 {
     ValuatorMask mask;
 
-    if (xwl_seat->pending_pointer_event.has_absolute) {
-        int sx;
-        int sy;
-        int dx;
-        int dy;
-
-        sx = wl_fixed_to_int(xwl_seat->pending_pointer_event.x);
-        sy = wl_fixed_to_int(xwl_seat->pending_pointer_event.y);
-        dx = xwl_seat->focus_window->window->drawable.x;
-        dy = xwl_seat->focus_window->window->drawable.y;
+    if (xwl_seat->pending_pointer_event.has_absolute ||
+        xwl_seat->pending_pointer_event.has_relative) {
+        int x;
+        int y;
+
+        if (xwl_seat->pending_pointer_event.has_absolute) {
+            int sx = wl_fixed_to_int(xwl_seat->pending_pointer_event.x);
+            int sy = wl_fixed_to_int(xwl_seat->pending_pointer_event.y);
+            int dx = xwl_seat->focus_window->window->drawable.x;
+            int dy = xwl_seat->focus_window->window->drawable.y;
+
+            x = dx + sx;
+            y = dy + sy;
+        } else {
+            miPointerGetPosition(xwl_seat->pointer, &x, &y);
+        }
 
         valuator_mask_zero(&mask);
-        valuator_mask_set(&mask, 0, dx + sx);
-        valuator_mask_set(&mask, 1, dy + sy);
+        if (xwl_seat->pending_pointer_event.has_relative) {
+            double dx_unaccel;
+            double dy_unaccel;
+
+            dx_unaccel = xwl_seat->pending_pointer_event.dx_unaccel;
+            dy_unaccel = xwl_seat->pending_pointer_event.dy_unaccel;
+            valuator_mask_set_absolute_unaccelerated(&mask, 0, x, dx_unaccel);
+            valuator_mask_set_absolute_unaccelerated(&mask, 1, y, dy_unaccel);
+        } else {
+            valuator_mask_set(&mask, 0, x);
+            valuator_mask_set(&mask, 1, y);
+        }
 
         QueuePointerEvents(xwl_seat->pointer, MotionNotify, 0,
                            POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
     }
 
     xwl_seat->pending_pointer_event.has_absolute = FALSE;
+    xwl_seat->pending_pointer_event.has_relative = FALSE;
 }
 
 static void
@@ -376,7 +393,7 @@ pointer_handle_motion(void *data, struct wl_pointer *pointer,
     xwl_seat->pending_pointer_event.y = sy_w;
 
     if (wl_proxy_get_version((struct wl_proxy *) xwl_seat->wl_pointer) < 5)
-        dispatch_pointer_event(xwl_seat);
+        dispatch_pointer_motion_event(xwl_seat);
 }
 
 static void
@@ -441,7 +458,7 @@ pointer_handle_frame(void *data, struct wl_pointer *wl_pointer)
 {
     struct xwl_seat *xwl_seat = data;
 
-    dispatch_pointer_event(xwl_seat);
+    dispatch_pointer_motion_event(xwl_seat);
 }
 
 static void
@@ -474,6 +491,32 @@ static const struct wl_pointer_listener pointer_listener = {
 };
 
 static void
+relative_pointer_handle_relative_motion(void *data,
+                                        struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1,
+                                        uint32_t utime_hi,
+                                        uint32_t utime_lo,
+                                        wl_fixed_t dxf,
+                                        wl_fixed_t dyf,
+                                        wl_fixed_t dx_unaccelf,
+                                        wl_fixed_t dy_unaccelf)
+{
+    struct xwl_seat *xwl_seat = data;
+
+    xwl_seat->pending_pointer_event.has_relative = TRUE;
+    xwl_seat->pending_pointer_event.dx = wl_fixed_to_double(dxf);
+    xwl_seat->pending_pointer_event.dy = wl_fixed_to_double(dyf);
+    xwl_seat->pending_pointer_event.dx_unaccel = wl_fixed_to_double(dx_unaccelf);
+    xwl_seat->pending_pointer_event.dy_unaccel = wl_fixed_to_double(dy_unaccelf);
+
+    if (wl_proxy_get_version((struct wl_proxy *) xwl_seat->wl_pointer) < 5)
+        dispatch_pointer_motion_event(xwl_seat);
+}
+
+static const struct zwp_relative_pointer_v1_listener relative_pointer_listener = {
+    relative_pointer_handle_relative_motion,
+};
+
+static void
 keyboard_handle_key(void *data, struct wl_keyboard *keyboard, uint32_t serial,
                     uint32_t time, uint32_t key, uint32_t state)
 {
@@ -891,6 +934,18 @@ release_pointer(struct xwl_seat *xwl_seat)
 static void
 init_relative_pointer(struct xwl_seat *xwl_seat)
 {
+    struct zwp_relative_pointer_manager_v1 *relative_pointer_manager =
+        xwl_seat->xwl_screen->relative_pointer_manager;
+
+    if (relative_pointer_manager) {
+        xwl_seat->wp_relative_pointer =
+            zwp_relative_pointer_manager_v1_get_relative_pointer(
+                relative_pointer_manager, xwl_seat->wl_pointer);
+        zwp_relative_pointer_v1_add_listener(xwl_seat->wp_relative_pointer,
+                                             &relative_pointer_listener,
+                                             xwl_seat);
+    }
+
     if (xwl_seat->relative_pointer == NULL) {
         xwl_seat->relative_pointer =
             add_device(xwl_seat, "xwayland-relative-pointer",
@@ -903,6 +958,11 @@ init_relative_pointer(struct xwl_seat *xwl_seat)
 static void
 release_relative_pointer(struct xwl_seat *xwl_seat)
 {
+    if (xwl_seat->wp_relative_pointer) {
+        zwp_relative_pointer_v1_destroy(xwl_seat->wp_relative_pointer);
+        xwl_seat->wp_relative_pointer = NULL;
+    }
+
     if (xwl_seat->relative_pointer)
         DisableDevice(xwl_seat->relative_pointer, TRUE);
 }
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index 1fbae15..24b3e91 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -125,6 +125,7 @@ struct xwl_seat {
     struct xwl_screen *xwl_screen;
     struct wl_seat *seat;
     struct wl_pointer *wl_pointer;
+    struct zwp_relative_pointer_v1 *wp_relative_pointer;
     struct wl_keyboard *wl_keyboard;
     struct wl_touch *wl_touch;
     struct wl_array keys;
@@ -150,6 +151,12 @@ struct xwl_seat {
         Bool has_absolute;
         wl_fixed_t x;
         wl_fixed_t y;
+
+        Bool has_relative;
+        double dx;
+        double dy;
+        double dx_unaccel;
+        double dy_unaccel;
     } pending_pointer_event;
 };
 
-- 
2.7.4



More information about the xorg-devel mailing list