diff --git a/gedit/gedit-utils.c b/gedit/gedit-utils.c
index 05feb2e..9851446 100644
--- a/gedit/gedit-utils.c
+++ b/gedit/gedit-utils.c
@@ -1545,3 +1545,31 @@ gedit_utils_decode_uri (const gchar *uri,
 	
 	return TRUE;
 }
+
+/* Copied from nautilus */
+gchar *
+gedit_utils_get_direct_save_filename (GdkDragContext *context)
+{
+	guchar *prop_text;
+	gint prop_len;
+	
+	if (!gdk_property_get (context->source_window, gdk_atom_intern ("XdndDirectSave0", FALSE),
+			       gdk_atom_intern ("text/plain", FALSE), 0, 1024, FALSE, NULL, NULL,
+			       &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';
+	
+	/* Verify that the file name provided by the source is valid */
+	if (*prop_text == '\0' ||
+	    strchr ((const gchar *) prop_text, G_DIR_SEPARATOR) != NULL) {
+		gedit_debug_message (DEBUG_UTILS, "Invalid filename provided by XDS drag site");
+		g_free (prop_text);
+		return NULL;
+	}
+	
+	return (gchar *)prop_text;
+}
diff --git a/gedit/gedit-utils.h b/gedit/gedit-utils.h
index ddf1d9c..b760928 100644
--- a/gedit/gedit-utils.h
+++ b/gedit/gedit-utils.h
@@ -155,6 +155,8 @@ gboolean	 gedit_utils_decode_uri 		(const gchar *uri,
 /* Turns data from a drop into a list of well formatted uris */
 gchar 	       **gedit_utils_drop_get_uris		(GtkSelectionData *selection_data);
 
+gchar           *gedit_utils_get_direct_save_filename	(GdkDragContext *context);
+
 G_END_DECLS
 
 #endif /* __GEDIT_UTILS_H__ */
diff --git a/gedit/gedit-window-private.h b/gedit/gedit-window-private.h
index 0467d8e..981e9d6 100644
--- a/gedit/gedit-window-private.h
+++ b/gedit/gedit-window-private.h
@@ -105,6 +105,8 @@ struct _GeditWindowPrivate
 
 	GFile          *default_location;
 
+	gchar          *direct_save_uri;
+
 	gboolean        removing_tabs : 1;
 	gboolean        dispose_has_run : 1;
 };
diff --git a/gedit/gedit-window.c b/gedit/gedit-window.c
index 0f53d96..f2da080 100644
--- a/gedit/gedit-window.c
+++ b/gedit/gedit-window.c
@@ -88,7 +88,13 @@ enum
 
 enum
 {
-	TARGET_URI_LIST = 100
+	TARGET_URI_LIST = 100,
+	TARGET_XDNDDIRECTSAVE
+};
+
+static const GtkTargetEntry drop_types [] = {
+	{ "text/uri-list", 0, TARGET_URI_LIST},
+	{ "XdndDirectSave0", 0, TARGET_XDNDDIRECTSAVE } /* XDS Protocol Type */
 };
 
 G_DEFINE_TYPE(GeditWindow, gedit_window, GTK_TYPE_WINDOW)
@@ -247,6 +253,8 @@ gedit_window_finalize (GObject *object)
 	if (window->priv->default_location != NULL)
 		g_object_unref (window->priv->default_location);
 
+	g_free (window->priv->direct_save_uri);
+
 	G_OBJECT_CLASS (gedit_window_parent_class)->finalize (object);
 }
 
@@ -2756,11 +2764,107 @@ drag_data_received_cb (GtkWidget        *widget,
 	if (window == NULL)
 		return;
 
-	if (info == TARGET_URI_LIST)
+	switch (info)
+	{
+		case TARGET_URI_LIST:
+			uri_list = gedit_utils_drop_get_uris(selection_data);
+			load_uris_from_drop (window, uri_list);
+			g_strfreev (uri_list);
+			break;
+		case TARGET_XDNDDIRECTSAVE:
+			/* Indicate that we don't provide "F" fallback */
+			if (selection_data->format == 8 &&
+			    selection_data->length == 1 &&
+			    selection_data->data[0] == 'F')
+			{
+				gdk_property_change (GDK_DRAWABLE (context->source_window),
+						     gdk_atom_intern ("XdndDirectSave0", FALSE),
+						     gdk_atom_intern ("text/plain", FALSE), 8,
+						     GDK_PROP_MODE_REPLACE, (const guchar *) "", 0);
+			}
+			else if (selection_data->format == 8 &&
+				 selection_data->length == 1 &&
+				 selection_data->data[0] == 'S' &&
+				 window->priv->direct_save_uri != NULL)
+			{
+				gchar **uris;
+				
+				uris = g_new (gchar *, 2);
+				uris[0] = window->priv->direct_save_uri;
+				uris[1] = NULL;
+				
+				load_uris_from_drop (window, uris);
+				g_free (uris);
+			}
+			break;
+	}
+}
+
+static void
+set_direct_save_uri (GeditWindow *window,
+		     GdkDragContext *context)
+{
+	gchar *filename;
+	
+	filename = gedit_utils_get_direct_save_filename (context);
+	
+	if (filename != NULL)
+	{
+		gchar *path;
+		gchar *uri;
+	
+		path = g_build_filename (g_get_tmp_dir (),
+					filename,
+					NULL);
+		
+		uri = g_filename_to_uri (path, NULL, NULL);
+		g_free (path);
+		
+		/* Change the property */
+		gdk_property_change (GDK_DRAWABLE (context->source_window),
+				     gdk_atom_intern ("XdndDirectSave0", FALSE),
+				     gdk_atom_intern ("text/plain", FALSE), 8,
+				     GDK_PROP_MODE_REPLACE, (const guchar *) uri,
+				     strlen (uri));
+		
+		g_free (window->priv->direct_save_uri);
+		window->priv->direct_save_uri = uri;
+	}
+	g_free (filename);
+}
+
+static void
+drag_drop_cb (GtkWidget      *widget,
+	      GdkDragContext *context,
+	      gint            x,
+	      gint            y,
+	      guint           time,
+	      gpointer        user_data)
+{
+	GeditWindow *window;
+	GtkTargetList *target_list;
+	GdkAtom target;
+	
+	window = get_drop_window (widget);
+	
+	target_list = gtk_drag_dest_get_target_list (widget);
+	target = gtk_drag_dest_find_target (widget, context, target_list);
+	
+	if (target != GDK_NONE)
 	{
-		uri_list = gedit_utils_drop_get_uris(selection_data);
-		load_uris_from_drop (window, uri_list);
-		g_strfreev (uri_list);
+		guint info;
+		gboolean found;
+		
+		found = gtk_target_list_find (target_list, target, &info);
+		g_assert (found);
+		
+		if (info == TARGET_XDNDDIRECTSAVE)
+		{
+			set_direct_save_uri (window, context);
+		}
+		
+		gtk_drag_get_data (GTK_WIDGET (widget), context,
+				   target, time);
 	}
 }
 
@@ -3761,6 +3865,7 @@ gedit_window_init (GeditWindow *window)
 	window->priv->dispose_has_run = FALSE;
 	window->priv->fullscreen_controls = NULL;
 	window->priv->fullscreen_animation_timeout_id = 0;
+	window->priv->direct_save_uri = NULL;
 
 	window->priv->message_bus = gedit_message_bus_new ();
 
@@ -3827,8 +3932,8 @@ gedit_window_init (GeditWindow *window)
 			   GTK_DEST_DEFAULT_MOTION |
 			   GTK_DEST_DEFAULT_HIGHLIGHT |
 			   GTK_DEST_DEFAULT_DROP,
-			   NULL,
-			   0,
+			   drop_types,
+			   G_N_ELEMENTS (drop_types),
 			   GDK_ACTION_COPY);
 
 	/* Add uri targets */
@@ -3836,7 +3941,7 @@ gedit_window_init (GeditWindow *window)
 	
 	if (tl == NULL)
 	{
-		tl = gtk_target_list_new (NULL, 0);
+		tl = gtk_target_list_new (drop_types, G_N_ELEMENTS (drop_types));
 		gtk_drag_dest_set_target_list (GTK_WIDGET (window), tl);
 		gtk_target_list_unref (tl);
 	}
@@ -3883,6 +3988,10 @@ gedit_window_init (GeditWindow *window)
 			  "drag_data_received",
 	                  G_CALLBACK (drag_data_received_cb), 
 	                  NULL);
+	g_signal_connect (window,
+			  "drag_drop",
+	                  G_CALLBACK (drag_drop_cb), 
+	                  NULL);
 
 	/* we can get the clipboard only after the widget
 	 * is realized */
