wayland: Split drop context into GdkWaylandDrop
authorBenjamin Otte <otte@redhat.com>
Wed, 30 May 2018 02:04:51 +0000 (04:04 +0200)
committerBenjamin Otte <otte@redhat.com>
Mon, 18 Jun 2018 21:49:52 +0000 (23:49 +0200)
GdkWaylandDrop no longer inherits from GdkDragContext now.

gdk/wayland/gdkdevice-wayland.c
gdk/wayland/gdkdnd-wayland.c
gdk/wayland/gdkdrop-wayland.c [new file with mode: 0644]
gdk/wayland/gdkprivate-wayland.h
gdk/wayland/meson.build

index 90093445acc31726ff28d7d74db3a97d3eb7c259..cbcf86bddace4579c2172ba3cb07a492ef9a0850 100644 (file)
@@ -246,7 +246,7 @@ struct _GdkWaylandSeat
   GdkClipboard *clipboard;
   GdkClipboard *primary_clipboard;
   struct wl_data_device *data_device;
-  GdkDragContext *drop_context;
+  GdkDrop *drop;
 
   /* Source/dest for non-local dnd */
   GdkSurface *foreign_dnd_surface;
@@ -1140,8 +1140,6 @@ data_offer_source_actions (void                 *data,
                            uint32_t              source_actions)
 {
   GdkWaylandSeat *seat = data;
-  GdkDragContext *drop_context;
-  GdkDevice *device;
 
   if (offer == seat->pending_offer)
     {
@@ -1149,16 +1147,12 @@ data_offer_source_actions (void                 *data,
       return;
     }
   
-  device = gdk_seat_get_pointer (GDK_SEAT (seat));
-  drop_context = gdk_wayland_device_get_drop_context (device);
-  if (drop_context == NULL)
+  if (seat->drop == NULL)
     return;
 
-  gdk_drag_context_set_actions (drop_context,
-                                gdk_wayland_actions_to_gdk_actions (source_actions),
-                                gdk_drag_context_get_suggested_action (drop_context));
+  gdk_wayland_drop_set_source_actions (seat->drop, source_actions);
 
-  gdk_drop_emit_motion_event (GDK_DROP (seat->drop_context),
+  gdk_drop_emit_motion_event (seat->drop,
                               FALSE,
                               seat->pointer_info.surface_x,
                               seat->pointer_info.surface_y,
@@ -1171,8 +1165,6 @@ data_offer_action (void                 *data,
                    uint32_t              action)
 {
   GdkWaylandSeat *seat = data;
-  GdkDragContext *drop_context;
-  GdkDevice *device;
 
   if (offer == seat->pending_offer)
     {
@@ -1180,16 +1172,12 @@ data_offer_action (void                 *data,
       return;
     }
   
-  device = gdk_seat_get_pointer (GDK_SEAT (seat));
-  drop_context = gdk_wayland_device_get_drop_context (device);
-  if (drop_context == NULL)
+  if (seat->drop == NULL)
     return;
 
-  gdk_drag_context_set_actions (drop_context,
-                                gdk_drag_context_get_actions (drop_context),
-                                gdk_wayland_actions_to_gdk_actions (action));
+  gdk_wayland_drop_set_action (seat->drop, action);
 
-  gdk_drop_emit_motion_event (GDK_DROP (seat->drop_context),
+  gdk_drop_emit_motion_event (seat->drop,
                               FALSE,
                               seat->pointer_info.surface_x,
                               seat->pointer_info.surface_y,
@@ -1235,7 +1223,7 @@ data_device_enter (void                  *data,
                    struct wl_data_offer  *offer)
 {
   GdkWaylandSeat *seat = data;
-  GdkSurface *dest_surface, *dnd_owner;
+  GdkSurface *dest_surface;
   GdkContentFormats *formats;
   GdkDevice *device;
 
@@ -1275,15 +1263,11 @@ data_device_enter (void                  *data,
   seat->pending_builder = NULL;
   seat->pending_offer = NULL;
 
-  seat->drop_context = _gdk_wayland_drop_context_new (device, formats, dest_surface, offer, serial);
-
-  dnd_owner = seat->foreign_dnd_surface;
-
-  _gdk_wayland_drag_context_set_source_surface (seat->drop_context, dnd_owner);
+  seat->drop = gdk_wayland_drop_new (device, formats, dest_surface, offer, serial);
 
   gdk_wayland_seat_discard_pending_offer (seat);
 
-  gdk_drop_emit_enter_event (GDK_DROP (seat->drop_context),
+  gdk_drop_emit_enter_event (seat->drop,
                              FALSE,
                              GDK_CURRENT_TIME);
 }
@@ -1297,17 +1281,17 @@ data_device_leave (void                  *data,
   GDK_DISPLAY_NOTE (seat->display, EVENTS,
             g_message ("data device leave, data device %p", data_device));
 
-  if (seat->drop_context == NULL)
+  if (seat->drop == NULL)
     return;
 
   g_object_unref (seat->pointer_info.focus);
   seat->pointer_info.focus = NULL;
 
-  gdk_drop_emit_leave_event (GDK_DROP (seat->drop_context),
+  gdk_drop_emit_leave_event (seat->drop,
                              FALSE,
                              GDK_CURRENT_TIME);
 
-  g_clear_object (&seat->drop_context);
+  g_clear_object (&seat->drop);
 }
 
 static void
@@ -1323,14 +1307,14 @@ data_device_motion (void                  *data,
             g_message ("data device motion, data_device = %p, time = %d, x = %f, y = %f",
                        data_device, time, wl_fixed_to_double (x), wl_fixed_to_double (y)));
 
-  if (seat->drop_context == NULL)
+  if (seat->drop == NULL)
     return;
 
   /* Update pointer state, so device state queries work during DnD */
   seat->pointer_info.surface_x = wl_fixed_to_double (x);
   seat->pointer_info.surface_y = wl_fixed_to_double (y);
 
-  gdk_drop_emit_motion_event (GDK_DROP (seat->drop_context),
+  gdk_drop_emit_motion_event (seat->drop,
                               FALSE,
                               seat->pointer_info.surface_x,
                               seat->pointer_info.surface_y,
@@ -1346,7 +1330,7 @@ data_device_drop (void                  *data,
   GDK_DISPLAY_NOTE (seat->display, EVENTS,
             g_message ("data device drop, data device %p", data_device));
 
-  gdk_drop_emit_drop_event (GDK_DROP (seat->drop_context),
+  gdk_drop_emit_drop_event (seat->drop,
                             FALSE,
                             seat->pointer_info.surface_x,
                             seat->pointer_info.surface_y,
@@ -4613,7 +4597,7 @@ gdk_wayland_seat_finalize (GObject *object)
   gdk_wayland_pointer_data_finalize (&seat->pointer_info);
   /* FIXME: destroy data_device */
   g_clear_object (&seat->keyboard_settings);
-  g_clear_object (&seat->drop_context);
+  g_clear_object (&seat->drop);
   g_clear_object (&seat->clipboard);
   g_clear_object (&seat->primary_clipboard);
   g_hash_table_destroy (seat->touches);
@@ -5196,14 +5180,6 @@ gdk_wayland_seat_get_wl_seat (GdkSeat *seat)
   return GDK_WAYLAND_SEAT (seat)->wl_seat;
 }
 
-GdkDragContext *
-gdk_wayland_device_get_drop_context (GdkDevice *device)
-{
-  GdkSeat *seat = gdk_device_get_seat (device);
-
-  return GDK_WAYLAND_SEAT (seat)->drop_context;
-}
-
 /**
  * gdk_wayland_device_get_node_path:
  * @device: a #GdkDevice
index 18adfa0c65c6eb458f664ceb2fafd04bfd1cc20a..f1767e62609d33bcb38f2490f6f57ec0b33afb06 100644 (file)
@@ -120,159 +120,6 @@ gdk_wayland_drag_context_drag_drop (GdkDragContext *context,
 {
 }
 
-/* Destination side */
-
-static void
-gdk_wayland_drop_context_set_status (GdkWaylandDragContext *context_wayland,
-                                     gboolean               accepted)
-{
-  if (accepted)
-    {
-      const char *const *mimetypes;
-      gsize i, n_mimetypes;
-      
-      mimetypes = gdk_content_formats_get_mime_types (gdk_drop_get_formats (GDK_DROP (context_wayland)), &n_mimetypes);
-      for (i = 0; i < n_mimetypes; i++)
-        {
-          if (mimetypes[i] != g_intern_static_string ("DELETE"))
-            break;
-        }
-
-      if (i < n_mimetypes)
-        {
-          wl_data_offer_accept (context_wayland->offer, context_wayland->serial, mimetypes[i]);
-          return;
-        }
-    }
-
-  wl_data_offer_accept (context_wayland->offer, context_wayland->serial, NULL);
-}
-
-static void
-gdk_wayland_drag_context_commit_status (GdkWaylandDragContext *wayland_context)
-{
-  GdkDisplay *display;
-  uint32_t dnd_actions;
-
-  display = gdk_drop_get_display (GDK_DROP (wayland_context));
-
-  dnd_actions = gdk_to_wl_actions (wayland_context->selected_action);
-
-  if (GDK_WAYLAND_DISPLAY (display)->data_device_manager_version >=
-      WL_DATA_OFFER_SET_ACTIONS_SINCE_VERSION)
-    {
-      if (gdk_drag_action_is_unique (wayland_context->selected_action))
-        {
-          wl_data_offer_set_actions (wayland_context->offer, dnd_actions, dnd_actions);
-        }
-      else
-        {
-          wl_data_offer_set_actions (wayland_context->offer,
-                                     dnd_actions | WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK,
-                                     WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK);
-        }
-    }
-
-  gdk_wayland_drop_context_set_status (wayland_context, wayland_context->selected_action != 0);
-}
-
-static void
-gdk_wayland_drag_context_status (GdkDrop       *drop,
-                                GdkDragAction  action)
-{
-  GdkWaylandDragContext *wayland_context;
-
-  wayland_context = GDK_WAYLAND_DRAG_CONTEXT (drop);
-  wayland_context->selected_action = action;
-
-  gdk_wayland_drag_context_commit_status (wayland_context);
-}
-
-static void
-gdk_wayland_drag_context_finish (GdkDrop       *drop,
-                                 GdkDragAction  action)
-{
-  GdkWaylandDragContext *wayland_context = GDK_WAYLAND_DRAG_CONTEXT (drop);
-  GdkDisplay *display = gdk_drop_get_display (drop);
-  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
-
-  wayland_context->selected_action = action;
-
-  if (action)
-    {
-      gdk_wayland_drag_context_commit_status (wayland_context);
-
-      if (display_wayland->data_device_manager_version >=
-          WL_DATA_OFFER_FINISH_SINCE_VERSION)
-        wl_data_offer_finish (wayland_context->offer);
-    }
-}
-
-static void
-gdk_wayland_drag_context_read_async (GdkDrop             *drop,
-                                     GdkContentFormats   *formats,
-                                     int                  io_priority,
-                                     GCancellable        *cancellable,
-                                     GAsyncReadyCallback  callback,
-                                     gpointer             user_data)
-{
-  GdkWaylandDragContext *wayland_context = GDK_WAYLAND_DRAG_CONTEXT (drop);
-  GdkDisplay *display;
-  GInputStream *stream;
-  const char *mime_type;
-  int pipe_fd[2];
-  GError *error = NULL;
-  GTask *task;
-
-  display = gdk_drop_get_display (drop),
-  task = g_task_new (drop, cancellable, callback, user_data);
-  g_task_set_priority (task, io_priority);
-  g_task_set_source_tag (task, gdk_wayland_drag_context_read_async);
-
-  GDK_DISPLAY_NOTE (display, DND, char *s = gdk_content_formats_to_string (formats);
-                 g_message ("%p: read for %s", drop, s);
-                 g_free (s); );
-  mime_type = gdk_content_formats_match_mime_type (formats,
-                                                   gdk_drop_get_formats (drop));
-  if (mime_type == NULL)
-    {
-      g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
-                               _("No compatible transfer format found"));
-      return;
-    }
-
-  g_task_set_task_data (task, (gpointer) mime_type, NULL);
-
-  if (!g_unix_open_pipe (pipe_fd, FD_CLOEXEC, &error))
-    {
-      g_task_return_error (task, error);
-      return;
-    }
-
-  wl_data_offer_receive (wayland_context->offer, mime_type, pipe_fd[1]);
-  stream = g_unix_input_stream_new (pipe_fd[0], TRUE);
-  close (pipe_fd[1]);
-  g_task_return_pointer (task, stream, g_object_unref);
-}
-
-static GInputStream *
-gdk_wayland_drag_context_read_finish (GdkDrop         *drop,
-                                      const char     **out_mime_type,
-                                      GAsyncResult    *result,
-                                      GError         **error)
-{
-  GTask *task;
-
-  g_return_val_if_fail (g_task_is_valid (result, G_OBJECT (drop)), NULL);
-  task = G_TASK (result);
-  g_return_val_if_fail (g_task_get_source_tag (task) == gdk_wayland_drag_context_read_async, NULL);
-
-  if (out_mime_type)
-    *out_mime_type = g_task_get_task_data (task);
-
-  return g_task_propagate_pointer (task, error);
-}
-
 static void
 gdk_wayland_drag_context_init (GdkWaylandDragContext *context_wayland)
 {
@@ -361,16 +208,10 @@ static void
 gdk_wayland_drag_context_class_init (GdkWaylandDragContextClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GdkDropClass *drop_class = GDK_DROP_CLASS (klass);
   GdkDragContextClass *context_class = GDK_DRAG_CONTEXT_CLASS (klass);
 
   object_class->finalize = gdk_wayland_drag_context_finalize;
 
-  drop_class->status = gdk_wayland_drag_context_status;
-  drop_class->finish = gdk_wayland_drag_context_finish;
-  drop_class->read_async = gdk_wayland_drag_context_read_async;
-  drop_class->read_finish = gdk_wayland_drag_context_read_finish;
-
   context_class->drag_abort = gdk_wayland_drag_context_drag_abort;
   context_class->drag_drop = gdk_wayland_drag_context_drag_drop;
   context_class->get_drag_surface = gdk_wayland_drag_context_get_drag_surface;
@@ -451,31 +292,6 @@ _gdk_wayland_surface_drag_begin (GdkSurface          *surface,
   return context;
 }
 
-
-GdkDragContext *
-_gdk_wayland_drop_context_new (GdkDevice            *device,
-                               GdkContentFormats    *formats,
-                               GdkSurface           *surface,
-                               struct wl_data_offer *offer,
-                               uint32_t              serial)
-
-{
-  GdkWaylandDragContext *context_wayland;
-  GdkDragContext *context;
-
-  context_wayland = g_object_new (GDK_TYPE_WAYLAND_DRAG_CONTEXT,
-                                  "device", device,
-                                  "formats", formats,
-                                  "surface", surface,
-                                  NULL);
-  context = GDK_DRAG_CONTEXT (context_wayland);
-  context->is_source = FALSE;
-  context_wayland->offer = offer;
-  context_wayland->serial = serial;
-
-  return context;
-}
-
 void
 _gdk_wayland_drag_context_set_source_surface (GdkDragContext *context,
                                              GdkSurface      *surface)
diff --git a/gdk/wayland/gdkdrop-wayland.c b/gdk/wayland/gdkdrop-wayland.c
new file mode 100644 (file)
index 0000000..a73fa8b
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gdkdndprivate.h"
+
+#include "gdkinternals.h"
+#include "gdkproperty.h"
+#include "gdkprivate-wayland.h"
+#include "gdkcontentformats.h"
+#include "gdkdisplay-wayland.h"
+#include "gdkintl.h"
+#include "gdkseat-wayland.h"
+
+#include "gdkdeviceprivate.h"
+
+#include <glib-unix.h>
+#include <gio/gunixinputstream.h>
+#include <gio/gunixoutputstream.h>
+#include <string.h>
+
+#define GDK_TYPE_WAYLAND_DROP              (gdk_wayland_drop_get_type ())
+#define GDK_WAYLAND_DROP(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_DROP, GdkWaylandDrop))
+#define GDK_WAYLAND_DROP_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WAYLAND_DROP, GdkWaylandDropClass))
+#define GDK_IS_WAYLAND_DROP(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_DROP))
+#define GDK_IS_WAYLAND_DROP_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WAYLAND_DROP))
+#define GDK_WAYLAND_DROP_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WAYLAND_DROP, GdkWaylandDropClass))
+
+typedef struct _GdkWaylandDrop GdkWaylandDrop;
+typedef struct _GdkWaylandDropClass GdkWaylandDropClass;
+
+struct _GdkWaylandDrop
+{
+  GdkDrop drop;
+
+  struct wl_data_offer *offer;
+  uint32_t source_actions;
+  uint32_t action;
+  GdkDragAction selected_action;
+  uint32_t serial;
+};
+
+struct _GdkWaylandDropClass
+{
+  GdkDropClass parent_class;
+};
+
+GType gdk_wayland_drop_get_type (void);
+
+G_DEFINE_TYPE (GdkWaylandDrop, gdk_wayland_drop, GDK_TYPE_DROP)
+
+static void
+gdk_wayland_drop_finalize (GObject *object)
+{
+  GdkWaylandDrop *wayland_drop = GDK_WAYLAND_DROP (object);
+
+  g_clear_pointer (&wayland_drop->offer, (GDestroyNotify) wl_data_offer_destroy);
+
+  G_OBJECT_CLASS (gdk_wayland_drop_parent_class)->finalize (object);
+}
+
+static inline uint32_t
+gdk_to_wl_actions (GdkDragAction action)
+{
+  uint32_t dnd_actions = 0;
+
+  if (action & (GDK_ACTION_COPY | GDK_ACTION_LINK))
+    dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
+  if (action & GDK_ACTION_MOVE)
+    dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
+  if (action & GDK_ACTION_ASK)
+    dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
+
+  return dnd_actions;
+}
+
+static void
+gdk_wayland_drop_drop_set_status (GdkWaylandDrop *drop_wayland,
+                                  gboolean        accepted)
+{
+  if (accepted)
+    {
+      const char *const *mimetypes;
+      gsize i, n_mimetypes;
+      
+      mimetypes = gdk_content_formats_get_mime_types (gdk_drop_get_formats (GDK_DROP (drop_wayland)), &n_mimetypes);
+      for (i = 0; i < n_mimetypes; i++)
+        {
+          if (mimetypes[i] != g_intern_static_string ("DELETE"))
+            break;
+        }
+
+      if (i < n_mimetypes)
+        {
+          wl_data_offer_accept (drop_wayland->offer, drop_wayland->serial, mimetypes[i]);
+          return;
+        }
+    }
+
+  wl_data_offer_accept (drop_wayland->offer, drop_wayland->serial, NULL);
+}
+
+static void
+gdk_wayland_drop_commit_status (GdkWaylandDrop *wayland_drop)
+{
+  GdkDisplay *display;
+  uint32_t dnd_actions;
+
+  display = gdk_drop_get_display (GDK_DROP (wayland_drop));
+
+  dnd_actions = gdk_to_wl_actions (wayland_drop->selected_action);
+
+  if (GDK_WAYLAND_DISPLAY (display)->data_device_manager_version >=
+      WL_DATA_OFFER_SET_ACTIONS_SINCE_VERSION)
+    {
+      if (gdk_drag_action_is_unique (wayland_drop->selected_action))
+        {
+          wl_data_offer_set_actions (wayland_drop->offer, dnd_actions, dnd_actions);
+        }
+      else
+        {
+          wl_data_offer_set_actions (wayland_drop->offer,
+                                     dnd_actions | WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK,
+                                     WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK);
+        }
+    }
+
+  gdk_wayland_drop_drop_set_status (wayland_drop, wayland_drop->selected_action != 0);
+}
+
+static void
+gdk_wayland_drop_status (GdkDrop       *drop,
+                         GdkDragAction  action)
+{
+  GdkWaylandDrop *wayland_drop;
+
+  wayland_drop = GDK_WAYLAND_DROP (drop);
+  wayland_drop->selected_action = action;
+
+  gdk_wayland_drop_commit_status (wayland_drop);
+}
+
+static void
+gdk_wayland_drop_finish (GdkDrop       *drop,
+                         GdkDragAction  action)
+{
+  GdkWaylandDrop *wayland_drop = GDK_WAYLAND_DROP (drop);
+  GdkDisplay *display = gdk_drop_get_display (drop);
+  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
+
+  wayland_drop->selected_action = action;
+
+  if (action)
+    {
+      gdk_wayland_drop_commit_status (wayland_drop);
+
+      if (display_wayland->data_device_manager_version >=
+          WL_DATA_OFFER_FINISH_SINCE_VERSION)
+        wl_data_offer_finish (wayland_drop->offer);
+    }
+}
+
+static void
+gdk_wayland_drop_read_async (GdkDrop             *drop,
+                             GdkContentFormats   *formats,
+                             int                  io_priority,
+                             GCancellable        *cancellable,
+                             GAsyncReadyCallback  callback,
+                             gpointer             user_data)
+{
+  GdkWaylandDrop *wayland_drop = GDK_WAYLAND_DROP (drop);
+  GdkDisplay *display;
+  GInputStream *stream;
+  const char *mime_type;
+  int pipe_fd[2];
+  GError *error = NULL;
+  GTask *task;
+
+  display = gdk_drop_get_display (drop),
+  task = g_task_new (drop, cancellable, callback, user_data);
+  g_task_set_priority (task, io_priority);
+  g_task_set_source_tag (task, gdk_wayland_drop_read_async);
+
+  GDK_DISPLAY_NOTE (display, DND, char *s = gdk_content_formats_to_string (formats);
+                    g_message ("%p: read for %s", drop, s);
+                    g_free (s); );
+  mime_type = gdk_content_formats_match_mime_type (formats,
+                                                   gdk_drop_get_formats (drop));
+  if (mime_type == NULL)
+    {
+      g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                               _("No compatible transfer format found"));
+      return;
+    }
+
+  g_task_set_task_data (task, (gpointer) mime_type, NULL);
+
+  if (!g_unix_open_pipe (pipe_fd, FD_CLOEXEC, &error))
+    {
+      g_task_return_error (task, error);
+      return;
+    }
+
+  wl_data_offer_receive (wayland_drop->offer, mime_type, pipe_fd[1]);
+  stream = g_unix_input_stream_new (pipe_fd[0], TRUE);
+  close (pipe_fd[1]);
+  g_task_return_pointer (task, stream, g_object_unref);
+}
+
+static GInputStream *
+gdk_wayland_drop_read_finish (GdkDrop       *drop,
+                              const char   **out_mime_type,
+                              GAsyncResult  *result,
+                              GError       **error)
+{
+  GTask *task;
+
+  g_return_val_if_fail (g_task_is_valid (result, G_OBJECT (drop)), NULL);
+  task = G_TASK (result);
+  g_return_val_if_fail (g_task_get_source_tag (task) == gdk_wayland_drop_read_async, NULL);
+
+  if (out_mime_type)
+    *out_mime_type = g_task_get_task_data (task);
+
+  return g_task_propagate_pointer (task, error);
+}
+
+static void
+gdk_wayland_drop_class_init (GdkWaylandDropClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GdkDropClass *drop_class = GDK_DROP_CLASS (klass);
+
+  object_class->finalize = gdk_wayland_drop_finalize;
+
+  drop_class->status = gdk_wayland_drop_status;
+  drop_class->finish = gdk_wayland_drop_finish;
+  drop_class->read_async = gdk_wayland_drop_read_async;
+  drop_class->read_finish = gdk_wayland_drop_read_finish;
+}
+
+static void
+gdk_wayland_drop_init (GdkWaylandDrop *drop)
+{
+}
+
+GdkDrop *
+gdk_wayland_drop_new (GdkDevice            *device,
+                      GdkContentFormats    *formats,
+                      GdkSurface           *surface,
+                      struct wl_data_offer *offer,
+                      uint32_t              serial)
+
+{
+  GdkWaylandDrop *drop;
+
+  drop = g_object_new (GDK_TYPE_WAYLAND_DROP,
+                       "device", device,
+                       "formats", formats,
+                       "surface", surface,
+                       NULL);
+  drop->offer = offer;
+  drop->serial = serial;
+
+  return GDK_DROP (drop);
+}
+
+static void
+gdk_wayland_drop_update_actions (GdkWaylandDrop *drop)
+{
+  GdkDragAction gdk_actions = 0;
+  uint32_t wl_actions;
+
+  if (drop->action & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
+    wl_actions = drop->source_actions;
+  else
+    wl_actions = drop->action;
+
+  if (wl_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
+    gdk_actions |= GDK_ACTION_COPY;
+  if (wl_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
+    gdk_actions |= GDK_ACTION_MOVE;
+
+  gdk_drop_set_actions (GDK_DROP (drop), gdk_actions);
+}
+
+void
+gdk_wayland_drop_set_source_actions (GdkDrop *drop,
+                                     uint32_t source_actions)
+{
+  GdkWaylandDrop *wayland_drop = GDK_WAYLAND_DROP (drop);
+
+  wayland_drop->source_actions = source_actions;
+
+  gdk_wayland_drop_update_actions (wayland_drop);
+}
+
+void
+gdk_wayland_drop_set_action (GdkDrop *drop,
+                             uint32_t action)
+{
+  GdkWaylandDrop *wayland_drop = GDK_WAYLAND_DROP (drop);
+
+  wayland_drop->action = action;
+
+  gdk_wayland_drop_update_actions (wayland_drop);
+}
+
index 29da9f9a2b048e8c8dd06266d8a82b422ef791a1..70af4491567e59c5e57140a9d91e80557a17a0ca 100644 (file)
@@ -104,11 +104,16 @@ GdkDragContext *_gdk_wayland_surface_drag_begin            (GdkSurface *surface,
 void            _gdk_wayland_surface_offset_next_wl_buffer (GdkSurface *surface,
                                                             int        x,
                                                             int        y);
-GdkDragContext * _gdk_wayland_drop_context_new (GdkDevice             *device,
-                                                GdkContentFormats     *formats,
-                                                GdkSurface            *surface,
-                                                struct wl_data_offer  *offer,
-                                                uint32_t               serial);
+GdkDrop *        gdk_wayland_drop_new                      (GdkDevice             *device,
+                                                            GdkContentFormats     *formats,
+                                                            GdkSurface            *surface,
+                                                            struct wl_data_offer  *offer,
+                                                            uint32_t               serial);
+void             gdk_wayland_drop_set_source_actions       (GdkDrop               *drop,
+                                                            uint32_t               source_actions);
+void             gdk_wayland_drop_set_action               (GdkDrop               *drop,
+                                                            uint32_t               action);
+
 void _gdk_wayland_drag_context_set_source_surface (GdkDragContext *context,
                                                   GdkSurface      *surface);
 
index fc6bbdfd825f64d33a580aa7729043d72a2f24c4..085224d2394634a2a053442eb75ef27667abd7ed 100644 (file)
@@ -6,6 +6,7 @@ gdk_wayland_sources = files([
   'gdkdevice-wayland.c',
   'gdkdisplay-wayland.c',
   'gdkdnd-wayland.c',
+  'gdkdrop-wayland.c',
   'gdkeventsource.c',
   'gdkglcontext-wayland.c',
   'gdkkeys-wayland.c',