xserver: Branch 'master'

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Jul 4 07:40:29 UTC 2022


 hw/xwayland/xwayland-input.c |  118 ++++++++++++++++++++++++-------------------
 hw/xwayland/xwayland-input.h |   10 +++
 2 files changed, 75 insertions(+), 53 deletions(-)

New commits:
commit e37eeb7af2a84d32f0a74feb00613efda6bc966e
Author: David Jacewicz <david.jacewicz27 at protonmail.com>
Date:   Fri Jun 17 15:13:13 2022 -0400

    xwayland: Aggregate scroll axis events to fix kinetic scrolling
    
    Pointer scroll events are collected in xwl_seat->pending_pointer_event
    as they are received in the pointer_handle_axis and
    pointer_handle_axis_discrete callbacks. They are dispatched together as a
    single event when pointer_handle_frame is called which "Indicates the end of a
    set of events that logically belong together" [1]. This patch also sends an
    event with dx=0, dy=0 when pointer_handle_axis_stop is called, which is what
    allows XWayland clients to recognise the end of a touchpad scroll.
    
    [1] https://wayland.app/protocols/wayland#wl_pointer:event:frame
    
    Signed-off-by: David Jacewicz <david.jacewicz27 at protonmail.com>
    Fixes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/926
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
index 325bcac0b..784972aed 100644
--- a/hw/xwayland/xwayland-input.c
+++ b/hw/xwayland/xwayland-input.c
@@ -51,12 +51,6 @@
 #include "xwayland-keyboard-grab-unstable-v1-client-protocol.h"
 #include "keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h"
 
-struct axis_discrete_pending {
-    struct xorg_list l;
-    uint32_t axis;
-    int32_t discrete;
-};
-
 struct sync_pending {
     struct xorg_list l;
     DeviceIntPtr pending_dev;
@@ -669,6 +663,36 @@ dispatch_relative_motion(struct xwl_seat *xwl_seat)
                        POINTER_RAWONLY, &mask);
 }
 
+static void
+dispatch_scroll_motion(struct xwl_seat *xwl_seat)
+{
+    ValuatorMask mask;
+    const int divisor = 10;
+    wl_fixed_t dy = xwl_seat->pending_pointer_event.scroll_dy;
+    wl_fixed_t dx = xwl_seat->pending_pointer_event.scroll_dx;
+    wl_fixed_t discrete_dy = xwl_seat->pending_pointer_event.scroll_discrete_dy;
+    wl_fixed_t discrete_dx = xwl_seat->pending_pointer_event.scroll_discrete_dx;
+
+    valuator_mask_zero(&mask);
+    if (xwl_seat->pending_pointer_event.has_vertical_scroll)
+        valuator_mask_set_double(&mask,
+                                 3,
+                                 wl_fixed_to_double(dy) / divisor);
+    else if (xwl_seat->pending_pointer_event.has_vertical_scroll_discrete)
+        valuator_mask_set(&mask, 3, discrete_dy);
+
+    if (xwl_seat->pending_pointer_event.has_horizontal_scroll)
+        valuator_mask_set_double(&mask,
+                                 2,
+                                 wl_fixed_to_double(dx) / divisor);
+    else if (xwl_seat->pending_pointer_event.has_horizontal_scroll_discrete)
+        valuator_mask_set(&mask, 2, discrete_dx);
+
+    QueuePointerEvents(get_pointer_device(xwl_seat),
+                       MotionNotify, 0, POINTER_RELATIVE, &mask);
+}
+
+
 static void
 dispatch_pointer_motion_event(struct xwl_seat *xwl_seat)
 {
@@ -685,8 +709,18 @@ dispatch_pointer_motion_event(struct xwl_seat *xwl_seat)
             dispatch_absolute_motion(xwl_seat);
     }
 
+    if (xwl_seat->pending_pointer_event.has_vertical_scroll ||
+        xwl_seat->pending_pointer_event.has_horizontal_scroll ||
+        xwl_seat->pending_pointer_event.has_vertical_scroll_discrete ||
+        xwl_seat->pending_pointer_event.has_horizontal_scroll_discrete)
+        dispatch_scroll_motion(xwl_seat);
+
     xwl_seat->pending_pointer_event.has_absolute = FALSE;
     xwl_seat->pending_pointer_event.has_relative = FALSE;
+    xwl_seat->pending_pointer_event.has_vertical_scroll = FALSE;
+    xwl_seat->pending_pointer_event.has_horizontal_scroll = FALSE;
+    xwl_seat->pending_pointer_event.has_vertical_scroll_discrete = FALSE;
+    xwl_seat->pending_pointer_event.has_horizontal_scroll_discrete = FALSE;
 }
 
 static void
@@ -743,42 +777,15 @@ pointer_handle_axis(void *data, struct wl_pointer *pointer,
                     uint32_t time, uint32_t axis, wl_fixed_t value)
 {
     struct xwl_seat *xwl_seat = data;
-    int index;
-    const int divisor = 10;
-    ValuatorMask mask;
-    struct axis_discrete_pending *pending = NULL;
-    struct axis_discrete_pending *iter;
 
     switch (axis) {
     case WL_POINTER_AXIS_VERTICAL_SCROLL:
-        index = 3;
-        break;
+        xwl_seat->pending_pointer_event.has_vertical_scroll = TRUE;
+        xwl_seat->pending_pointer_event.scroll_dy = value;
     case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
-        index = 2;
-        break;
-    default:
-        return;
-    }
-
-    xorg_list_for_each_entry(iter, &xwl_seat->axis_discrete_pending, l) {
-        if (iter->axis == axis) {
-            pending = iter;
-            break;
-        }
+        xwl_seat->pending_pointer_event.has_horizontal_scroll = TRUE;
+        xwl_seat->pending_pointer_event.scroll_dx = value;
     }
-
-    valuator_mask_zero(&mask);
-
-    if (pending) {
-        valuator_mask_set(&mask, index, pending->discrete);
-        xorg_list_del(&pending->l);
-        free(pending);
-    } else {
-        valuator_mask_set_double(&mask, index, wl_fixed_to_double(value) / divisor);
-    }
-
-    QueuePointerEvents(get_pointer_device(xwl_seat),
-                       MotionNotify, 0, POINTER_RELATIVE, &mask);
 }
 
 static void
@@ -801,6 +808,18 @@ static void
 pointer_handle_axis_stop(void *data, struct wl_pointer *wl_pointer,
                          uint32_t time, uint32_t axis)
 {
+    struct xwl_seat *xwl_seat = data;
+
+    switch (axis) {
+    case WL_POINTER_AXIS_VERTICAL_SCROLL:
+        xwl_seat->pending_pointer_event.has_vertical_scroll = TRUE;
+        xwl_seat->pending_pointer_event.scroll_dy = 0;
+        break;
+    case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
+        xwl_seat->pending_pointer_event.has_horizontal_scroll = TRUE;
+        xwl_seat->pending_pointer_event.scroll_dx = 0;
+        break;
+    }
 }
 
 static void
@@ -809,14 +828,16 @@ pointer_handle_axis_discrete(void *data, struct wl_pointer *wl_pointer,
 {
     struct xwl_seat *xwl_seat = data;
 
-    struct axis_discrete_pending *pending = malloc(sizeof *pending);
-    if (!pending)
-        return;
-
-    pending->axis = axis;
-    pending->discrete = discrete;
-
-    xorg_list_add(&pending->l, &xwl_seat->axis_discrete_pending);
+    switch (axis) {
+    case WL_POINTER_AXIS_VERTICAL_SCROLL:
+        xwl_seat->pending_pointer_event.has_vertical_scroll_discrete = TRUE;
+        xwl_seat->pending_pointer_event.scroll_discrete_dy = discrete;
+        break;
+    case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
+        xwl_seat->pending_pointer_event.has_horizontal_scroll_discrete = TRUE;
+        xwl_seat->pending_pointer_event.scroll_discrete_dx = discrete;
+        break;
+    }
 }
 
 static const struct wl_pointer_listener pointer_listener = {
@@ -1832,7 +1853,6 @@ create_input_device(struct xwl_screen *xwl_screen, uint32_t id, uint32_t version
     wl_array_init(&xwl_seat->keys);
 
     xorg_list_init(&xwl_seat->touches);
-    xorg_list_init(&xwl_seat->axis_discrete_pending);
     xorg_list_init(&xwl_seat->sync_pending);
 }
 
@@ -1841,7 +1861,6 @@ xwl_seat_destroy(struct xwl_seat *xwl_seat)
 {
     struct xwl_touch *xwl_touch, *next_xwl_touch;
     struct sync_pending *p, *npd;
-    struct axis_discrete_pending *ad, *ad_next;
 
     xorg_list_for_each_entry_safe(xwl_touch, next_xwl_touch,
                                   &xwl_seat->touches, link_touch) {
@@ -1854,11 +1873,6 @@ xwl_seat_destroy(struct xwl_seat *xwl_seat)
         free (p);
     }
 
-    xorg_list_for_each_entry_safe(ad, ad_next, &xwl_seat->axis_discrete_pending, l) {
-        xorg_list_del(&ad->l);
-        free(ad);
-    }
-
     release_tablet_manager_seat(xwl_seat);
 
     release_grab(xwl_seat);
diff --git a/hw/xwayland/xwayland-input.h b/hw/xwayland/xwayland-input.h
index dbe215bdb..4fd175b13 100644
--- a/hw/xwayland/xwayland-input.h
+++ b/hw/xwayland/xwayland-input.h
@@ -93,7 +93,6 @@ struct xwl_seat {
     char *keymap;
     struct wl_surface *keyboard_focus;
 
-    struct xorg_list axis_discrete_pending;
     struct xorg_list sync_pending;
 
     struct xwl_pointer_warp_emulator *pointer_warp_emulator;
@@ -111,6 +110,15 @@ struct xwl_seat {
         double dy;
         double dx_unaccel;
         double dy_unaccel;
+
+        wl_fixed_t scroll_dy;
+        wl_fixed_t scroll_dx;
+        int32_t scroll_discrete_dy;
+        int32_t scroll_discrete_dx;
+        Bool has_vertical_scroll;
+        Bool has_horizontal_scroll;
+        Bool has_vertical_scroll_discrete;
+        Bool has_horizontal_scroll_discrete;
     } pending_pointer_event;
 
     struct xorg_list tablets;


More information about the xorg-commit mailing list