[gtk+/multitouch: 77/121] Introduce GdkTouchCluster



commit 038c97f11d83c9bd0435b70a39ed9a27c49e1dcc
Author: Carlos Garnacho <carlosg gnome org>
Date:   Tue Mar 1 09:09:59 2011 +0100

    Introduce GdkTouchCluster
    
    This is a per-window/device object to gather a group of touch IDs
    as a single entity.

 docs/reference/gdk/gdk-docs.sgml     |    1 +
 docs/reference/gdk/gdk3-sections.txt |   19 ++
 docs/reference/gdk/gdk3.types        |    1 +
 gdk/Makefile.am                      |    2 +
 gdk/gdk.h                            |    1 +
 gdk/gdk.symbols                      |    5 +
 gdk/gdktouchcluster.c                |  346 ++++++++++++++++++++++++++++++++++
 gdk/gdktouchcluster.h                |   69 +++++++
 8 files changed, 444 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/gdk/gdk-docs.sgml b/docs/reference/gdk/gdk-docs.sgml
index 8674acd..ec25447 100644
--- a/docs/reference/gdk/gdk-docs.sgml
+++ b/docs/reference/gdk/gdk-docs.sgml
@@ -33,6 +33,7 @@
     <xi:include href="xml/windows.xml" />
     <xi:include href="xml/events.xml" />
     <xi:include href="xml/event_structs.xml" />
+    <xi:include href="xml/touchcluster.xml" />
     <xi:include href="xml/keys.xml" />
     <xi:include href="xml/selections.xml" />
     <xi:include href="xml/dnd.xml" />
diff --git a/docs/reference/gdk/gdk3-sections.txt b/docs/reference/gdk/gdk3-sections.txt
index 5f6ba56..82c8483 100644
--- a/docs/reference/gdk/gdk3-sections.txt
+++ b/docs/reference/gdk/gdk3-sections.txt
@@ -860,6 +860,25 @@ gdk_owner_change_get_type
 </SECTION>
 
 <SECTION>
+<TITLE>Multitouch</TITLE>
+<FILE>touchcluster</FILE>
+GdkTouchCluster
+gdk_touch_cluster_add_touch
+gdk_touch_cluster_remove_touch
+gdk_touch_cluster_remove_all
+gdk_touch_cluster_set_device
+gdk_touch_cluster_get_device
+gdk_touch_cluster_get_touches
+
+<SUBSECTION Standard>
+GDK_TYPE_TOUCH_CLUSTER
+
+<SUBSECTION Private>
+gdk_touch_cluster_get_type
+</SECTION>
+
+
+<SECTION>
 <TITLE>Cursors</TITLE>
 <FILE>cursors</FILE>
 GdkCursor
diff --git a/docs/reference/gdk/gdk3.types b/docs/reference/gdk/gdk3.types
index abf4374..e33ee38 100644
--- a/docs/reference/gdk/gdk3.types
+++ b/docs/reference/gdk/gdk3.types
@@ -9,5 +9,6 @@ gdk_display_manager_get_type
 gdk_drag_context_get_type
 gdk_keymap_get_type
 gdk_screen_get_type
+gdk_touch_cluster_get_type
 gdk_visual_get_type
 gdk_window_get_type
diff --git a/gdk/Makefile.am b/gdk/Makefile.am
index 0c38d9a..8aaee29 100644
--- a/gdk/Makefile.am
+++ b/gdk/Makefile.am
@@ -88,6 +88,7 @@ gdk_public_h_sources = 				\
 	gdkselection.h				\
 	gdktestutils.h				\
 	gdkthreads.h				\
+	gdktouchcluster.h			\
 	gdktypes.h				\
 	gdkvisual.h				\
 	gdkwindow.h
@@ -130,6 +131,7 @@ gdk_c_sources = 				\
 	gdkrgba.c				\
 	gdkscreen.c				\
 	gdkselection.c				\
+	gdktouchcluster.c			\
 	gdkvisual.c				\
 	gdkwindow.c				\
 	gdkwindowimpl.c
diff --git a/gdk/gdk.h b/gdk/gdk.h
index 2b84969..5bbf62e 100644
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -53,6 +53,7 @@
 #include <gdk/gdkselection.h>
 #include <gdk/gdktestutils.h>
 #include <gdk/gdkthreads.h>
+#include <gdk/gdktouchcluster.h>
 #include <gdk/gdktypes.h>
 #include <gdk/gdkvisual.h>
 #include <gdk/gdkwindow.h>
diff --git a/gdk/gdk.symbols b/gdk/gdk.symbols
index 5f37e05..46fd138 100644
--- a/gdk/gdk.symbols
+++ b/gdk/gdk.symbols
@@ -328,6 +328,11 @@ gdk_threads_enter
 gdk_threads_init
 gdk_threads_leave
 gdk_threads_set_lock_functions
+gdk_touch_cluster_add_touch
+gdk_touch_cluster_get_device
+gdk_touch_cluster_get_type G_GNUC_CONST
+gdk_touch_cluster_list_touches
+gdk_touch_cluster_remove_touch
 gdk_unicode_to_keyval
 gdk_utf8_to_string_target
 gdk_visibility_state_get_type
diff --git a/gdk/gdktouchcluster.c b/gdk/gdktouchcluster.c
new file mode 100644
index 0000000..9bc0474
--- /dev/null
+++ b/gdk/gdktouchcluster.c
@@ -0,0 +1,346 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2011 Carlos Garnacho <carlosg gnome org>
+ *
+ * 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 "gdktouchcluster.h"
+#include "gdkintl.h"
+
+/**
+ * SECTION:touchcluster
+ * @Short_description: Multitouch handling
+ * @Title: Multitouch
+ * @See_also: #GdkEventMultiTouch
+ *
+ * #GdkTouchCluster is an object that gathers touch IDs from a
+ * touch-enabled slave #GdkDevice, in order to send
+ * #GdkEventMultiTouch<!-- --> events whenever a contained touch ID
+ * is updated.
+ *
+ * #GdkTouchCluster<!-- -->s are always associated to a window,
+ * you need to create them through gdk_window_create_touch_cluster(),
+ * and free them through gdk_window_remove_touch_cluster().
+ *
+ * Touch IDs from devices can be obtained from %GDK_TOUCH_PRESS,
+ * %GDK_TOUCH_MOTION or %GDK_TOUCH_RELEASE events through
+ * gdk_event_get_touch_id(), and then be added via
+ * gdk_touch_cluster_add_touch(). Note that touch IDs are
+ * highly transitive, even be an incrementable number only
+ * identifying the current touch event stream, so touch IDs
+ * should always be gotten from these events.
+ *
+ * Anytime a touch ID is within a cluster, no %GDK_TOUCH_PRESS,
+ * %GDK_TOUCH_MOTION or %GDK_TOUCH_RELEASE events will happen
+ * for the individual touch. The event will be available instead
+ * as part of the #GdkMultitouchEvent that will be emitted. This
+ * will hold true until gdk_touch_cluster_remove_touch() is
+ * called for it. Note that GTK+ will automatically take a
+ * touch ID out of any cluster if %GDK_TOUCH_RELEASE is gotten
+ * internally.
+ */
+
+typedef struct GdkTouchClusterPrivate GdkTouchClusterPrivate;
+
+struct GdkTouchClusterPrivate
+{
+  GdkDevice *device;
+  GList *touches;
+};
+
+enum {
+  PROP_0,
+  PROP_DEVICE
+};
+
+enum {
+  TOUCH_ADDED,
+  TOUCH_REMOVED,
+  LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+static void   gdk_touch_cluster_finalize     (GObject      *object);
+static void   gdk_touch_cluster_set_property (GObject      *object,
+                                              guint         prop_id,
+                                              const GValue *value,
+                                              GParamSpec   *pspec);
+static void   gdk_touch_cluster_get_property (GObject      *object,
+                                              guint         prop_id,
+                                              GValue       *value,
+                                              GParamSpec   *pspec);
+
+
+G_DEFINE_TYPE (GdkTouchCluster, gdk_touch_cluster, G_TYPE_OBJECT)
+
+static void
+gdk_touch_cluster_class_init (GdkTouchClusterClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gdk_touch_cluster_finalize;
+  object_class->get_property = gdk_touch_cluster_get_property;
+  object_class->set_property = gdk_touch_cluster_set_property;
+
+  g_object_class_install_property (object_class,
+                                   PROP_DEVICE,
+                                   g_param_spec_object ("device",
+                                                        P_("Device"),
+                                                        P_("Device attached to the cluster"),
+                                                        GDK_TYPE_DEVICE,
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+                                                        G_PARAM_STATIC_STRINGS));
+
+  signals[TOUCH_ADDED] =
+    g_signal_new (g_intern_static_string ("touch-added"),
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GdkTouchClusterClass, touch_added),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__UINT,
+                  G_TYPE_NONE, 1, G_TYPE_UINT);
+  signals[TOUCH_REMOVED] =
+    g_signal_new (g_intern_static_string ("touch-removed"),
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GdkTouchClusterClass, touch_removed),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__UINT,
+                  G_TYPE_NONE, 1, G_TYPE_UINT);
+
+  g_type_class_add_private (object_class, sizeof (GdkTouchClusterPrivate));
+}
+
+static void
+gdk_touch_cluster_init (GdkTouchCluster *cluster)
+{
+  cluster->priv = G_TYPE_INSTANCE_GET_PRIVATE (cluster,
+                                               GDK_TYPE_TOUCH_CLUSTER,
+                                               GdkTouchClusterPrivate);
+}
+
+static void
+gdk_touch_cluster_finalize (GObject *object)
+{
+  GdkTouchClusterPrivate *priv;
+
+  priv = GDK_TOUCH_CLUSTER (object)->priv;
+  g_list_free (priv->touches);
+
+  G_OBJECT_CLASS (gdk_touch_cluster_parent_class)->finalize (object);
+}
+
+static void
+gdk_touch_cluster_set_property (GObject      *object,
+                                guint         prop_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+  switch (prop_id)
+    {
+    case PROP_DEVICE:
+      gdk_touch_cluster_set_device (GDK_TOUCH_CLUSTER (object),
+                                    g_value_get_object (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gdk_touch_cluster_get_property (GObject      *object,
+                                guint         prop_id,
+                                GValue       *value,
+                                GParamSpec   *pspec)
+{
+  GdkTouchClusterPrivate *priv;
+
+  priv = GDK_TOUCH_CLUSTER (object)->priv;
+
+  switch (prop_id)
+    {
+    case PROP_DEVICE:
+      g_value_set_object (value, priv->device);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+/**
+ * gdk_touch_cluster_add_touch:
+ * @cluster: a #GdkTouchCluster
+ * @touch_id: a touch ID from a touch event
+ *
+ * Adds a touch ID to @cluster, so it will generate a
+ * %GDK_MULTITOUCH_ADDED event, followed by %GDK_MULTITOUCH_UPDATED
+ * events whenever this touch ID is updated.
+ *
+ * If @touch_id already pertained to another #GdkTouchCluster, it
+ * will be removed from it, generating a %GDK_MULTITOUCH_REMOVED
+ * for that another cluster.
+ **/
+void
+gdk_touch_cluster_add_touch (GdkTouchCluster *cluster,
+                             guint            touch_id)
+{
+  GdkTouchClusterPrivate *priv;
+
+  g_return_if_fail (GDK_IS_TOUCH_CLUSTER (cluster));
+
+  priv = cluster->priv;
+
+  if (!g_list_find (priv->touches, GUINT_TO_POINTER (touch_id)))
+    {
+      priv->touches = g_list_prepend (priv->touches, GUINT_TO_POINTER (touch_id));
+      g_signal_emit (cluster, signals [TOUCH_ADDED], 0, touch_id);
+    }
+}
+
+/**
+ * gdk_touch_cluster_remove_touch:
+ * @cluster: a #GdkTouchCluster
+ * @touch_id: a touch ID from a touch event
+ *
+ * Removes a touch ID from @cluster, generating a %GDK_MULTITOUCH_REMOVED
+ * event for @cluster, and causing any further input from @touch_id
+ * to be reported trough %GDK_TOUCH_MOTION events.
+ *
+ * <note><para>
+ * Note that GTK+ automatically removes a touch ID from any cluster
+ * if a %GDK_TOUCH_RELEASE event is gotten internally.
+ * </para></note>
+ **/
+void
+gdk_touch_cluster_remove_touch (GdkTouchCluster *cluster,
+                                guint            touch_id)
+{
+  GdkTouchClusterPrivate *priv;
+  GList *link;
+
+  g_return_if_fail (GDK_IS_TOUCH_CLUSTER (cluster));
+
+  priv = cluster->priv;
+
+  link = g_list_find (priv->touches, GUINT_TO_POINTER (touch_id));
+
+  if (link)
+    {
+      priv->touches = g_list_remove_link (priv->touches, link);
+      g_signal_emit (cluster, signals [TOUCH_REMOVED], 0, touch_id);
+      g_list_free1 (link);
+    }
+}
+
+/**
+ * gdk_touch_cluster_remove_all:
+ * @cluster: a #GdkTouchCluster
+ *
+ * Removes all touch IDs from @cluster.
+ **/
+void
+gdk_touch_cluster_remove_all (GdkTouchCluster *cluster)
+{
+  GdkTouchClusterPrivate *priv;
+  GList *link;
+
+  g_return_if_fail (GDK_IS_TOUCH_CLUSTER (cluster));
+
+  priv = cluster->priv;
+  link = priv->touches;
+
+  while (link)
+    {
+      priv->touches = g_list_remove_link (priv->touches, link);
+      g_signal_emit (cluster, signals [TOUCH_REMOVED], 0, link->data);
+    }
+
+  g_list_free (priv->touches);
+  priv->touches = NULL;
+}
+
+
+/**
+ * gdk_touch_cluster_get_touches:
+ * @cluster: a #GdkTouchCluster
+ *
+ * Returns a const list of touch IDs as #guint.
+ *
+ * Returns: (transfer none): A list of touch IDs.
+ **/
+GList *
+gdk_touch_cluster_get_touches (GdkTouchCluster *cluster)
+{
+  GdkTouchClusterPrivate *priv;
+
+  g_return_val_if_fail (GDK_IS_TOUCH_CLUSTER (cluster), NULL);
+
+  priv = cluster->priv;
+  return priv->touches;
+}
+
+/**
+ * gdk_touch_cluster_set_device:
+ * @cluster: a #GdkTouchCluster
+ * @device: a #GdkDevice
+ *
+ * Sets the current device associated to @cluster, all contained
+ * touch IDs must pertain to this device. As a consequence,
+ * gdk_touch_cluster_remove_all() will be called on @cluster
+ * if the current device changes.
+ **/
+void
+gdk_touch_cluster_set_device (GdkTouchCluster *cluster,
+                              GdkDevice       *device)
+{
+  GdkTouchClusterPrivate *priv;
+
+  g_return_if_fail (GDK_IS_TOUCH_CLUSTER (cluster));
+  g_return_if_fail (!device || GDK_IS_DEVICE (device));
+
+  priv = cluster->priv;
+
+  if (priv->device != device)
+    gdk_touch_cluster_remove_all (cluster);
+
+  priv->device = device;
+}
+
+/**
+ * gdk_touch_cluster_get_device:
+ * @cluster: a #GdkTouchCluster
+ *
+ * Returns the slave/floating device this touch cluster pertains to,
+ * only touch IDs from this device can be included in @cluster.
+ * the #GdkDevice will typically have the %GDK_SOURCE_TOUCH input source.
+ *
+ * Returns: (transfer none): The #GdkDevice generating the contained touch IDs
+ **/
+GdkDevice *
+gdk_touch_cluster_get_device (GdkTouchCluster *cluster)
+{
+  GdkTouchClusterPrivate *priv;
+
+  g_return_val_if_fail (GDK_IS_TOUCH_CLUSTER (cluster), NULL);
+
+  priv = cluster->priv;
+  return priv->device;
+}
diff --git a/gdk/gdktouchcluster.h b/gdk/gdktouchcluster.h
new file mode 100644
index 0000000..0904df5
--- /dev/null
+++ b/gdk/gdktouchcluster.h
@@ -0,0 +1,69 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2011 Carlos Garnacho <carlosg gnome org>
+ *
+ * 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.
+ */
+
+#ifndef __GDK_TOUCH_CLUSTER_H__
+#define __GDK_TOUCH_CLUSTER_H__
+
+#include <glib-object.h>
+#include <gdk/gdkdevice.h>
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_TOUCH_CLUSTER         (gdk_touch_cluster_get_type ())
+#define GDK_TOUCH_CLUSTER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_TOUCH_CLUSTER, GdkTouchCluster))
+#define GDK_IS_TOUCH_CLUSTER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_TOUCH_CLUSTER))
+
+typedef struct _GdkTouchCluster GdkTouchCluster;
+typedef struct _GdkTouchClusterClass GdkTouchClusterClass;
+
+struct _GdkTouchCluster
+{
+  GObject parent_instance;
+  gpointer priv;
+};
+
+struct _GdkTouchClusterClass
+{
+  GObjectClass parent_class;
+
+  void (* touch_added)   (GdkTouchCluster *cluster,
+                          guint            touch_id);
+  void (* touch_removed) (GdkTouchCluster *cluster,
+                          guint            touch_id);
+
+  gpointer padding[16];
+};
+
+GType       gdk_touch_cluster_get_type     (void) G_GNUC_CONST;
+
+void        gdk_touch_cluster_add_touch    (GdkTouchCluster *cluster,
+                                            guint            touch_id);
+void        gdk_touch_cluster_remove_touch (GdkTouchCluster *cluster,
+                                            guint            touch_id);
+void        gdk_touch_cluster_remove_all   (GdkTouchCluster *cluster);
+
+GList *     gdk_touch_cluster_get_touches  (GdkTouchCluster *cluster);
+
+void        gdk_touch_cluster_set_device   (GdkTouchCluster *cluster,
+                                            GdkDevice       *device);
+GdkDevice * gdk_touch_cluster_get_device   (GdkTouchCluster *cluster);
+
+G_END_DECLS
+
+#endif /* __GDK_TOUCH_CLUSTER_H__ */



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