[gtk/dnd-gestures-2: 53/150] Add an async read function for selection
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/dnd-gestures-2: 53/150] Add an async read function for selection
- Date: Tue, 7 Jan 2020 06:56:23 +0000 (UTC)
commit eceb61c6354dc086d871df0d2a7e9a09b35a99b1
Author: Matthias Clasen <mclasen redhat com>
Date: Fri Jan 3 00:14:49 2020 -0500
Add an async read function for selection
This is meant as a replacement for ::drag-data-received
in cases where a #GtkSelectionData object is still needed,
such as when using GtkTreeModel DND support.
gtk/gtkdragdest.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
gtk/gtkdragdest.h | 12 +++++
2 files changed, 154 insertions(+)
---
diff --git a/gtk/gtkdragdest.c b/gtk/gtkdragdest.c
index d079c198d3..22e7519537 100644
--- a/gtk/gtkdragdest.c
+++ b/gtk/gtkdragdest.c
@@ -34,6 +34,7 @@
#include "gtktypebuiltins.h"
#include "gtkeventcontroller.h"
#include "gtkmarshalers.h"
+#include "gtkselectionprivate.h"
static void
@@ -794,3 +795,144 @@ gtk_drag_unhighlight (GtkWidget *widget)
gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_DROP_ACTIVE);
}
+
+
+static void
+gtk_drag_get_data_got_data (GObject *source,
+ GAsyncResult *result,
+ gpointer data)
+{
+ GTask *task = data;
+ gssize written;
+ GError *error = NULL;
+ guchar *bytes;
+ gsize size;
+ GtkSelectionData *sdata;
+ GtkDropTarget *dest;
+ GdkDrop *drop;
+ GdkDisplay *display;
+
+ written = g_output_stream_splice_finish (G_OUTPUT_STREAM (source), result, &error);
+ if (written < 0)
+ {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ bytes = g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (source));
+ size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (source));
+
+ dest = GTK_DROP_TARGET (g_task_get_source_object (task));
+ drop = GDK_DROP (g_object_get_data (G_OBJECT (task), "drop"));
+ display = GDK_DISPLAY (g_object_get_data (G_OBJECT (task), "display"));
+
+ sdata = g_slice_new0 (GtkSelectionData);
+ sdata->target = g_task_get_task_data (task);
+ sdata->type = g_task_get_task_data (task);
+ sdata->format = 8;
+ sdata->length = size;
+ sdata->data = bytes ? bytes : (guchar *)g_strdup ("");
+ sdata->display = display;
+
+ set_drop (dest, drop);
+ g_task_return_pointer (task, sdata, NULL);
+ set_drop (dest, NULL);
+
+ g_object_unref (task);
+}
+
+static void
+gtk_drag_get_data_got_stream (GObject *source,
+ GAsyncResult *result,
+ gpointer data)
+{
+ GTask *task = data;
+ GInputStream *input_stream;
+ GOutputStream *output_stream;
+ GError *error = NULL;
+ const char *mime_type;
+
+ input_stream = gdk_drop_read_finish (GDK_DROP (source), result, &mime_type, &error);
+ if (input_stream == NULL)
+ {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ g_task_set_task_data (task, (gpointer)g_intern_string (mime_type), NULL);
+
+ output_stream = g_memory_output_stream_new_resizable ();
+ g_output_stream_splice_async (output_stream,
+ input_stream,
+ G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ gtk_drag_get_data_got_data,
+ task);
+ g_object_unref (output_stream);
+ g_object_unref (input_stream);
+}
+
+/**
+ * gtk_drop_target_read_selection:
+ * @dest: a #GtkDropTarget
+ * @target: the data format to read
+ * @cancellable: (nullable): a cancellable
+ * @callback: callback to call on completion
+ * @user_data: data to pass to @callback
+ *
+ * Asynchronously reads the dropped data from an ongoing
+ * drag on a #GtkDropTarget, and returns the data in a
+ * #GtkSelectionData object.
+ *
+ * This function is meant for cases where a #GtkSelectionData
+ * object is needed, such as when using the #GtkTreeModel DND
+ * support. In most other cases, the #GdkDrop async read
+ * APIs that return in input stream or #GValue are more
+ * convenient and should be preferred.
+ */
+void
+gtk_drop_target_read_selection (GtkDropTarget *dest,
+ GdkAtom target,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+
+ 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));
+
+ gdk_drop_read_async (dest->drop,
+ (const char *[2]) { target, NULL },
+ G_PRIORITY_DEFAULT,
+ NULL,
+ gtk_drag_get_data_got_stream,
+ task);
+}
+
+/**
+ * gtk_drop_target_read_selection_finish:
+ * @dest: a #GtkDropTarget
+ * @result: a #GAsyncResult
+ * @error: (allow-none): location to store error information on failure, or %NULL
+ *
+ * Finishes an async drop read operation, see gtk_drop_target_read_selection().
+ *
+ * Returns: (nullable) (transfer full): the #GtkSelectionData, or %NULL
+ */
+GtkSelectionData *
+gtk_drop_target_read_selection_finish (GtkDropTarget *dest,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (GTK_IS_DROP_TARGET (dest), NULL);
+
+ return g_task_propagate_pointer (G_TASK (result), error);
+}
diff --git a/gtk/gtkdragdest.h b/gtk/gtkdragdest.h
index 5c48fd7227..24190d8120 100644
--- a/gtk/gtkdragdest.h
+++ b/gtk/gtkdragdest.h
@@ -125,6 +125,18 @@ GtkWidget *gtk_drop_target_get_target (GtkDropTarget *dest);
GDK_AVAILABLE_IN_ALL
const char *gtk_drop_target_find_mimetype (GtkDropTarget *dest);
+GDK_AVAILABLE_IN_ALL
+void gtk_drop_target_read_selection (GtkDropTarget *dest,
+ GdkAtom target,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data);
+GDK_AVAILABLE_IN_ALL
+GtkSelectionData *gtk_drop_target_read_selection_finish
+ (GtkDropTarget *dest,
+ GAsyncResult *result,
+ GError **error);
+
GDK_AVAILABLE_IN_ALL
void gtk_drag_highlight (GtkWidget *widget);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]