forked from AuroraMiddleware/gtk
dnd: Introduce gdk_drop_read_async() and use it
This is the replacement for selection usage. Backend implementations for X11 (missing support for backwards compat formats like COMPOUND_TEXT) and Wayland are included. GTK code should be adapted to use gdk_drop_read_*() functions instead of gtk_drag_get_data().
This commit is contained in:
parent
963264a73a
commit
803cbd576f
80
gdk/gdkdnd.c
80
gdk/gdkdnd.c
@ -309,6 +309,40 @@ gdk_drag_context_finalize (GObject *object)
|
||||
G_OBJECT_CLASS (gdk_drag_context_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_context_read_local_async (GdkDragContext *context,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (context, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, io_priority);
|
||||
g_task_set_source_tag (task, gdk_drag_context_read_local_async);
|
||||
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("Reading not implemented."));
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
gdk_drag_context_read_local_finish (GdkDragContext *context,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (result, context), NULL);
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gdk_drag_context_read_local_async, NULL);
|
||||
|
||||
if (out_mime_type)
|
||||
*out_mime_type = g_task_get_task_data (G_TASK (result));
|
||||
|
||||
return g_task_propagate_pointer (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_context_class_init (GdkDragContextClass *klass)
|
||||
{
|
||||
@ -637,6 +671,52 @@ gdk_drag_get_selection (GdkDragContext *context)
|
||||
return GDK_DRAG_CONTEXT_GET_CLASS (context)->get_selection (context);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drop_read_async (GdkDragContext *context,
|
||||
const char **mime_types,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkContentFormats *formats;
|
||||
|
||||
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
|
||||
g_return_if_fail (mime_types != NULL && mime_types[0] != NULL);
|
||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
formats = gdk_content_formats_new (mime_types, g_strv_length ((char **) mime_types));
|
||||
|
||||
GDK_DRAG_CONTEXT_GET_CLASS (context)->read_async (context,
|
||||
formats,
|
||||
io_priority,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
|
||||
gdk_content_formats_unref (formats);
|
||||
}
|
||||
|
||||
GInputStream *
|
||||
gdk_drop_read_finish (GdkDragContext *context,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
if (g_async_result_is_tagged (result, gdk_drag_context_read_local_async))
|
||||
{
|
||||
return gdk_drag_context_read_local_finish (context, out_mime_type, result, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GDK_DRAG_CONTEXT_GET_CLASS (context)->read_finish (context, out_mime_type, result, error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_context_get_drag_window:
|
||||
* @context: a #GdkDragContext
|
||||
|
13
gdk/gdkdnd.h
13
gdk/gdkdnd.h
@ -121,6 +121,19 @@ void gdk_drop_finish (GdkDragContext *context,
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkAtom gdk_drag_get_selection (GdkDragContext *context);
|
||||
|
||||
GDK_AVAILABLE_IN_3_94
|
||||
void gdk_drop_read_async (GdkDragContext *context,
|
||||
const char **mime_types,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GDK_AVAILABLE_IN_3_94
|
||||
GInputStream * gdk_drop_read_finish (GdkDragContext *context,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
/* Source side */
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
|
@ -87,6 +87,16 @@ struct _GdkDragContextClass {
|
||||
void (*drop_finish) (GdkDragContext *context,
|
||||
gboolean success,
|
||||
guint32 time_);
|
||||
void (* read_async) (GdkDragContext *context,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GInputStream * (* read_finish) (GdkDragContext *context,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
gboolean (*drop_status) (GdkDragContext *context);
|
||||
GdkWindow* (*get_drag_window) (GdkDragContext *context);
|
||||
void (*set_hotspot) (GdkDragContext *context,
|
||||
|
@ -24,10 +24,14 @@
|
||||
#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_DRAG_CONTEXT (gdk_wayland_drag_context_get_type ())
|
||||
@ -324,6 +328,80 @@ gdk_wayland_drag_context_drop_finish (GdkDragContext *context,
|
||||
gdk_wayland_selection_set_offer (display, selection, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_read_async (GdkDragContext *context,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
GdkContentFormats *dnd_formats;
|
||||
GInputStream *stream;
|
||||
struct wl_data_offer *offer;
|
||||
const char *mime_type;
|
||||
int pipe_fd[2];
|
||||
GError *error = NULL;
|
||||
GTask *task;
|
||||
|
||||
display = gdk_drag_context_get_display (context),
|
||||
task = g_task_new (context, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, io_priority);
|
||||
g_task_set_source_tag (task, gdk_wayland_drag_context_read_async);
|
||||
|
||||
GDK_NOTE (DND, char *s = gdk_content_formats_to_string (formats);
|
||||
g_printerr ("%p: read for %s\n", context, s);
|
||||
g_free (s); );
|
||||
dnd_formats = gdk_wayland_selection_get_targets (display,
|
||||
gdk_drag_get_selection (context));
|
||||
mime_type = gdk_content_formats_match_mime_type (formats, dnd_formats);
|
||||
if (mime_type == NULL)
|
||||
{
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("No compatible transfer format found"));
|
||||
return;
|
||||
}
|
||||
/* offer formats should be empty if we have no offer */
|
||||
offer = gdk_wayland_selection_get_offer (display,
|
||||
gdk_drag_get_selection (context));
|
||||
g_assert (offer);
|
||||
|
||||
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_accept (offer,
|
||||
_gdk_wayland_display_get_serial (GDK_WAYLAND_DISPLAY (display)),
|
||||
mime_type);
|
||||
wl_data_offer_receive (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 (GdkDragContext *context,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
g_return_val_if_fail (g_task_is_valid (result, G_OBJECT (context)), 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 gboolean
|
||||
gdk_wayland_drag_context_drop_status (GdkDragContext *context)
|
||||
{
|
||||
@ -471,6 +549,9 @@ gdk_wayland_drag_context_class_init (GdkWaylandDragContextClass *klass)
|
||||
context_class->drag_drop = gdk_wayland_drag_context_drag_drop;
|
||||
context_class->drop_reply = gdk_wayland_drag_context_drop_reply;
|
||||
context_class->drop_finish = gdk_wayland_drag_context_drop_finish;
|
||||
context_class->drop_finish = gdk_wayland_drag_context_drop_finish;
|
||||
context_class->read_async = gdk_wayland_drag_context_read_async;
|
||||
context_class->read_finish = gdk_wayland_drag_context_read_finish;
|
||||
context_class->drop_status = gdk_wayland_drag_context_drop_status;
|
||||
context_class->get_selection = gdk_wayland_drag_context_get_selection;
|
||||
context_class->get_drag_window = gdk_wayland_drag_context_get_drag_window;
|
||||
|
@ -287,7 +287,7 @@ static const struct {
|
||||
{ "SAVE_TARGETS", NULL, NULL, "NULL", 32, handle_save_targets }
|
||||
};
|
||||
|
||||
static GSList *
|
||||
GSList *
|
||||
gdk_x11_clipboard_formats_to_targets (GdkContentFormats *formats)
|
||||
{
|
||||
GSList *targets;
|
||||
|
@ -36,6 +36,7 @@ GType gdk_x11_clipboard_get_type (void) G_GNUC_CO
|
||||
GdkClipboard * gdk_x11_clipboard_new (GdkDisplay *display,
|
||||
const gchar *selection);
|
||||
|
||||
GSList * gdk_x11_clipboard_formats_to_targets (GdkContentFormats *formats);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -25,16 +25,19 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkx11dnd.h"
|
||||
#include "gdkdndprivate.h"
|
||||
#include "gdkdeviceprivate.h"
|
||||
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkasync.h"
|
||||
#include "gdkcontentformatsprivate.h"
|
||||
#include "gdkclipboardprivate.h"
|
||||
#include "gdkclipboard-x11.h"
|
||||
#include "gdkdeviceprivate.h"
|
||||
#include "gdkdisplay-x11.h"
|
||||
#include "gdkdndprivate.h"
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdkproperty.h"
|
||||
#include "gdkprivate-x11.h"
|
||||
#include "gdkscreen-x11.h"
|
||||
#include "gdkdisplay-x11.h"
|
||||
#include "gdkselectioninputstream-x11.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
@ -242,6 +245,135 @@ static void gdk_x11_drag_context_cancel (GdkDragContext *con
|
||||
static void gdk_x11_drag_context_drop_performed (GdkDragContext *context,
|
||||
guint32 time);
|
||||
|
||||
static void
|
||||
gdk_x11_drag_context_read_got_stream (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
GTask *task = data;
|
||||
GError *error = NULL;
|
||||
GInputStream *stream;
|
||||
const char *type;
|
||||
int format;
|
||||
|
||||
stream = gdk_x11_selection_input_stream_new_finish (res, &type, &format, &error);
|
||||
if (stream == NULL)
|
||||
{
|
||||
GSList *targets, *next;
|
||||
|
||||
targets = g_task_get_task_data (task);
|
||||
next = targets->next;
|
||||
if (next)
|
||||
{
|
||||
GdkDragContext *context = GDK_DRAG_CONTEXT (g_task_get_source_object (task));
|
||||
|
||||
GDK_NOTE (DND, g_printerr ("reading %s failed, trying %s next\n",
|
||||
(char *) targets->data, (char *) next->data));
|
||||
targets->next = NULL;
|
||||
g_task_set_task_data (task, next, (GDestroyNotify) g_slist_free);
|
||||
gdk_x11_selection_input_stream_new_async (gdk_drag_context_get_display (context),
|
||||
gdk_drag_get_selection (context),
|
||||
next->data,
|
||||
CurrentTime,
|
||||
g_task_get_priority (task),
|
||||
g_task_get_cancellable (task),
|
||||
gdk_x11_drag_context_read_got_stream,
|
||||
task);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_task_return_error (task, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *mime_type = ((GSList *) g_task_get_task_data (task))->data;
|
||||
#if 0
|
||||
gsize i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (special_targets); i++)
|
||||
{
|
||||
if (g_str_equal (mime_type, special_targets[i].x_target))
|
||||
{
|
||||
g_assert (special_targets[i].mime_type != NULL);
|
||||
|
||||
GDK_NOTE(CLIPBOARD, g_printerr ("%s: reading with converter from %s to %s\n",
|
||||
cb->selection, mime_type, special_targets[i].mime_type));
|
||||
mime_type = g_intern_string (special_targets[i].mime_type);
|
||||
g_task_set_task_data (task, g_slist_prepend (NULL, (gpointer) mime_type), (GDestroyNotify) g_slist_free);
|
||||
stream = special_targets[i].convert (cb, stream, type, format);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
GDK_NOTE(DND, g_printerr ("reading DND as %s now\n",
|
||||
mime_type));
|
||||
g_task_return_pointer (task, stream, g_object_unref);
|
||||
}
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_drag_context_read_async (GdkDragContext *context,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GSList *targets;
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (context, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, io_priority);
|
||||
g_task_set_source_tag (task, gdk_x11_drag_context_read_async);
|
||||
|
||||
targets = gdk_x11_clipboard_formats_to_targets (formats);
|
||||
g_task_set_task_data (task, targets, (GDestroyNotify) g_slist_free);
|
||||
if (targets == NULL)
|
||||
{
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("No compatible transfer format found"));
|
||||
return;
|
||||
}
|
||||
|
||||
GDK_NOTE(DND, g_printerr ("new read for %s (%u other options)\n",
|
||||
(char *) targets->data, g_slist_length (targets->next)));
|
||||
gdk_x11_selection_input_stream_new_async (gdk_drag_context_get_display (context),
|
||||
gdk_drag_get_selection (context),
|
||||
targets->data,
|
||||
CurrentTime,
|
||||
io_priority,
|
||||
cancellable,
|
||||
gdk_x11_drag_context_read_got_stream,
|
||||
task);
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
gdk_x11_drag_context_read_finish (GdkDragContext *context,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
g_return_val_if_fail (g_task_is_valid (result, G_OBJECT (context)), NULL);
|
||||
task = G_TASK (result);
|
||||
g_return_val_if_fail (g_task_get_source_tag (task) == gdk_x11_drag_context_read_async, NULL);
|
||||
|
||||
if (out_mime_type)
|
||||
{
|
||||
GSList *targets;
|
||||
|
||||
targets = g_task_get_task_data (task);
|
||||
*out_mime_type = targets ? targets->data : NULL;
|
||||
}
|
||||
|
||||
return g_task_propagate_pointer (task, error);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_drag_context_class_init (GdkX11DragContextClass *klass)
|
||||
{
|
||||
@ -258,6 +390,8 @@ gdk_x11_drag_context_class_init (GdkX11DragContextClass *klass)
|
||||
context_class->drop_reply = gdk_x11_drag_context_drop_reply;
|
||||
context_class->drop_finish = gdk_x11_drag_context_drop_finish;
|
||||
context_class->drop_status = gdk_x11_drag_context_drop_status;
|
||||
context_class->read_async = gdk_x11_drag_context_read_async;
|
||||
context_class->read_finish = gdk_x11_drag_context_read_finish;
|
||||
context_class->get_selection = gdk_x11_drag_context_get_selection;
|
||||
context_class->get_drag_window = gdk_x11_drag_context_get_drag_window;
|
||||
context_class->set_hotspot = gdk_x11_drag_context_set_hotspot;
|
||||
|
135
gtk/gtkdnd.c
135
gtk/gtkdnd.c
@ -326,6 +326,115 @@ gtk_drag_get_event_actions (const GdkEvent *event,
|
||||
* Destination side *
|
||||
********************/
|
||||
|
||||
typedef struct {
|
||||
GdkDragContext *context;
|
||||
GtkWidget *widget;
|
||||
const char *mime_type;
|
||||
guint time;
|
||||
} GtkDragGetData;
|
||||
|
||||
static void
|
||||
gtk_drag_get_data_finish (GtkDragGetData *data,
|
||||
guchar *bytes,
|
||||
gsize size)
|
||||
{
|
||||
GtkDragDestSite *site;
|
||||
GtkSelectionData sdata;
|
||||
|
||||
site = g_object_get_data (G_OBJECT (data->widget), "gtk-drag-dest");
|
||||
|
||||
sdata.selection = gdk_drag_get_selection (data->context);
|
||||
sdata.target = data->mime_type;
|
||||
sdata.type = data->mime_type;
|
||||
sdata.format = 8;
|
||||
sdata.length = size;
|
||||
sdata.data = bytes;
|
||||
sdata.display = gtk_widget_get_display (data->widget);
|
||||
|
||||
if (site && site->target_list)
|
||||
{
|
||||
if (gdk_content_formats_contain_mime_type (site->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->context,
|
||||
&sdata,
|
||||
data->time);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_signal_emit_by_name (data->widget,
|
||||
"drag-data-received",
|
||||
data->context,
|
||||
&sdata,
|
||||
data->time);
|
||||
}
|
||||
|
||||
if (site && site->flags & GTK_DEST_DEFAULT_DROP)
|
||||
{
|
||||
|
||||
gtk_drag_finish (data->context,
|
||||
size > 0,
|
||||
(gdk_drag_context_get_selected_action (data->context) == GDK_ACTION_MOVE),
|
||||
data->time);
|
||||
}
|
||||
|
||||
g_object_unref (data->widget);
|
||||
g_slice_free (GtkDragGetData, data);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_drag_get_data_got_data (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
gssize written;
|
||||
|
||||
written = g_output_stream_splice_finish (G_OUTPUT_STREAM (source), result, NULL);
|
||||
if (written < 0)
|
||||
{
|
||||
gtk_drag_get_data_finish (data, NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_drag_get_data_finish (data,
|
||||
g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (source)),
|
||||
g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (source)));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_drag_get_data_got_stream (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkDragGetData *data = user_data;
|
||||
GInputStream *input_stream;
|
||||
GOutputStream *output_stream;
|
||||
|
||||
input_stream = gdk_drop_read_finish (GDK_DRAG_CONTEXT (source), &data->mime_type, result, NULL);
|
||||
if (input_stream == NULL)
|
||||
{
|
||||
gtk_drag_get_data_finish (data, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
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,
|
||||
data);
|
||||
g_object_unref (output_stream);
|
||||
g_object_unref (input_stream);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_drag_get_data: (method)
|
||||
* @widget: the widget that will receive the
|
||||
@ -351,25 +460,23 @@ gtk_drag_get_data (GtkWidget *widget,
|
||||
GdkAtom target,
|
||||
guint32 time_)
|
||||
{
|
||||
GtkWidget *selection_widget;
|
||||
GtkDragGetData *data;
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
|
||||
|
||||
selection_widget = gtk_drag_get_ipc_widget (widget);
|
||||
data = g_slice_new0 (GtkDragGetData);
|
||||
data->widget = g_object_ref (widget);
|
||||
data->context = context;
|
||||
data->mime_type = target;
|
||||
data->time = time_;
|
||||
|
||||
g_object_ref (context);
|
||||
g_object_ref (widget);
|
||||
|
||||
g_signal_connect (selection_widget, "selection-received",
|
||||
G_CALLBACK (gtk_drag_selection_received), widget);
|
||||
|
||||
g_object_set_data (G_OBJECT (selection_widget), I_("drag-context"), context);
|
||||
|
||||
gtk_selection_convert (selection_widget,
|
||||
gdk_drag_get_selection (context),
|
||||
target,
|
||||
time_);
|
||||
gdk_drop_read_async (context,
|
||||
(const gchar *[2]) { target, NULL },
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
gtk_drag_get_data_got_stream,
|
||||
data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user