[gtk/dnd-gestures-2: 1/26] Add a GtkDropTarget object



commit 13db5e796dd36f14c936b75c14e137cd2f2d3425
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Dec 31 01:54:43 2019 -0500

    Add a GtkDropTarget object
    
    Add an explicit GtkDropTarget object, and move the destination-side
    DND signals here. The object is used by connecting to its signals
    and attaching it to a widget with gtk_drop_target_attach().

 gtk/gtkdnd.c             |  89 +++++----
 gtk/gtkdndprivate.h      |   4 +-
 gtk/gtkdragdest.c        | 474 +++++++++++++++++++++++++++++++++++++++++++----
 gtk/gtkdragdest.h        |  69 ++++++-
 gtk/gtkdragdestprivate.h |  46 +++++
 5 files changed, 607 insertions(+), 75 deletions(-)
---
diff --git a/gtk/gtkdnd.c b/gtk/gtkdnd.c
index 20bcb774e1..dc6e5d8cfe 100644
--- a/gtk/gtkdnd.c
+++ b/gtk/gtkdnd.c
@@ -26,7 +26,7 @@
 
 #include "gtkdndprivate.h"
 
-#include "gtkdragdest.h"
+#include "gtkdragdestprivate.h"
 #include "gtkimageprivate.h"
 #include "gtkintl.h"
 #include "gtkmain.h"
@@ -111,6 +111,7 @@ static GtkDragDestInfo *  gtk_drag_get_dest_info     (GdkDrop        *drop,
  * Destination side *
  ********************/
 
+
 typedef struct {
   GdkDrop *drop;
   GtkWidget *widget;
@@ -124,6 +125,9 @@ gtk_drag_get_data_finish (GtkDragGetData *data,
 {
   GtkDragDestSite *site;
   GtkSelectionData sdata;
+  GdkContentFormats *target_list = NULL;
+  GdkDragAction actions = 0;
+  GtkDestDefaults flags = 0;
 
   site = g_object_get_data (G_OBJECT (data->widget), "gtk-drag-dest");
 
@@ -133,30 +137,30 @@ gtk_drag_get_data_finish (GtkDragGetData *data,
   sdata.length = size;
   sdata.data = bytes ? bytes : (guchar *)g_strdup ("");
   sdata.display = gtk_widget_get_display (data->widget);
-  
-  if (site && site->target_list)
+
+  if (site)
+    {
+      target_list = gtk_drop_target_get_formats (site->dest);
+      actions = gtk_drop_target_get_actions (site->dest);
+      flags = gtk_drop_target_get_defaults (site->dest);
+    }
+
+  if (target_list)
     {
-      if (gdk_content_formats_contain_mime_type (site->target_list, data->mime_type))
+      if (gdk_content_formats_contain_mime_type (target_list, data->mime_type))
         {
-          if (!(site->flags & GTK_DEST_DEFAULT_DROP) ||
-              size >= 0)
-            g_signal_emit_by_name (data->widget,
-                                   "drag-data-received",
-                                   data->drop,
-                                   &sdata);
+          if (!(flags & GTK_DEST_DEFAULT_DROP) || size >= 0)
+            gtk_drop_target_emit_drag_data_received (site->dest, data->drop, &sdata);
         }
     }
   else
     {
-      g_signal_emit_by_name (data->widget,
-                             "drag-data-received",
-                             data->drop,
-                             &sdata);
+      gtk_drop_target_emit_drag_data_received (site->dest, data->drop, &sdata);
     }
   
-  if (site && site->flags & GTK_DEST_DEFAULT_DROP)
+  if (flags & GTK_DEST_DEFAULT_DROP)
     {
-      GdkDragAction action = site->actions & gdk_drop_get_actions (data->drop);
+      GdkDragAction action = actions & gdk_drop_get_actions (data->drop);
 
       if (size == 0)
         action = 0;
@@ -535,16 +539,20 @@ gtk_drag_dest_leave (GtkWidget      *widget,
                      guint           time)
 {
   GtkDragDestSite *site;
+  GtkDestDefaults flags;
+  gboolean track_motion;
 
   site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
   g_return_if_fail (site != NULL);
 
-  if ((site->flags & GTK_DEST_DEFAULT_HIGHLIGHT) && site->have_drag)
+  flags = gtk_drop_target_get_defaults (site->dest);
+  track_motion = gtk_drop_target_get_track_motion (site->dest);
+
+  if ((flags & GTK_DEST_DEFAULT_HIGHLIGHT) && site->have_drag)
     gtk_drag_unhighlight (widget);
 
-  if (!(site->flags & GTK_DEST_DEFAULT_MOTION) || site->have_drag ||
-      site->track_motion)
-    g_signal_emit_by_name (widget, "drag-leave", drop, time);
+  if (!(flags & GTK_DEST_DEFAULT_MOTION) || site->have_drag || track_motion)
+    gtk_drop_target_emit_drag_leave (site->dest, drop, time);
   
   site->have_drag = FALSE;
 }
@@ -557,43 +565,52 @@ gtk_drag_dest_motion (GtkWidget *widget,
                       guint      time)
 {
   GtkDragDestSite *site;
+  GdkDragAction dest_actions;
+  GtkDestDefaults flags;
+  gboolean track_motion;
   gboolean retval;
 
   site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
   g_return_val_if_fail (site != NULL, FALSE);
 
-  if (site->track_motion || site->flags & GTK_DEST_DEFAULT_MOTION)
+  dest_actions = gtk_drop_target_get_actions (site->dest);
+  flags = gtk_drop_target_get_defaults (site->dest);
+  track_motion = gtk_drop_target_get_track_motion (site->dest);
+
+  if (track_motion || flags & GTK_DEST_DEFAULT_MOTION)
     {
       GdkDragAction actions;
+      GdkAtom target;
       
       actions = gdk_drop_get_actions (drop);
 
-      if ((actions & site->actions) == 0)
+      if ((dest_actions & actions) == 0)
         actions = 0;
 
-      if (actions && gtk_drag_dest_find_target (widget, drop, NULL))
+      target = gtk_drop_target_match (site->dest, drop);
+
+      if (actions && target)
         {
           if (!site->have_drag)
             {
               site->have_drag = TRUE;
-              if (site->flags & GTK_DEST_DEFAULT_HIGHLIGHT)
+              if (flags & GTK_DEST_DEFAULT_HIGHLIGHT)
                 gtk_drag_highlight (widget);
             }
 
-          gdk_drop_status (drop, site->actions);
+          gdk_drop_status (drop, dest_actions);
         }
       else
         {
           gdk_drop_status (drop, 0);
-          if (!site->track_motion)
+          if (!track_motion)
             return TRUE;
         }
     }
 
-  g_signal_emit_by_name (widget, "drag-motion",
-                         drop, x, y, &retval);
+  retval = gtk_drop_target_emit_drag_motion (site->dest, drop, x, y);
 
-  return (site->flags & GTK_DEST_DEFAULT_MOTION) ? TRUE : retval;
+  return (flags & GTK_DEST_DEFAULT_MOTION) ? TRUE : retval;
 }
 
 static gboolean
@@ -605,17 +622,22 @@ gtk_drag_dest_drop (GtkWidget *widget,
 {
   GtkDragDestSite *site;
   GtkDragDestInfo *info;
+  GtkDestDefaults flags;
   gboolean retval;
 
   site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
   g_return_val_if_fail (site != NULL, FALSE);
 
+  flags = gtk_drop_target_get_defaults (site->dest);
+
   info = gtk_drag_get_dest_info (drop, FALSE);
   g_return_val_if_fail (info != NULL, FALSE);
 
-  if (site->flags & GTK_DEST_DEFAULT_DROP)
+  if (flags & GTK_DEST_DEFAULT_DROP)
     {
-      GdkAtom target = gtk_drag_dest_find_target (widget, drop, NULL);
+      GdkAtom target;
+
+      target = gtk_drop_target_match (site->dest, drop);
 
       if (target == NULL)
         {
@@ -626,8 +648,7 @@ gtk_drag_dest_drop (GtkWidget *widget,
         gtk_drag_get_data (widget, drop, target);
     }
 
-  g_signal_emit_by_name (widget, "drag-drop",
-                         drop, x, y, &retval);
+  retval = gtk_drop_target_emit_drag_drop (site->dest, drop, x, y);
 
-  return (site->flags & GTK_DEST_DEFAULT_DROP) ? TRUE : retval;
+  return (flags & GTK_DEST_DEFAULT_DROP) ? TRUE : retval;
 }
diff --git a/gtk/gtkdndprivate.h b/gtk/gtkdndprivate.h
index 45448a17e2..65dce27d7e 100644
--- a/gtk/gtkdndprivate.h
+++ b/gtk/gtkdndprivate.h
@@ -29,13 +29,11 @@
 typedef struct _GtkDragDestSite GtkDragDestSite;
 struct _GtkDragDestSite
 {
+  GtkDropTarget     *dest;
   GtkDestDefaults    flags;
-  GdkContentFormats *target_list;
-  GdkDragAction      actions;
   guint              do_proxy     : 1;
   guint              proxy_coords : 1;
   guint              have_drag    : 1;
-  guint              track_motion : 1;
 };
 
 G_BEGIN_DECLS
diff --git a/gtk/gtkdragdest.c b/gtk/gtkdragdest.c
index da2205e09d..0ba26ddfe3 100644
--- a/gtk/gtkdragdest.c
+++ b/gtk/gtkdragdest.c
@@ -25,11 +25,15 @@
 #include "config.h"
 
 #include "gtkdragdest.h"
+#include "gtkdragdestprivate.h"
 
 #include "gtkdnd.h"
 #include "gtkdndprivate.h"
 #include "gtkintl.h"
 #include "gtknative.h"
+#include "gtktypebuiltins.h"
+#include "gtkeventcontroller.h"
+#include "gtkmarshalers.h"
 
 
 static void
@@ -56,8 +60,7 @@ gtk_drag_dest_site_destroy (gpointer data)
 {
   GtkDragDestSite *site = data;
 
-  if (site->target_list)
-    gdk_content_formats_unref (site->target_list);
+  g_clear_object (&site->dest);
 
   g_slice_free (GtkDragDestSite, site);
 }
@@ -71,23 +74,16 @@ gtk_drag_dest_set_internal (GtkWidget       *widget,
   old_site = g_object_get_data (G_OBJECT (widget), I_("gtk-drag-dest"));
   if (old_site)
     {
-      g_signal_handlers_disconnect_by_func (widget,
-                                            gtk_drag_dest_realized,
-                                            old_site);
-      g_signal_handlers_disconnect_by_func (widget,
-                                            gtk_drag_dest_hierarchy_changed,
-                                            old_site);
-
-      site->track_motion = old_site->track_motion;
+      g_signal_handlers_disconnect_by_func (widget, gtk_drag_dest_realized, old_site);
+      g_signal_handlers_disconnect_by_func (widget, gtk_drag_dest_hierarchy_changed, old_site);
+      gtk_drop_target_set_track_motion (site->dest, gtk_drop_target_get_track_motion (old_site->dest));
     }
 
   if (gtk_widget_get_realized (widget))
     gtk_drag_dest_realized (widget);
 
-  g_signal_connect (widget, "realize",
-                    G_CALLBACK (gtk_drag_dest_realized), site);
-  g_signal_connect (widget, "notify::root",
-                    G_CALLBACK (gtk_drag_dest_hierarchy_changed), site);
+  g_signal_connect (widget, "realize", G_CALLBACK (gtk_drag_dest_realized), site);
+  g_signal_connect (widget, "notify::root", G_CALLBACK (gtk_drag_dest_hierarchy_changed), site);
 
   g_object_set_data_full (G_OBJECT (widget), I_("gtk-drag-dest"),
                           site, gtk_drag_dest_site_destroy);
@@ -142,7 +138,7 @@ gtk_drag_dest_set_internal (GtkWidget       *widget,
  * }
  * ]|
  */
-void
+GtkDropTarget *
 gtk_drag_dest_set (GtkWidget         *widget,
                    GtkDestDefaults    flags,
                    GdkContentFormats *targets,
@@ -150,20 +146,16 @@ gtk_drag_dest_set (GtkWidget         *widget,
 {
   GtkDragDestSite *site;
 
-  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
 
   site = g_slice_new0 (GtkDragDestSite);
 
-  site->flags = flags;
+  site->dest = gtk_drop_target_new (flags, targets, actions);
   site->have_drag = FALSE;
-  if (targets)
-    site->target_list = gdk_content_formats_ref (targets);
-  else
-    site->target_list = NULL;
-  site->actions = actions;
-  site->track_motion = FALSE;
 
   gtk_drag_dest_set_internal (widget, site);
+
+  return site->dest;
 }
 
 /**
@@ -213,7 +205,7 @@ gtk_drag_dest_get_target_list (GtkWidget *widget)
 
   site = g_object_get_data (G_OBJECT (widget), I_("gtk-drag-dest"));
 
-  return site ? site->target_list : NULL;
+  return site ? gtk_drop_target_get_formats (site->dest) : NULL;
 }
 
 /**
@@ -242,13 +234,7 @@ gtk_drag_dest_set_target_list (GtkWidget     *widget,
       return;
     }
 
-  if (target_list)
-    gdk_content_formats_ref (target_list);
-
-  if (site->target_list)
-    gdk_content_formats_unref (site->target_list);
-
-  site->target_list = target_list;
+  gtk_drop_target_set_formats (site->dest, target_list);
 }
 
 /**
@@ -350,7 +336,7 @@ gtk_drag_dest_set_track_motion (GtkWidget *widget,
 
   g_return_if_fail (site != NULL);
 
-  site->track_motion = track_motion != FALSE;
+  gtk_drop_target_set_track_motion (site->dest, track_motion);
 }
 
 /**
@@ -373,7 +359,7 @@ gtk_drag_dest_get_track_motion (GtkWidget *widget)
   site = g_object_get_data (G_OBJECT (widget), I_("gtk-drag-dest"));
 
   if (site)
-    return site->track_motion;
+    return gtk_drop_target_get_track_motion (site->dest);
 
   return FALSE;
 }
@@ -414,3 +400,425 @@ gtk_drag_dest_find_target (GtkWidget         *widget,
                                               gdk_drop_get_formats (drop));
 }
 
+
+struct _GtkDropTarget
+{
+  GObject parent_instance;
+
+  GdkContentFormats *formats;
+  GdkDragAction actions;
+  GtkDestDefaults defaults;
+  gboolean track_motion;
+
+  GtkWidget *widget;
+  GdkDrop *drop;
+};
+
+struct _GtkDropTargetClass
+{
+  GObjectClass parent_class;
+};
+
+enum {
+  PROP_FORMATS = 1,
+  PROP_ACTIONS,
+  PROP_DEFAULTS,
+  PROP_TRACK_MOTION,
+  NUM_PROPERTIES
+};
+
+static GParamSpec *properties[NUM_PROPERTIES];
+
+enum {
+  DRAG_LEAVE,
+  DRAG_MOTION,
+  DRAG_DROP,
+  DRAG_DATA_RECEIVED,
+  NUM_SIGNALS
+};
+
+static guint signals[NUM_SIGNALS];
+
+G_DEFINE_TYPE (GtkDropTarget, gtk_drop_target, G_TYPE_OBJECT);
+
+static void
+gtk_drop_target_init (GtkDropTarget *dest)
+{
+  dest->defaults = GTK_DEST_DEFAULT_ALL;
+}
+
+static void
+gtk_drop_target_finalize (GObject *object)
+{
+  GtkDropTarget *dest = GTK_DROP_TARGET (object);
+
+  g_clear_pointer (&dest->formats, gdk_content_formats_unref);
+
+  G_OBJECT_CLASS (gtk_drop_target_parent_class)->finalize (object);
+}
+
+static void
+gtk_drop_target_set_property (GObject      *object,
+                            guint         prop_id,
+                            const GValue *value,
+                            GParamSpec   *pspec)
+{
+  GtkDropTarget *dest = GTK_DROP_TARGET (object);
+
+  switch (prop_id)
+    {
+    case PROP_FORMATS:
+      gtk_drop_target_set_formats (dest, g_value_get_boxed (value));
+      break;
+
+    case PROP_ACTIONS:
+      gtk_drop_target_set_actions (dest, g_value_get_flags (value));
+      break;
+
+    case PROP_DEFAULTS:
+      gtk_drop_target_set_defaults (dest, g_value_get_flags (value));
+      break;
+
+    case PROP_TRACK_MOTION:
+      gtk_drop_target_set_track_motion (dest, g_value_get_boolean (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtk_drop_target_get_property (GObject    *object,
+                            guint       prop_id,
+                            GValue     *value,
+                            GParamSpec *pspec)
+{
+  GtkDropTarget *dest = GTK_DROP_TARGET (object);
+
+  switch (prop_id)
+    {
+    case PROP_FORMATS:
+      g_value_set_object (value, gtk_drop_target_get_formats (dest));
+      break;
+
+    case PROP_ACTIONS:
+      g_value_set_flags (value, gtk_drop_target_get_actions (dest));
+      break;
+
+    case PROP_DEFAULTS:
+      g_value_set_flags (value, gtk_drop_target_get_defaults (dest));
+      break;
+
+    case PROP_TRACK_MOTION:
+      g_value_set_boolean (value, gtk_drop_target_get_track_motion (dest));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtk_drop_target_class_init (GtkDropTargetClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_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;
+
+  properties[PROP_FORMATS] =
+       g_param_spec_boxed ("formats", P_("Formats"), P_("Formats"),
+                           GDK_TYPE_CONTENT_FORMATS,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+  properties[PROP_ACTIONS] =
+       g_param_spec_flags ("actions", P_("Actions"), P_("Actions"),
+                           GDK_TYPE_DRAG_ACTION, 0,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+  properties[PROP_DEFAULTS] =
+       g_param_spec_flags ("defaults", P_("Defaults"), P_("Defaults"),
+                           GTK_TYPE_DEST_DEFAULTS, GTK_DEST_DEFAULT_ALL,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+  properties[PROP_TRACK_MOTION] =
+       g_param_spec_boolean ("track-motion", P_("Track motion"), P_("Track motion"),
+                             FALSE,
+                             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+  g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
+
+  signals[DRAG_LEAVE] =
+      g_signal_new (I_("drag-leave"),
+                    G_TYPE_FROM_CLASS (class),
+                    G_SIGNAL_RUN_LAST,
+                    0,
+                    NULL, NULL,
+                    NULL,
+                    G_TYPE_NONE, 0);
+
+  signals[DRAG_MOTION] =
+      g_signal_new (I_("drag-motion"),
+                    G_TYPE_FROM_CLASS (class),
+                    G_SIGNAL_RUN_LAST,
+                    0,
+                    NULL, NULL,
+                    NULL,
+                    G_TYPE_BOOLEAN, 2,
+                    G_TYPE_INT, G_TYPE_INT);
+
+  signals[DRAG_DROP] =
+      g_signal_new (I_("drag-drop"),
+                    G_TYPE_FROM_CLASS (class),
+                    G_SIGNAL_RUN_LAST,
+                    0,
+                    NULL, NULL,
+                    NULL,
+                    G_TYPE_BOOLEAN, 2,
+                    G_TYPE_INT, G_TYPE_INT);
+
+  signals[DRAG_DATA_RECEIVED] =
+      g_signal_new (I_("drag-data-received"),
+                    G_TYPE_FROM_CLASS (class),
+                    G_SIGNAL_RUN_LAST,
+                    0,
+                    NULL, NULL,
+                    _gtk_marshal_VOID__BOXED,
+                    G_TYPE_NONE, 1,
+                    GTK_TYPE_SELECTION_DATA | G_SIGNAL_TYPE_STATIC_SCOPE);
+  g_signal_set_va_marshaller (signals[DRAG_DATA_RECEIVED],
+                              G_TYPE_FROM_CLASS (class),
+                              _gtk_marshal_VOID__BOXEDv);
+}
+
+GtkDropTarget *
+gtk_drop_target_new (GtkDestDefaults    defaults,
+                     GdkContentFormats *formats,
+                     GdkDragAction      actions)
+{
+  return g_object_new (GTK_TYPE_DROP_TARGET,
+                       "defaults", defaults,
+                       "formats", formats,
+                       "actions", actions,
+                       NULL);
+}
+
+void
+gtk_drop_target_set_formats (GtkDropTarget       *dest,
+                           GdkContentFormats *formats)
+{
+  g_return_if_fail (GTK_IS_DROP_TARGET (dest));
+
+  if (dest->formats == formats)
+    return;
+
+  if (dest->formats)
+    gdk_content_formats_unref (dest->formats);
+
+  dest->formats = formats;
+
+  if (dest->formats)
+    gdk_content_formats_ref (dest->formats);
+
+  g_object_notify_by_pspec (G_OBJECT (dest), properties[PROP_FORMATS]);
+}
+
+GdkContentFormats *
+gtk_drop_target_get_formats (GtkDropTarget *dest)
+{
+  g_return_val_if_fail (GTK_IS_DROP_TARGET (dest), NULL);
+  
+  return dest->formats;
+}
+
+void
+gtk_drop_target_set_actions (GtkDropTarget   *dest,
+                           GdkDragAction  actions)
+{
+  g_return_if_fail (GTK_IS_DROP_TARGET (dest));
+  
+  if (dest->actions == actions)
+    return;
+
+  dest->actions = actions;
+
+  g_object_notify_by_pspec (G_OBJECT (dest), properties[PROP_ACTIONS]);
+}
+
+GdkDragAction
+gtk_drop_target_get_actions (GtkDropTarget *dest)
+{
+  g_return_val_if_fail (GTK_IS_DROP_TARGET (dest), 0);
+
+  return dest->actions;
+}
+
+void
+gtk_drop_target_set_defaults (GtkDropTarget     *dest,
+                            GtkDestDefaults  defaults)
+{
+  g_return_if_fail (GTK_IS_DROP_TARGET (dest));
+  
+  if (dest->defaults == defaults)
+    return;
+
+  dest->defaults = defaults;
+
+  g_object_notify_by_pspec (G_OBJECT (dest), properties[PROP_DEFAULTS]);
+}
+
+GtkDestDefaults
+gtk_drop_target_get_defaults (GtkDropTarget *dest)
+{
+  g_return_val_if_fail (GTK_IS_DROP_TARGET (dest), GTK_DEST_DEFAULT_ALL);
+
+  return dest->defaults;
+}
+
+void
+gtk_drop_target_set_track_motion (GtkDropTarget *dest,
+                                gboolean     track_motion)
+{
+  g_return_if_fail (GTK_IS_DROP_TARGET (dest));
+
+  if (dest->track_motion == track_motion)
+    return;
+
+  dest->track_motion = track_motion;
+
+  g_object_notify_by_pspec (G_OBJECT (dest), properties[PROP_TRACK_MOTION]);
+}
+
+gboolean
+gtk_drop_target_get_track_motion (GtkDropTarget *dest)
+{
+  g_return_val_if_fail (GTK_IS_DROP_TARGET (dest), FALSE);
+
+  return dest->track_motion;
+}
+
+void
+gtk_drop_target_attach (GtkDropTarget *dest,
+                        GtkWidget     *widget)
+{
+  GtkDragDestSite *site;
+
+  g_return_if_fail (GTK_IS_DROP_TARGET (dest));
+  g_return_if_fail (dest->widget == NULL);
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  dest->widget = widget;
+
+  site = g_slice_new0 (GtkDragDestSite);
+
+  site->dest = dest;
+  site->have_drag = FALSE;
+
+  gtk_drag_dest_set_internal (widget, site);
+}
+
+void
+gtk_drop_target_detach (GtkDropTarget *dest)
+{
+  g_return_if_fail (GTK_IS_DROP_TARGET (dest));
+
+  if (dest->widget)
+    {
+      gtk_drag_dest_unset (dest->widget);
+      dest->widget = NULL;
+    }
+}
+
+GtkWidget *
+gtk_drop_target_get_target (GtkDropTarget *dest)
+{
+  g_return_val_if_fail (GTK_IS_DROP_TARGET (dest), NULL);
+
+  return dest->widget;
+}
+
+GdkDrop *
+gtk_drop_target_get_drop (GtkDropTarget *dest)
+{
+  g_return_val_if_fail (GTK_IS_DROP_TARGET (dest), NULL);
+
+  return dest->drop;
+}
+
+const char *
+gtk_drop_target_match (GtkDropTarget *dest,
+                       GdkDrop       *drop)
+{
+  GdkContentFormats *formats;
+  const char *match;
+
+  formats = gdk_content_formats_ref (dest->formats);
+  formats = gdk_content_formats_union_deserialize_mime_types (formats);
+
+  match = gdk_content_formats_match_mime_type (formats, gdk_drop_get_formats (drop));
+
+  gdk_content_formats_unref (formats);
+
+  return match;
+}
+
+const char *
+gtk_drop_target_find_mimetype (GtkDropTarget *dest)
+{
+  if (!dest->drop)
+    return NULL;
+
+  return gtk_drop_target_match (dest, dest->drop);
+}
+
+void
+gtk_drop_target_emit_drag_leave (GtkDropTarget    *dest,
+                                 GdkDrop          *drop,
+                                 guint             time)
+{
+  dest->drop = drop;
+  g_signal_emit (dest, signals[DRAG_LEAVE], 0, time);
+  dest->drop = NULL;
+}
+
+gboolean
+gtk_drop_target_emit_drag_motion (GtkDropTarget    *dest,
+                                  GdkDrop          *drop,
+                                  int               x,
+                                  int               y)
+{
+  gboolean result = FALSE;
+
+  dest->drop = drop;
+  g_signal_emit (dest, signals[DRAG_MOTION], 0, x, y, &result);
+  dest->drop = NULL;
+
+  return result;
+}
+
+gboolean
+gtk_drop_target_emit_drag_drop (GtkDropTarget    *dest,
+                                GdkDrop          *drop,
+                                int               x,
+                                int               y)
+{
+  gboolean result = FALSE;
+
+  dest->drop = drop;
+  g_signal_emit (dest, signals[DRAG_DROP], 0, x, y, &result);
+  dest->drop = NULL;
+
+  return result;
+}
+
+void
+gtk_drop_target_emit_drag_data_received (GtkDropTarget    *dest,
+                                         GdkDrop          *drop,
+                                         GtkSelectionData *sdata)
+{
+  dest->drop = drop;
+  g_signal_emit (dest, signals[DRAG_DATA_RECEIVED], 0, sdata);
+  dest->drop = NULL;
+}
diff --git a/gtk/gtkdragdest.h b/gtk/gtkdragdest.h
index f241f514a7..9a8c68a709 100644
--- a/gtk/gtkdragdest.h
+++ b/gtk/gtkdragdest.h
@@ -37,6 +37,8 @@
 
 G_BEGIN_DECLS
 
+typedef struct _GtkDropTarget GtkDropTarget;
+
 /**
  * GtkDestDefaults:
  * @GTK_DEST_DEFAULT_MOTION: If set for a widget, GTK+, during a drag over this
@@ -46,7 +48,7 @@ G_BEGIN_DECLS
  * @GTK_DEST_DEFAULT_HIGHLIGHT: If set for a widget, GTK+ will draw a highlight on
  *   this widget as long as a drag is over this widget and the widget drag format
  *   and action are acceptable.
- * @GTK_DEST_DEFAULT_DROP: If set for a widget, when a drop occurs, GTK+ will
+ * @GTK_DEST_DEFAULT_OP: If set for a widget, when a drop occurs, GTK+ will
  *   will check if the drag matches this widget’s list of possible formats and
  *   actions. If so, GTK+ will call gtk_drag_get_data() on behalf of the widget.
  *   Whether or not the drop is successful, GTK+ will call gdk_drag_finish(). If
@@ -67,10 +69,10 @@ typedef enum {
 } GtkDestDefaults;
 
 GDK_AVAILABLE_IN_ALL
-void gtk_drag_dest_set   (GtkWidget            *widget,
-                          GtkDestDefaults       flags,
-                          GdkContentFormats    *targets,
-                          GdkDragAction         actions);
+GtkDropTarget *gtk_drag_dest_set   (GtkWidget            *widget,
+                                    GtkDestDefaults       flags,
+                                    GdkContentFormats    *targets,
+                                    GdkDragAction         actions);
 
 GDK_AVAILABLE_IN_ALL
 void gtk_drag_dest_unset (GtkWidget          *widget);
@@ -98,6 +100,63 @@ GDK_AVAILABLE_IN_ALL
 gboolean       gtk_drag_dest_get_track_motion  (GtkWidget *widget);
 
 
+#define GTK_TYPE_DROP_TARGET         (gtk_drop_target_get_type ())
+#define GTK_DROP_TARGET(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_DROP_TARGET, GtkDropTarget))
+#define GTK_DROP_TARGET_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_DROP_TARGET, 
GtkDropTargetClass))
+#define GTK_IS_DROP_TARGET(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_DROP_TARGET))
+#define GTK_IS_DROP_TARGET_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_DROP_TARGET))
+#define GTK_DROP_TARGET_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_DROP_TARGET, 
GtkDropTargetClass))
+
+typedef struct _GtkDropTargetClass GtkDropTargetClass;
+
+GDK_AVAILABLE_IN_ALL
+GType              gtk_drop_target_get_type    (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_ALL
+GtkDropTarget       *gtk_drop_target_new          (GtkDestDefaults    defaults,
+                                                   GdkContentFormats *formats,
+                                                   GdkDragAction      actions);
+
+GDK_AVAILABLE_IN_ALL
+void               gtk_drop_target_set_formats  (GtkDropTarget       *dest,
+                                               GdkContentFormats *formats);
+GDK_AVAILABLE_IN_ALL
+GdkContentFormats *gtk_drop_target_get_formats  (GtkDropTarget       *dest);
+
+GDK_AVAILABLE_IN_ALL
+void               gtk_drop_target_set_actions  (GtkDropTarget       *dest,
+                                               GdkDragAction      actions);
+GDK_AVAILABLE_IN_ALL
+GdkDragAction      gtk_drop_target_get_actions  (GtkDropTarget       *dest);
+
+GDK_AVAILABLE_IN_ALL
+void               gtk_drop_target_set_defaults (GtkDropTarget       *dest,
+                                               GtkDestDefaults    defaults);
+GDK_AVAILABLE_IN_ALL
+GtkDestDefaults    gtk_drop_target_get_defaults (GtkDropTarget       *dest);
+
+GDK_AVAILABLE_IN_ALL
+void               gtk_drop_target_set_track_motion (GtkDropTarget       *dest,
+                                                   gboolean           track_motion);
+GDK_AVAILABLE_IN_ALL
+gboolean           gtk_drop_target_get_track_motion (GtkDropTarget       *dest);
+
+GDK_AVAILABLE_IN_ALL
+void               gtk_drop_target_attach (GtkDropTarget *dest,
+                                           GtkWidget     *widget);
+GDK_AVAILABLE_IN_ALL
+void               gtk_drop_target_detach (GtkDropTarget *dest);
+
+GDK_AVAILABLE_IN_ALL
+GdkDrop           *gtk_drop_target_get_drop (GtkDropTarget *dest);
+
+GDK_AVAILABLE_IN_ALL
+GtkWidget         *gtk_drop_target_get_target (GtkDropTarget *dest);
+
+GDK_AVAILABLE_IN_ALL
+const char        *gtk_drop_target_find_mimetype (GtkDropTarget *dest);
+
+
 G_END_DECLS
 
 #endif /* __GTK_DRAG_DEST_H__ */
diff --git a/gtk/gtkdragdestprivate.h b/gtk/gtkdragdestprivate.h
new file mode 100644
index 0000000000..deb772763f
--- /dev/null
+++ b/gtk/gtkdragdestprivate.h
@@ -0,0 +1,46 @@
+
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2020 Matthias Clasen
+ *
+ * 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/>.
+ */
+
+#ifndef __GTK_DRAG_DEST_PRIVATE_H__
+#define __GTK_DRAG_DEST_PRIVATE_H__
+
+#include "gtkdragdest.h"
+
+G_BEGIN_DECLS
+
+void gtk_drop_target_emit_drag_data_received (GtkDropTarget    *dest,
+                                              GdkDrop          *drop,
+                                              GtkSelectionData *sdata);
+void gtk_drop_target_emit_drag_leave         (GtkDropTarget    *dest,
+                                              GdkDrop          *drop,
+                                              guint             time);
+gboolean gtk_drop_target_emit_drag_motion    (GtkDropTarget    *dest,
+                                              GdkDrop          *drop,
+                                              int               x,
+                                              int               y);
+gboolean gtk_drop_target_emit_drag_drop      (GtkDropTarget    *dest,
+                                              GdkDrop          *drop,
+                                              int               x,
+                                              int               y);
+
+const char * gtk_drop_target_match           (GtkDropTarget *dest,
+                                              GdkDrop       *drop);
+
+G_END_DECLS
+
+#endif


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