[gtk/dnd-gestures-2: 79/150] Turn GtkDropTarget into an event controller



commit 8bae93edeb995f1d4102c14d22954a1440f16023
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Jan 5 22:53:53 2020 -0500

    Turn GtkDropTarget into an event controller
    
    We are still propagating the drag events manually,
    but we are now calling gtk_widget_run_controllers
    to pass them to drop targets.

 gtk/gtkdnd.c        | 140 ++++++++---------------------------------
 gtk/gtkdndprivate.h |  14 +++++
 gtk/gtkdragdest.c   | 178 +++++++++++++++++++++++++++++++++++++++-------------
 3 files changed, 176 insertions(+), 156 deletions(-)
---
diff --git a/gtk/gtkdnd.c b/gtk/gtkdnd.c
index eda5c11f6f..eff878ed03 100644
--- a/gtk/gtkdnd.c
+++ b/gtk/gtkdnd.c
@@ -63,26 +63,9 @@
  */
 
 
-typedef struct _GtkDragDestInfo GtkDragDestInfo;
-
-struct _GtkDragDestInfo
-{
-  GtkWidget         *widget;              /* Widget in which drag is in */
-  GdkDrop           *drop;                /* drop */
-};
-
 /* Forward declarations */
-static GtkWidget *gtk_drop_find_widget          (GtkWidget        *widget,
+static gboolean gtk_drop_find_widget            (GtkWidget        *widget,
                                                  GdkEvent         *event);
-static void     gtk_drag_dest_leave             (GtkWidget        *widget,
-                                                 GdkDrop          *drop);
-static gboolean gtk_drop_target_handle_event    (GtkDropTarget    *dest,
-                                                 GdkEvent         *event);
-static void     gtk_drag_dest_set_widget        (GtkDragDestInfo  *info,
-                                                 GtkWidget        *widget);
-
-static GtkDragDestInfo *  gtk_drag_get_dest_info     (GdkDrop        *drop,
-                                                      gboolean        create);
 
 
 /*
@@ -116,41 +99,17 @@ _gtk_drag_dest_handle_event (GtkWidget *toplevel,
       break;
       
     case GDK_DRAG_LEAVE:
-      if (info->widget)
+      if (info->dest)
         {
-          gtk_drag_dest_leave (info->widget, drop);
-          gtk_drag_dest_set_widget (info, NULL);
+          gtk_drop_target_emit_drag_leave (info->dest, drop);
+          gtk_drag_dest_set_target (info, NULL);
         }
       break;
       
     case GDK_DRAG_MOTION:
     case GDK_DROP_START:
       {
-        GtkWidget *widget;
-
-        if (event_type == GDK_DROP_START)
-          {
-            /* We send a leave here so that the widget unhighlights
-             * properly.
-             */
-            if (info->widget)
-              {
-                gtk_drag_dest_leave (info->widget, drop);
-                gtk_drag_dest_set_widget (info, NULL);
-              }
-          }
-
-        widget = gtk_drop_find_widget (toplevel, event);
-
-        if (info->widget && info->widget != widget)
-          {
-            gtk_drag_dest_leave (info->widget, drop);
-            gtk_drag_dest_set_widget (info, NULL);
-          }
-
-        if (widget)
-          gtk_drag_dest_set_widget (info, widget);
-        else
+        if (!gtk_drop_find_widget (toplevel, event))
           gdk_drop_status (drop, 0);
       }
       break;
@@ -160,7 +119,7 @@ _gtk_drag_dest_handle_event (GtkWidget *toplevel,
     }
 }
 
-static GtkWidget *
+static gboolean
 gtk_drop_find_widget (GtkWidget *event_widget,
                       GdkEvent  *event)
 {
@@ -170,26 +129,25 @@ gtk_drop_find_widget (GtkWidget *event_widget,
 
   if (!gtk_widget_get_mapped (event_widget) ||
       !gtk_widget_get_sensitive (event_widget))
-    return NULL;
+    return FALSE;
 
   gdk_event_get_coords (event, &x, &y);
 
   widget = gtk_widget_pick (event_widget, x, y, GTK_PICK_DEFAULT);
 
   if (!widget)
-    return NULL;
+    return FALSE;
 
   gtk_widget_translate_coordinates (event_widget, widget, x, y, &wx, &wy);
 
   while (widget)
     {
-      GtkDropTarget *dest;
       GtkWidget *parent;
       GList *hierarchy = NULL;
       gboolean found = FALSE;
 
       if (!gtk_widget_get_mapped (widget))
-        return NULL;
+        return FALSE;
 
       if (gtk_widget_get_state_flags (widget) & GTK_STATE_FLAG_INSENSITIVE)
         {
@@ -207,17 +165,9 @@ gtk_drop_find_widget (GtkWidget *event_widget,
           hierarchy = g_list_prepend (hierarchy, g_object_ref (parent));
         }
 
-      /* If the current widget is registered as a drop site, check to
-       * emit "drag-motion" to check if we are actually in a drop
-       * site.
-       */
-      dest = gtk_drop_target_get (widget);
-      if (dest)
-        {
-          gdk_event_set_coords (event, wx, wy);
-          found = gtk_drop_target_handle_event (dest, event);
-          gdk_event_set_coords (event, x, y);
-        }
+      gdk_event_set_coords (event, wx, wy);
+      found = gtk_widget_run_controllers (widget, event, GTK_PHASE_BUBBLE);
+      gdk_event_set_coords (event, x, y);
 
       if (!found)
         {
@@ -236,33 +186,33 @@ gtk_drop_find_widget (GtkWidget *event_widget,
       g_list_free_full (hierarchy, g_object_unref);
 
       if (found)
-        return widget;
+        return TRUE;
 
       if (parent)
         g_object_remove_weak_pointer (G_OBJECT (parent), (gpointer *) &parent);
       else
-        return NULL;
+        return FALSE;
 
       if (!gtk_widget_translate_coordinates (widget, parent, wx, wy, &wx, &wy))
-        return NULL;
+        return FALSE;
 
       widget = parent;
     }
 
-  return NULL;
+  return FALSE;
 }
 
-static void
-gtk_drag_dest_set_widget (GtkDragDestInfo *info,
-                          GtkWidget       *widget)
+void
+gtk_drag_dest_set_target (GtkDragDestInfo *info,
+                          GtkDropTarget   *dest)
 {
-  if (info->widget)
-    g_object_remove_weak_pointer (G_OBJECT (info->widget), (gpointer *) &info->widget);
+  if (info->dest)
+    g_object_remove_weak_pointer (G_OBJECT (info->dest), (gpointer *) &info->dest);
 
-  info->widget = widget;
+  info->dest = dest;
 
-  if (info->widget)
-    g_object_add_weak_pointer (G_OBJECT (info->widget), (gpointer *) &info->widget);
+  if (info->dest)
+    g_object_add_weak_pointer (G_OBJECT (info->dest), (gpointer *) &info->dest);
 }
 
 static void
@@ -270,12 +220,12 @@ gtk_drag_dest_info_destroy (gpointer data)
 {
   GtkDragDestInfo *info = (GtkDragDestInfo *)data;
 
-  gtk_drag_dest_set_widget (info, NULL);
+  gtk_drag_dest_set_target (info, NULL);
 
   g_slice_free (GtkDragDestInfo, data);
 }
 
-static GtkDragDestInfo *
+GtkDragDestInfo *
 gtk_drag_get_dest_info (GdkDrop  *drop,
                         gboolean  create)
 {
@@ -295,41 +245,3 @@ gtk_drag_get_dest_info (GdkDrop  *drop,
 
   return info;
 }
-
-/*
- * Default drag handlers
- */
-static void  
-gtk_drag_dest_leave (GtkWidget *widget,
-                     GdkDrop   *drop)
-{
-  GtkDropTarget *dest;
-
-  dest = gtk_drop_target_get (widget);
-  g_return_if_fail (dest != NULL);
-
-  gtk_drop_target_emit_drag_leave (dest, drop);
-}
-
-static gboolean
-gtk_drop_target_handle_event (GtkDropTarget *dest,
-                              GdkEvent      *event)
-{
-  GdkDrop *drop;
-  double x, y;
-
-  drop = gdk_event_get_drop (event);
-  gdk_event_get_coords (event, &x, &y);
-
-  switch ((int)gdk_event_get_event_type (event))
-    {
-    case GDK_DRAG_MOTION:
-      return gtk_drop_target_emit_drag_motion (dest, drop, x, y);
-    case GDK_DROP_START:
-      return gtk_drop_target_emit_drag_drop (dest, drop, x, y);
-    default:
-      break;
-    }
-
-  return FALSE;
-}
diff --git a/gtk/gtkdndprivate.h b/gtk/gtkdndprivate.h
index ad829e05b7..b316a9fded 100644
--- a/gtk/gtkdndprivate.h
+++ b/gtk/gtkdndprivate.h
@@ -20,6 +20,7 @@
 #define __GTK_DND_PRIVATE_H__
 
 #include "gtkwidget.h"
+#include "gtkdragdest.h"
 
 
 G_BEGIN_DECLS
@@ -27,6 +28,19 @@ G_BEGIN_DECLS
 void                    _gtk_drag_dest_handle_event     (GtkWidget              *toplevel,
                                                         GdkEvent               *event);
 
+typedef struct _GtkDragDestInfo GtkDragDestInfo;
+
+struct _GtkDragDestInfo
+{
+  GtkDropTarget     *dest;
+  GdkDrop           *drop;                /* drop */
+};
+
+GtkDragDestInfo * gtk_drag_get_dest_info   (GdkDrop          *drop,
+                                            gboolean          create);
+void              gtk_drag_dest_set_target (GtkDragDestInfo  *info,
+                                            GtkDropTarget    *dest);
+
 G_END_DECLS
 
 #endif /* __GTK_DND_PRIVATE_H__ */
diff --git a/gtk/gtkdragdest.c b/gtk/gtkdragdest.c
index 4ad84fbe2f..cd12f995ed 100644
--- a/gtk/gtkdragdest.c
+++ b/gtk/gtkdragdest.c
@@ -31,7 +31,7 @@
 #include "gtkintl.h"
 #include "gtknative.h"
 #include "gtktypebuiltins.h"
-#include "gtkeventcontroller.h"
+#include "gtkeventcontrollerprivate.h"
 #include "gtkmarshalers.h"
 #include "gtkselectionprivate.h"
 
@@ -51,7 +51,7 @@
 
 struct _GtkDropTarget
 {
-  GObject parent_instance;
+  GtkEventController parent_object;
 
   GdkContentFormats *formats;
   GdkDragAction actions;
@@ -64,7 +64,7 @@ struct _GtkDropTarget
 
 struct _GtkDropTargetClass
 {
-  GObjectClass parent_class;
+  GtkEventControllerClass parent_class;
 
   gboolean (*drag_motion) (GtkDropTarget *dest,
                            int            x,
@@ -94,7 +94,15 @@ static gboolean gtk_drop_target_drag_motion (GtkDropTarget *dest,
                                              int            x,
                                              int            y);
 
-G_DEFINE_TYPE (GtkDropTarget, gtk_drop_target, G_TYPE_OBJECT);
+static gboolean gtk_drop_target_handle_event (GtkEventController *controller,
+                                              const GdkEvent     *event);
+static gboolean gtk_drop_target_filter_event (GtkEventController *controller,
+                                              const GdkEvent     *event);
+static void     gtk_drop_target_set_widget   (GtkEventController *controller,
+                                              GtkWidget          *widget);
+static void     gtk_drop_target_unset_widget (GtkEventController *controller);
+
+G_DEFINE_TYPE (GtkDropTarget, gtk_drop_target, GTK_TYPE_EVENT_CONTROLLER);
 
 static void
 gtk_drop_target_init (GtkDropTarget *dest)
@@ -165,11 +173,17 @@ static void
 gtk_drop_target_class_init (GtkDropTargetClass *class)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (class);
+  GtkEventControllerClass *controller_class = GTK_EVENT_CONTROLLER_CLASS (class);
 
   object_class->finalize = gtk_drop_target_finalize;
   object_class->set_property = gtk_drop_target_set_property;
   object_class->get_property = gtk_drop_target_get_property;
 
+  controller_class->handle_event = gtk_drop_target_handle_event;
+  controller_class->filter_event = gtk_drop_target_filter_event;
+  controller_class->set_widget = gtk_drop_target_set_widget;
+  controller_class->unset_widget = gtk_drop_target_unset_widget;
+
   class->drag_motion = gtk_drop_target_drag_motion;
 
   /**
@@ -445,28 +459,11 @@ void
 gtk_drop_target_attach (GtkDropTarget *dest,
                         GtkWidget     *widget)
 {
-  GtkDropTarget *old_dest;
-
   g_return_if_fail (GTK_IS_DROP_TARGET (dest));
-  g_return_if_fail (dest->widget == NULL);
   g_return_if_fail (GTK_IS_WIDGET (widget));
 
-  old_dest = g_object_get_data (G_OBJECT (widget), I_("gtk-drag-dest"));
-  if (old_dest)
-    {
-      g_signal_handlers_disconnect_by_func (widget, gtk_drag_dest_realized, old_dest);
-      g_signal_handlers_disconnect_by_func (widget, gtk_drag_dest_hierarchy_changed, old_dest);
-    }
-
-  if (gtk_widget_get_realized (widget))
-    gtk_drag_dest_realized (widget);
-
-  dest->widget = widget;
-
-  g_signal_connect (widget, "realize", G_CALLBACK (gtk_drag_dest_realized), dest);
-  g_signal_connect (widget, "notify::root", G_CALLBACK (gtk_drag_dest_hierarchy_changed), dest);
-
-  g_object_set_data_full (G_OBJECT (widget), I_("gtk-drag-dest"), dest, g_object_unref);
+  gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (dest), GTK_PHASE_BUBBLE);
+  gtk_widget_add_controller (widget, GTK_EVENT_CONTROLLER (dest));
 }
 
 /**
@@ -478,17 +475,12 @@ gtk_drop_target_attach (GtkDropTarget *dest,
 void
 gtk_drop_target_detach (GtkDropTarget *dest)
 {
-  g_return_if_fail (GTK_IS_DROP_TARGET (dest));
-
-  if (dest->widget)
-    {
-      g_signal_handlers_disconnect_by_func (dest->widget, gtk_drag_dest_realized, dest);
-      g_signal_handlers_disconnect_by_func (dest->widget, gtk_drag_dest_hierarchy_changed, dest);
+  GtkWidget *widget;
 
-      g_object_set_data (G_OBJECT (dest->widget), I_("gtk-drag-dest"), NULL);
+  g_return_if_fail (GTK_IS_DROP_TARGET (dest));
 
-      dest->widget = NULL;
-    }
+  widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest));
+  gtk_widget_remove_controller (widget, GTK_EVENT_CONTROLLER (dest));
 }
 
 /**
@@ -504,7 +496,7 @@ gtk_drop_target_get_target (GtkDropTarget *dest)
 {
   g_return_val_if_fail (GTK_IS_DROP_TARGET (dest), NULL);
 
-  return dest->widget;
+  return gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest));
 }
 
 /**
@@ -650,6 +642,10 @@ void
 gtk_drop_target_set_armed (GtkDropTarget *dest,
                            gboolean       armed)
 {
+  GtkWidget *widget;
+
+  widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest));
+
   dest->armed_pending = FALSE;
 
   if (dest->armed == armed)
@@ -657,13 +653,10 @@ gtk_drop_target_set_armed (GtkDropTarget *dest,
 
   dest->armed = armed;
 
-  if (dest->widget)
-    {
-      if (armed)
-        gtk_drag_highlight (dest->widget);
-      else
-        gtk_drag_unhighlight (dest->widget);
-    }
+  if (armed)
+    gtk_drag_highlight (widget);
+  else
+    gtk_drag_unhighlight (widget);
 
   g_object_notify_by_pspec (G_OBJECT (dest), properties[PROP_ARMED]);
 }
@@ -674,6 +667,104 @@ gtk_drop_target_get_armed (GtkDropTarget *dest)
   return dest->armed;
 }
 
+static gboolean
+gtk_drop_target_filter_event (GtkEventController *controller,
+                              const GdkEvent     *event)
+{
+  switch ((int)gdk_event_get_event_type (event))
+    {
+    case GDK_DRAG_ENTER:
+    case GDK_DRAG_LEAVE:
+    case GDK_DRAG_MOTION:
+    case GDK_DROP_START:
+      return GTK_EVENT_CONTROLLER_CLASS (gtk_drop_target_parent_class)->filter_event (controller, event);
+
+    default:;
+    }
+
+  return TRUE;
+}
+
+static gboolean
+gtk_drop_target_handle_event (GtkEventController *controller,
+                              const GdkEvent     *event)
+{
+  GtkDropTarget *dest = GTK_DROP_TARGET (controller);
+  GdkDrop *drop;
+  GtkDragDestInfo *info;
+  double x, y;
+  gboolean found = FALSE;
+
+  gdk_event_get_coords (event, &x, &y);
+
+  drop = gdk_event_get_drop (event);
+  info = gtk_drag_get_dest_info (drop, TRUE);
+
+  switch ((int)gdk_event_get_event_type (event))
+    {
+    case GDK_DRAG_MOTION:
+      found = gtk_drop_target_emit_drag_motion (dest, drop, x, y);
+      break;
+
+    case GDK_DROP_START:
+      /* We send a leave before the drop so that the widget unhighlights
+       * properly.
+       */
+      if (info->dest)
+        {
+          gtk_drop_target_emit_drag_leave (info->dest, drop);
+          gtk_drag_dest_set_target (info, NULL);
+        }
+
+      found = gtk_drop_target_emit_drag_drop (dest, drop, x, y);
+      break;
+
+    default:
+      break;
+    }
+
+  if (found)
+    {
+      if (info->dest && info->dest != dest)
+        {
+          gtk_drop_target_emit_drag_leave (info->dest, drop);
+          gtk_drag_dest_set_target (info, NULL);
+        }
+
+      gtk_drag_dest_set_target (info, dest);
+    }
+
+  return found;
+}
+
+static void
+gtk_drop_target_set_widget (GtkEventController *controller,
+                            GtkWidget          *widget)
+{
+  GtkDropTarget *dest = GTK_DROP_TARGET (controller);
+
+  GTK_EVENT_CONTROLLER_CLASS (gtk_drop_target_parent_class)->set_widget (controller, widget);
+
+  if (gtk_widget_get_realized (widget))
+    gtk_drag_dest_realized (widget);
+
+  g_signal_connect (widget, "realize", G_CALLBACK (gtk_drag_dest_realized), dest);
+  g_signal_connect (widget, "notify::root", G_CALLBACK (gtk_drag_dest_hierarchy_changed), dest);
+}
+
+static void
+gtk_drop_target_unset_widget (GtkEventController *controller)
+{
+  GtkWidget *widget;
+
+  widget = gtk_event_controller_get_widget (controller);
+
+  g_signal_handlers_disconnect_by_func (widget, gtk_drag_dest_realized, controller);
+  g_signal_handlers_disconnect_by_func (widget, gtk_drag_dest_hierarchy_changed, controller);
+
+  GTK_EVENT_CONTROLLER_CLASS (gtk_drop_target_parent_class)->unset_widget (controller);
+}
+
 /**
  * gtk_drag_highlight: (method)
  * @widget: a widget to highlight
@@ -810,13 +901,16 @@ gtk_drop_target_read_selection (GtkDropTarget       *dest,
                                 gpointer             user_data)
 {
   GTask *task;
+  GtkWidget *widget;
 
   g_return_if_fail (GTK_IS_DROP_TARGET (dest));
 
   task = g_task_new (dest, NULL, callback, user_data);
   g_object_set_data_full (G_OBJECT (task), "drop", g_object_ref (dest->drop), g_object_unref);
-  if (dest->widget)
-    g_object_set_data (G_OBJECT (task), "display", gtk_widget_get_display (dest->widget));
+
+  widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest));
+  if (widget)
+    g_object_set_data (G_OBJECT (task), "display", gtk_widget_get_display (widget));
 
   gdk_drop_read_async (dest->drop,
                        (const char *[2]) { target, NULL },


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