From ea9d6f0a957bf633e7217b2045949779c36aba38 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Thu, 31 May 2018 21:45:22 +0200 Subject: [PATCH] drop: Implement shortcut for local DND Now that we have the drop->drag, we can use the same shortcut we use in the clipboard code to shortcut DND operations. --- gdk/gdkdrop.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 87 insertions(+), 8 deletions(-) diff --git a/gdk/gdkdrop.c b/gdk/gdkdrop.c index 8155ca4a32..cd0f987800 100644 --- a/gdk/gdkdrop.c +++ b/gdk/gdkdrop.c @@ -30,6 +30,7 @@ #include "gdkeventsprivate.h" #include "gdkinternals.h" #include "gdkintl.h" +#include "gdkpipeiostreamprivate.h" #include "gdksurface.h" typedef struct _GdkDropPrivate GdkDropPrivate; @@ -70,6 +71,20 @@ gdk_drop_default_status (GdkDrop *self, { } +static void +gdk_drop_read_local_write_done (GObject *drag, + GAsyncResult *result, + gpointer stream) +{ + /* we don't care about the error, we just want to clean up */ + gdk_drag_context_write_finish (GDK_DRAG_CONTEXT (drag), result, NULL); + + /* XXX: Do we need to close_async() here? */ + g_output_stream_close (stream, NULL, NULL); + + g_object_unref (stream); +} + static void gdk_drop_read_local_async (GdkDrop *self, GdkContentFormats *formats, @@ -78,14 +93,53 @@ gdk_drop_read_local_async (GdkDrop *self, GAsyncReadyCallback callback, gpointer user_data) { + GdkDropPrivate *priv = gdk_drop_get_instance_private (self); + GdkContentFormats *content_formats; + const char *mime_type; GTask *task; task = g_task_new (self, cancellable, callback, user_data); g_task_set_priority (task, io_priority); g_task_set_source_tag (task, gdk_drop_read_local_async); - g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - _("Reading not implemented.")); + if (priv->drag == NULL) + { + g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Drag'n'drop from other applications is not supported.")); + g_object_unref (task); + return; + } + + content_formats = gdk_content_provider_ref_formats (priv->drag->content); + content_formats = gdk_content_formats_union_serialize_mime_types (content_formats); + mime_type = gdk_content_formats_match_mime_type (content_formats, formats); + + if (mime_type != NULL) + { + GOutputStream *output_stream; + GIOStream *stream; + + stream = gdk_pipe_io_stream_new (); + output_stream = g_io_stream_get_output_stream (stream); + gdk_drag_context_write_async (priv->drag, + mime_type, + output_stream, + io_priority, + cancellable, + gdk_drop_read_local_write_done, + g_object_ref (output_stream)); + g_task_set_task_data (task, (gpointer) mime_type, NULL); + g_task_return_pointer (task, g_object_ref (g_io_stream_get_input_stream (stream)), g_object_unref); + + g_object_unref (stream); + } + else + { + g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("No compatible formats to transfer contents.")); + } + + gdk_content_formats_unref (content_formats); g_object_unref (task); } @@ -498,6 +552,36 @@ gdk_drop_finish (GdkDrop *self, GDK_DROP_GET_CLASS (self)->finish (self, action); } +static void +gdk_drop_read_internal (GdkDrop *self, + GdkContentFormats *formats, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GdkDropPrivate *priv = gdk_drop_get_instance_private (self); + + if (priv->drag) + { + gdk_drop_read_local_async (self, + formats, + io_priority, + cancellable, + callback, + user_data); + } + else + { + GDK_DROP_GET_CLASS (self)->read_async (self, + formats, + io_priority, + cancellable, + callback, + user_data); + } +} + /** * gdk_drop_read_async: * @self: a #GdkDrop @@ -530,12 +614,7 @@ gdk_drop_read_async (GdkDrop *self, formats = gdk_content_formats_new (mime_types, g_strv_length ((char **) mime_types)); - GDK_DROP_GET_CLASS (self)->read_async (self, - formats, - io_priority, - cancellable, - callback, - user_data); + gdk_drop_read_internal (self, formats, io_priority, cancellable, callback, user_data); gdk_content_formats_unref (formats); } -- 2.30.2