[gtk/wip/matthiasc/popup5: 28/128] Introduce event controller propagation limits



commit f73d4a8a7d8125579b6b8f0ec96b32ad737c1eab
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Apr 29 02:19:44 2019 +0000

    Introduce event controller propagation limits
    
    Limit event handlers by default to only handle
    events targeting the same surface as their widget.

 docs/reference/gtk/gtk4-sections.txt |  3 ++
 gtk/gtkenums.h                       | 17 +++++++
 gtk/gtkeventcontroller.c             | 86 +++++++++++++++++++++++++++++++++++-
 gtk/gtkeventcontroller.h             |  6 +++
 4 files changed, 110 insertions(+), 2 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 93cfc5fc20..e35edb2288 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -6518,6 +6518,9 @@ GtkEventController
 GtkPropagationPhase
 gtk_event_controller_get_propagation_phase
 gtk_event_controller_set_propagation_phase
+GtkPropagationLimit
+gtk_event_controller_get_propagation_limit
+gtk_event_controller_set_propagation_limit
 gtk_event_controller_handle_event
 gtk_event_controller_get_widget
 gtk_event_controller_reset
diff --git a/gtk/gtkenums.h b/gtk/gtkenums.h
index d18f3f995d..6d1bf81295 100644
--- a/gtk/gtkenums.h
+++ b/gtk/gtkenums.h
@@ -967,6 +967,23 @@ typedef enum
   GTK_PHASE_TARGET
 } GtkPropagationPhase;
 
+/**
+ * GtkPropagationLimit:
+ * @GTK_LIMIT_NONE: Events are handled regardless of what their
+ *   target is.
+ * @GTK_LIMIT_SAME_NATIVE: Events are only handled if their target
+ *   is in the same #GtkNative as the event controllers widget. Note
+ *   that some event types have two targets (origin and destination).
+ *
+ * Describes limits of a #GtkEventController for handling events
+ * targeting other widgets.
+ */
+typedef enum
+{
+  GTK_LIMIT_NONE,
+  GTK_LIMIT_SAME_NATIVE
+} GtkPropagationLimit;
+
 /**
  * GtkEventSequenceState:
  * @GTK_EVENT_SEQUENCE_NONE: The sequence is handled, but not grabbed.
diff --git a/gtk/gtkeventcontroller.c b/gtk/gtkeventcontroller.c
index d085cd5899..5f3635cf74 100644
--- a/gtk/gtkeventcontroller.c
+++ b/gtk/gtkeventcontroller.c
@@ -32,17 +32,20 @@
 #include "config.h"
 #include "gtkeventcontroller.h"
 #include "gtkeventcontrollerprivate.h"
+
 #include "gtkwidgetprivate.h"
 #include "gtktypebuiltins.h"
 #include "gtkmarshalers.h"
 #include "gtkprivate.h"
 #include "gtkintl.h"
+#include "gtknative.h"
 
 typedef struct _GtkEventControllerPrivate GtkEventControllerPrivate;
 
 enum {
   PROP_WIDGET = 1,
   PROP_PROPAGATION_PHASE,
+  PROP_PROPAGATION_LIMIT,
   LAST_PROP
 };
 
@@ -52,6 +55,7 @@ struct _GtkEventControllerPrivate
 {
   GtkWidget *widget;
   GtkPropagationPhase phase;
+  GtkPropagationLimit limit;
 };
 
 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GtkEventController, gtk_event_controller, G_TYPE_OBJECT)
@@ -79,8 +83,35 @@ gtk_event_controller_filter_event_default (GtkEventController *self,
 {
   GtkEventControllerPrivate *priv = gtk_event_controller_get_instance_private (self);
 
-  if (priv->widget)
-    return !gtk_widget_is_sensitive (priv->widget);
+  if (priv->widget && !gtk_widget_is_sensitive (priv->widget))
+    return TRUE;
+
+  if (priv->limit == GTK_LIMIT_SAME_NATIVE)
+    {
+      GtkWidget *native;
+      GtkWidget *native2;
+      GtkWidget *target;
+
+      native = gtk_widget_get_ancestor (priv->widget, GTK_TYPE_NATIVE);
+
+      target = GTK_WIDGET (gdk_event_get_target (event));
+      if (target)
+        {
+          native2 = gtk_widget_get_ancestor (target, GTK_TYPE_NATIVE);
+          if (native == native2)
+            return FALSE;
+        }
+
+      target = GTK_WIDGET (gdk_event_get_related_target (event));
+      if (target)
+        {
+          native2 = gtk_widget_get_ancestor (target, GTK_TYPE_NATIVE);
+          if (native == native2)
+            return FALSE;
+        }
+
+      return TRUE;
+    }
 
   return FALSE;
 }
@@ -106,6 +137,10 @@ gtk_event_controller_set_property (GObject      *object,
       gtk_event_controller_set_propagation_phase (self,
                                                   g_value_get_enum (value));
       break;
+    case PROP_PROPAGATION_LIMIT:
+      gtk_event_controller_set_propagation_limit (self,
+                                                  g_value_get_enum (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -128,6 +163,9 @@ gtk_event_controller_get_property (GObject    *object,
     case PROP_PROPAGATION_PHASE:
       g_value_set_enum (value, priv->phase);
       break;
+    case PROP_PROPAGATION_LIMIT:
+      g_value_set_enum (value, priv->limit);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -157,6 +195,7 @@ gtk_event_controller_class_init (GtkEventControllerClass *klass)
                            P_("Widget the gesture relates to"),
                            GTK_TYPE_WIDGET,
                            GTK_PARAM_READABLE);
+
   /**
    * GtkEventController:propagation-phase:
    *
@@ -170,6 +209,19 @@ gtk_event_controller_class_init (GtkEventControllerClass *klass)
                          GTK_PHASE_BUBBLE,
                          GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
 
+  /**
+   * GtkEventController:propagation-limit:
+   *
+   * The limit for which events this controller will handle.
+   */
+  properties[PROP_PROPAGATION_LIMIT] =
+      g_param_spec_enum ("propagation-limit",
+                         P_("Propagation limit"),
+                         P_("Propagation limit for events handled by this controller"),
+                         GTK_TYPE_PROPAGATION_LIMIT,
+                         GTK_LIMIT_SAME_NATIVE,
+                         GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
+
   g_object_class_install_properties (object_class, LAST_PROP, properties);
 }
 
@@ -180,6 +232,7 @@ gtk_event_controller_init (GtkEventController *controller)
 
   priv = gtk_event_controller_get_instance_private (controller);
   priv->phase = GTK_PHASE_BUBBLE;
+  priv->limit = GTK_LIMIT_SAME_NATIVE;
 }
 
 /**
@@ -311,3 +364,32 @@ gtk_event_controller_set_propagation_phase (GtkEventController  *controller,
 
   g_object_notify_by_pspec (G_OBJECT (controller), properties[PROP_PROPAGATION_PHASE]);
 }
+
+GtkPropagationLimit
+gtk_event_controller_get_propagation_limit (GtkEventController *controller)
+{
+  GtkEventControllerPrivate *priv;
+
+  g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER (controller), GTK_LIMIT_SAME_NATIVE);
+
+  priv = gtk_event_controller_get_instance_private (controller);
+
+  return priv->limit;
+}
+void
+gtk_event_controller_set_propagation_limit (GtkEventController  *controller,
+                                            GtkPropagationLimit  limit)
+{
+  GtkEventControllerPrivate *priv;
+
+  g_return_if_fail (GTK_IS_EVENT_CONTROLLER (controller));
+
+  priv = gtk_event_controller_get_instance_private (controller);
+
+  if (priv->limit == limit)
+    return;
+
+  priv->limit = limit;
+
+  g_object_notify_by_pspec (G_OBJECT (controller), properties[PROP_PROPAGATION_LIMIT]);
+}
diff --git a/gtk/gtkeventcontroller.h b/gtk/gtkeventcontroller.h
index f2f2b6a2b0..963f440e6a 100644
--- a/gtk/gtkeventcontroller.h
+++ b/gtk/gtkeventcontroller.h
@@ -59,6 +59,12 @@ GDK_AVAILABLE_IN_ALL
 void                gtk_event_controller_set_propagation_phase (GtkEventController  *controller,
                                                                 GtkPropagationPhase  phase);
 
+GDK_AVAILABLE_IN_ALL
+GtkPropagationLimit gtk_event_controller_get_propagation_limit (GtkEventController *controller);
+
+GDK_AVAILABLE_IN_ALL
+void                gtk_event_controller_set_propagation_limit (GtkEventController  *controller,
+                                                                GtkPropagationLimit  limit);
 G_END_DECLS
 
 #endif /* __GTK_EVENT_CONTROLLER_H__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]