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.
This commit is contained in:
Carlos Garnacho
2011-10-25 02:32:07 +02:00
parent bb448f619c
commit 576ba1a03d
4 changed files with 137 additions and 1 deletions

View File

@@ -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);

View File

@@ -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;
}
}
}

View File

@@ -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__ */

View File

@@ -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__ */