[nautilus] Complete XDS support



commit a76fe6975c0e3a31aa8d8ab4ddf3b7afbafbe274
Author: James Dietrich <jdietrch fastmail fm>
Date:   Tue Oct 27 19:10:57 2009 -0400

    Complete XDS support
    
    https://bugzilla.gnome.org/show_bug.cgi?id=585790

 libnautilus-private/nautilus-dnd.h                 |    2 +
 libnautilus-private/nautilus-file-dnd.c            |    1 +
 libnautilus-private/nautilus-file-operations.c     |   10 ++-
 libnautilus-private/nautilus-file-operations.h     |    1 +
 libnautilus-private/nautilus-icon-container.c      |   17 ++++
 libnautilus-private/nautilus-icon-container.h      |    8 ++
 libnautilus-private/nautilus-icon-dnd.c            |   71 ++++++++++++++----
 libnautilus-private/nautilus-marshal.list          |    1 +
 libnautilus-private/nautilus-tree-view-drag-dest.c |   78 +++++++++++++++++---
 libnautilus-private/nautilus-tree-view-drag-dest.h |    8 ++
 src/file-manager/fm-directory-view.c               |   58 ++++++++++++++-
 src/file-manager/fm-directory-view.h               |    8 ++
 src/file-manager/fm-icon-view.c                    |   11 +++
 src/file-manager/fm-list-view.c                    |   12 +++
 14 files changed, 255 insertions(+), 31 deletions(-)
---
diff --git a/libnautilus-private/nautilus-dnd.h b/libnautilus-private/nautilus-dnd.h
index 353a1f8..633054c 100644
--- a/libnautilus-private/nautilus-dnd.h
+++ b/libnautilus-private/nautilus-dnd.h
@@ -40,6 +40,7 @@
 #define NAUTILUS_ICON_DND_RESET_BACKGROUND_TYPE "x-special/gnome-reset-background"
 #define NAUTILUS_ICON_DND_ROOTWINDOW_DROP_TYPE	"application/x-rootwindow-drop"
 #define NAUTILUS_ICON_DND_XDNDDIRECTSAVE_TYPE	"XdndDirectSave0" /* XDS Protocol Type */
+#define NAUTILUS_ICON_DND_RAW_TYPE	"application/octet-stream"
 
 /* Item of the drag selection list */
 typedef struct {
@@ -60,6 +61,7 @@ typedef enum {
 	NAUTILUS_ICON_DND_TEXT,
 	NAUTILUS_ICON_DND_RESET_BACKGROUND,
 	NAUTILUS_ICON_DND_XDNDDIRECTSAVE,
+	NAUTILUS_ICON_DND_RAW,
 	NAUTILUS_ICON_DND_ROOTWINDOW_DROP
 } NautilusIconDndTargetType;
 
diff --git a/libnautilus-private/nautilus-file-dnd.c b/libnautilus-private/nautilus-file-dnd.c
index 5502857..6901b83 100644
--- a/libnautilus-private/nautilus-file-dnd.c
+++ b/libnautilus-private/nautilus-file-dnd.c
@@ -122,6 +122,7 @@ nautilus_drag_can_accept_info (NautilusFile *drop_target_item,
 			return nautilus_drag_can_accept_files (drop_target_item);
 
 		case NAUTILUS_ICON_DND_XDNDDIRECTSAVE:
+		case NAUTILUS_ICON_DND_RAW:
 			return nautilus_drag_can_accept_files (drop_target_item); /* Check if we can accept files at this location */
 
 		case NAUTILUS_ICON_DND_KEYWORD:
diff --git a/libnautilus-private/nautilus-file-operations.c b/libnautilus-private/nautilus-file-operations.c
index f9ee6e0..76dcaaf 100644
--- a/libnautilus-private/nautilus-file-operations.c
+++ b/libnautilus-private/nautilus-file-operations.c
@@ -117,6 +117,7 @@ typedef struct {
 	gboolean make_dir;
 	GFile *src;
 	char *src_data;
+	int length;
 	GdkPoint position;
 	gboolean has_position;
 	GFile *created_file;
@@ -5638,6 +5639,7 @@ create_job (GIOSchedulerJob *io_job,
 	char *primary, *secondary, *details;
 	int response;
 	char *data;
+	int length;
 	GFileOutputStream *out;
 	gboolean handled_invalid_filename;
 	int max_length;
@@ -5711,8 +5713,10 @@ create_job (GIOSchedulerJob *io_job,
 					   &error);
 		} else {
 			data = "";
+			length = 0;
 			if (job->src_data) {
 				data = job->src_data;
+				length = job->length;
 			}
 
 			out = g_file_create (dest,
@@ -5721,7 +5725,7 @@ create_job (GIOSchedulerJob *io_job,
 					     &error);
 			if (out) {
 				res = g_output_stream_write_all (G_OUTPUT_STREAM (out),
-								 data, strlen (data),
+								 data, length,
 								 NULL,
 								 common->cancellable,
 								 &error);
@@ -5944,6 +5948,7 @@ nautilus_file_operations_new_file (GtkWidget *parent_view,
 				   const char *parent_dir,
 				   const char *target_filename,
 				   const char *initial_contents,
+				   int length,
 				   NautilusCreateCallback done_callback,
 				   gpointer done_callback_data)
 {
@@ -5963,7 +5968,8 @@ nautilus_file_operations_new_file (GtkWidget *parent_view,
 		job->position = *target_point;
 		job->has_position = TRUE;
 	}
-	job->src_data = g_strdup (initial_contents);
+	job->src_data = g_memdup (initial_contents, length);
+	job->length = length;
 	job->filename = g_strdup (target_filename);
 
 	g_io_scheduler_push_job (create_job,
diff --git a/libnautilus-private/nautilus-file-operations.h b/libnautilus-private/nautilus-file-operations.h
index 9d1410e..7c19e25 100644
--- a/libnautilus-private/nautilus-file-operations.h
+++ b/libnautilus-private/nautilus-file-operations.h
@@ -61,6 +61,7 @@ void nautilus_file_operations_new_file    (GtkWidget                 *parent_vie
 					   const char                *parent_dir,
 					   const char                *target_filename,
 					   const char                *initial_contents,
+					   int                        length,
 					   NautilusCreateCallback     done_callback,
 					   gpointer                   data);
 void nautilus_file_operations_new_file_from_template (GtkWidget               *parent_view,
diff --git a/libnautilus-private/nautilus-icon-container.c b/libnautilus-private/nautilus-icon-container.c
index 8c07f26..03af3a9 100644
--- a/libnautilus-private/nautilus-icon-container.c
+++ b/libnautilus-private/nautilus-icon-container.c
@@ -270,6 +270,7 @@ enum {
 	HANDLE_NETSCAPE_URL,
 	HANDLE_URI_LIST,
 	HANDLE_TEXT,
+	HANDLE_RAW,
 	PREVIEW,
 	SELECTION_CHANGED,
 	ICON_ADDED,
@@ -5855,6 +5856,22 @@ nautilus_icon_container_class_init (NautilusIconContainerClass *class)
 				GDK_TYPE_DRAG_ACTION,
 				G_TYPE_INT,
 				G_TYPE_INT);
+	signals[HANDLE_RAW]
+		= g_signal_new ("handle_raw",
+		                G_TYPE_FROM_CLASS (class),
+		                G_SIGNAL_RUN_LAST,
+		                G_STRUCT_OFFSET (NautilusIconContainerClass,
+						 handle_raw),
+		                NULL, NULL,
+		                nautilus_marshal_VOID__POINTER_INT_STRING_STRING_ENUM_INT_INT,
+		                G_TYPE_NONE, 7,
+				G_TYPE_POINTER,
+				G_TYPE_INT,
+				G_TYPE_STRING,
+				G_TYPE_STRING,
+				GDK_TYPE_DRAG_ACTION,
+				G_TYPE_INT,
+				G_TYPE_INT);
 	signals[GET_CONTAINER_URI] 
 		= g_signal_new ("get_container_uri",
 		                G_TYPE_FROM_CLASS (class),
diff --git a/libnautilus-private/nautilus-icon-container.h b/libnautilus-private/nautilus-icon-container.h
index d5f4473..0ec896d 100644
--- a/libnautilus-private/nautilus-icon-container.h
+++ b/libnautilus-private/nautilus-icon-container.h
@@ -120,6 +120,14 @@ typedef struct {
 						   GdkDragAction action,
 						   int x,
 						   int y);
+	void	     (* handle_raw)		  (NautilusIconContainer *container,
+						   char *raw_data,
+						   int length,
+						   const char *target_uri,
+						   const char *direct_save_uri,
+						   GdkDragAction action,
+						   int x,
+						   int y);
 
 	/* Queries on the container for subclass/client.
 	 * These must be implemented. The default "do nothing" is not good enough.
diff --git a/libnautilus-private/nautilus-icon-dnd.c b/libnautilus-private/nautilus-icon-dnd.c
index e2ad56c..8a1283f 100644
--- a/libnautilus-private/nautilus-icon-dnd.c
+++ b/libnautilus-private/nautilus-icon-dnd.c
@@ -75,6 +75,7 @@ static const GtkTargetEntry drop_types [] = {
 	{ NAUTILUS_ICON_DND_KEYWORD_TYPE, 0, NAUTILUS_ICON_DND_KEYWORD },
 	{ NAUTILUS_ICON_DND_RESET_BACKGROUND_TYPE,  0, NAUTILUS_ICON_DND_RESET_BACKGROUND },
 	{ NAUTILUS_ICON_DND_XDNDDIRECTSAVE_TYPE, 0, NAUTILUS_ICON_DND_XDNDDIRECTSAVE }, /* XDS Protocol Type */
+	{ NAUTILUS_ICON_DND_RAW_TYPE, 0, NAUTILUS_ICON_DND_RAW },
 	/* Must be last: */
 	{ NAUTILUS_ICON_DND_ROOTWINDOW_DROP_TYPE,  0, NAUTILUS_ICON_DND_ROOTWINDOW_DROP }
 };
@@ -383,7 +384,7 @@ get_direct_save_filename (GdkDragContext *context)
 			       &prop_len, &prop_text) && prop_text != NULL) {
 		return NULL;
 	}
-	
+
 	/* Zero-terminate the string */
 	prop_text = g_realloc (prop_text, prop_len + 1);
 	prop_text[prop_len] = '\0';
@@ -773,6 +774,29 @@ receive_dropped_text (NautilusIconContainer *container, const char *text, GdkDra
 	g_free (drop_target);
 }
 
+/* handle dropped raw data */
+static void
+receive_dropped_raw (NautilusIconContainer *container, const char *raw_data, int length, const char *direct_save_uri, GdkDragContext *context, int x, int y)
+{
+	char *drop_target;
+
+	if (raw_data == NULL) {
+		return;
+	}
+
+	drop_target = nautilus_icon_container_find_drop_target (container, context, x, y, NULL, TRUE);
+
+	g_signal_emit_by_name (container, "handle_raw",
+			       raw_data,
+			       length,
+			       drop_target,
+			       direct_save_uri,
+			       context->action,
+			       x, y);
+
+	g_free (drop_target);
+}
+
 static int
 auto_scroll_timeout_callback (gpointer data)
 {
@@ -1304,6 +1328,7 @@ nautilus_icon_container_get_drop_action (NautilusIconContainer *container,
 
 	case NAUTILUS_ICON_DND_TEXT:
 	case NAUTILUS_ICON_DND_XDNDDIRECTSAVE:
+	case NAUTILUS_ICON_DND_RAW:
 		*action = GDK_ACTION_COPY;
 		break;
 	}
@@ -1699,6 +1724,8 @@ drag_data_received_callback (GtkWidget *widget,
     	NautilusDragInfo *drag_info;
 	EelBackground *background;
 	char *tmp;
+	const char *tmp_raw;
+	int length;
 	gboolean success;
 
 	drag_info = &(NAUTILUS_ICON_CONTAINER (widget)->details->dnd_info->drag_info);
@@ -1717,6 +1744,7 @@ drag_data_received_callback (GtkWidget *widget,
 	case NAUTILUS_ICON_DND_TEXT:
 	case NAUTILUS_ICON_DND_RESET_BACKGROUND:
 	case NAUTILUS_ICON_DND_XDNDDIRECTSAVE:
+	case NAUTILUS_ICON_DND_RAW:
 		/* Save the data so we can do the actual work on drop. */
 		if (drag_info->selection_data != NULL) {
 			gtk_selection_data_free (drag_info->selection_data);
@@ -1786,6 +1814,15 @@ drag_data_received_callback (GtkWidget *widget,
 			success = TRUE;
 			g_free (tmp);
 			break;
+		case NAUTILUS_ICON_DND_RAW:
+			length = gtk_selection_data_get_length (data);
+			tmp_raw = gtk_selection_data_get_data (data);
+			receive_dropped_raw
+				(NAUTILUS_ICON_CONTAINER (widget),
+				 tmp_raw, length, drag_info->direct_save_uri,
+				 context, x, y);
+			success = TRUE;
+			break;
 		case NAUTILUS_ICON_DND_RESET_BACKGROUND:
 			background = eel_get_widget_background (widget);
 			if (background != NULL) {
@@ -1797,18 +1834,18 @@ drag_data_received_callback (GtkWidget *widget,
 			/* Do nothing, everything is done by the sender */
 			break;
 		case NAUTILUS_ICON_DND_XDNDDIRECTSAVE:
-			/* Indicate that we don't provide "F" fallback */
-          		if (drag_info->selection_data->format == 8 &&
+			if (drag_info->selection_data->format == 8 &&
 			    drag_info->selection_data->length == 1 &&
 			    drag_info->selection_data->data[0] == 'F') {
-	              		gdk_property_change (GDK_DRAWABLE (context->source_window),
-						     gdk_atom_intern (NAUTILUS_ICON_DND_XDNDDIRECTSAVE_TYPE, FALSE),
-						     gdk_atom_intern ("text/plain", FALSE), 8,
-						     GDK_PROP_MODE_REPLACE, (const guchar *) "", 0);
-            		} else if (drag_info->selection_data->format == 8 &&
-				   drag_info->selection_data->length == 1 &&
-				   drag_info->selection_data->data[0] == 'S' &&
-				   drag_info->direct_save_uri != NULL) {
+				gtk_drag_get_data (widget, context,
+				                  gdk_atom_intern (NAUTILUS_ICON_DND_RAW_TYPE,
+				                                   FALSE),
+				                  time);
+				return;
+			} else if (drag_info->selection_data->format == 8 &&
+			           drag_info->selection_data->length == 1 &&
+			           drag_info->selection_data->data[0] == 'S' &&
+			           drag_info->direct_save_uri != NULL) {
 				GdkPoint p;
 				GFile *location;
 
@@ -1816,13 +1853,15 @@ drag_data_received_callback (GtkWidget *widget,
 
 				nautilus_file_changes_queue_file_added (location);
 				p.x = x; p.y = y;
-				nautilus_file_changes_queue_schedule_position_set (location,
-										   p,
-										   gdk_screen_get_number (gtk_widget_get_screen (widget)));
+				nautilus_file_changes_queue_schedule_position_set (
+				                 location,
+				                 p,
+				                 gdk_screen_get_number (
+				                             gtk_widget_get_screen (widget)));
 				g_object_unref (location);
 				nautilus_file_changes_consume_changes (TRUE);
-            		}
-		        success = TRUE;
+				success = TRUE;
+			}
 			break;
 		}
 		gtk_drag_finish (context, success, FALSE, time);
diff --git a/libnautilus-private/nautilus-marshal.list b/libnautilus-private/nautilus-marshal.list
index 0279047..6eaf200 100644
--- a/libnautilus-private/nautilus-marshal.list
+++ b/libnautilus-private/nautilus-marshal.list
@@ -19,3 +19,4 @@ VOID:POINTER,STRING,ENUM,INT,INT
 VOID:STRING,STRING,ENUM,INT,INT
 VOID:STRING,ENUM,INT,INT
 VOID:STRING,STRING
+VOID:POINTER,INT,STRING,STRING,ENUM,INT,INT
diff --git a/libnautilus-private/nautilus-tree-view-drag-dest.c b/libnautilus-private/nautilus-tree-view-drag-dest.c
index 20646ef..7e00e51 100644
--- a/libnautilus-private/nautilus-tree-view-drag-dest.c
+++ b/libnautilus-private/nautilus-tree-view-drag-dest.c
@@ -70,6 +70,7 @@ enum {
 	HANDLE_NETSCAPE_URL,
 	HANDLE_URI_LIST,
 	HANDLE_TEXT,
+	HANDLE_RAW,
 	LAST_SIGNAL
 };
 
@@ -89,6 +90,7 @@ static const GtkTargetEntry drag_types [] = {
 	{ NAUTILUS_ICON_DND_URI_LIST_TYPE, 0, NAUTILUS_ICON_DND_URI_LIST },
 	{ NAUTILUS_ICON_DND_KEYWORD_TYPE, 0, NAUTILUS_ICON_DND_KEYWORD },
 	{ NAUTILUS_ICON_DND_XDNDDIRECTSAVE_TYPE, 0, NAUTILUS_ICON_DND_XDNDDIRECTSAVE }, /* XDS Protocol Type */
+	{ NAUTILUS_ICON_DND_RAW_TYPE, 0, NAUTILUS_ICON_DND_RAW }
 };
 
 
@@ -431,6 +433,7 @@ get_drop_action (NautilusTreeViewDragDest *dest,
 		return context->suggested_action;
 
 	case NAUTILUS_ICON_DND_TEXT:
+	case NAUTILUS_ICON_DND_RAW:
 	case NAUTILUS_ICON_DND_XDNDDIRECTSAVE:
 		return GDK_ACTION_COPY;
 
@@ -699,6 +702,29 @@ receive_dropped_text (NautilusTreeViewDragDest *dest,
 	g_free (drop_target);
 }
 
+static void
+receive_dropped_raw (NautilusTreeViewDragDest *dest,
+		      const char *raw_data, int length,
+		      GdkDragContext *context,
+		      int x, int y)
+{
+	char *drop_target;
+
+	if (!dest->details->drag_data) {
+		return;
+	}
+
+	drop_target = get_drop_target_uri_at_pos (dest, x, y);
+	g_assert (drop_target != NULL);
+
+	g_signal_emit (dest, signals[HANDLE_RAW], 0,
+		       raw_data, length, drop_target,
+		       dest->details->direct_save_uri,
+		       context->action,
+		       x, y);
+
+	g_free (drop_target);
+}
 
 static void
 receive_dropped_netscape_url (NautilusTreeViewDragDest *dest,
@@ -749,21 +775,23 @@ receive_dropped_keyword (NautilusTreeViewDragDest *dest,
 	g_free (drop_target_uri);
 }
 
-static void
+static gboolean
 receive_xds (NautilusTreeViewDragDest *dest,
+	     GtkWidget *widget,
+	     guint32 time,
 	     GdkDragContext *context,
 	     int x, int y)
 {
 	GFile *location;
 
-	/* Indicate that we don't provide "F" fallback */
 	if (dest->details->drag_data->format == 8 
 	    && dest->details->drag_data->length == 1 
 	    && dest->details->drag_data->data[0] == 'F') {
-		gdk_property_change (GDK_DRAWABLE (context->source_window),
-				     gdk_atom_intern (NAUTILUS_ICON_DND_XDNDDIRECTSAVE_TYPE, FALSE),
-				     gdk_atom_intern ("text/plain", FALSE), 8,
-				     GDK_PROP_MODE_REPLACE, (const guchar *) "", 0);
+		gtk_drag_get_data (widget, context,
+		                  gdk_atom_intern (NAUTILUS_ICON_DND_RAW_TYPE,
+		                                  FALSE),
+		                  time);
+		return FALSE;
 	} else if (dest->details->drag_data->format == 8 
 		   && dest->details->drag_data->length == 1 
 		   && dest->details->drag_data->data[0] == 'S') {
@@ -775,6 +803,7 @@ receive_xds (NautilusTreeViewDragDest *dest,
 
 		g_object_unref (location);
 	}
+	return TRUE;
 }
 
 
@@ -789,7 +818,9 @@ drag_data_received_callback (GtkWidget *widget,
 			     gpointer data)
 {
 	NautilusTreeViewDragDest *dest;
-	gboolean success;
+	const char *tmp;
+	int length;
+	gboolean success, finished;
 	
 	dest = NAUTILUS_TREE_VIEW_DRAG_DEST (data);
 
@@ -806,6 +837,7 @@ drag_data_received_callback (GtkWidget *widget,
 
 	if (dest->details->drop_occurred) {
 		success = FALSE;
+		finished = TRUE;
 		switch (info) {
 		case NAUTILUS_ICON_DND_GNOME_ICON_LIST :
 			receive_dropped_icons (dest, context, x, y);
@@ -823,19 +855,27 @@ drag_data_received_callback (GtkWidget *widget,
 			receive_dropped_text (dest, context, x, y);
 			success = TRUE;
 			break;
+		case NAUTILUS_ICON_DND_RAW:
+			length = gtk_selection_data_get_length (selection_data);
+			tmp = gtk_selection_data_get_data (selection_data);
+			receive_dropped_raw (dest, tmp, length, context, x, y);
+			success = TRUE;
+			break;
 		case NAUTILUS_ICON_DND_KEYWORD:
 			receive_dropped_keyword (dest, context, x, y);
 			success = TRUE;
 			break;
 		case NAUTILUS_ICON_DND_XDNDDIRECTSAVE:
-			receive_xds (dest, context, x, y);
+			finished = receive_xds (dest, widget, time, context, x, y);
 			success = TRUE;
 			break;
 		}
 
-		dest->details->drop_occurred = FALSE;
-		free_drag_data (dest);
-		gtk_drag_finish (context, success, FALSE, time);
+		if (finished) {
+			dest->details->drop_occurred = FALSE;
+			free_drag_data (dest);
+			gtk_drag_finish (context, success, FALSE, time);
+		}
 	}
 
 	/* appease GtkTreeView by preventing its drag_data_receive
@@ -1101,6 +1141,22 @@ nautilus_tree_view_drag_dest_class_init (NautilusTreeViewDragDestClass *class)
 			      GDK_TYPE_DRAG_ACTION,
 			      G_TYPE_INT,
 			      G_TYPE_INT);
+	signals[HANDLE_RAW] =
+		g_signal_new ("handle_raw",
+			      G_TYPE_FROM_CLASS (class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (NautilusTreeViewDragDestClass,
+					       handle_raw),
+			      NULL, NULL,
+			      nautilus_marshal_VOID__POINTER_INT_STRING_STRING_ENUM_INT_INT,
+			      G_TYPE_NONE, 7,
+			      G_TYPE_POINTER,
+			      G_TYPE_INT,
+			      G_TYPE_STRING,
+			      G_TYPE_STRING,
+			      GDK_TYPE_DRAG_ACTION,
+			      G_TYPE_INT,
+			      G_TYPE_INT);
 }
 
 
diff --git a/libnautilus-private/nautilus-tree-view-drag-dest.h b/libnautilus-private/nautilus-tree-view-drag-dest.h
index 71944fc..d5a8c0a 100644
--- a/libnautilus-private/nautilus-tree-view-drag-dest.h
+++ b/libnautilus-private/nautilus-tree-view-drag-dest.h
@@ -82,6 +82,14 @@ struct _NautilusTreeViewDragDestClass {
 				  GdkDragAction action,
 				  int x,
 				  int y);
+	void (* handle_raw)    (NautilusTreeViewDragDest *dest,
+				  char *raw_data,
+				  int length,
+				  const char *target_uri,
+				  const char *direct_save_uri,
+				  GdkDragAction action,
+				  int x,
+				  int y);
 };
 
 GType                     nautilus_tree_view_drag_dest_get_type (void);
diff --git a/src/file-manager/fm-directory-view.c b/src/file-manager/fm-directory-view.c
index 4d9a6b0..abecc08 100644
--- a/src/file-manager/fm-directory-view.c
+++ b/src/file-manager/fm-directory-view.c
@@ -4036,6 +4036,7 @@ fm_directory_view_new_file_with_initial_contents (FMDirectoryView *directory_vie
 						  const char *parent_uri,
 						  const char *filename,
 						  const char *initial_contents,
+						  int length,
 						  GdkPoint *pos)
 {
 	NewFolderData *data;
@@ -4050,7 +4051,7 @@ fm_directory_view_new_file_with_initial_contents (FMDirectoryView *directory_vie
 
 	nautilus_file_operations_new_file (GTK_WIDGET (directory_view),
 					   pos, parent_uri, filename,
-					   initial_contents,
+					   initial_contents, length,
 					   new_folder_done, data);
 }
 
@@ -4075,6 +4076,7 @@ fm_directory_view_new_file (FMDirectoryView *directory_view,
 								  parent_uri != NULL ? parent_uri : container_uri,
 								  NULL,
 								  NULL,
+								  0,
 								  NULL);
 		g_free (container_uri);
 		return;
@@ -10278,6 +10280,7 @@ fm_directory_view_handle_text_drop (FMDirectoryView  *view,
 				    int               x,
 				    int               y)
 {
+	int length;
 	char *container_uri;
 	GdkPoint pos;
 
@@ -10293,6 +10296,8 @@ fm_directory_view_handle_text_drop (FMDirectoryView  *view,
 		g_assert (container_uri != NULL);
 	}
 
+	length = strlen (text);
+
 	pos.x = x;
 	pos.y = y;
 	fm_directory_view_widget_to_file_operation_position (view, &pos);
@@ -10301,7 +10306,56 @@ fm_directory_view_handle_text_drop (FMDirectoryView  *view,
 		view, target_uri != NULL ? target_uri : container_uri,
 		/* Translator: This is the filename used for when you dnd text to a directory */
 		_("dropped text.txt"),
-		text, &pos);
+		text, length, &pos);
+
+	g_free (container_uri);
+}
+
+void
+fm_directory_view_handle_raw_drop (FMDirectoryView  *view,
+				    const char       *raw_data,
+				    int               length,
+				    const char       *target_uri,
+				    const char       *direct_save_uri,
+				    GdkDragAction     action,
+				    int               x,
+				    int               y)
+{
+	char *container_uri, *filename;
+	GFile *direct_save_full;
+	GdkPoint pos;
+
+	if (raw_data == NULL) {
+		return;
+	}
+
+	g_return_if_fail (action == GDK_ACTION_COPY);
+
+	container_uri = NULL;
+	if (target_uri == NULL) {
+		container_uri = fm_directory_view_get_backing_uri (view);
+		g_assert (container_uri != NULL);
+	}
+
+	pos.x = x;
+	pos.y = y;
+	fm_directory_view_widget_to_file_operation_position (view, &pos);
+
+	filename = NULL;
+	if (direct_save_uri != NULL) {
+		direct_save_full = g_file_new_for_uri (direct_save_uri);
+		filename = g_file_get_basename (direct_save_full);
+	}
+	if (filename == NULL) {
+		/* Translator: This is the filename used for when you dnd raw
+		 * data to a directory, if the source didn't supply a name.
+		 */
+		filename = _("dropped data");
+	}
+
+	fm_directory_view_new_file_with_initial_contents (
+		view, target_uri != NULL ? target_uri : container_uri,
+		filename, raw_data, length, &pos);
 
 	g_free (container_uri);
 }
diff --git a/src/file-manager/fm-directory-view.h b/src/file-manager/fm-directory-view.h
index 5a8db15..acee811 100644
--- a/src/file-manager/fm-directory-view.h
+++ b/src/file-manager/fm-directory-view.h
@@ -465,6 +465,14 @@ void                fm_directory_view_handle_text_drop                 (FMDirect
 									GdkDragAction     action,
 									int               x,
 									int               y);
+void                fm_directory_view_handle_raw_drop                 (FMDirectoryView  *view,
+									const char       *raw_data,
+									int               length,
+									const char       *target_uri,
+									const char       *direct_save_uri,
+									GdkDragAction     action,
+									int               x,
+									int               y);
 void                fm_directory_view_freeze_updates                   (FMDirectoryView  *view);
 void                fm_directory_view_unfreeze_updates                 (FMDirectoryView  *view);
 void                fm_directory_view_add_subdirectory                (FMDirectoryView  *view,
diff --git a/src/file-manager/fm-icon-view.c b/src/file-manager/fm-icon-view.c
index 09d5fe9..bdb71f8 100644
--- a/src/file-manager/fm-icon-view.c
+++ b/src/file-manager/fm-icon-view.c
@@ -2757,6 +2757,15 @@ icon_view_handle_text (NautilusIconContainer *container, const char *text,
 					    text, target_uri, action, x, y);
 }
 
+static void
+icon_view_handle_raw (NautilusIconContainer *container, const char *raw_data,
+		       int length, const char *target_uri, const char *direct_save_uri,
+		       GdkDragAction action, int x, int y, FMIconView *view)
+{
+	fm_directory_view_handle_raw_drop (FM_DIRECTORY_VIEW (view),
+					    raw_data, length, target_uri, direct_save_uri, action, x, y);
+}
+
 static char *
 icon_view_get_first_visible_file (NautilusView *view)
 {
@@ -2989,6 +2998,8 @@ fm_icon_view_init (FMIconView *icon_view)
 				 G_CALLBACK (icon_view_handle_uri_list), icon_view, 0);
 	g_signal_connect_object (get_icon_container (icon_view), "handle_text",
 				 G_CALLBACK (icon_view_handle_text), icon_view, 0);
+	g_signal_connect_object (get_icon_container (icon_view), "handle_raw",
+				 G_CALLBACK (icon_view_handle_raw), icon_view, 0);
 }
 
 static NautilusView *
diff --git a/src/file-manager/fm-list-view.c b/src/file-manager/fm-list-view.c
index a093d1e..902f242 100644
--- a/src/file-manager/fm-list-view.c
+++ b/src/file-manager/fm-list-view.c
@@ -1220,6 +1220,16 @@ list_view_handle_text (NautilusTreeViewDragDest *dest, const char *text,
 }
 
 static void
+list_view_handle_raw (NautilusTreeViewDragDest *dest, const char *raw_data,
+		       int length, const char *target_uri, const char *direct_save_uri,
+		       GdkDragAction action, int x, int y, FMListView *view)
+{
+	fm_directory_view_handle_raw_drop (FM_DIRECTORY_VIEW (view),
+					    raw_data, length, target_uri, direct_save_uri,
+					    action, x, y);
+}
+
+static void
 move_copy_items_callback (NautilusTreeViewDragDest *dest,
 			  const GList *item_uris,
 			  const char *target_uri,
@@ -1401,6 +1411,8 @@ create_and_set_up_tree_view (FMListView *view)
 				 G_CALLBACK (list_view_handle_uri_list), view, 0);
 	g_signal_connect_object (view->details->drag_dest, "handle_text",
 				 G_CALLBACK (list_view_handle_text), view, 0);
+	g_signal_connect_object (view->details->drag_dest, "handle_raw",
+				 G_CALLBACK (list_view_handle_raw), view, 0);
 
 	g_signal_connect_object (gtk_tree_view_get_selection (view->details->tree_view),
 				 "changed",



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]