[gtk+/wip/carlosg/event-as-object: 836/844] gdk: Implement motion history as motion event data
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/carlosg/event-as-object: 836/844] gdk: Implement motion history as motion event data
- Date: Wed, 13 Dec 2017 17:08:03 +0000 (UTC)
commit c153f441083109a7b3895e9d823eb0b66e3ee3a9
Author: Carlos Garnacho <carlosg gnome org>
Date: Tue Oct 31 12:37:50 2017 +0100
gdk: Implement motion history as motion event data
In the motion compression phase the coalesced events will be saved
as a GdkTimeCoord on the motion event that shall be delivered.
For simplicity (and because history doesn't make much sense otherwise)
event history is only recorded while there are buttons pressed, this
also tidily ensures that those coalesced events would have the same
target widget on the gtk side than the delivered one, because of
implicit grabs.
gdk/gdkevents.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++
gdk/gdkevents.h | 1 +
gdk/gdkeventsprivate.h | 1 +
3 files changed, 58 insertions(+), 0 deletions(-)
---
diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c
index 8a0baba..d8e5637 100644
--- a/gdk/gdkevents.c
+++ b/gdk/gdkevents.c
@@ -337,13 +337,37 @@ _gdk_event_unqueue (GdkDisplay *display)
return event;
}
+static void
+gdk_event_push_history (GdkEvent *event,
+ const GdkEvent *history_event)
+{
+ GdkTimeCoord *hist;
+ GdkDevice *device;
+ gint i, n_axes;
+
+ g_assert (event->any.type == GDK_MOTION_NOTIFY);
+ g_assert (history_event->any.type == GDK_MOTION_NOTIFY);
+
+ hist = g_new0 (GdkTimeCoord, 1);
+
+ device = gdk_event_get_device (history_event);
+ n_axes = gdk_device_get_n_axes (device);
+
+ for (i = 0; i <= MIN (n_axes, GDK_MAX_TIMECOORD_AXES); i++)
+ gdk_event_get_axis (history_event, i, &hist->axes[i]);
+
+ event->motion.history = g_list_prepend (event->motion.history, hist);
+}
+
void
_gdk_event_queue_handle_motion_compression (GdkDisplay *display)
{
GList *tmp_list;
GList *pending_motions = NULL;
+ GList *history = NULL;
GdkWindow *pending_motion_window = NULL;
GdkDevice *pending_motion_device = NULL;
+ GdkEvent *last_motion = NULL;
/* If the last N events in the event queue are motion notify
* events for the same window, drop all but the last */
@@ -371,6 +395,9 @@ _gdk_event_queue_handle_motion_compression (GdkDisplay *display)
if (!event->any.window->event_compression)
break;
+ if (!last_motion)
+ last_motion = event;
+
pending_motion_window = event->any.window;
pending_motion_device = event->any.device;
pending_motions = tmp_list;
@@ -381,6 +408,15 @@ _gdk_event_queue_handle_motion_compression (GdkDisplay *display)
while (pending_motions && pending_motions->next != NULL)
{
GList *next = pending_motions->next;
+
+ history = g_list_prepend (history, pending_motions->data);
+
+ if (last_motion &&
+ (last_motion->motion.state &
+ (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK |
+ GDK_BUTTON4_MASK | GDK_BUTTON5_MASK)))
+ gdk_event_push_history (last_motion, pending_motions->data);
+
gdk_event_free (pending_motions->data);
display->queued_events = g_list_delete_link (display->queued_events,
pending_motions);
@@ -558,6 +594,12 @@ gdk_event_get_pointer_emulated (GdkEvent *event)
return (event->any.flags & GDK_EVENT_POINTER_EMULATED) != 0;
}
+static GdkTimeCoord *
+copy_time_coord (const GdkTimeCoord *coord)
+{
+ return g_memdup (coord, sizeof (GdkTimeCoord));
+}
+
/**
* gdk_event_copy:
* @event: a #GdkEvent
@@ -642,6 +684,12 @@ gdk_event_copy (const GdkEvent *event)
sizeof (gdouble) * gdk_device_get_n_axes (event->any.device));
if (event->motion.tool)
g_object_ref (new_event->motion.tool);
+
+ if (event->motion.history)
+ {
+ new_event->motion.history = g_list_copy_deep (event->motion.history,
+ (GCopyFunc) copy_time_coord, NULL);
+ }
break;
case GDK_SELECTION_CLEAR:
@@ -726,6 +774,7 @@ gdk_event_finalize (GObject *object)
case GDK_MOTION_NOTIFY:
g_clear_object (&event->motion.tool);
g_free (event->motion.axes);
+ g_list_free_full (event->motion.history, g_free);
break;
case GDK_SELECTION_CLEAR:
@@ -2715,3 +2764,10 @@ gdk_event_get_axes (GdkEvent *event,
return FALSE;
}
+GList *
+gdk_event_get_history (const GdkEvent *event)
+{
+ if (event->any.type != GDK_MOTION_NOTIFY)
+ return NULL;
+ return g_list_reverse (g_list_copy (event->motion.history));
+}
diff --git a/gdk/gdkevents.h b/gdk/gdkevents.h
index 1a67b65..aa17f5a 100644
--- a/gdk/gdkevents.h
+++ b/gdk/gdkevents.h
@@ -736,6 +736,7 @@ GDK_AVAILABLE_IN_3_92
gboolean gdk_event_get_axes (GdkEvent *event,
gdouble **axes,
guint *n_axes);
+GList * gdk_event_get_history (const GdkEvent *event);
G_END_DECLS
diff --git a/gdk/gdkeventsprivate.h b/gdk/gdkeventsprivate.h
index c8f3253..0358053 100644
--- a/gdk/gdkeventsprivate.h
+++ b/gdk/gdkeventsprivate.h
@@ -121,6 +121,7 @@ struct _GdkEventMotion
gint16 is_hint;
GdkDeviceTool *tool;
gdouble x_root, y_root;
+ GList *history;
};
/**
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]