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:
@@ -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);
|
||||
|
||||
114
gtk/gtkwidget.c
114
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
Reference in New Issue
Block a user