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



commit 53b0a977ba57ae9d4100c2bd5ed6de105a7289f3
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        |  114 ++++++++++++++++++++++++++++++++++++++++++++++++
 gtk/gtkwidget.h        |   10 ++++-
 gtk/gtkwidgetprivate.h |    4 ++
 4 files changed, 137 insertions(+), 1 deletions(-)
---
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index a468f1d..adb0d52 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -1775,6 +1775,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 b439be0..49b3410 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,7 @@ struct _GtkWidgetPrivate
   GtkWidget *parent;
 
   GSList *captured_events;
+  GArray *gestures;
 
 #ifdef G_ENABLE_DEBUG
   /* Number of gtk_widget_push_verify_invariants () */
@@ -484,6 +486,7 @@ enum {
   CAPTURED_EVENT,
   PRESS_AND_HOLD,
   MULTITOUCH_EVENT,
+  GESTURE,
   LAST_SIGNAL
 };
 
@@ -755,6 +758,7 @@ static GQuark           quark_modifier_style = 0;
 static GQuark           quark_enabled_devices = 0;
 static GQuark           quark_size_groups = 0;
 static GQuark           quark_press_and_hold = 0;
+static GQuark           quark_gestures_interpreter = 0;
 GParamSpecPool         *_gtk_widget_child_property_pool = NULL;
 GObjectNotifyContext   *_gtk_widget_child_property_notify_context = NULL;
 
@@ -880,6 +884,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
   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_press_and_hold = g_quark_from_static_string ("gtk-widget-press-and-hold");
+  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);
@@ -3147,6 +3152,15 @@ gtk_widget_class_init (GtkWidgetClass *klass)
 		  G_TYPE_INT,
 		  G_TYPE_INT);
 
+  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);
@@ -10706,6 +10720,9 @@ gtk_widget_finalize (GObject *object)
       g_slist_free (priv->captured_events);
     }
 
+  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"
@@ -14518,3 +14535,100 @@ gtk_widget_release_captured_events (GtkWidget *widget,
   g_slist_free (priv->captured_events);
   priv->captured_events = NULL;
 }
+
+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 90201c6..fc76377 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -444,6 +444,9 @@ struct _GtkWidgetClass
   gboolean     (* multitouch_event)       (GtkWidget             *widget,
                                            GdkEventMultiTouch    *event);
 
+  void         (* gesture)                (GtkWidget          *widget,
+                                           guint               gesture_id);
+
   /*< private >*/
 
   GtkWidgetClassPrivate *priv;
@@ -452,7 +455,6 @@ struct _GtkWidgetClass
   void (*_gtk_reserved2) (void);
   void (*_gtk_reserved3) (void);
   void (*_gtk_reserved4) (void);
-  void (*_gtk_reserved5) (void);
 };
 
 struct _GtkWidgetAuxInfo
@@ -911,6 +913,12 @@ GdkModifierType   gtk_widget_get_modifier_mask (GtkWidget         *widget,
 void              gtk_widget_release_captured_events (GtkWidget *widget,
                                                       gboolean   emit);
 
+/* Gestures */
+void gtk_widget_enable_gesture (GtkWidget       *widget,
+                                GtkGestureType   gesture);
+void gtk_widget_disable_gesture (GtkWidget      *widget,
+                                 GtkGestureType  gesture);
+
 G_END_DECLS
 
 #endif /* __GTK_WIDGET_H__ */
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index f475e14..ecf0e12 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -173,6 +173,10 @@ gboolean          _gtk_widget_press_and_hold_check_cancel    (GtkWidget      *wi
 gboolean          _gtk_widget_press_and_hold_check_threshold (GtkWidget      *widget,
                                                               GdkEventMotion *event);
 
+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]