[gtk+/wip/events: 3/11] gdk: Make event sequences real objects



commit b45382914ff62a8c21f77ee7e00c9fafec3c12c3
Author: Benjamin Otte <otte redhat com>
Date:   Mon Mar 5 13:58:00 2012 +0100

    gdk: Make event sequences real objects
    
    So far this fact is hidden from the implementation. The usefulness of
    this change will soon become apparent.

 gdk/Makefile.am                |    2 +
 gdk/gdkdevice.c                |   14 +++++++
 gdk/gdkdeviceprivate.h         |    1 +
 gdk/gdkevents.c                |    3 +
 gdk/gdkeventsequence.c         |   85 ++++++++++++++++++++++++++++++++++++++++
 gdk/gdkeventsequenceprivate.h  |   44 ++++++++++++++++++++
 gdk/gdkwindow.c                |    5 +-
 gdk/x11/gdkdevicemanager-xi2.c |   26 ++++++++----
 8 files changed, 170 insertions(+), 10 deletions(-)
---
diff --git a/gdk/Makefile.am b/gdk/Makefile.am
index 6b647e5..f3dd659 100644
--- a/gdk/Makefile.am
+++ b/gdk/Makefile.am
@@ -101,6 +101,7 @@ gdk_private_headers = 				\
 	gdkdisplaymanagerprivate.h		\
 	gdkdisplayprivate.h			\
 	gdkdndprivate.h				\
+	gdkeventsequenceprivate.h		\
 	gdkscreenprivate.h			\
 	gdkinternals.h				\
 	gdkintl.h				\
@@ -121,6 +122,7 @@ gdk_c_sources = 				\
 	gdkdisplaymanager.c			\
 	gdkdnd.c				\
 	gdkevents.c     			\
+	gdkeventsequence.c			\
 	gdkglobals.c				\
 	gdkkeys.c				\
 	gdkkeyuni.c				\
diff --git a/gdk/gdkdevice.c b/gdk/gdkdevice.c
index 01b325b..0f49858 100644
--- a/gdk/gdkdevice.c
+++ b/gdk/gdkdevice.c
@@ -21,6 +21,7 @@
 
 #include "gdkdeviceprivate.h"
 #include "gdkdisplayprivate.h"
+#include "gdkeventsequenceprivate.h"
 #include "gdkinternals.h"
 #include "gdkintl.h"
 
@@ -275,6 +276,7 @@ static void
 gdk_device_dispose (GObject *object)
 {
   GdkDevice *device = GDK_DEVICE (object);
+  GSList *list;
 
   if (device->type == GDK_DEVICE_TYPE_SLAVE)
     _gdk_device_remove_slave (device->associated, device);
@@ -288,6 +290,18 @@ gdk_device_dispose (GObject *object)
       device->associated = NULL;
     }
 
+  for (list = device->sequences; list; list = list->next)
+    {
+      GdkEventSequence *sequence = list->data;
+
+      /* Set device to NULL in advance so that the unreffing doesn't
+       * modify the list we iterate over */
+      sequence->device = NULL;
+      gdk_event_sequence_unref (sequence);
+    }
+  g_slist_free (device->sequences);
+  device->sequences = NULL;
+
   if (device->axes)
     {
       g_array_free (device->axes, TRUE);
diff --git a/gdk/gdkdeviceprivate.h b/gdk/gdkdeviceprivate.h
index 9e057d8..be1370d 100644
--- a/gdk/gdkdeviceprivate.h
+++ b/gdk/gdkdeviceprivate.h
@@ -56,6 +56,7 @@ struct _GdkDevice
   GList *slaves;
   GdkDeviceType type;
   GArray *axes;
+  GSList *sequences;
 };
 
 struct _GdkDeviceClass
diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c
index db37512..f93a246 100644
--- a/gdk/gdkevents.c
+++ b/gdk/gdkevents.c
@@ -26,6 +26,7 @@
 
 #include "gdkinternals.h"
 #include "gdkdisplayprivate.h"
+#include "gdkeventsequenceprivate.h"
 
 #include <string.h>
 #include <math.h>
@@ -600,6 +601,7 @@ gdk_event_copy (const GdkEvent *event)
     case GDK_TOUCH_UPDATE:
     case GDK_TOUCH_END:
     case GDK_TOUCH_CANCEL:
+      new_event->touch.sequence = gdk_event_sequence_ref (event->touch.sequence);
       if (event->touch.axes)
         new_event->touch.axes = g_memdup (event->touch.axes,
                                            sizeof (gdouble) * gdk_device_get_n_axes (event->touch.device));
@@ -689,6 +691,7 @@ gdk_event_free (GdkEvent *event)
     case GDK_TOUCH_END:
     case GDK_TOUCH_CANCEL:
       g_free (event->touch.axes);
+      gdk_event_sequence_unref (event->touch.sequence);
       break;
 
     case GDK_EXPOSE:
diff --git a/gdk/gdkeventsequence.c b/gdk/gdkeventsequence.c
new file mode 100644
index 0000000..34c815e
--- /dev/null
+++ b/gdk/gdkeventsequence.c
@@ -0,0 +1,85 @@
+/* gdkeventsequence.h - tracking sequences of events
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.â See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "gdkeventsequenceprivate.h"
+
+#include "gdkdeviceprivate.h"
+
+/* XXX: Does not return a reference - should we change that? */
+GdkEventSequence *
+gdk_event_sequence_new (GdkDevice *device,
+                        guint      sequence_id)
+{
+  GdkEventSequence *sequence = g_slice_new0 (GdkEventSequence);
+
+  /* device owns sequence, so cannot ref device here */
+  sequence->ref_count = 1;
+  sequence->device = device;
+  sequence->sequence_id = sequence_id;
+  sequence->axes = g_new0 (gdouble, gdk_device_get_n_axes (device));
+
+  device->sequences = g_slist_prepend (device->sequences, sequence);
+
+  return sequence;
+}
+
+GdkEventSequence *
+gdk_event_sequence_lookup (GdkDevice *device,
+                           guint      sequence_id)
+{
+  GSList *list;
+
+  for (list = device->sequences; list; list = list->next)
+    {
+      GdkEventSequence *sequence = list->data;
+
+      if (sequence->sequence_id == sequence_id)
+        return sequence;
+    }
+
+  return NULL;
+}
+
+GdkEventSequence *
+gdk_event_sequence_ref (GdkEventSequence *sequence)
+{
+  sequence->ref_count++;
+
+  return sequence;
+}
+
+void
+gdk_event_sequence_unref (GdkEventSequence *sequence)
+{
+  sequence->ref_count--;
+  if (sequence->ref_count > 0)
+    return;
+
+  if (sequence->device)
+    {
+      GdkDevice *device = sequence->device;
+
+      device->sequences = g_slist_remove (device->sequences, sequence);
+    }
+
+  g_free (sequence->axes);
+  g_slice_free (GdkEventSequence, sequence);
+}
diff --git a/gdk/gdkeventsequenceprivate.h b/gdk/gdkeventsequenceprivate.h
new file mode 100644
index 0000000..7352042
--- /dev/null
+++ b/gdk/gdkeventsequenceprivate.h
@@ -0,0 +1,44 @@
+/* gdkeventsequence.h - tracking sequences of events
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.â See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
+#error "Only <gdk/gdk.h> can be included directly."
+#endif
+
+#ifndef __GDK_EVENT_SEQUENCE_H__
+#define __GDK_EVENT_SEQUENCE_H__
+
+#include <gdk/gdktypes.h>
+
+struct _GdkEventSequence {
+  GdkDevice *device;
+  guint sequence_id;
+  guint ref_count;
+  double *axes;
+};
+
+GdkEventSequence *      gdk_event_sequence_new          (GdkDevice              *device,
+                                                         guint                   sequence_id);
+GdkEventSequence *      gdk_event_sequence_lookup       (GdkDevice              *device,
+                                                         guint                   sequence_id);
+
+GdkEventSequence *      gdk_event_sequence_ref          (GdkEventSequence       *sequence);
+void                    gdk_event_sequence_unref        (GdkEventSequence       *sequence);
+
+#endif  /* __GDK_EVENT_SEQUENCE_H__ */
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 72f0a18..b54065d 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -29,6 +29,7 @@
 
 #include "gdkwindow.h"
 
+#include "gdkeventsequenceprivate.h"
 #include "gdkrectangle.h"
 #include "gdkinternals.h"
 #include "gdkintl.h"
@@ -9483,7 +9484,7 @@ proxy_pointer_event (GdkDisplay                 *display,
             {
               event->touch.time = time_;
               event->touch.state = state | GDK_BUTTON1_MASK;
-              event->touch.sequence = source_event->touch.sequence;
+              event->touch.sequence = gdk_event_sequence_ref (source_event->touch.sequence);
               event->touch.emulating_pointer = source_event->touch.emulating_pointer;
               convert_toplevel_coords_to_window (event_win,
                                                  toplevel_x, toplevel_y,
@@ -9772,7 +9773,7 @@ proxy_button_event (GdkEvent *source_event,
       event->touch.device = source_event->touch.device;
       event->touch.axes = g_memdup (source_event->touch.axes,
                                      sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
-      event->touch.sequence = source_event->touch.sequence;
+      event->touch.sequence = gdk_event_sequence_ref (source_event->touch.sequence);
       event->touch.emulating_pointer = source_event->touch.emulating_pointer;
 
       gdk_event_set_source_device (event, source_device);
diff --git a/gdk/x11/gdkdevicemanager-xi2.c b/gdk/x11/gdkdevicemanager-xi2.c
index 9377588..2ac5682 100644
--- a/gdk/x11/gdkdevicemanager-xi2.c
+++ b/gdk/x11/gdkdevicemanager-xi2.c
@@ -23,6 +23,7 @@
 #include "gdkdevicemanagerprivate-core.h"
 #include "gdkdeviceprivate.h"
 #include "gdkdisplayprivate.h"
+#include "gdkeventsequenceprivate.h"
 #include "gdkeventtranslator.h"
 #include "gdkprivate-x11.h"
 #include "gdkintl.h"
@@ -1426,6 +1427,20 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
                                              GUINT_TO_POINTER (xev->sourceid));
         gdk_event_set_source_device (event, source_device);
 
+        event->touch.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
+
+        if (ev->evtype == XI_TouchBegin)
+          {
+            event->touch.state |= GDK_BUTTON1_MASK;
+            event->touch.sequence = gdk_event_sequence_new (event->touch.device, xev->detail);
+            gdk_event_sequence_ref (event->touch.sequence);
+          }
+        else
+          {
+            /* no ref here, we want the sequence to go away with the event */
+            event->touch.sequence = gdk_event_sequence_lookup (event->touch.device, xev->detail);
+          }
+
         event->touch.axes = translate_axes (event->touch.device,
                                             event->touch.x,
                                             event->touch.y,
@@ -1441,13 +1456,6 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
             gdk_device_get_axis (device, event->touch.axes, GDK_AXIS_Y, &event->touch.y);
           }
 
-        event->touch.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
-
-        if (ev->evtype == XI_TouchBegin)
-          event->touch.state |= GDK_BUTTON1_MASK;
-
-        event->touch.sequence = GUINT_TO_POINTER (xev->detail);
-
         if (xev->flags & XITouchEmulatingPointer)
           {
             event->touch.emulating_pointer = TRUE;
@@ -1480,7 +1488,6 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
                             xev->flags & XITouchEmulatingPointer));
 
         event->touch.window = window;
-        event->touch.sequence = GUINT_TO_POINTER (xev->detail);
         event->touch.type = GDK_TOUCH_UPDATE;
         event->touch.time = xev->time;
         event->touch.x = (gdouble) xev->event_x;
@@ -1495,6 +1502,9 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
                                              GUINT_TO_POINTER (xev->sourceid));
         gdk_event_set_source_device (event, source_device);
 
+        event->touch.sequence = gdk_event_sequence_lookup (event->touch.device, xev->detail);
+        gdk_event_sequence_ref (event->touch.sequence);
+
         event->touch.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
 
         event->touch.state |= GDK_BUTTON1_MASK;



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