diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index 90ee8587a3..f9027ce952 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1781,6 +1781,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 492843c480..02c31e52b5 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" @@ -404,6 +405,7 @@ struct _GtkWidgetPrivate GtkWidget *parent; GSList *captured_events; + GArray *gestures; #ifdef G_ENABLE_DEBUG /* Number of gtk_widget_push_verify_invariants () */ @@ -489,6 +491,7 @@ enum { CAPTURED_EVENT, PRESS_AND_HOLD, MULTITOUCH_EVENT, + GESTURE, LAST_SIGNAL }; @@ -761,6 +764,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; @@ -886,6 +890,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); @@ -3154,6 +3159,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); @@ -10757,6 +10771,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" @@ -14592,3 +14609,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 90201c62b1..fc76377bfb 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 5889c25620..05afe8a41d 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -178,6 +178,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__ */