[gtk/scroll-compression] Keep scroll history



commit 2321c785003642d79c922b1d1f5269a2ce225ff5
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Jun 8 20:29:38 2020 -0400

    Keep scroll history
    
    Similar to how we keep motion history for compressed
    events, keep scroll history for compressed scroll
    events.

 gdk/gdkevents.c        | 75 +++++++++++++++++++++++++++++++++++++++++++-------
 gdk/gdkevents.h        | 11 ++++++++
 gdk/gdkeventsprivate.h |  4 +++
 3 files changed, 80 insertions(+), 10 deletions(-)
---
diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c
index 1b20a57dac..7c621f7e5b 100644
--- a/gdk/gdkevents.c
+++ b/gdk/gdkevents.c
@@ -632,9 +632,7 @@ gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
   GdkEvent *last_event = NULL;
   GList *scrolls = NULL;
   double delta_x, delta_y;
-  double dx, dy;
-
-  delta_x = delta_y = 0;
+  GArray *history = NULL;
 
   l = g_queue_peek_tail_link (&display->queued_events);
 
@@ -664,18 +662,31 @@ gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
       device = event->device;
       scrolls = l;
 
-      gdk_scroll_event_get_deltas (event, &dx, &dy);
-      delta_x += dx;
-      delta_y += dy;
-
       l = l->prev;
     }
 
+  delta_x = delta_y = 0;
+
   while (scrolls && scrolls->next != NULL)
     {
+      GdkEvent *event = scrolls->data;
       GList *next = scrolls->next;
+      GdkScrollHistory h;
+      double dx, dy;
+
+      if (!history)
+        history = g_array_new (FALSE, TRUE, sizeof (GdkScrollHistory));
+
+      gdk_scroll_event_get_deltas (event, &dx, &dy);
+      delta_x += dx;
+      delta_y += dy;
 
-      gdk_event_unref (scrolls->data);
+      h.time = gdk_event_get_time (event);
+      h.delta_x = dx;
+      h.delta_y = dy;
+      g_array_append_val (history, h);
+
+      gdk_event_unref (event);
       g_queue_delete_link (&display->queued_events, scrolls);
       scrolls = next;
     }
@@ -683,19 +694,23 @@ gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
   if (scrolls)
     {
       GdkEvent *old_event, *event;
+      double dx, dy;
 
       old_event = scrolls->data;
 
+      gdk_scroll_event_get_deltas (old_event, &dx, &dy);
       event = gdk_scroll_event_new (surface,
                                     device,
                                     gdk_event_get_source_device (old_event),
                                     gdk_event_get_device_tool (old_event),
                                     gdk_event_get_time (old_event),
                                     gdk_event_get_modifier_state (old_event),
-                                    delta_x,
-                                    delta_y,
+                                    delta_x + dx,
+                                    delta_y + dy,
                                     gdk_scroll_event_is_stop (old_event));
 
+      ((GdkScrollEvent *)event)->history = history;
+
       g_queue_delete_link (&display->queued_events, scrolls);
       g_queue_push_tail (&display->queued_events, event);
     }
@@ -2247,6 +2262,8 @@ gdk_scroll_event_finalize (GdkEvent *event)
   GdkScrollEvent *self = (GdkScrollEvent *) event;
 
   g_clear_object (&self->tool);
+  if (self->history)
+    g_array_free (self->history, TRUE);
 
   GDK_EVENT_SUPER (self)->finalize (event);
 }
@@ -2394,6 +2411,44 @@ gdk_scroll_event_is_stop (GdkEvent *event)
   return self->is_stop;
 }
 
+/**
+ * gdk_scroll_event_get_history:
+ * @event: (type GdkScrollEvent): a scroll #GdkEvent
+ * @out_n: (out): Return location for the length of the returned array
+ *
+ * Retrieves the history of the @event, as a list of times and deltas.
+ *
+ * Returns: (transfer container) (array length=out_n) (nullable): an
+ *   array of #GdkScrollHistory
+ */
+GdkScrollHistory *
+gdk_scroll_event_get_history (GdkEvent *event,
+                              guint    *out_n)
+{
+  GdkScrollEvent *self = (GdkScrollEvent *) event;
+
+  g_return_val_if_fail (GDK_IS_EVENT (event), NULL);
+  g_return_val_if_fail (GDK_IS_EVENT_TYPE (event, GDK_SCROLL), NULL);
+  g_return_val_if_fail (out_n != NULL, NULL);
+
+  if (self->history &&
+      self->history->len > 0)
+    {
+      GdkScrollHistory *result;
+
+      *out_n = self->history->len;
+
+      result = g_new (GdkScrollHistory, self->history->len);
+      memcpy (result, self->history->data, sizeof (GdkScrollHistory) * self->history->len);
+
+      return result;
+    }
+
+  *out_n = 0;
+
+  return NULL;
+}
+
 /* }}} */
 
 /* {{{ GdkTouchpadEvent */
diff --git a/gdk/gdkevents.h b/gdk/gdkevents.h
index e702717541..17f76ce0d8 100644
--- a/gdk/gdkevents.h
+++ b/gdk/gdkevents.h
@@ -392,6 +392,17 @@ GDK_AVAILABLE_IN_ALL
 void                    gdk_scroll_event_get_deltas     (GdkEvent *event,
                                                          double   *delta_x,
                                                          double   *delta_y);
+
+typedef struct {
+  guint32 time;
+  double delta_x;
+  double delta_y;
+} GdkScrollHistory;
+
+GDK_AVAILABLE_IN_ALL
+GdkScrollHistory *      gdk_scroll_event_get_history    (GdkEvent *event,
+                                                         guint    *out_n);
+
 GDK_AVAILABLE_IN_ALL
 gboolean                gdk_scroll_event_is_stop        (GdkEvent *event);
 GDK_AVAILABLE_IN_ALL
diff --git a/gdk/gdkeventsprivate.h b/gdk/gdkeventsprivate.h
index 0fd0b3e908..a21e458746 100644
--- a/gdk/gdkeventsprivate.h
+++ b/gdk/gdkeventsprivate.h
@@ -211,6 +211,9 @@ struct _GdkTouchEvent
  * @pointer_emulated: whether the scroll event was the result of
  *   a pointer emulation
  * @tool: a #GdkDeviceTool
+ * @history: (element-type GdkScrollHistory): array of times and deltas
+ *   for other scroll events that were compressed before delivering the
+ *   current event
  *
  * Generated from button presses for the buttons 4 to 7. Wheel mice are
  * usually configured to generate button press events for buttons 4 and 5
@@ -232,6 +235,7 @@ struct _GdkScrollEvent
   gboolean pointer_emulated;
   gboolean is_stop;
   GdkDeviceTool *tool;
+  GArray *history; /* <GdkScrollHistory> */
 };
 
 /*


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]