[Spice-devel] [RFC] [PATCH spice-gtk 3/4] DND: handle "drag-data-received" signal

Dunrong Huang riegamaths at gmail.com
Mon Nov 5 01:01:17 PST 2012


When user drags a file to SpiceDisplay and drops it, a signal named
"drag-data-received" will be emitted, the signal will be received by
SpiceDisplay, then our signal handler will receive data which contains
file path, and call spice_dnd_process() to transfer file to guest.

Signed-off-by: Dunrong Huang <riegamaths at gmail.com>
---
 gtk/spice-widget.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/gtk/spice-widget.c b/gtk/spice-widget.c
index cdcff03..ecb3d4e 100644
--- a/gtk/spice-widget.c
+++ b/gtk/spice-widget.c
@@ -38,6 +38,7 @@
 #include "spice-widget-priv.h"
 #include "spice-gtk-session-priv.h"
 #include "vncdisplaykeymap.h"
+#include "spice-dnd.h"
 
 #include "glib-compat.h"
 
@@ -464,14 +465,61 @@ static gboolean grab_broken(SpiceDisplay *self, GdkEventGrabBroken *event,
     return false;
 }
 
+/* TODO: support transfering multiple files and directories. */
+static void dnd_receive(SpiceDisplay *self, GdkDragContext *drag_context, gint x,
+                        gint y, GtkSelectionData *data, guint info,
+                        guint time, gpointer *user_data)
+{
+    int len;
+    char *uri = NULL;
+    char *buf;
+    int i;
+    GFile *f = NULL;
+    char *path = NULL;
+
+    buf = (char *)gtk_selection_data_get_data_with_length(data, &len);
+    if (buf == NULL) {
+        goto done;
+    }
+
+    /* original uri may terminate with network proper \r\n
+       e.g. file:///root/example.txt\r\n, strip \r\n */
+    uri = g_malloc0(len + 1);
+    memcpy(uri, buf, len);
+    i = len - 1;
+    while (uri[i] == '\n' || uri[i] == '\r') {
+        uri[i] = '\0';
+        if (--i < 0)
+            break;
+    }
+
+    /* Gets the absolute pathname */
+    f = g_file_new_for_uri(uri);
+    path = g_file_get_path(f);
+    g_object_unref(f);
+    if (!path) {
+        goto done;
+    }
+
+    spice_dnd_process(self, path);
+
+done:
+    gtk_drag_finish(drag_context, TRUE, FALSE, time);
+    g_free(path);
+    g_free(uri);
+}
+
 static void spice_display_init(SpiceDisplay *display)
 {
     GtkWidget *widget = GTK_WIDGET(display);
     SpiceDisplayPrivate *d;
+    GtkTargetEntry targets = {"text/plain", 0, 0};
 
     d = display->priv = SPICE_DISPLAY_GET_PRIVATE(display);
 
     g_signal_connect(display, "grab-broken-event", G_CALLBACK(grab_broken), NULL);
+    gtk_drag_dest_set(widget, GTK_DEST_DEFAULT_ALL, &targets, 1, GDK_ACTION_COPY);
+    g_signal_connect(display, "drag-data-received", G_CALLBACK(dnd_receive), NULL);
     gtk_widget_add_events(widget,
                           GDK_STRUCTURE_MASK |
                           GDK_POINTER_MOTION_MASK |
-- 
1.7.12.4



More information about the Spice-devel mailing list