[gtk+/multitouch: 19/23] gtk: Add helper API to handle gestures



commit 5c64c1fc71b9a2af107b9a04c1159cb02d00a083
Author: Carlos Garnacho <carlosg gnome org>
Date:   Tue Oct 25 02:32:07 2011 +0200

    gtk: Add helper API to handle gestures
    
    Although GtkGesturesInterpreter can be used standalone, GtkWidget
    deserves helper API to enable support for gestures. gestures can
    be enabled/disabled, and the ::gesture signal can be used to get
    the gesture ID.
    
    The internal GtkWidget gestures interpreter is only handled by
    touch events, if gestures are needed for other devices, a
    standalone gestures interpreter must be used.

 gtk/gtkmain.c          |   10 ++++
 gtk/gtkwidget.c        |  115 ++++++++++++++++++++++++++++++++++++++++++++++++
 gtk/gtkwidget.h        |   12 ++++-
 gtk/gtkwidgetprivate.h |    4 ++
 4 files changed, 138 insertions(+), 3 deletions(-)
---
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index 79eaeb5..1e6f130 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -1738,6 +1738,16 @@ gtk_main_do_event (GdkEvent *event)
       _gtk_tooltip_handle_event (event);
     }
 
+  /* Handle gestures for touch events */
+  if (gdk_event_get_touch_id (event, NULL))
+    {
+      _gtk_widget_gesture_stroke (grab_widget, event);
+
+      if (event->type == GDK_BUTTON_RELEASE ||
+          event->type == GDK_TOUCH_RELEASE)
+        _gtk_widget_gesture_finish (grab_widget);
+    }
+
   tmp_list = current_events;
   current_events = g_list_remove_link (current_events, tmp_list);
   g_list_free_1 (tmp_list);
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 4bdc562..8eae99f 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -60,6 +60,7 @@
 #include "gtkcssprovider.h"
 #include "gtkanimationdescription.h"
 #include "gtkmodifierstyle.h"
+#include "gtkgesturesinterpreter.h"
 #include "gtkversion.h"
 #include "gtkdebug.h"
 #include "gtkplug.h"
@@ -399,6 +400,8 @@ struct _GtkWidgetPrivate
   /* The widget's parent */
   GtkWidget *parent;
 
+  GArray *gestures;
+
 #ifdef G_ENABLE_DEBUG
   /* Number of gtk_widget_push_verify_invariants () */
   guint verifying_invariants_count;
@@ -481,6 +484,7 @@ enum {
   DRAG_FAILED,
   STYLE_UPDATED,
   MULTITOUCH_EVENT,
+  GESTURE,
   LAST_SIGNAL
 };
 
@@ -731,6 +735,7 @@ static GQuark		quark_visual = 0;
 static GQuark           quark_modifier_style = 0;
 static GQuark           quark_enabled_devices = 0;
 static GQuark           quark_size_groups = 0;
+static GQuark           quark_gestures_interpreter = 0;
 GParamSpecPool         *_gtk_widget_child_property_pool = NULL;
 GObjectNotifyContext   *_gtk_widget_child_property_notify_context = NULL;
 
@@ -856,6 +861,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
   quark_modifier_style = g_quark_from_static_string ("gtk-widget-modifier-style");
   quark_enabled_devices = g_quark_from_static_string ("gtk-widget-enabled-devices");
   quark_size_groups = g_quark_from_static_string ("gtk-widget-size-groups");
+  quark_gestures_interpreter = g_quark_from_static_string ("gtk-widget-gestures-interpreter");
 
   style_property_spec_pool = g_param_spec_pool_new (FALSE);
   _gtk_widget_child_property_pool = g_param_spec_pool_new (TRUE);
@@ -3010,6 +3016,15 @@ gtk_widget_class_init (GtkWidgetClass *klass)
 		  _gtk_marshal_BOOLEAN__UINT,
                   G_TYPE_BOOLEAN, 1, G_TYPE_UINT);
 
+  widget_signals[GESTURE] =
+    g_signal_new (I_("gesture"),
+                  G_TYPE_FROM_CLASS (klass),
+		  G_SIGNAL_RUN_LAST,
+		  G_STRUCT_OFFSET (GtkWidgetClass, gesture),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__UINT,
+                  G_TYPE_NONE, 1, G_TYPE_UINT);
+
   binding_set = gtk_binding_set_by_class (klass);
   gtk_binding_entry_add_signal (binding_set, GDK_KEY_F10, GDK_SHIFT_MASK,
                                 "popup-menu", 0);
@@ -10740,6 +10755,9 @@ gtk_widget_finalize (GObject *object)
 
   _gtk_widget_free_cached_sizes (widget);
 
+  if (priv->gestures)
+    g_array_free (priv->gestures, TRUE);
+
   if (g_object_is_floating (object))
     g_warning ("A floating object was finalized. This means that someone\n"
                "called g_object_unref() on an object that had only a floating\n"
@@ -14601,3 +14619,100 @@ gtk_widget_get_modifier_mask (GtkWidget         *widget,
   return gdk_keymap_get_modifier_mask (gdk_keymap_get_for_display (display),
                                        intent);
 }
+
+void
+_gtk_widget_gesture_stroke (GtkWidget *widget,
+                            GdkEvent  *event)
+{
+  GtkGesturesInterpreter *interpreter;
+  GtkWidgetPrivate *priv;
+
+  priv = widget->priv;
+
+  if (!priv->gestures ||
+      priv->gestures->len == 0)
+    return;
+
+  interpreter = g_object_get_qdata (G_OBJECT (widget), quark_gestures_interpreter);
+  g_assert (interpreter != NULL);
+
+  gtk_gestures_interpreter_feed_event (interpreter, event);
+}
+
+void
+_gtk_widget_gesture_finish (GtkWidget *widget)
+{
+  GtkGesturesInterpreter *interpreter;
+  GtkWidgetPrivate *priv;
+  guint gesture;
+
+  priv = widget->priv;
+
+  if (!priv->gestures ||
+      priv->gestures->len == 0)
+    return;
+
+  interpreter = g_object_get_qdata (G_OBJECT (widget), quark_gestures_interpreter);
+  g_assert (interpreter != NULL);
+
+  if (gtk_gestures_interpreter_finish (interpreter, &gesture))
+    g_signal_emit (widget, widget_signals[GESTURE], 0, gesture);
+}
+
+void
+gtk_widget_enable_gesture (GtkWidget *widget,
+                           guint      gesture_id)
+{
+  GtkGesturesInterpreter *interpreter;
+  GtkWidgetPrivate *priv;
+
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  priv = widget->priv;
+  interpreter = g_object_get_qdata (G_OBJECT (widget), quark_gestures_interpreter);
+
+  if (!interpreter)
+    {
+      interpreter = gtk_gestures_interpreter_new ();
+      g_object_set_qdata_full (G_OBJECT (widget), quark_gestures_interpreter,
+                               interpreter, (GDestroyNotify) g_object_unref);
+    }
+
+  if (!gtk_gestures_interpreter_add_gesture (interpreter, gesture_id))
+    return;
+
+  if (!priv->gestures)
+    priv->gestures = g_array_new (FALSE, FALSE, sizeof (guint));
+
+  g_array_append_val (priv->gestures, gesture_id);
+}
+
+void
+gtk_widget_disable_gesture (GtkWidget *widget,
+                            guint      gesture_id)
+{
+  GtkGesturesInterpreter *interpreter;
+  GtkWidgetPrivate *priv;
+  guint i;
+
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  priv = widget->priv;
+
+  if (!priv->gestures ||
+      priv->gestures->len == 0)
+    return;
+
+  interpreter = g_object_get_qdata (G_OBJECT (widget), quark_gestures_interpreter);
+  g_assert (interpreter != NULL);
+
+  for (i = 0; i < priv->gestures->len; i++)
+    {
+      if (gesture_id == g_array_index (priv->gestures, guint, i))
+        {
+          g_array_remove_index (priv->gestures, i);
+          gtk_gestures_interpreter_remove_gesture (interpreter, gesture_id);
+          break;
+        }
+    }
+}
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index 8babc9d..f4ad657 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -428,8 +428,10 @@ struct _GtkWidgetClass
   void         (* style_updated)          (GtkWidget *widget);
 
   /* Multitouch */
-  gboolean (* multitouch_event) (GtkWidget          *widget,
-                                 GdkEventMultiTouch *event);
+  gboolean     (* multitouch_event)       (GtkWidget          *widget,
+                                           GdkEventMultiTouch *event);
+  void         (* gesture)                (GtkWidget          *widget,
+                                           guint               gesture_id);
 
   /*< private >*/
 
@@ -441,7 +443,6 @@ struct _GtkWidgetClass
   void (*_gtk_reserved4) (void);
   void (*_gtk_reserved5) (void);
   void (*_gtk_reserved6) (void);
-  void (*_gtk_reserved7) (void);
 };
 
 struct _GtkWidgetAuxInfo
@@ -955,6 +956,11 @@ GtkWidgetPath *   gtk_widget_get_path (GtkWidget *widget);
 GdkModifierType   gtk_widget_get_modifier_mask (GtkWidget         *widget,
                                                 GdkModifierIntent  intent);
 
+/* Gestures */
+void gtk_widget_enable_gesture (GtkWidget       *widget,
+                                GtkGestureType   gesture);
+void gtk_widget_disable_gesture (GtkWidget      *widget,
+                                 GtkGestureType  gesture);
 
 G_END_DECLS
 
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index afda633..05eaa78 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -157,6 +157,10 @@ void              _gtk_widget_buildable_finish_accelerator (GtkWidget *widget,
                                                             GtkWidget *toplevel,
                                                             gpointer   user_data);
 
+void _gtk_widget_gesture_stroke (GtkWidget *widget,
+                                 GdkEvent  *event);
+void _gtk_widget_gesture_finish (GtkWidget *widget);
+
 G_END_DECLS
 
 #endif /* __GTK_WIDGET_PRIVATE_H__ */



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