Tomas Bzatek 954e163
diff -up nautilus-2.25.1/libnautilus-private/nautilus-tree-view-drag-dest.c.orig nautilus-2.25.1/libnautilus-private/nautilus-tree-view-drag-dest.c
Tomas Bzatek 954e163
--- nautilus-2.25.1/libnautilus-private/nautilus-tree-view-drag-dest.c.orig	2008-10-06 11:54:32.000000000 +0200
Tomas Bzatek 954e163
+++ nautilus-2.25.1/libnautilus-private/nautilus-tree-view-drag-dest.c	2008-12-04 11:35:04.174034560 +0100
Tomas Bzatek 03f2335
@@ -21,6 +21,7 @@
Tomas Bzatek 03f2335
  * Boston, MA 02111-1307, USA.
Tomas Bzatek 03f2335
  * 
Tomas Bzatek 03f2335
  * Author: Dave Camp <dave@ximian.com>
Tomas Bzatek 03f2335
+ * XDS support: Benedikt Meurer <benny@xfce.org> (adapted by Amos Brocco <amos.brocco@unifr.ch>)
Tomas Bzatek 03f2335
  */
Tomas Bzatek 03f2335
 
Tomas Bzatek 03f2335
 /* nautilus-tree-view-drag-dest.c: Handles drag and drop for treeviews which 
Tomas Bzatek 954e163
@@ -33,9 +34,13 @@
Tomas Bzatek 954e163
 #include <eel/eel-gtk-macros.h>
Tomas Bzatek 72afc33
 #include <gtk/gtk.h>
Tomas Bzatek 72afc33
 #include "nautilus-file-dnd.h"
Tomas Bzatek 72afc33
+#include "nautilus-file-changes-queue.h"
Tomas Bzatek 03f2335
 #include "nautilus-icon-dnd.h"
Tomas Bzatek 03f2335
 #include "nautilus-link.h"
Tomas Bzatek 03f2335
 #include "nautilus-marshal.h"
Tomas Bzatek 03f2335
+#include "nautilus-debug-log.h"
Tomas Bzatek 03f2335
+#include <stdio.h>
Tomas Bzatek 03f2335
+#include <string.h>
Tomas Bzatek 03f2335
 
Tomas Bzatek 03f2335
 #define AUTO_SCROLL_MARGIN 20
Tomas Bzatek 03f2335
 
Tomas Bzatek 954e163
@@ -54,6 +59,8 @@ struct _NautilusTreeViewDragDestDetails 
Tomas Bzatek 03f2335
 	guint highlight_id;
Tomas Bzatek 03f2335
 	guint scroll_id;
Tomas Bzatek 03f2335
 	guint expand_id;
Tomas Bzatek 03f2335
+	
Tomas Bzatek 72afc33
+	char *direct_save_uri;
Tomas Bzatek 03f2335
 };
Tomas Bzatek 03f2335
 
Tomas Bzatek 03f2335
 enum {
Tomas Bzatek 954e163
@@ -80,7 +87,8 @@ static const GtkTargetEntry drag_types [
Tomas Bzatek 03f2335
 	/* prefer "_NETSCAPE_URL" over "text/uri-list" to satisfy web browsers. */
Tomas Bzatek 03f2335
 	{ NAUTILUS_ICON_DND_NETSCAPE_URL_TYPE, 0, NAUTILUS_ICON_DND_NETSCAPE_URL },
Tomas Bzatek 03f2335
 	{ NAUTILUS_ICON_DND_URI_LIST_TYPE, 0, NAUTILUS_ICON_DND_URI_LIST },
Tomas Bzatek 03f2335
-	{ NAUTILUS_ICON_DND_KEYWORD_TYPE, 0, NAUTILUS_ICON_DND_KEYWORD }
Tomas Bzatek 03f2335
+	{ NAUTILUS_ICON_DND_KEYWORD_TYPE, 0, NAUTILUS_ICON_DND_KEYWORD },
Tomas Bzatek 03f2335
+	{ NAUTILUS_ICON_DND_XDNDDIRECTSAVE_TYPE, 0, NAUTILUS_ICON_DND_XDNDDIRECTSAVE }, /* XDS Protocol Type */
Tomas Bzatek 03f2335
 };
Tomas Bzatek 03f2335
 
Tomas Bzatek 03f2335
 
Tomas Bzatek 954e163
@@ -244,6 +252,12 @@ get_drag_data (NautilusTreeViewDragDest 
Tomas Bzatek 72afc33
 	target = gtk_drag_dest_find_target (GTK_WIDGET (dest->details->tree_view), 
Tomas Bzatek 72afc33
 					    context, 
Tomas Bzatek 72afc33
 					    NULL);
Tomas Bzatek 72afc33
+	if (target == gdk_atom_intern (NAUTILUS_ICON_DND_XDNDDIRECTSAVE_TYPE, FALSE) &&
Tomas Bzatek 72afc33
+	    !dest->details->drop_occurred) {
Tomas Bzatek 72afc33
+		dest->details->drag_type = NAUTILUS_ICON_DND_XDNDDIRECTSAVE;
Tomas Bzatek 72afc33
+		dest->details->have_drag_data = TRUE;
Tomas Bzatek 72afc33
+		return;
Tomas Bzatek 72afc33
+	}
Tomas Bzatek 72afc33
 
Tomas Bzatek 72afc33
 	gtk_drag_get_data (GTK_WIDGET (dest->details->tree_view),
Tomas Bzatek 72afc33
 			   context, target, time);
Tomas Bzatek 954e163
@@ -263,6 +277,9 @@ free_drag_data (NautilusTreeViewDragDest
Tomas Bzatek 72afc33
 		nautilus_drag_destroy_selection_list (dest->details->drag_list);
Tomas Bzatek 72afc33
 		dest->details->drag_list = NULL;
Tomas Bzatek 72afc33
 	}
Tomas Bzatek 72afc33
+
Tomas Bzatek 72afc33
+	g_free (dest->details->direct_save_uri);
Tomas Bzatek 72afc33
+	dest->details->direct_save_uri = NULL;
Tomas Bzatek 72afc33
 }
Tomas Bzatek 72afc33
 
Tomas Bzatek 72afc33
 static char *
Tomas Bzatek 954e163
@@ -407,6 +424,7 @@ get_drop_action (NautilusTreeViewDragDes
Tomas Bzatek 03f2335
 		return context->suggested_action;
Tomas Bzatek 03f2335
 
Tomas Bzatek 03f2335
 	case NAUTILUS_ICON_DND_TEXT:
Tomas Bzatek 03f2335
+	case NAUTILUS_ICON_DND_XDNDDIRECTSAVE:
Tomas Bzatek 03f2335
 		return GDK_ACTION_COPY;
Tomas Bzatek 03f2335
 
Tomas Bzatek 03f2335
 	case NAUTILUS_ICON_DND_KEYWORD:
Tomas Bzatek 954e163
@@ -717,6 +735,35 @@ receive_dropped_keyword (NautilusTreeVie
Tomas Bzatek 72afc33
 	g_free (drop_target_uri);
Tomas Bzatek 72afc33
 }
Tomas Bzatek 72afc33
 
Tomas Bzatek 72afc33
+static void
Tomas Bzatek 72afc33
+receive_xds (NautilusTreeViewDragDest *dest,
Tomas Bzatek 72afc33
+	     GdkDragContext *context,
Tomas Bzatek 72afc33
+	     int x, int y)
Tomas Bzatek 72afc33
+{
Tomas Bzatek 72afc33
+	GFile *location;
Tomas Bzatek 72afc33
+
Tomas Bzatek 72afc33
+	/* Indicate that we don't provide "F" fallback */
Tomas Bzatek 72afc33
+	if (G_UNLIKELY (dest->details->drag_data->format == 8 
Tomas Bzatek 72afc33
+			&& dest->details->drag_data->length == 1 
Tomas Bzatek 72afc33
+			&& dest->details->drag_data->data[0] == 'F')) {
Tomas Bzatek 72afc33
+		gdk_property_change (GDK_DRAWABLE (context->source_window),
Tomas Bzatek 72afc33
+				     gdk_atom_intern (NAUTILUS_ICON_DND_XDNDDIRECTSAVE_TYPE, FALSE),
Tomas Bzatek 72afc33
+				     gdk_atom_intern ("text/plain", FALSE), 8,
Tomas Bzatek 72afc33
+				     GDK_PROP_MODE_REPLACE, (const guchar *) "", 0);
Tomas Bzatek 72afc33
+	} else if (G_LIKELY (dest->details->drag_data->format == 8 
Tomas Bzatek 72afc33
+			     && dest->details->drag_data->length == 1 
Tomas Bzatek 72afc33
+			     && dest->details->drag_data->data[0] == 'S')) {
Tomas Bzatek 72afc33
+		g_assert (dest->details->direct_save_uri != NULL);
Tomas Bzatek 72afc33
+		location = g_file_new_for_uri (dest->details->direct_save_uri);
Tomas Bzatek 72afc33
+
Tomas Bzatek 72afc33
+		nautilus_file_changes_queue_file_added (location);
Tomas Bzatek 72afc33
+		nautilus_file_changes_consume_changes (TRUE);
Tomas Bzatek 72afc33
+
Tomas Bzatek 72afc33
+		g_object_unref (location);
Tomas Bzatek 72afc33
+	}
Tomas Bzatek 72afc33
+}
Tomas Bzatek 72afc33
+
Tomas Bzatek 72afc33
+
Tomas Bzatek 72afc33
 static gboolean
Tomas Bzatek 72afc33
 drag_data_received_callback (GtkWidget *widget,
Tomas Bzatek 72afc33
 			     GdkDragContext *context,
Tomas Bzatek 954e163
@@ -766,6 +813,10 @@ drag_data_received_callback (GtkWidget *
Tomas Bzatek 03f2335
 			receive_dropped_keyword (dest, context, x, y);
Tomas Bzatek 03f2335
 			success = TRUE;
Tomas Bzatek 03f2335
 			break;
Tomas Bzatek 03f2335
+		case NAUTILUS_ICON_DND_XDNDDIRECTSAVE:
Tomas Bzatek 72afc33
+			receive_xds (dest, context, x, y);
Tomas Bzatek 03f2335
+			success = TRUE;
Tomas Bzatek 03f2335
+			break;
Tomas Bzatek 03f2335
 		}
Tomas Bzatek 03f2335
 
Tomas Bzatek 03f2335
 		dest->details->drop_occurred = FALSE;
Tomas Bzatek 954e163
@@ -781,6 +832,79 @@ drag_data_received_callback (GtkWidget *
Tomas Bzatek 72afc33
 	return TRUE;
Tomas Bzatek 72afc33
 }
Tomas Bzatek 72afc33
 
Tomas Bzatek 72afc33
+static char *
Tomas Bzatek 72afc33
+get_direct_save_filename (GdkDragContext *context)
Tomas Bzatek 72afc33
+{
Tomas Bzatek 72afc33
+	guchar *prop_text;
Tomas Bzatek 72afc33
+	gint prop_len;
Tomas Bzatek 72afc33
+	
Tomas Bzatek 72afc33
+	if (!gdk_property_get (context->source_window, gdk_atom_intern (NAUTILUS_ICON_DND_XDNDDIRECTSAVE_TYPE, FALSE),
Tomas Bzatek 72afc33
+			       gdk_atom_intern ("text/plain", FALSE), 0, 1024, FALSE, NULL, NULL,
Tomas Bzatek 72afc33
+			       &prop_len, &prop_text) && prop_text != NULL) {
Tomas Bzatek 72afc33
+		return NULL;
Tomas Bzatek 72afc33
+	}
Tomas Bzatek 72afc33
+
Tomas Bzatek 72afc33
+	/* Zero-terminate the string */
Tomas Bzatek 72afc33
+	prop_text = g_realloc (prop_text, prop_len + 1);
Tomas Bzatek 72afc33
+	prop_text[prop_len] = '\0';
Tomas Bzatek 72afc33
+
Tomas Bzatek 72afc33
+	/* Verify that the file name provided by the source is valid */
Tomas Bzatek 72afc33
+	if (*prop_text == '\0' ||
Tomas Bzatek 72afc33
+	    strchr ((const gchar *) prop_text, G_DIR_SEPARATOR) != NULL) {
Tomas Bzatek 72afc33
+		nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_USER,
Tomas Bzatek 72afc33
+				    "Invalid filename provided by XDS drag site");
Tomas Bzatek 72afc33
+		g_free (prop_text);
Tomas Bzatek 72afc33
+		return NULL;
Tomas Bzatek 72afc33
+	}
Tomas Bzatek 72afc33
+
Tomas Bzatek 72afc33
+	return prop_text;
Tomas Bzatek 72afc33
+}
Tomas Bzatek 72afc33
+
Tomas Bzatek 72afc33
+static gboolean
Tomas Bzatek 72afc33
+set_direct_save_uri (NautilusTreeViewDragDest *dest,
Tomas Bzatek 72afc33
+		     GdkDragContext *context,
Tomas Bzatek 72afc33
+		     int x, int y)
Tomas Bzatek 72afc33
+{
Tomas Bzatek 72afc33
+	GFile *base, *child;
Tomas Bzatek 72afc33
+	char *drop_uri;
Tomas Bzatek 72afc33
+	char *filename, *uri;
Tomas Bzatek 72afc33
+
Tomas Bzatek 72afc33
+	g_assert (dest->details->direct_save_uri == NULL);
Tomas Bzatek 72afc33
+
Tomas Bzatek 72afc33
+	uri = NULL;
Tomas Bzatek 72afc33
+
Tomas Bzatek 72afc33
+	drop_uri = get_drop_target_uri_at_pos (dest, x, y);
Tomas Bzatek 72afc33
+	if (drop_uri != NULL) {
Tomas Bzatek 72afc33
+		filename = get_direct_save_filename (context);
Tomas Bzatek 72afc33
+		if (filename != NULL) {
Tomas Bzatek 72afc33
+			/* Resolve relative path */
Tomas Bzatek 72afc33
+			base = g_file_new_for_uri (drop_uri);
Tomas Bzatek 72afc33
+			child = g_file_get_child (base, filename);
Tomas Bzatek 72afc33
+			uri = g_file_get_uri (child);
Tomas Bzatek 72afc33
+
Tomas Bzatek 72afc33
+			g_object_unref (base);
Tomas Bzatek 72afc33
+			g_object_unref (child);
Tomas Bzatek 72afc33
+
Tomas Bzatek 72afc33
+			/* Change the property */
Tomas Bzatek 72afc33
+			gdk_property_change (GDK_DRAWABLE (context->source_window),
Tomas Bzatek 72afc33
+					     gdk_atom_intern (NAUTILUS_ICON_DND_XDNDDIRECTSAVE_TYPE, FALSE),
Tomas Bzatek 72afc33
+					     gdk_atom_intern ("text/plain", FALSE), 8,
Tomas Bzatek 72afc33
+					     GDK_PROP_MODE_REPLACE, (const guchar *) uri,
Tomas Bzatek 72afc33
+					     strlen (uri));
Tomas Bzatek 72afc33
+
Tomas Bzatek 72afc33
+			dest->details->direct_save_uri = uri;
Tomas Bzatek 72afc33
+		} else {
Tomas Bzatek 72afc33
+			nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_USER,
Tomas Bzatek 72afc33
+					    "Invalid filename provided by XDS drag site");
Tomas Bzatek 72afc33
+		}
Tomas Bzatek 72afc33
+	} else {
Tomas Bzatek 72afc33
+		nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_USER,
Tomas Bzatek 72afc33
+				    "Could not retrieve XDS drop destination");
Tomas Bzatek 72afc33
+	}
Tomas Bzatek 72afc33
+
Tomas Bzatek 72afc33
+	return uri != NULL;
Tomas Bzatek 72afc33
+}
Tomas Bzatek 72afc33
+
Tomas Bzatek 72afc33
 static gboolean
Tomas Bzatek 72afc33
 drag_drop_callback (GtkWidget *widget,
Tomas Bzatek 72afc33
 		    GdkDragContext *context,
Tomas Bzatek 954e163
@@ -790,8 +914,24 @@ drag_drop_callback (GtkWidget *widget,
Tomas Bzatek 03f2335
 		    gpointer data)
Tomas Bzatek 03f2335
 {
Tomas Bzatek 03f2335
 	NautilusTreeViewDragDest *dest;
Tomas Bzatek 03f2335
+	guint info;
Tomas Bzatek 03f2335
+	GdkAtom target;
Tomas Bzatek 03f2335
 
Tomas Bzatek 03f2335
 	dest = NAUTILUS_TREE_VIEW_DRAG_DEST (data);
Tomas Bzatek 03f2335
+	
Tomas Bzatek 03f2335
+	target = gtk_drag_dest_find_target (GTK_WIDGET (dest->details->tree_view), 
Tomas Bzatek 03f2335
+					    context, 
Tomas Bzatek 03f2335
+					    NULL);
Tomas Bzatek 72afc33
+	if (target == GDK_NONE) {
Tomas Bzatek 72afc33
+		return FALSE;
Tomas Bzatek 72afc33
+	}
Tomas Bzatek 72afc33
+
Tomas Bzatek 03f2335
+	info = dest->details->drag_type;
Tomas Bzatek 72afc33
+
Tomas Bzatek 72afc33
+	if (info == NAUTILUS_ICON_DND_XDNDDIRECTSAVE &&
Tomas Bzatek 72afc33
+	    !set_direct_save_uri (dest, context, x, y)) {
Tomas Bzatek 03f2335
+		return FALSE;
Tomas Bzatek 03f2335
+	}
Tomas Bzatek 03f2335
 
Tomas Bzatek 03f2335
 	dest->details->drop_occurred = TRUE;
Tomas Bzatek 03f2335