dnd: Add GdkDrop base class for GdkDragContext
authorBenjamin Otte <otte@redhat.com>
Mon, 30 Apr 2018 12:10:44 +0000 (14:10 +0200)
committerBenjamin Otte <otte@redhat.com>
Mon, 18 Jun 2018 21:49:19 +0000 (23:49 +0200)
The ultimate goal of this patch series is to split GdkDragContext into
GdkDrop + GdkDrag classes for the destination and source side of a dnd
operation.

The refactoring is meant to work something like this:
1. Introduce GdkDrop as a base class
2. Make all drop related code (like GdkEvent) use GdkDrop instead of
   GdkDragContext. Move/duplicate APIs to allow that.
3. Port all drop contexts in the backends from GdkDragContext to GdkDrop
4. Delete all APIs in GdkDragContext that aren't needed anymore.
5. Make GdkDragContext no longer a GdkDrop subclass
6. Rename GdkDragContext to GdkDrag

gdk/gdk.h
gdk/gdkdnd.c
gdk/gdkdndprivate.h
gdk/gdkdrop.c [new file with mode: 0644]
gdk/gdkdrop.h [new file with mode: 0644]
gdk/gdkdropprivate.h [new file with mode: 0644]
gdk/gdktypes.h
gdk/meson.build
testsuite/gtk/notify.c
testsuite/gtk/objects-finalize.c

index 59279d30117b8a1026d372db80a378c0569757fb..3362f9aefc6705fe94609c23b5c1e4c1fbaecb3a 100644 (file)
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -46,6 +46,7 @@
 #include <gdk/gdkdisplaymanager.h>
 #include <gdk/gdkdnd.h>
 #include <gdk/gdkdrawcontext.h>
+#include <gdk/gdkdrop.h>
 #include <gdk/gdkenumtypes.h>
 #include <gdk/gdkevents.h>
 #include <gdk/gdkframeclock.h>
index 191ef7eb754c6997e7db4c734005c070ce510282..083adf9a5ae39bdaa7e675e3dc4569dfaad620a3 100644 (file)
 #include "gdkenumtypes.h"
 #include "gdkeventsprivate.h"
 
+#define DROP_SUBCLASS 1
+
 typedef struct _GdkDragContextPrivate GdkDragContextPrivate;
 
 struct _GdkDragContextPrivate 
 {
+#ifndef DROP_SUBCLASS
   GdkDisplay *display;
   GdkDevice *device;
+#endif
   GdkContentFormats *formats;
 };
 
@@ -60,9 +64,11 @@ static struct {
 enum {
   PROP_0,
   PROP_CONTENT,
+#ifndef DROP_SUBCLASS
   PROP_DEVICE,
   PROP_DISPLAY,
   PROP_FORMATS,
+#endif
   N_PROPERTIES
 };
 
@@ -78,7 +84,7 @@ static GParamSpec *properties[N_PROPERTIES] = { NULL, };
 static guint signals[N_SIGNALS] = { 0 };
 static GList *contexts = NULL;
 
-G_DEFINE_TYPE_WITH_PRIVATE (GdkDragContext, gdk_drag_context, G_TYPE_OBJECT)
+G_DEFINE_TYPE_WITH_PRIVATE (GdkDragContext, gdk_drag_context, GDK_TYPE_DROP)
 
 /**
  * SECTION:dnd
@@ -114,11 +120,15 @@ G_DEFINE_TYPE_WITH_PRIVATE (GdkDragContext, gdk_drag_context, G_TYPE_OBJECT)
 GdkDisplay *
 gdk_drag_context_get_display (GdkDragContext *context)
 {
+#ifdef DROP_SUBCLASS
+  return gdk_drop_get_display (GDK_DROP (context));
+#else
   GdkDragContextPrivate *priv = gdk_drag_context_get_instance_private (context);
 
   g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
 
   return priv->display;
+#endif
 }
 
 /**
@@ -136,6 +146,12 @@ gdk_drag_context_get_formats (GdkDragContext *context)
 
   g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
 
+#ifdef DROP_SUBCLASS
+  GdkContentFormats *formats = gdk_drop_get_formats (GDK_DROP (context));
+
+  if (formats)
+    return formats;
+#endif
   return priv->formats;
 }
 
@@ -231,11 +247,15 @@ gdk_drag_context_get_dest_surface (GdkDragContext *context)
 GdkDevice *
 gdk_drag_context_get_device (GdkDragContext *context)
 {
+#ifdef DROP_SUBCLASS
+  return gdk_drop_get_device (GDK_DROP (context));
+#else
   GdkDragContextPrivate *priv = gdk_drag_context_get_instance_private (context);
 
   g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
 
   return priv->device;
+#endif
 }
 
 static void
@@ -264,6 +284,7 @@ gdk_drag_context_set_property (GObject      *gobject,
         }
       break;
 
+#ifndef DROP_SUBCLASS
     case PROP_DEVICE:
       priv->device = g_value_dup_object (value);
       g_assert (priv->device != NULL);
@@ -286,6 +307,7 @@ gdk_drag_context_set_property (GObject      *gobject,
           g_assert (priv->formats != NULL);
         }
       break;
+#endif
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
@@ -300,7 +322,9 @@ gdk_drag_context_get_property (GObject    *gobject,
                                GParamSpec *pspec)
 {
   GdkDragContext *context = GDK_DRAG_CONTEXT (gobject);
+#ifndef DROP_SUBCLASS
   GdkDragContextPrivate *priv = gdk_drag_context_get_instance_private (context);
+#endif
 
   switch (prop_id)
     {
@@ -308,6 +332,7 @@ gdk_drag_context_get_property (GObject    *gobject,
       g_value_set_object (value, context->content);
       break;
 
+#ifndef DROP_SUBCLASS
     case PROP_DEVICE:
       g_value_set_object (value, priv->device);
       break;
@@ -319,6 +344,7 @@ gdk_drag_context_get_property (GObject    *gobject,
     case PROP_FORMATS:
       g_value_set_boxed (value, priv->formats);
       break;
+#endif
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
@@ -405,6 +431,7 @@ gdk_drag_context_class_init (GdkDragContextClass *klass)
                          G_PARAM_STATIC_STRINGS |
                          G_PARAM_EXPLICIT_NOTIFY);
 
+#ifndef DROP_SUBCLASS
   /**
    * GdkDragContext:device:
    *
@@ -448,6 +475,7 @@ gdk_drag_context_class_init (GdkDragContextClass *klass)
                         G_PARAM_CONSTRUCT_ONLY |
                         G_PARAM_STATIC_STRINGS |
                         G_PARAM_EXPLICIT_NOTIFY);
+#endif
 
   /**
    * GdkDragContext::cancel:
index 8f779dabb2ae186b52a7b715408776c5a931e09c..9c240f084ad66462d1493298735d1987f8fc781e 100644 (file)
@@ -20,6 +20,8 @@
 
 #include "gdkdnd.h"
 
+#include "gdkdropprivate.h"
+
 G_BEGIN_DECLS
 
 
@@ -31,7 +33,7 @@ typedef struct _GdkDragContextClass GdkDragContextClass;
 
 
 struct _GdkDragContextClass {
-  GObjectClass parent_class;
+  GdkDropClass parent_class;
 
   void        (*drag_status)   (GdkDragContext  *context,
                                 GdkDragAction    action,
@@ -77,7 +79,7 @@ struct _GdkDragContextClass {
 };
 
 struct _GdkDragContext {
-  GObject parent_instance;
+  GdkDrop parent_instance;
 
   /*< private >*/
   gboolean is_source;
diff --git a/gdk/gdkdrop.c b/gdk/gdkdrop.c
new file mode 100644 (file)
index 0000000..0e7bb8f
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * Copyright © 2018 Benjamin Otte
+ *
+ * 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.1 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/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+#include "config.h"
+
+#include "gdkdndprivate.h"
+#include "gdkdisplay.h"
+#include "gdksurface.h"
+#include "gdkintl.h"
+#include "gdkcontentformats.h"
+#include "gdkcontentprovider.h"
+#include "gdkcontentserializer.h"
+#include "gdkcursor.h"
+#include "gdkenumtypes.h"
+#include "gdkeventsprivate.h"
+
+typedef struct _GdkDropPrivate GdkDropPrivate;
+
+struct _GdkDropPrivate {
+  GdkDevice *device;
+  GdkContentFormats *formats;
+};
+
+enum {
+  PROP_0,
+  PROP_DEVICE,
+  PROP_DISPLAY,
+  PROP_FORMATS,
+  N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+G_DEFINE_TYPE_WITH_PRIVATE (GdkDrop, gdk_drop, G_TYPE_OBJECT)
+
+/**
+ * GdkDrop:
+ *
+ * The GdkDrop struct contains only private fields and
+ * should not be accessed directly.
+ */
+
+static void
+gdk_drop_init (GdkDrop *self)
+{
+}
+
+static void
+gdk_drop_set_property (GObject      *gobject,
+                       guint         prop_id,
+                       const GValue *value,
+                       GParamSpec   *pspec)
+{
+  GdkDrop *self = GDK_DROP (gobject);
+  GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
+
+  switch (prop_id)
+    {
+    case PROP_DEVICE:
+      priv->device = g_value_dup_object (value);
+      g_assert (priv->device != NULL);
+      break;
+
+    case PROP_FORMATS:
+      priv->formats = g_value_dup_boxed (value);
+#ifdef DROP_SUBCLASS
+      g_assert (priv->formats != NULL);
+#endif
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gdk_drop_get_property (GObject    *gobject,
+                       guint       prop_id,
+                       GValue     *value,
+                       GParamSpec *pspec)
+{
+  GdkDrop *self = GDK_DROP (gobject);
+  GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
+
+  switch (prop_id)
+    {
+    case PROP_DEVICE:
+      g_value_set_object (value, priv->device);
+      break;
+
+    case PROP_DISPLAY:
+      g_value_set_object (value, gdk_device_get_display (priv->device));
+      break;
+
+    case PROP_FORMATS:
+      g_value_set_boxed (value, priv->formats);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gdk_drop_finalize (GObject *object)
+{
+  GdkDrop *self = GDK_DROP (object);
+  GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
+
+  g_clear_object (&priv->device);
+
+  G_OBJECT_CLASS (gdk_drop_parent_class)->finalize (object);
+}
+
+static void
+gdk_drop_class_init (GdkDropClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->get_property = gdk_drop_get_property;
+  object_class->set_property = gdk_drop_set_property;
+  object_class->finalize = gdk_drop_finalize;
+
+  /**
+   * GdkDrop:device:
+   *
+   * The #GdkDevice performing the drop
+   */
+  properties[PROP_DEVICE] =
+    g_param_spec_object ("device",
+                         "Device",
+                         "The device performing the drop",
+                         GDK_TYPE_DEVICE,
+                         G_PARAM_READWRITE |
+                         G_PARAM_CONSTRUCT_ONLY |
+                         G_PARAM_STATIC_STRINGS |
+                         G_PARAM_EXPLICIT_NOTIFY);
+
+  /**
+   * GdkDrop:display:
+   *
+   * The #GdkDisplay that the drop belongs to.
+   */
+  properties[PROP_DISPLAY] =
+    g_param_spec_object ("display",
+                         "Display",
+                         "Display this drag belongs to",
+                         GDK_TYPE_DISPLAY,
+                         G_PARAM_READABLE |
+                         G_PARAM_STATIC_STRINGS |
+                         G_PARAM_EXPLICIT_NOTIFY);
+
+  /**
+   * GdkDrop:formats:
+   *
+   * The possible formats that the drop can provide its data in.
+   */
+  properties[PROP_FORMATS] =
+    g_param_spec_boxed ("formats",
+                        "Formats",
+                        "The possible formats for data",
+                        GDK_TYPE_CONTENT_FORMATS,
+                        G_PARAM_READWRITE |
+                        G_PARAM_CONSTRUCT_ONLY |
+                        G_PARAM_STATIC_STRINGS |
+                        G_PARAM_EXPLICIT_NOTIFY);
+  g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+/**
+ * gdk_drop_get_display:
+ * @self: a #GdkDrop
+ *
+ * Gets the #GdkDisplay that @self was created for.
+ *
+ * Returns: (transfer none): a #GdkDisplay
+ **/
+GdkDisplay *
+gdk_drop_get_display (GdkDrop *self)
+{
+  GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
+
+  g_return_val_if_fail (GDK_IS_DROP (self), NULL);
+
+  return gdk_device_get_display (priv->device);
+}
+
+/**
+ * gdk_drop_get_device:
+ * @self: a #GdkDrop
+ *
+ * Returns the #GdkDevice performing the drop.
+ *
+ * Returns: (transfer none): The #GdkDevice performing the drop.
+ **/
+GdkDevice *
+gdk_drop_get_device (GdkDrop *self)
+{
+  GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
+
+  g_return_val_if_fail (GDK_IS_DROP (self), NULL);
+
+  return priv->device;
+}
+
+/**
+ * gdk_drop_get_formats:
+ * @self: a #GdkDrop
+ *
+ * Returns the #GdkContentFormats that the drop offers the data
+ * to be read in.
+ *
+ * Returns: (transfer none): The possible #GdkContentFormats
+ **/
+GdkContentFormats *
+gdk_drop_get_formats (GdkDrop *self)
+{
+  GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
+
+  g_return_val_if_fail (GDK_IS_DROP (self), NULL);
+
+  return priv->formats;
+}
+
diff --git a/gdk/gdkdrop.h b/gdk/gdkdrop.h
new file mode 100644 (file)
index 0000000..e8a5423
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright © 2018 Benjamin Otte
+ *
+ * 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.1 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/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+
+#ifndef __GDK_DROP_H__
+#define __GDK_DROP_H__
+
+#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
+#error "Only <gdk/gdk.h> can be included directly."
+#endif
+
+#include <gdk/gdktypes.h>
+#include <gdk/gdkversionmacros.h>
+
+G_BEGIN_DECLS
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDrop, g_object_unref)
+
+#define GDK_TYPE_DROP              (gdk_drop_get_type ())
+#define GDK_DROP(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_DROP, GdkDrop))
+#define GDK_IS_DROP(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_DROP))
+
+GDK_AVAILABLE_IN_ALL
+GType                   gdk_drop_get_type               (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_ALL
+GdkDisplay *            gdk_drop_get_display            (GdkDrop                *self);
+GDK_AVAILABLE_IN_ALL
+GdkDevice *             gdk_drop_get_device             (GdkDrop                *self);
+GDK_AVAILABLE_IN_ALL
+GdkContentFormats *     gdk_drop_get_formats            (GdkDrop                *self);
+
+G_END_DECLS
+
+#endif /* __GDK_DROP_H__ */
diff --git a/gdk/gdkdropprivate.h b/gdk/gdkdropprivate.h
new file mode 100644 (file)
index 0000000..6ddcfb4
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright © 2018 Benjamin Otte
+ *
+ * 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.1 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/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+#ifndef __GDK_DROP_PRIVATE_H__
+#define __GDK_DROP_PRIVATE_H__
+
+#include "gdkdrop.h"
+
+G_BEGIN_DECLS
+
+
+#define GDK_DROP_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DROP, GdkDropClass))
+#define GDK_IS_DROP_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DROP))
+#define GDK_DROP_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DROP, GdkDropClass))
+
+typedef struct _GdkDropClass GdkDropClass;
+
+
+struct _GdkDrop {
+  GObject parent_instance;
+};
+
+struct _GdkDropClass {
+  GObjectClass parent_class;
+};
+
+
+G_END_DECLS
+
+#endif
index f2081c1536d9d0ef7c69e8fe0e05cc2a83547740..ba799fb4ced79ef950b4c1786eaea1f2e039ce06 100644 (file)
@@ -124,6 +124,7 @@ typedef struct _GdkCursor             GdkCursor;
 typedef struct _GdkTexture            GdkTexture;
 typedef struct _GdkDevice             GdkDevice;
 typedef struct _GdkDragContext        GdkDragContext;
+typedef struct _GdkDrop               GdkDrop;
 
 typedef struct _GdkClipboard          GdkClipboard;
 typedef struct _GdkDisplayManager     GdkDisplayManager;
index f4ec66a53b55229faaece3054c35f256538fe48e..4a2e24073c12598d80d489c59caf96d70be25d41 100644 (file)
@@ -17,6 +17,7 @@ gdk_public_sources = files([
   'gdkdisplaymanager.c',
   'gdkdnd.c',
   'gdkdrawcontext.c',
+  'gdkdrop.c',
   'gdkevents.c',
   'gdkframeclock.c',
   'gdkframeclockidle.c',
@@ -66,6 +67,7 @@ gdk_public_headers = files([
   'gdkdisplaymanager.h',
   'gdkdnd.h',
   'gdkdrawcontext.h',
+  'gdkdrop.h',
   'gdkevents.h',
   'gdkframeclock.h',
   'gdkframetimings.h',
index 2738cca4ae4b9debdd92eac30a9162da532591ee..4c340c38de431dcd54ea7926ac0bdd3026343fd6 100644 (file)
@@ -419,6 +419,15 @@ test_type (gconstpointer data)
                                NULL);
       gdk_content_formats_unref (formats);
     }
+  else if (g_str_equal (g_type_name (type), "GdkDrop"))
+    {
+      GdkContentFormats *formats = gdk_content_formats_new_for_gtype (G_TYPE_STRING);
+      instance = g_object_new (type,
+                               "device", gdk_seat_get_pointer (gdk_display_get_default_seat (gdk_display_get_default ())),
+                               "formats", formats,
+                               NULL);
+      gdk_content_formats_unref (formats);
+    }
   else
     instance = g_object_new (type, NULL);
 
index a712ee8aba4f287e9b65d29882165a796562ffc5..79f81100a577e956491507949904bc9b14bf26d5 100644 (file)
@@ -54,7 +54,8 @@ test_finalize_object (gconstpointer data)
 
   if (g_str_equal (g_type_name (test_type), "GdkClipboard"))
     object = g_object_new (test_type, "display", gdk_display_get_default (), NULL);
-  else if (g_str_equal (g_type_name (test_type), "GdkDragContext"))
+  else if (g_str_equal (g_type_name (test_type), "GdkDragContext") ||
+           g_str_equal (g_type_name (test_type), "GdkDrop"))
     {
       GdkContentFormats *formats = gdk_content_formats_new_for_gtype (G_TYPE_STRING);
       object = g_object_new (test_type,