Blob Blame History Raw
From 7aebc9e63d6551a3e12cf6da1d9da4253c116e71 Mon Sep 17 00:00:00 2001
From: Carlos Garnacho <carlosg@gnome.org>
Date: Tue, 5 Mar 2024 12:51:30 +0100
Subject: [PATCH 1/4] clutter: Pass scroll source to discrete events

This piece of information was lost, always returning
"unknown". We can do better on the native backend.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3642>
---
 clutter/clutter/clutter-event-private.h | 1 +
 clutter/clutter/clutter-event.c         | 2 ++
 src/backends/native/meta-seat-impl.c    | 1 +
 src/backends/x11/meta-seat-x11.c        | 1 +
 4 files changed, 5 insertions(+)

diff --git a/clutter/clutter/clutter-event-private.h b/clutter/clutter/clutter-event-private.h
index 35740c9b7ee..52c45163851 100644
--- a/clutter/clutter/clutter-event-private.h
+++ b/clutter/clutter/clutter-event-private.h
@@ -64,6 +64,7 @@ ClutterEvent * clutter_event_scroll_discrete_new (ClutterEventFlags       flags,
                                                   ClutterInputDeviceTool *tool,
                                                   ClutterModifierType     modifiers,
                                                   graphene_point_t        coords,
+                                                  ClutterScrollSource     scroll_source,
                                                   ClutterScrollDirection  direction);
 CLUTTER_EXPORT
 ClutterEvent * clutter_event_crossing_new (ClutterEventType      type,
diff --git a/clutter/clutter/clutter-event.c b/clutter/clutter/clutter-event.c
index 7723c85048b..d204574d0b9 100644
--- a/clutter/clutter/clutter-event.c
+++ b/clutter/clutter/clutter-event.c
@@ -2017,6 +2017,7 @@ clutter_event_scroll_discrete_new (ClutterEventFlags       flags,
                                    ClutterInputDeviceTool *tool,
                                    ClutterModifierType     modifiers,
                                    graphene_point_t        coords,
+                                   ClutterScrollSource     scroll_source,
                                    ClutterScrollDirection  direction)
 {
   ClutterEvent *event;
@@ -2031,6 +2032,7 @@ clutter_event_scroll_discrete_new (ClutterEventFlags       flags,
   event->scroll.x = coords.x;
   event->scroll.y = coords.y;
   event->scroll.direction = direction;
+  event->scroll.scroll_source = scroll_source;
   event->scroll.modifier_state = modifiers;
   event->scroll.tool = tool;
 
diff --git a/src/backends/native/meta-seat-impl.c b/src/backends/native/meta-seat-impl.c
index 87bf15c7b42..8bb9bd05eb2 100644
--- a/src/backends/native/meta-seat-impl.c
+++ b/src/backends/native/meta-seat-impl.c
@@ -990,6 +990,7 @@ notify_discrete_scroll (ClutterInputDevice     *input_device,
                                        NULL,
                                        modifiers,
                                        GRAPHENE_POINT_INIT (x, y),
+                                       scroll_source,
                                        direction);
 
   queue_event (seat_impl, event);
diff --git a/src/backends/x11/meta-seat-x11.c b/src/backends/x11/meta-seat-x11.c
index 0560a0d77d3..e76a9d0467a 100644
--- a/src/backends/x11/meta-seat-x11.c
+++ b/src/backends/x11/meta-seat-x11.c
@@ -2378,6 +2378,7 @@ meta_seat_x11_translate_event (MetaSeatX11  *seat,
                                                        tool,
                                                        state,
                                                        GRAPHENE_POINT_INIT (x, y),
+                                                       CLUTTER_SCROLL_SOURCE_UNKNOWN,
                                                        scroll_direction);
 
             g_debug ("scroll: win:0x%x, device:%d '%s', time:%d "
-- 
GitLab


From ddc76d878e937665f90a9a35c87229f9711a91b8 Mon Sep 17 00:00:00 2001
From: Carlos Garnacho <carlosg@gnome.org>
Date: Tue, 5 Mar 2024 13:30:24 +0100
Subject: [PATCH 2/4] wayland: Fix handling of non-v120 discrete events on
 wl_seat >= v8

Unveiled by commit e0c4b2b241 ("backends/native: Mark the emulated smooth
scroll event as such"). The sudden "lack" of smooth scroll events (Used by
Clutter to forward v120 events) made it evident we silently ignore Clutter
discrete events, as we don't send wl_pointer.axis_value120 for these.

Fix this by assigning a value120 value to discrete scroll events. This
makes wl_pointer.axis_value120 events actually sent on non-v120 mice.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3642>
---
 src/wayland/meta-wayland-pointer.c | 44 +++++++++++++++++++-----------
 1 file changed, 28 insertions(+), 16 deletions(-)

diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index bbff7e2565e..81db9e4f54b 100644
--- a/src/wayland/meta-wayland-pointer.c
+++ b/src/wayland/meta-wayland-pointer.c
@@ -748,24 +748,28 @@ handle_scroll_event (MetaWaylandPointer *pointer,
       is_discrete_event = TRUE;
       y_value = -DEFAULT_AXIS_STEP_DISTANCE;
       y_discrete = -1;
+      y_value120 = y_discrete * 120;
       break;
 
     case CLUTTER_SCROLL_DOWN:
       is_discrete_event = TRUE;
       y_value = DEFAULT_AXIS_STEP_DISTANCE;
       y_discrete = 1;
+      y_value120 = y_discrete * 120;
       break;
 
     case CLUTTER_SCROLL_LEFT:
       is_discrete_event = TRUE;
       x_value = -DEFAULT_AXIS_STEP_DISTANCE;
       x_discrete = -1;
+      x_value120 = x_discrete * 120;
       break;
 
     case CLUTTER_SCROLL_RIGHT:
       is_discrete_event = TRUE;
       x_value = DEFAULT_AXIS_STEP_DISTANCE;
       x_discrete = 1;
+      x_value120 = x_discrete * 120;
       break;
 
     case CLUTTER_SCROLL_SMOOTH:
@@ -805,19 +809,23 @@ handle_scroll_event (MetaWaylandPointer *pointer,
       /* X axis */
       if (client_version >= WL_POINTER_AXIS_VALUE120_SINCE_VERSION)
         {
-          if (is_value120_event && x_value120 != 0)
-            wl_pointer_send_axis_value120 (resource,
-                                           WL_POINTER_AXIS_HORIZONTAL_SCROLL,
-                                           x_value120);
+          if (x_value120 != 0)
+            {
+              wl_pointer_send_axis_value120 (resource,
+                                             WL_POINTER_AXIS_HORIZONTAL_SCROLL,
+                                             x_value120);
+            }
 
           send_axis_x = !is_discrete_event;
         }
       else if (client_version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION)
         {
-          if (is_discrete_event && x_discrete != 0)
-            wl_pointer_send_axis_discrete (resource,
-                                           WL_POINTER_AXIS_HORIZONTAL_SCROLL,
-                                           x_discrete);
+          if (x_discrete != 0)
+            {
+              wl_pointer_send_axis_discrete (resource,
+                                             WL_POINTER_AXIS_HORIZONTAL_SCROLL,
+                                             x_discrete);
+            }
 
           send_axis_x = !is_value120_event;
         }
@@ -834,19 +842,23 @@ handle_scroll_event (MetaWaylandPointer *pointer,
       /* Y axis */
       if (client_version >= WL_POINTER_AXIS_VALUE120_SINCE_VERSION)
         {
-          if (is_value120_event && y_value120 != 0)
-            wl_pointer_send_axis_value120 (resource,
-                                           WL_POINTER_AXIS_VERTICAL_SCROLL,
-                                           y_value120);
+          if (y_value120 != 0)
+            {
+              wl_pointer_send_axis_value120 (resource,
+                                             WL_POINTER_AXIS_VERTICAL_SCROLL,
+                                             y_value120);
+            }
 
           send_axis_y = !is_discrete_event;
         }
       else if (client_version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION)
         {
-          if (is_discrete_event && y_discrete != 0)
-            wl_pointer_send_axis_discrete (resource,
-                                           WL_POINTER_AXIS_VERTICAL_SCROLL,
-                                           y_discrete);
+          if (y_discrete != 0)
+            {
+              wl_pointer_send_axis_discrete (resource,
+                                             WL_POINTER_AXIS_VERTICAL_SCROLL,
+                                             y_discrete);
+            }
 
           send_axis_y = !is_value120_event;
         }
-- 
GitLab


From 39d8e44f5e17ee1204fac3048de4743bec3aa5e4 Mon Sep 17 00:00:00 2001
From: Carlos Garnacho <carlosg@gnome.org>
Date: Tue, 5 Mar 2024 13:39:17 +0100
Subject: [PATCH 3/4] wayland: Always send wl_pointer.axis after
 .axis_value120/discrete

The wl_pointer.axis_discrete axis (applicable to wl_seat <= v8) is
meant to be sent together with wl_pointer.axis events in the same
frame. And the wl_pointer.axis_value120 event replaces it in
wl_seat >= v9, but has the same relation with the other information
available in a frame.

This emission should not be conditional to anything, so drop the
various checks leading to maybe sending wl_pointer.axis or not.

This fixes emission of wl_pointer.axis in conjunction with discrete
events, for some combinations of versions and (non)value120 mice.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3642>
---
 src/wayland/meta-wayland-pointer.c | 21 +++------------------
 1 file changed, 3 insertions(+), 18 deletions(-)

diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index 81db9e4f54b..4d1971c3474 100644
--- a/src/wayland/meta-wayland-pointer.c
+++ b/src/wayland/meta-wayland-pointer.c
@@ -716,7 +716,6 @@ handle_scroll_event (MetaWaylandPointer *pointer,
   int32_t x_value120 = 0, y_value120 = 0;
   enum wl_pointer_axis_source source = -1;
   MetaWaylandPointerClient *client;
-  gboolean is_discrete_event = FALSE, is_value120_event = FALSE;
   ClutterScrollFinishFlags finish_flags;
 
   if (clutter_event_get_flags (event) & CLUTTER_EVENT_FLAG_POINTER_EMULATED)
@@ -745,28 +744,24 @@ handle_scroll_event (MetaWaylandPointer *pointer,
   switch (clutter_event_get_scroll_direction (event))
     {
     case CLUTTER_SCROLL_UP:
-      is_discrete_event = TRUE;
       y_value = -DEFAULT_AXIS_STEP_DISTANCE;
       y_discrete = -1;
       y_value120 = y_discrete * 120;
       break;
 
     case CLUTTER_SCROLL_DOWN:
-      is_discrete_event = TRUE;
       y_value = DEFAULT_AXIS_STEP_DISTANCE;
       y_discrete = 1;
       y_value120 = y_discrete * 120;
       break;
 
     case CLUTTER_SCROLL_LEFT:
-      is_discrete_event = TRUE;
       x_value = -DEFAULT_AXIS_STEP_DISTANCE;
       x_discrete = -1;
       x_value120 = x_discrete * 120;
       break;
 
     case CLUTTER_SCROLL_RIGHT:
-      is_discrete_event = TRUE;
       x_value = DEFAULT_AXIS_STEP_DISTANCE;
       x_discrete = 1;
       x_value120 = x_discrete * 120;
@@ -783,8 +778,7 @@ handle_scroll_event (MetaWaylandPointer *pointer,
         x_value = wl_fixed_from_double (dx) * factor;
         y_value = wl_fixed_from_double (dy) * factor;
 
-        is_value120_event = (source == WL_POINTER_AXIS_SOURCE_WHEEL);
-        if (is_value120_event)
+        if (source == WL_POINTER_AXIS_SOURCE_WHEEL)
           {
             x_value120 = (int32_t) (dx * 120);
             y_value120 = (int32_t) (dy * 120);
@@ -801,7 +795,6 @@ handle_scroll_event (MetaWaylandPointer *pointer,
   wl_resource_for_each (resource, &client->pointer_resources)
     {
       int client_version = wl_resource_get_version (resource);
-      gboolean send_axis_x = TRUE, send_axis_y = TRUE;
 
       if (client_version >= WL_POINTER_AXIS_SOURCE_SINCE_VERSION)
         wl_pointer_send_axis_source (resource, source);
@@ -815,8 +808,6 @@ handle_scroll_event (MetaWaylandPointer *pointer,
                                              WL_POINTER_AXIS_HORIZONTAL_SCROLL,
                                              x_value120);
             }
-
-          send_axis_x = !is_discrete_event;
         }
       else if (client_version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION)
         {
@@ -826,11 +817,9 @@ handle_scroll_event (MetaWaylandPointer *pointer,
                                              WL_POINTER_AXIS_HORIZONTAL_SCROLL,
                                              x_discrete);
             }
-
-          send_axis_x = !is_value120_event;
         }
 
-      if (x_value && send_axis_x)
+      if (x_value)
         wl_pointer_send_axis (resource, clutter_event_get_time (event),
                               WL_POINTER_AXIS_HORIZONTAL_SCROLL, x_value);
 
@@ -848,8 +837,6 @@ handle_scroll_event (MetaWaylandPointer *pointer,
                                              WL_POINTER_AXIS_VERTICAL_SCROLL,
                                              y_value120);
             }
-
-          send_axis_y = !is_discrete_event;
         }
       else if (client_version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION)
         {
@@ -859,11 +846,9 @@ handle_scroll_event (MetaWaylandPointer *pointer,
                                              WL_POINTER_AXIS_VERTICAL_SCROLL,
                                              y_discrete);
             }
-
-          send_axis_y = !is_value120_event;
         }
 
-      if (y_value && send_axis_y)
+      if (y_value)
         wl_pointer_send_axis (resource, clutter_event_get_time (event),
                               WL_POINTER_AXIS_VERTICAL_SCROLL, y_value);
 
-- 
GitLab


From ab8e145e25ae70024b9838856663a18a5aaf3ff1 Mon Sep 17 00:00:00 2001
From: Carlos Garnacho <carlosg@gnome.org>
Date: Tue, 5 Mar 2024 13:43:57 +0100
Subject: [PATCH 4/4] wayland: Filter scroll events based on source

The POINTER_EMULATED flag was a convenience to filter either
side of smooth/discrete events that we should ignore based on
the source.

This distinction was challenged, first by v120 mice that use
Clutter smooth events to deliver semi-discrete changes, second
by commit e0c4b2b241 ("backends/native: Mark the emulated smooth
scroll event as such") which made the smooth events be flagged
as emulated, and the discrete whole-step events marked as
real.

This distinction feels convenient for the time being, since
upper layers might be confused by real smooth scroll events
without finish flags. Adapt to this change at MetaWaylandPointer
so that we drop the POINTER_EMULATED check, and the events are
perhaps filtered based on their source and the preferred
wl_seat version of the client that we are talking to.

This handles the whole grid of combinations:
- wheel sources with wl_seat >=8 result in wl_pointer.axis_value120
  from "emulated" smooth scroll events, with value120 information.
- wheel sources with wl_seat < 8 result in wl_pointer.axis_discrete
  from "real" discrete scroll events.
- finger/continuous sources prefer smooth events. Previously, always
  non-emulated for those.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3642>
---
 src/wayland/meta-wayland-pointer.c | 34 +++++++++++++++++++++++++++---
 1 file changed, 31 insertions(+), 3 deletions(-)

diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index 4d1971c3474..9d5a381cd4d 100644
--- a/src/wayland/meta-wayland-pointer.c
+++ b/src/wayland/meta-wayland-pointer.c
@@ -706,6 +706,34 @@ handle_button_event (MetaWaylandPointer *pointer,
     }
 }
 
+static gboolean
+maybe_filter_scroll_event (const ClutterEvent *event,
+                           int                 client_version)
+{
+  ClutterScrollSource source;
+
+  source = clutter_event_get_scroll_source (event);
+
+  switch (clutter_event_get_scroll_direction (event))
+    {
+    case CLUTTER_SCROLL_UP:
+    case CLUTTER_SCROLL_DOWN:
+    case CLUTTER_SCROLL_LEFT:
+    case CLUTTER_SCROLL_RIGHT:
+      if (source == CLUTTER_SCROLL_SOURCE_WHEEL)
+        return client_version >= WL_POINTER_AXIS_VALUE120_SINCE_VERSION;
+
+      return TRUE;
+    case CLUTTER_SCROLL_SMOOTH:
+      if (source == CLUTTER_SCROLL_SOURCE_WHEEL)
+        return client_version < WL_POINTER_AXIS_VALUE120_SINCE_VERSION;
+
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
 static void
 handle_scroll_event (MetaWaylandPointer *pointer,
                      const ClutterEvent *event)
@@ -718,9 +746,6 @@ handle_scroll_event (MetaWaylandPointer *pointer,
   MetaWaylandPointerClient *client;
   ClutterScrollFinishFlags finish_flags;
 
-  if (clutter_event_get_flags (event) & CLUTTER_EVENT_FLAG_POINTER_EMULATED)
-    return;
-
   client = pointer->focus_client;
   if (!client)
     return;
@@ -796,6 +821,9 @@ handle_scroll_event (MetaWaylandPointer *pointer,
     {
       int client_version = wl_resource_get_version (resource);
 
+      if (maybe_filter_scroll_event (event, client_version))
+        continue;
+
       if (client_version >= WL_POINTER_AXIS_SOURCE_SINCE_VERSION)
         wl_pointer_send_axis_source (resource, source);
 
-- 
GitLab