diff --git a/3642.patch b/3642.patch new file mode 100644 index 0000000..a25b739 --- /dev/null +++ b/3642.patch @@ -0,0 +1,424 @@ +From 7aebc9e63d6551a3e12cf6da1d9da4253c116e71 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +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: +--- + 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 +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: +--- + 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 +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: +--- + 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 +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: +--- + 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 + diff --git a/mutter.spec b/mutter.spec index 0ad3c79..7b9abb5 100644 --- a/mutter.spec +++ b/mutter.spec @@ -42,6 +42,10 @@ Patch: 0001-Revert-x11-Use-input-region-from-frame-window-for-de.patch # which solves the problems reported with #3329 alone Patch: 0001-modified-3329.patch +# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3642 +# Fix mouse wheel scrolling +Patch: 3642.patch + BuildRequires: pkgconfig(gobject-introspection-1.0) >= 1.41.0 BuildRequires: pkgconfig(sm) BuildRequires: pkgconfig(libwacom)