[gtk+/wip/carlosg/event-delivery-cleanups: 2/30] gtk: Run GtkWidgetClass event signals inside a GtkEventController



commit 3f9164ccf43911da4beaf4ab0e62c1e1c322773e
Author: Carlos Garnacho <carlosg gnome org>
Date:   Fri May 26 18:55:30 2017 +0200

    gtk: Run GtkWidgetClass event signals inside a GtkEventController
    
    This will allow further cleanups and optimizations in capture/target/bubble
    event delivery. For simplicity, ATM every widget will receive its own
    GtkEventControllerLegacy, it could be desirable to add finer control over
    this in the future, so widgets that fully use event controllers for input
    management can do away without this legacy piece.

 gtk/gtkeventcontrollerlegacy.c        |   56 +++++++++++++++++++
 gtk/gtkeventcontrollerlegacyprivate.h |   51 +++++++++++++++++
 gtk/gtkwidget.c                       |   97 ++++++++++++++++++++++++---------
 gtk/gtkwidgetprivate.h                |    6 ++
 gtk/meson.build                       |    2 +
 5 files changed, 185 insertions(+), 27 deletions(-)
---
diff --git a/gtk/gtkeventcontrollerlegacy.c b/gtk/gtkeventcontrollerlegacy.c
new file mode 100644
index 0000000..737312d
--- /dev/null
+++ b/gtk/gtkeventcontrollerlegacy.c
@@ -0,0 +1,56 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2017, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s): Carlos Garnacho <carlosg gnome org>
+ */
+
+#include "config.h"
+#include "gtkeventcontrollerlegacyprivate.h"
+
+G_DEFINE_TYPE (GtkEventControllerLegacy, _gtk_event_controller_legacy,
+               GTK_TYPE_EVENT_CONTROLLER)
+
+static gboolean
+gtk_event_controller_legacy_handle_event (GtkEventController *controller,
+                                          const GdkEvent     *event)
+{
+  GtkWidget *widget = gtk_event_controller_get_widget (controller);
+
+  return gtk_widget_emit_event_signals (widget, event);
+}
+
+static void
+_gtk_event_controller_legacy_class_init (GtkEventControllerLegacyClass *klass)
+{
+  GtkEventControllerClass *controller_class = GTK_EVENT_CONTROLLER_CLASS (klass);
+
+  controller_class->handle_event = gtk_event_controller_legacy_handle_event;
+}
+
+static void
+_gtk_event_controller_legacy_init (GtkEventControllerLegacy *controller)
+{
+}
+
+GtkEventController *
+_gtk_event_controller_legacy_new (GtkWidget *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+
+  return g_object_new (GTK_TYPE_EVENT_CONTROLLER_LEGACY,
+                       "widget", widget,
+                       NULL);
+}
diff --git a/gtk/gtkeventcontrollerlegacyprivate.h b/gtk/gtkeventcontrollerlegacyprivate.h
new file mode 100644
index 0000000..3ec9426
--- /dev/null
+++ b/gtk/gtkeventcontrollerlegacyprivate.h
@@ -0,0 +1,51 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2017, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s): Carlos Garnacho <carlosg gnome org>
+ */
+
+#ifndef __GTK_EVENT_CONTROLLER_LEGACY_H__
+#define __GTK_EVENT_CONTROLLER_LEGACY_H__
+
+#include "gtkeventcontrollerprivate.h"
+#include "gtkwidgetprivate.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_EVENT_CONTROLLER_LEGACY         (_gtk_event_controller_legacy_get_type ())
+#define GTK_EVENT_CONTROLLER_LEGACY(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), 
GTK_TYPE_EVENT_CONTROLLER_LEGACY, GtkEventControllerLegacy))
+#define GTK_EVENT_CONTROLLER_LEGACY_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), 
GTK_TYPE_EVENT_CONTROLLER_LEGACY, GtkEventControllerLegacyClass))
+#define GTK_IS_EVENT_CONTROLLER_LEGACY(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), 
GTK_TYPE_EVENT_CONTROLLER_LEGACY))
+#define GTK_IS_EVENT_CONTROLLER_LEGACY_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), 
GTK_TYPE_EVENT_CONTROLLER_LEGACY))
+#define GTK_EVENT_CONTROLLER_LEGACY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), 
GTK_TYPE_EVENT_CONTROLLER_LEGACY, GtkEventControllerLegacyClass))
+
+typedef struct _GtkEventControllerLegacy GtkEventControllerLegacy;
+typedef struct _GtkEventControllerLegacyClass GtkEventControllerLegacyClass;
+
+struct _GtkEventControllerLegacy
+{
+  GtkEventController parent_instance;
+};
+
+struct _GtkEventControllerLegacyClass
+{
+  GtkEventControllerClass parent_class;
+};
+
+GType               _gtk_event_controller_legacy_get_type  (void) G_GNUC_CONST;
+GtkEventController *_gtk_event_controller_legacy_new       (GtkWidget *widget);
+
+#endif /* __GTK_EVENT_CONTROLLER_LEGACY_H__ */
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 9042af9..ad0b283 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -74,6 +74,7 @@
 #include "gtkcssshadowsvalueprivate.h"
 #include "gtkdebugupdatesprivate.h"
 #include "gsk/gskdebugprivate.h"
+#include "gtkeventcontrollerlegacyprivate.h"
 
 #include "inspector/window.h"
 
@@ -3844,6 +3845,8 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
   gtk_css_node_set_visible (priv->cssnode, priv->visible);
   /* need to set correct type here, and only class has the correct type here */
   gtk_css_node_set_widget_type (priv->cssnode, G_TYPE_FROM_CLASS (g_class));
+
+  gtk_widget_init_legacy_controller (widget);
 }
 
 
@@ -6463,16 +6466,14 @@ static gboolean
 gtk_widget_real_button_event (GtkWidget      *widget,
                               GdkEventButton *event)
 {
-  return _gtk_widget_run_controllers (widget, (GdkEvent *) event,
-                                      GTK_PHASE_BUBBLE);
+  return GDK_EVENT_PROPAGATE;
 }
 
 static gboolean
 gtk_widget_real_motion_event (GtkWidget      *widget,
                               GdkEventMotion *event)
 {
-  return _gtk_widget_run_controllers (widget, (GdkEvent *) event,
-                                      GTK_PHASE_BUBBLE);
+  return GDK_EVENT_PROPAGATE;
 }
 
 static gboolean
@@ -6515,10 +6516,6 @@ gtk_widget_real_touch_event (GtkWidget     *widget,
   gboolean return_val;
   gint signum;
 
-  if (!event->emulating_pointer)
-    return _gtk_widget_run_controllers (widget, (GdkEvent*) event,
-                                        GTK_PHASE_BUBBLE);
-
   if (event->type == GDK_TOUCH_BEGIN ||
       event->type == GDK_TOUCH_END)
     {
@@ -6584,8 +6581,7 @@ static gboolean
 gtk_widget_real_grab_broken_event (GtkWidget          *widget,
                                    GdkEventGrabBroken *event)
 {
-  return _gtk_widget_run_controllers (widget, (GdkEvent*) event,
-                                      GTK_PHASE_BUBBLE);
+  return GDK_EVENT_PROPAGATE;
 }
 
 #define WIDGET_REALIZED_FOR_EVENT(widget, event) \
@@ -6824,7 +6820,7 @@ static gint
 gtk_widget_event_internal (GtkWidget      *widget,
                            const GdkEvent *event)
 {
-  gboolean return_val = FALSE, handled;
+  gboolean return_val = FALSE;
   GdkEvent *event_copy;
 
   /* We check only once for is-still-visible; if someone
@@ -6835,7 +6831,27 @@ gtk_widget_event_internal (GtkWidget      *widget,
   if (!event_window_is_still_viewable (event))
     return TRUE;
 
-  g_object_ref (widget);
+  /* Non input events get handled right away */
+  switch (event->type)
+    {
+    case GDK_VISIBILITY_NOTIFY:
+    case GDK_EXPOSE:
+    case GDK_NOTHING:
+    case GDK_DELETE:
+    case GDK_DESTROY:
+    case GDK_CONFIGURE:
+    case GDK_MAP:
+    case GDK_UNMAP:
+    case GDK_WINDOW_STATE:
+    case GDK_PROPERTY_NOTIFY:
+    case GDK_SELECTION_CLEAR:
+    case GDK_SELECTION_REQUEST:
+    case GDK_SELECTION_NOTIFY:
+      return gtk_widget_emit_event_signals (widget, event);
+    default:
+      break;
+    }
+
   event_copy = gdk_event_copy (event);
 
   translate_event_coordinates (event_copy, widget);
@@ -6843,18 +6859,39 @@ gtk_widget_event_internal (GtkWidget      *widget,
   if (widget == gtk_get_event_target (event_copy))
     return_val |= _gtk_widget_run_controllers (widget, event_copy, GTK_PHASE_TARGET);
 
-  g_signal_emit (widget, widget_signals[EVENT], 0, event_copy, &handled);
-  return_val |= handled | !WIDGET_REALIZED_FOR_EVENT (widget, event_copy);
+  /* XXX: Tooltips should be handled through captured events in the toplevel */
+  if (event_copy->type == GDK_FOCUS_CHANGE)
+    {
+      if (event_copy->focus_change.in)
+        _gtk_tooltip_focus_in (widget);
+      else
+        _gtk_tooltip_focus_out (widget);
+    }
+
+  return_val |= _gtk_widget_run_controllers (widget, event_copy, GTK_PHASE_BUBBLE);
+  gdk_event_free (event_copy);
+
+  return return_val;
+}
+
+gboolean
+gtk_widget_emit_event_signals (GtkWidget      *widget,
+                               const GdkEvent *event)
+{
+  gboolean return_val = FALSE, handled;
+
+  g_object_ref (widget);
+
+  g_signal_emit (widget, widget_signals[EVENT], 0, event, &handled);
+  return_val |= handled | !WIDGET_REALIZED_FOR_EVENT (widget, event);
   if (!return_val)
     {
       gint signal_num;
 
-      switch (event_copy->type)
+      switch (event->type)
        {
         case GDK_TOUCHPAD_SWIPE:
         case GDK_TOUCHPAD_PINCH:
-          return_val |= _gtk_widget_run_controllers (widget, event_copy, GTK_PHASE_BUBBLE);
-          /* Fall through */
         case GDK_PAD_BUTTON_PRESS:
         case GDK_PAD_BUTTON_RELEASE:
         case GDK_PAD_RING:
@@ -6905,11 +6942,7 @@ gtk_widget_event_internal (GtkWidget      *widget,
          signal_num = LEAVE_NOTIFY_EVENT;
          break;
        case GDK_FOCUS_CHANGE:
-         signal_num = event_copy->focus_change.in ? FOCUS_IN_EVENT : FOCUS_OUT_EVENT;
-         if (event_copy->focus_change.in)
-           _gtk_tooltip_focus_in (widget);
-         else
-           _gtk_tooltip_focus_out (widget);
+         signal_num = event->focus_change.in ? FOCUS_IN_EVENT : FOCUS_OUT_EVENT;
          break;
        case GDK_CONFIGURE:
          signal_num = CONFIGURE_EVENT;
@@ -6945,23 +6978,22 @@ gtk_widget_event_internal (GtkWidget      *widget,
          signal_num = GRAB_BROKEN_EVENT;
          break;
        default:
-         g_warning ("gtk_widget_event(): unhandled event type: %d", event_copy->type);
+         g_warning ("gtk_widget_event(): unhandled event type: %d", event->type);
          signal_num = -1;
          break;
        }
       if (signal_num != -1)
         {
-         g_signal_emit (widget, widget_signals[signal_num], 0, event_copy, &handled);
+         g_signal_emit (widget, widget_signals[signal_num], 0, event, &handled);
           return_val |= handled;
         }
     }
-  if (WIDGET_REALIZED_FOR_EVENT (widget, event_copy))
-    g_signal_emit (widget, widget_signals[EVENT_AFTER], 0, event_copy);
+  if (WIDGET_REALIZED_FOR_EVENT (widget, event))
+    g_signal_emit (widget, widget_signals[EVENT_AFTER], 0, event);
   else
     return_val = TRUE;
 
   g_object_unref (widget);
-  gdk_event_free (event_copy);
 
   return return_val;
 }
@@ -15549,3 +15581,14 @@ gtk_widget_get_pass_through (GtkWidget *widget)
 {
   return widget->priv->pass_through;
 }
+
+void
+gtk_widget_init_legacy_controller (GtkWidget *widget)
+{
+  GtkEventController *controller;
+
+  controller = _gtk_event_controller_legacy_new (widget);
+  g_object_set_data_full (G_OBJECT (widget),
+                          "gtk-widget-legacy-event-controller",
+                          controller, g_object_unref);
+}
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index 4c76ca1..6e0b746 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -334,6 +334,12 @@ void              gtk_widget_set_pass_through              (GtkWidget *widget,
                                                             gboolean   pass_through);
 gboolean          gtk_widget_get_pass_through              (GtkWidget *widget);
 
+gboolean          gtk_widget_emit_event_signals            (GtkWidget      *widget,
+                                                            const GdkEvent *event);
+
+void              gtk_widget_init_legacy_controller        (GtkWidget *widget);
+
+
 /* inline getters */
 
 static inline GtkWidget *
diff --git a/gtk/meson.build b/gtk/meson.build
index 20b0410..5dc3188 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -146,6 +146,7 @@ gtk_public_sources = files([
   'gtkentrybuffer.c',
   'gtkentrycompletion.c',
   'gtkeventcontroller.c',
+  'gtkeventcontrollerlegacy.c',
   'gtkexpander.c',
   'gtkfilechooser.c',
   'gtkfilechooserbutton.c',
@@ -364,6 +365,7 @@ gtk_public_sources = files([
 gtk_private_type_headers = files([
   'gtkcsstypesprivate.h',
   'gtktexthandleprivate.h',
+  'gtkeventcontrollerlegacyprivate.h',
 ])
 
 gtk_private_headers = gtk_private_type_headers + files([


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