[gtk+/multitouch: 19/27] gtk: Add helper API to handle gestures
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/multitouch: 19/27] gtk: Add helper API to handle gestures
- Date: Wed, 23 Nov 2011 23:12:02 +0000 (UTC)
commit c90016cf5f55f90cbe002fc6b02b0cd16e6703a5
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 eaee284..2416343 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);
@@ -10695,6 +10709,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"
@@ -14507,3 +14524,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]