[Spice-devel] [PATCH spice-gtk V5 2/3] file-xfer: handle "drag-data-received" signal

Dunrong Huang riegamaths at gmail.com
Sat Jan 5 02:59:19 PST 2013


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 should receive data which contains
file path, and call spice_main_file_copy_async() to transfer file to guest.

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

diff --git a/gtk/spice-widget.c b/gtk/spice-widget.c
index a8d3ce9..17adf8f 100644
--- a/gtk/spice-widget.c
+++ b/gtk/spice-widget.c
@@ -464,14 +464,60 @@ static gboolean grab_broken(SpiceDisplay *self, GdkEventGrabBroken *event,
     return false;
 }
 
+static void drag_data_received_callback(SpiceDisplay *self,
+                                        GdkDragContext *drag_context,
+                                        gint x,
+                                        gint y,
+                                        GtkSelectionData *data,
+                                        guint info,
+                                        guint time,
+                                        gpointer *user_data)
+{
+    int len;
+    char *buf;
+    gchar **file_urls;
+    int n_files;
+    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(self);
+    int i = 0;
+    GFile **files;
+
+    /* We get a buf like:
+     * file:///root/a.txt\r\nfile:///root/b.txt\r\n
+     */
+    SPICE_DEBUG("%s: drag a file", __FUNCTION__);
+    buf = (char *)gtk_selection_data_get_data_with_length(data, &len);
+    g_return_if_fail(buf != NULL);
+
+    file_urls = g_uri_list_extract_uris(buf);
+    n_files = g_strv_length(file_urls);
+    files = g_malloc0(sizeof(GFile *) * (n_files + 1));
+    for (i = 0; i < n_files; i++) {
+        files[i] = g_file_new_for_uri(file_urls[i]);
+    }
+    g_strfreev(file_urls);
+
+    spice_main_file_copy_async(d->main, files, 0, NULL, NULL,
+                               NULL, NULL, NULL);
+    for (i = 0; i < n_files; i++) {
+        g_object_unref(files[i]);
+    }
+    g_free(files);
+
+    gtk_drag_finish(drag_context, TRUE, FALSE, time);
+}
+
 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(drag_data_received_callback), NULL);
     gtk_widget_add_events(widget,
                           GDK_STRUCTURE_MASK |
                           GDK_POINTER_MOTION_MASK |
-- 
1.8.0



More information about the Spice-devel mailing list