gtkeventcontrollerscroll: Always accumulate discrete deltas
authorJosé Expósito <jose.exposito89@gmail.com>
Mon, 20 Sep 2021 18:00:04 +0000 (20:00 +0200)
committerCarlos Garnacho <carlosg@gnome.org>
Wed, 10 Aug 2022 14:23:58 +0000 (14:23 +0000)
When GTK_EVENT_CONTROLLER_SCROLL_DISCRETE is set, accumulate deltas also
for mouse scroll so a high-resolution mouse wheel click behaves in the
in the same manner as a low-resolution mouse wheel click.

gtk/gtkeventcontrollerscroll.c

index e51cb7b241a0f98c90bdcf88a99aef4f5aa57595..197574dca821105e697650f73caa51c710df9659 100644 (file)
@@ -85,6 +85,8 @@ struct _GtkEventControllerScroll
   /* For discrete event coalescing */
   double cur_dx;
   double cur_dy;
+  double last_cur_dx;
+  double last_cur_dy;
 
   GdkScrollUnit cur_unit;
 
@@ -337,6 +339,17 @@ gtk_event_controller_scroll_handle_hold_event (GtkEventController *controller,
   return GDK_EVENT_PROPAGATE;
 }
 
+static gboolean
+should_reset_discrete_acc (double current_delta,
+                           double last_delta)
+{
+  if (last_delta == 0)
+    return TRUE;
+
+  return (current_delta < 0 && last_delta > 0) ||
+         (current_delta > 0 && last_delta < 0);
+}
+
 static gboolean
 gtk_event_controller_scroll_handle_event (GtkEventController *controller,
                                           GdkEvent           *event,
@@ -422,6 +435,45 @@ gtk_event_controller_scroll_handle_event (GtkEventController *controller,
         dy = 0;
       if ((scroll->flags & GTK_EVENT_CONTROLLER_SCROLL_HORIZONTAL) == 0)
         dx = 0;
+
+      if (scroll->flags & GTK_EVENT_CONTROLLER_SCROLL_DISCRETE)
+        {
+          int steps;
+
+          if (dx != 0)
+            {
+              if (should_reset_discrete_acc (dx, scroll->last_cur_dx))
+                scroll->cur_dx = 0;
+
+              scroll->last_cur_dx = dx;
+            }
+
+          if (dy != 0)
+            {
+              if (should_reset_discrete_acc (dy, scroll->last_cur_dy))
+                scroll->cur_dy = 0;
+
+              scroll->last_cur_dy = dy;
+            }
+
+          scroll->cur_dx += dx;
+          scroll->cur_dy += dy;
+          dx = dy = 0;
+
+          if (ABS (scroll->cur_dx) >= 1)
+            {
+              steps = trunc (scroll->cur_dx);
+              scroll->cur_dx -= steps;
+              dx = steps;
+            }
+
+          if (ABS (scroll->cur_dy) >= 1)
+            {
+              steps = trunc (scroll->cur_dy);
+              scroll->cur_dy -= steps;
+              dy = steps;
+            }
+        }
     }
 
   scroll->cur_unit = scroll_unit;