[gtk+/gestures: 11/13] widget: Hook GtkEventController to widget event processing.
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/gestures: 11/13] widget: Hook GtkEventController to widget event processing.
- Date: Wed, 26 Feb 2014 23:11:01 +0000 (UTC)
commit 445e2d9819ced912dfaa19f37cf9f41ffefcdc7a
Author: Carlos Garnacho <carlosg gnome org>
Date: Wed Feb 26 12:50:31 2014 +0100
widget: Hook GtkEventController to widget event processing.
A controller can be optionally hooked on the capture or the bubble
phase, so the controller will automatically receive and handle events
as they arrive without further interaction.
gtk/gtkenums.h | 6 ++
gtk/gtkwidget.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
gtk/gtkwidget.h | 12 ++++
3 files changed, 181 insertions(+), 4 deletions(-)
---
diff --git a/gtk/gtkenums.h b/gtk/gtkenums.h
index 74ff8e0..eb54825 100644
--- a/gtk/gtkenums.h
+++ b/gtk/gtkenums.h
@@ -1268,6 +1268,12 @@ typedef enum
typedef enum
{
+ GTK_PHASE_CAPTURE,
+ GTK_PHASE_BUBBLE
+} GtkPropagationPhase;
+
+typedef enum
+{
GTK_EVENT_SEQUENCE_NONE,
GTK_EVENT_SEQUENCE_CLAIMED,
GTK_EVENT_SEQUENCE_DENIED
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 52cf13f..198d496 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -395,6 +395,11 @@ typedef struct {
GDestroyNotify destroy_notify;
} GtkWidgetTemplate;
+typedef struct {
+ GtkEventController *controller;
+ guint propagation_phase : 2;
+} EventControllerData;
+
struct _GtkWidgetPrivate
{
/* The state of the widget. Needs to be able to hold all GtkStateFlags bits
@@ -504,6 +509,8 @@ struct _GtkWidgetPrivate
/* Number of gtk_widget_push_verify_invariants () */
guint verifying_invariants_count;
#endif /* G_ENABLE_DEBUG */
+
+ GList *event_controllers;
};
struct _GtkWidgetClassPrivate
@@ -6891,6 +6898,48 @@ _gtk_widget_set_captured_event_handler (GtkWidget *widget,
g_object_set_data (G_OBJECT (widget), "captured-event-handler", callback);
}
+static GdkEventMask
+_gtk_widget_get_controllers_evmask (GtkWidget *widget)
+{
+ EventControllerData *data;
+ GdkEventMask evmask = 0;
+ GtkWidgetPrivate *priv;
+ GList *l;
+
+ priv = widget->priv;
+
+ for (l = priv->event_controllers; l; l = l->next)
+ {
+ data = l->data;
+ evmask |= gtk_event_controller_get_event_mask (data->controller);
+ }
+
+ return evmask;
+}
+
+static gboolean
+_gtk_widget_run_controllers (GtkWidget *widget,
+ const GdkEvent *event,
+ GtkPropagationPhase phase)
+{
+ EventControllerData *data;
+ gboolean handled = FALSE;
+ GtkWidgetPrivate *priv;
+ GList *l;
+
+ priv = widget->priv;
+
+ for (l = priv->event_controllers; l; l = l->next)
+ {
+ data = l->data;
+
+ if (data->propagation_phase == phase)
+ handled |= gtk_event_controller_handle_event (data->controller, event);
+ }
+
+ return handled;
+}
+
gboolean
_gtk_widget_captured_event (GtkWidget *widget,
GdkEvent *event)
@@ -6912,13 +6961,15 @@ _gtk_widget_captured_event (GtkWidget *widget,
if (!event_window_is_still_viewable (event))
return TRUE;
+ return_val = _gtk_widget_run_controllers (widget, event, GTK_PHASE_CAPTURE);
+
handler = g_object_get_data (G_OBJECT (widget), "captured-event-handler");
if (!handler)
- return FALSE;
+ return return_val;
g_object_ref (widget);
- return_val = handler (widget, event);
+ return_val |= handler (widget, event);
return_val |= !WIDGET_REALIZED_FOR_EVENT (widget, event);
/* The widget that was originally to receive the event
@@ -7116,6 +7167,7 @@ gtk_widget_event_internal (GtkWidget *widget,
g_object_ref (widget);
+ return_val |= _gtk_widget_run_controllers (widget, event, GTK_PHASE_BUBBLE);
g_signal_emit (widget, widget_signals[EVENT], 0, event, &return_val);
return_val |= !WIDGET_REALIZED_FOR_EVENT (widget, event);
if (!return_val)
@@ -10658,8 +10710,11 @@ gtk_widget_add_events_internal_list (GtkWidget *widget,
gint events,
GList *window_list)
{
+ GdkEventMask controllers_mask;
GList *l;
+ controllers_mask = _gtk_widget_get_controllers_evmask (widget);
+
for (l = window_list; l != NULL; l = l->next)
{
GdkWindow *window = l->data;
@@ -10671,9 +10726,16 @@ gtk_widget_add_events_internal_list (GtkWidget *widget,
GList *children;
if (device)
- gdk_window_set_device_events (window, device, gdk_window_get_events (window) | events);
+ {
+ gdk_window_set_device_events (window, device,
+ gdk_window_get_events (window) |
+ events | controllers_mask);
+ }
else
- gdk_window_set_events (window, gdk_window_get_events (window) | events);
+ {
+ gdk_window_set_events (window, gdk_window_get_events (window) |
+ events | controllers_mask);
+ }
children = gdk_window_get_children (window);
gtk_widget_add_events_internal_list (widget, device, events, children);
@@ -11546,6 +11608,7 @@ gtk_widget_finalize (GObject *object)
{
GtkWidget *widget = GTK_WIDGET (object);
GtkWidgetPrivate *priv = widget->priv;
+ EventControllerData *controller_data;
GtkWidgetAuxInfo *aux_info;
GtkAccessible *accessible;
@@ -11575,6 +11638,15 @@ gtk_widget_finalize (GObject *object)
_gtk_size_request_cache_free (&priv->requests);
+ while (priv->event_controllers)
+ {
+ controller_data = priv->event_controllers->data;
+ g_object_unref (controller_data->controller);
+ g_free (controller_data);
+ priv->event_controllers= g_list_delete_link (priv->event_controllers,
+ priv->event_controllers);
+ }
+
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"
@@ -16235,3 +16307,90 @@ gtk_widget_get_template_child (GtkWidget *widget,
return ret;
}
+
+void
+gtk_widget_add_controller (GtkWidget *widget,
+ GtkEventController *controller,
+ GtkPropagationPhase phase)
+{
+ EventControllerData *data;
+ GtkWidgetPrivate *priv;
+ GList *l;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (GTK_IS_EVENT_CONTROLLER (controller));
+ g_return_if_fail (phase == GTK_PHASE_CAPTURE ||
+ phase == GTK_PHASE_BUBBLE);
+
+ priv = widget->priv;
+
+ for (l = priv->event_controllers; l; l = l->next)
+ {
+ data = l->data;
+
+ if (data->controller != controller)
+ continue;
+
+ data->propagation_phase = phase;
+ return;
+ }
+
+ data = g_new0 (EventControllerData, 1);
+ data->controller = g_object_ref (controller);
+ data->propagation_phase = phase;
+ priv->event_controllers = g_list_prepend (priv->event_controllers, data);
+}
+
+void
+gtk_widget_remove_controller (GtkWidget *widget,
+ GtkEventController *controller)
+{
+ EventControllerData *data;
+ GtkWidgetPrivate *priv;
+ GList *l;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (GTK_IS_EVENT_CONTROLLER (controller));
+
+ priv = widget->priv;
+
+ for (l = priv->event_controllers; l; l = l->next)
+ {
+ data = l->data;
+
+ if (data->controller != controller)
+ continue;
+
+ /* FIXME: reset controller */
+
+ g_object_unref (data->controller);
+ g_free (data);
+ priv->event_controllers = g_list_delete_link (priv->event_controllers, l);
+ return;
+ }
+}
+
+GList *
+gtk_widget_list_controllers (GtkWidget *widget,
+ GtkPropagationPhase phase)
+{
+ EventControllerData *data;
+ GtkWidgetPrivate *priv;
+ GList *l, *retval = NULL;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+ g_return_val_if_fail (phase == GTK_PHASE_CAPTURE ||
+ phase == GTK_PHASE_BUBBLE, NULL);
+
+ priv = widget->priv;
+
+ for (l = priv->event_controllers; l; l = l->next)
+ {
+ data = l->data;
+
+ if (data->propagation_phase == phase)
+ retval = g_list_prepend (retval, data->controller);
+ }
+
+ return retval;
+}
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index bf47657..6b09b09 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -33,6 +33,7 @@
#include <gtk/gtkaccelgroup.h>
#include <gtk/gtkborder.h>
#include <gtk/gtktypes.h>
+#include <gtk/gtkeventcontroller.h>
#include <atk/atk.h>
G_BEGIN_DECLS
@@ -1468,6 +1469,17 @@ void gtk_widget_class_bind_template_child_full (GtkWidgetClass *
gboolean internal_child,
gssize struct_offset);
+GDK_AVAILABLE_IN_3_12
+void gtk_widget_add_controller (GtkWidget *widget,
+ GtkEventController *controller,
+ GtkPropagationPhase phase);
+GDK_AVAILABLE_IN_3_12
+void gtk_widget_remove_controller (GtkWidget *widget,
+ GtkEventController *controller);
+GDK_AVAILABLE_IN_3_12
+GList * gtk_widget_list_controllers (GtkWidget *widget,
+ GtkPropagationPhase phase);
+
G_END_DECLS
#endif /* __GTK_WIDGET_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]