desktop icon patch



Ok, here is the patch with all the desktop changes i talked about in the
last email. If anyone want to look for silly bugs in it, be my guest.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 Alexander Larsson                                            Red Hat, Inc 
                   alexl redhat com    alla lysator liu se 
He's a time-tossed guerilla farmboy for the 21st century. She's a high-kicking 
winged mechanic married to the Mob. They fight crime! 
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/nautilus/ChangeLog,v
retrieving revision 1.5805
diff -u -p -r1.5805 ChangeLog
--- ChangeLog	14 May 2003 15:24:28 -0000	1.5805
+++ ChangeLog	15 May 2003 17:08:04 -0000
@@ -1,3 +1,126 @@
+2003-05-15  Alexander Larsson  <alexl redhat com>
+
+	* libnautilus-private/Makefile.am:
+	Added new files.
+	
+	* libnautilus-private/apps_nautilus_preferences.schemas.in:
+	* libnautilus-private/nautilus-global-preferences.[ch]:
+	New prefs for home and trash links.
+	
+	* libnautilus-private/nautilus-desktop-directory.[ch]:
+	New files. Implements the NautilusDesktop object for the
+	virtual x-nautilus-desktop: uri. The directory merges the contents
+	of the directory with the real desktop directory.
+	
+	* libnautilus-private/nautilus-desktop-directory-file.[ch]:
+	New files. Implements the Nautilusfile corresponding to
+	NautilusDestkopDirectory.
+	
+	* libnautilus-private/nautilus-desktop-icon-file.[ch]:
+	New files.
+	Implement NautilusFile for a virtual file in a NautilusDesktopDirectory.
+	Gets all the actual file data from a NautilusDesktopLink.
+
+	* libnautilus-private/nautilus-desktop-link-monitor.[ch]:
+	New files.
+	Keep track of home and trash visibility prefs and mounted volumes and
+	create/destroy corresponding NautilusDesktopLink object.
+	
+	* libnautilus-private/nautilus-desktop-link.[ch]:
+	New files.
+	Keeps track of all the real information in a desktop icon link.
+	These are home, trash and volume links at the moment.
+	
+	* libnautilus-private/nautilus-directory-async.c:
+	Indentation correction.
+	
+	* libnautilus-private/nautilus-directory.c:
+	(nautilus_directory_new):
+	Create NautilusDesktopDirectory objects for x-nautilus-desktop: uris
+	
+	* libnautilus-private/nautilus-dnd.c: (nautilus_drag_items_local):
+	Handle NULL GnomeVFSURIs.
+	(nautilus_drag_items_on_desktop): New function to check if items
+	are on the desktop.
+	(nautilus_drag_default_drop_action_for_icons):
+	Special case desktop uris.
+	(nautilus_drag_selection_includes_special_link):
+	Convert from old-style special links to current.
+	
+	* libnautilus-private/nautilus-dnd.h:
+	New function nautilus_drag_items_on_desktop.
+	
+	* libnautilus-private/nautilus-file-operations.c:
+	(is_special_link), (nautilus_file_operations_copy_move):
+	Convert from old-style special links to current.
+	(nautilus_file_operations_delete):
+	Special case desktop links
+	
+	* libnautilus-private/nautilus-file-utilities.[ch]:
+	(nautilus_get_desktop_directory):
+	(nautilus_get_gmc_desktop_directory):
+	Change desktop dir to ~/Desktop
+	(nautilus_get_desktop_directory_uri):
+	New function to return desktop dir as a uri.
+
+	
+	* libnautilus-private/nautilus-file.c:
+	(nautilus_file_new_from_relative_uri),
+	(nautilus_file_get_internal):
+	Handle creation of desktop icon files.
+	(nautilus_file_can_rename), (rename_guts),
+	(nautilus_file_get_drop_target_uri):
+	Update for new special links.
+	(nautilus_file_is_in_desktop):
+	Update for new desktop dir.
+	(nautilus_file_get_uri):
+	Fix uris for self owned files. This changed due to
+	the new canonicalization rules for foo:
+	
+	
+	* libnautilus-private/nautilus-icon-dnd.c:
+	(nautilus_icon_container_selection_items_local),
+	(handle_nonlocal_move):
+	Handle desktop uri.
+	
+	* src/Nautilus_shell.server.in:
+	icon view handles x-nautilus-desktop: uris
+	
+	* src/nautilus-application.c: (finish_startup):
+	Initialize the desktop link monitor
+	
+	* src/nautilus-desktop-window.c:
+	(nautilus_desktop_window_update_directory):
+	Show x-nautilus-desktop: 
+	
+	* src/file-manager/fm-desktop-icon-view.c:
+	(fm_desktop_icon_view_finalize), (fm_desktop_icon_view_init),
+	(volume_ops_callback), (trash_link_is_selection),
+	(volume_link_is_selection), (volume_link_device_type),
+	(real_supports_zooming):
+	
+	* src/file-manager/fm-directory-view.c:
+	Remove lots of old support for desktop icon.
+	Reimplement some of it with the new desktop icon support.
+	
+	* src/file-manager/fm-directory-view.h:
+	New function fm_directory_view_get_backing_uri
+	
+	* src/file-manager/fm-icon-container.c:
+	(fm_icon_container_get_icon_text):
+	Don't show extra text for desktop icons
+	(get_sort_category): Update for new desktop icons
+	
+	* src/file-manager/fm-icon-view.c: (icon_view_handle_uri_list):
+	Use get_backing_uri()
+	
+	* src/file-manager/fm-properties-window.c: (get_target_file):
+	Use the new desktop icon support.
+	
+	* libnautilus-private/nautilus-icon-container.c:
+	(lay_down_icons_tblr):
+	Don't loop forever if icon doesn't in the height of the container.
+
 2003-05-14 Gaute Lindkvist <lindkvis stud ntnu no>
 
 	* libnautilus-private/nautilus-icon-canvas-item.c
Index: libnautilus-private/Makefile.am
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/Makefile.am,v
retrieving revision 1.229
diff -u -p -r1.229 Makefile.am
--- libnautilus-private/Makefile.am	3 May 2003 05:10:53 -0000	1.229
+++ libnautilus-private/Makefile.am	15 May 2003 17:08:04 -0000
@@ -56,6 +56,16 @@ libnautilus_private_la_SOURCES = \
 	nautilus-customization-data.h \
 	nautilus-default-file-icon.c \
 	nautilus-default-file-icon.h \
+	nautilus-desktop-directory.c \
+	nautilus-desktop-directory.h \
+	nautilus-desktop-directory-file.c \
+	nautilus-desktop-directory-file.h \
+	nautilus-desktop-icon-file.c \
+	nautilus-desktop-icon-file.h \
+	nautilus-desktop-link.c \
+	nautilus-desktop-link.h \
+	nautilus-desktop-link-monitor.c \
+	nautilus-desktop-link-monitor.h \
 	nautilus-directory-async.c \
 	nautilus-directory-background.c \
 	nautilus-directory-background.h \
Index: libnautilus-private/apps_nautilus_preferences.schemas.in
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/apps_nautilus_preferences.schemas.in,v
retrieving revision 1.2
diff -u -p -r1.2 apps_nautilus_preferences.schemas.in
--- libnautilus-private/apps_nautilus_preferences.schemas.in	5 May 2003 13:32:54 -0000	1.2
+++ libnautilus-private/apps_nautilus_preferences.schemas.in	15 May 2003 17:08:04 -0000
@@ -700,6 +700,64 @@
          </long>
       </locale>
     </schema>
-    
+
+    <schema>
+      <key>/schemas/apps/nautilus/desktop/home_icon_visible</key>
+      <applyto>/apps/nautilus/desktop/home_icon_visible</applyto>
+      <owner>nautilus</owner>
+      <type>bool</type>
+      <default>true</default>
+      <locale name="C">
+         <short>Home icon visible on desktop</short>
+         <long>
+          If this is set to true, an icon linking to the home directory
+	  will be put on the desktop.
+         </long>
+      </locale>
+    </schema>
+
+    <schema>
+      <key>/schemas/apps/nautilus/desktop/trash_icon_visible</key>
+      <applyto>/apps/nautilus/desktop/trash_icon_visible</applyto>
+      <owner>nautilus</owner>
+      <type>bool</type>
+      <default>true</default>
+      <locale name="C">
+         <short>Trash icon visible on desktop</short>
+         <long>
+          If this is set to true, an icon linking to the trash
+	  will be put on the desktop.
+         </long>
+      </locale>
+    </schema>
+
+    <schema>
+      <key>/schemas/apps/nautilus/desktop/home_icon_name</key>
+      <applyto>/apps/nautilus/desktop/home_icon_name</applyto>
+      <owner>nautilus</owner>
+      <type>string</type>
+      <locale name="C">
+         <short>Desktop home icon name</short>
+         <long>
+          This name can be set if you want a custom name
+	  for the home link icon on the desktop.
+         </long>
+      </locale>
+    </schema>
+        
+    <schema>
+      <key>/schemas/apps/nautilus/desktop/trash_icon_name</key>
+      <applyto>/apps/nautilus/desktop/trash_icon_name</applyto>
+      <owner>nautilus</owner>
+      <type>string</type>
+      <locale name="C">
+         <short>Desktop trash icon name</short>
+         <long>
+          This name can be set if you want a custom name
+	  for the trash icon on the desktop.
+         </long>
+      </locale>
+    </schema>
+        
   </schemalist>  
 </gconfschemafile>
Index: libnautilus-private/nautilus-desktop-directory-file.c
===================================================================
RCS file: libnautilus-private/nautilus-desktop-directory-file.c
diff -N libnautilus-private/nautilus-desktop-directory-file.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libnautilus-private/nautilus-desktop-directory-file.c	15 May 2003 17:08:04 -0000
@@ -0,0 +1,549 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+   nautilus-desktop-directory-file.c: Subclass of NautilusFile to help implement the
+   virtual desktop.
+ 
+   Copyright (C) 2003 Red Hat, Inc.
+  
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+  
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+  
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+  
+   Author: Alexander Larsson <alexl redhat com>
+*/
+
+#include <config.h>
+#include "nautilus-desktop-directory-file.h"
+
+#include "nautilus-directory-notify.h"
+#include "nautilus-directory-private.h"
+#include "nautilus-file-attributes.h"
+#include "nautilus-file-private.h"
+#include "nautilus-file-utilities.h"
+#include <eel/eel-glib-extensions.h>
+#include <eel/eel-gtk-macros.h>
+#include "nautilus-desktop-directory.h"
+#include <gtk/gtksignal.h>
+#include <libgnome/gnome-i18n.h>
+#include <string.h>
+
+struct NautilusDesktopDirectoryFileDetails {
+	NautilusDesktopDirectory *desktop_directory;
+
+  	NautilusFile *real_dir_file;
+
+	GHashTable *callbacks;
+	GHashTable *monitors;
+};
+
+typedef struct {
+	NautilusDesktopDirectoryFile *desktop_file;
+	NautilusFileCallback callback;
+	gpointer callback_data;
+
+	NautilusFileAttributes delegated_attributes;
+	NautilusFileAttributes non_delegated_attributes;
+
+	GList *non_ready_files;
+
+	gboolean initializing;
+} DesktopCallback;
+
+typedef struct {
+	NautilusDesktopDirectoryFile *desktop_file;
+
+	NautilusFileAttributes delegated_attributes;
+	NautilusFileAttributes non_delegated_attributes;
+} DesktopMonitor;
+
+
+static void nautilus_desktop_directory_file_init       (gpointer   object,
+						  gpointer   klass);
+static void nautilus_desktop_directory_file_class_init (gpointer   klass);
+
+EEL_CLASS_BOILERPLATE (NautilusDesktopDirectoryFile,
+		       nautilus_desktop_directory_file,
+		       NAUTILUS_TYPE_FILE)
+
+static guint
+desktop_callback_hash (gconstpointer desktop_callback_as_pointer)
+{
+	const DesktopCallback *desktop_callback;
+
+	desktop_callback = desktop_callback_as_pointer;
+	return GPOINTER_TO_UINT (desktop_callback->callback)
+		^ GPOINTER_TO_UINT (desktop_callback->callback_data);
+}
+
+static gboolean
+desktop_callback_equal (gconstpointer desktop_callback_as_pointer,
+		      gconstpointer desktop_callback_as_pointer_2)
+{
+	const DesktopCallback *desktop_callback, *desktop_callback_2;
+
+	desktop_callback = desktop_callback_as_pointer;
+	desktop_callback_2 = desktop_callback_as_pointer_2;
+
+	return desktop_callback->callback == desktop_callback_2->callback
+		&& desktop_callback->callback_data == desktop_callback_2->callback_data;
+}
+
+     
+static void
+real_file_changed_callback (NautilusFile *real_file,
+			    gpointer callback_data)
+{
+	NautilusDesktopDirectoryFile *desktop_file;
+	
+	desktop_file = NAUTILUS_DESKTOP_DIRECTORY_FILE (callback_data);
+	nautilus_file_changed (NAUTILUS_FILE (desktop_file));
+}
+
+static NautilusFileAttributes 
+get_delegated_attributes_mask (void)
+{
+	return NAUTILUS_FILE_ATTRIBUTE_DEEP_COUNTS |
+		NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT |
+		NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES;
+}
+
+static void
+partition_attributes (NautilusFileAttributes attributes,
+		      NautilusFileAttributes *delegated_attributes,
+		      NautilusFileAttributes *non_delegated_attributes)
+{
+	NautilusFileAttributes mask;
+
+	mask = get_delegated_attributes_mask ();
+
+	*delegated_attributes = attributes & mask;
+	*non_delegated_attributes = attributes & ~mask;
+}
+
+static void
+desktop_directory_file_monitor_add (NautilusFile *file,
+				    gconstpointer client,
+				    NautilusFileAttributes attributes)
+{
+	NautilusDesktopDirectoryFile *desktop_file;
+	DesktopMonitor *monitor;
+
+	desktop_file = NAUTILUS_DESKTOP_DIRECTORY_FILE (file);
+
+	/* Map the client to a unique value so this doesn't interfere
+	 * with direct monitoring of the file by the same client.
+	 */
+	monitor = g_hash_table_lookup (desktop_file->details->monitors, client);
+	if (monitor != NULL) {
+		g_assert (monitor->desktop_file == desktop_file);
+	} else {
+		monitor = g_new0 (DesktopMonitor, 1);
+		monitor->desktop_file = desktop_file;
+		g_hash_table_insert (desktop_file->details->monitors,
+				     (gpointer) client, monitor);
+	}
+
+	partition_attributes (attributes,
+			      &monitor->delegated_attributes,
+			      &monitor->non_delegated_attributes);
+
+	/* Pawn off partioned attributes to real dir file */
+	nautilus_file_monitor_add (desktop_file->details->real_dir_file,
+				   monitor, monitor->delegated_attributes);
+
+	/* Do the rest ourself */
+	nautilus_directory_monitor_add_internal
+		(file->details->directory, file,
+		 monitor, TRUE, TRUE,
+		 monitor->non_delegated_attributes,
+		 NULL, NULL);
+}
+
+static void
+desktop_directory_file_monitor_remove (NautilusFile *file,
+				       gconstpointer client)
+{
+	NautilusDesktopDirectoryFile *desktop_file;
+	DesktopMonitor *monitor;
+	
+	desktop_file = NAUTILUS_DESKTOP_DIRECTORY_FILE (file);
+	
+	/* Map the client to the value used by the earlier add call. */
+        monitor = g_hash_table_lookup (desktop_file->details->monitors, client);
+	if (monitor == NULL) {
+		return;
+	}
+
+	/* Call through to the real file remove calls. */
+	g_hash_table_remove (desktop_file->details->monitors, client);
+
+	/* Remove the locally handled parts */
+	nautilus_directory_monitor_remove_internal
+		(file->details->directory, file, client);
+}
+
+static void
+desktop_callback_destroy (DesktopCallback *desktop_callback)
+{
+	g_assert (desktop_callback != NULL);
+	g_assert (NAUTILUS_IS_DESKTOP_DIRECTORY_FILE (desktop_callback->desktop_file));
+
+	nautilus_file_unref (NAUTILUS_FILE (desktop_callback->desktop_file));
+	g_list_free (desktop_callback->non_ready_files);
+	g_free (desktop_callback);
+}
+
+static void
+desktop_callback_check_done (DesktopCallback *desktop_callback)
+{
+	/* Check if we are ready. */
+	if (desktop_callback->initializing ||
+	    desktop_callback->non_ready_files != NULL) {
+		return;
+	}
+
+	/* Remove from the hash table before sending it. */
+	g_hash_table_remove (desktop_callback->desktop_file->details->callbacks,
+			     desktop_callback);
+
+	/* We are ready, so do the real callback. */
+	(* desktop_callback->callback) (NAUTILUS_FILE (desktop_callback->desktop_file),
+					desktop_callback->callback_data);
+
+	/* And we are done. */
+	desktop_callback_destroy (desktop_callback);
+}
+
+static void
+desktop_callback_remove_file (DesktopCallback *desktop_callback,
+			      NautilusFile *file)
+{
+	desktop_callback->non_ready_files = g_list_remove
+		(desktop_callback->non_ready_files, file);
+	desktop_callback_check_done (desktop_callback);
+}
+
+static void
+ready_callback (NautilusFile *file,
+		gpointer callback_data)
+{
+	DesktopCallback *desktop_callback;
+
+	g_assert (NAUTILUS_IS_FILE (file));
+	g_assert (callback_data != NULL);
+
+	desktop_callback = callback_data;
+	g_assert (g_list_find (desktop_callback->non_ready_files, file) != NULL);
+
+	desktop_callback_remove_file (desktop_callback, file);
+}
+
+static void
+desktop_directory_file_call_when_ready (NautilusFile *file,
+					NautilusFileAttributes attributes,
+					NautilusFileCallback callback,
+					gpointer callback_data)
+
+{
+	NautilusDesktopDirectoryFile *desktop_file;
+	DesktopCallback search_key, *desktop_callback;
+
+	desktop_file = NAUTILUS_DESKTOP_DIRECTORY_FILE (file);
+
+	/* Check to be sure we aren't overwriting. */
+	search_key.callback = callback;
+	search_key.callback_data = callback_data;
+	if (g_hash_table_lookup (desktop_file->details->callbacks, &search_key) != NULL) {
+		g_warning ("tried to add a new callback while an old one was pending");
+		return;
+	}
+
+	/* Create a desktop_callback record. */
+	desktop_callback = g_new0 (DesktopCallback, 1);
+	nautilus_file_ref (file);
+	desktop_callback->desktop_file = desktop_file;
+	desktop_callback->callback = callback;
+	desktop_callback->callback_data = callback_data;
+	desktop_callback->initializing = TRUE;
+
+	partition_attributes (attributes,
+			      &desktop_callback->delegated_attributes,
+			      &desktop_callback->non_delegated_attributes);
+
+	desktop_callback->non_ready_files = g_list_prepend
+		(desktop_callback->non_ready_files, file);
+	desktop_callback->non_ready_files = g_list_prepend
+		(desktop_callback->non_ready_files, desktop_file->details->real_dir_file);
+	
+	/* Put it in the hash table. */
+	g_hash_table_insert (desktop_file->details->callbacks,
+			     desktop_callback, desktop_callback);
+
+	/* Now connect to each file's call_when_ready. */
+	nautilus_directory_call_when_ready_internal
+		(file->details->directory, file,
+		 desktop_callback->non_delegated_attributes,
+		 FALSE, NULL, ready_callback, desktop_callback);
+	nautilus_file_call_when_ready
+			(desktop_file->details->real_dir_file,
+			 desktop_callback->delegated_attributes,
+			 ready_callback, desktop_callback);
+
+	desktop_callback->initializing = FALSE;
+
+	/* Check if any files became read while we were connecting up
+	 * the call_when_ready callbacks (also handles the pathological
+	 * case where there are no files at all).
+	 */
+	desktop_callback_check_done (desktop_callback);
+
+}
+
+static void
+desktop_directory_file_cancel_call_when_ready (NautilusFile *file,
+					       NautilusFileCallback callback,
+					       gpointer callback_data)
+{
+	NautilusDesktopDirectoryFile *desktop_file;
+	DesktopCallback search_key, *desktop_callback;
+
+	desktop_file = NAUTILUS_DESKTOP_DIRECTORY_FILE (file);
+
+	/* Find the entry in the table. */
+	search_key.callback = callback;
+	search_key.callback_data = callback_data;
+	desktop_callback = g_hash_table_lookup (desktop_file->details->callbacks, &search_key);
+	if (desktop_callback == NULL) {
+		return;
+	}
+
+	/* Remove from the hash table before working with it. */
+	g_hash_table_remove (desktop_callback->desktop_file->details->callbacks, desktop_callback);
+
+	/* Tell the real directory to cancel the call. */
+	nautilus_directory_cancel_callback_internal
+		(file->details->directory, file,
+		 NULL, ready_callback, desktop_callback);
+	
+	nautilus_file_cancel_call_when_ready
+		(desktop_file->details->real_dir_file,
+		 ready_callback, desktop_callback);
+	
+	desktop_callback_destroy (desktop_callback);
+}
+
+static gboolean
+real_check_if_ready (NautilusFile *file,
+		     NautilusFileAttributes attributes)
+{
+	return nautilus_directory_check_if_ready_internal
+		(file->details->directory, file,
+		 attributes);
+}
+
+static gboolean
+desktop_directory_file_check_if_ready (NautilusFile *file,
+				       NautilusFileAttributes attributes)
+{
+	NautilusFileAttributes delegated_attributes, non_delegated_attributes;
+	NautilusDesktopDirectoryFile *desktop_file;
+
+	desktop_file = NAUTILUS_DESKTOP_DIRECTORY_FILE (file);
+
+	partition_attributes (attributes,
+			      &delegated_attributes,
+			      &non_delegated_attributes);
+
+	return real_check_if_ready (file, non_delegated_attributes) &&
+		nautilus_file_check_if_ready (desktop_file->details->real_dir_file,
+					      delegated_attributes);
+}
+
+static GnomeVFSFileType
+desktop_directory_file_get_file_type (NautilusFile *file)
+{
+	return GNOME_VFS_FILE_TYPE_DIRECTORY;
+}			      
+
+static gboolean
+desktop_directory_file_get_item_count (NautilusFile *file, 
+				       guint *count,
+				       gboolean *count_unreadable)
+{
+	NautilusDesktopDirectoryFile *desktop_file;
+	gboolean got_count;
+	
+	desktop_file = NAUTILUS_DESKTOP_DIRECTORY_FILE (file);
+	
+	got_count = nautilus_file_get_directory_item_count (desktop_file->details->real_dir_file,
+							    count,
+							    count_unreadable);
+
+	if (count) {
+		*count += g_list_length (file->details->directory->details->file_list);
+	}
+	
+	return got_count;
+}
+
+static NautilusRequestStatus
+desktop_directory_file_get_deep_counts (NautilusFile *file,
+					guint *directory_count,
+					guint *file_count,
+					guint *unreadable_directory_count,
+					GnomeVFSFileSize *total_size)
+{
+	NautilusDesktopDirectoryFile *desktop_file;
+	NautilusRequestStatus status;
+
+	desktop_file = NAUTILUS_DESKTOP_DIRECTORY_FILE (file);
+	
+	status = nautilus_file_get_deep_counts (desktop_file->details->real_dir_file,
+						directory_count,
+						file_count,
+						unreadable_directory_count,
+						total_size);
+
+	if (file_count) {
+		*file_count += g_list_length (file->details->directory->details->file_list);
+	}
+	
+	return status;
+}
+
+static gboolean
+desktop_directory_file_get_date (NautilusFile *file,
+				 NautilusDateType date_type,
+				 time_t *date)
+{
+	NautilusDesktopDirectoryFile *desktop_file;
+
+	desktop_file = NAUTILUS_DESKTOP_DIRECTORY_FILE (file);
+
+	return nautilus_file_get_date (desktop_file->details->real_dir_file,
+				       date_type,
+				       date);
+}
+
+static char *
+desktop_directory_file_get_where_string (NautilusFile *file)
+{
+	return g_strdup (_("on the desktop"));
+}
+
+
+static void
+monitor_destroy (gpointer data)
+{
+	DesktopMonitor *monitor = data;
+	
+	nautilus_file_monitor_remove
+		(NAUTILUS_FILE (monitor->desktop_file->details->real_dir_file), monitor);
+	g_free (monitor);
+}
+
+static void
+nautilus_desktop_directory_file_init (gpointer object, gpointer klass)
+{
+	NautilusDesktopDirectoryFile *desktop_file;
+	NautilusDesktopDirectory *desktop_directory;
+	NautilusDirectory *real_dir;
+	NautilusFile *real_dir_file;
+
+	desktop_file = NAUTILUS_DESKTOP_DIRECTORY_FILE (object);
+
+	desktop_directory = NAUTILUS_DESKTOP_DIRECTORY (nautilus_directory_get (EEL_DESKTOP_URI));
+
+	desktop_file->details = g_new0 (NautilusDesktopDirectoryFileDetails, 1);
+	desktop_file->details->desktop_directory = desktop_directory;
+
+	desktop_file->details->callbacks = g_hash_table_new
+		(desktop_callback_hash, desktop_callback_equal);
+	desktop_file->details->monitors = g_hash_table_new_full (NULL, NULL,
+								 NULL, monitor_destroy);
+	
+	real_dir = nautilus_desktop_directory_get_real_directory (desktop_directory);
+	real_dir_file = nautilus_directory_get_corresponding_file (real_dir);
+	nautilus_directory_unref (real_dir);
+	
+	desktop_file->details->real_dir_file = real_dir_file;
+	
+	g_signal_connect_object (real_dir_file, "changed",
+				 G_CALLBACK (real_file_changed_callback), desktop_file, 0);
+}
+
+
+static void
+desktop_callback_remove_file_cover (gpointer key,
+				    gpointer value,
+				    gpointer callback_data)
+{
+	desktop_callback_remove_file
+		(value, NAUTILUS_FILE (callback_data));
+}
+
+
+static void
+desktop_finalize (GObject *object)
+{
+	NautilusDesktopDirectoryFile *desktop_file;
+	NautilusDesktopDirectory *desktop_directory;
+
+	desktop_file = NAUTILUS_DESKTOP_DIRECTORY_FILE (object);
+	desktop_directory = desktop_file->details->desktop_directory;
+
+	/* Todo: ghash now safe? */
+	eel_g_hash_table_safe_for_each
+		(desktop_file->details->callbacks,
+		 desktop_callback_remove_file_cover,
+		 desktop_file->details->real_dir_file);
+	
+	if (g_hash_table_size (desktop_file->details->callbacks) != 0) {
+		g_warning ("call_when_ready still pending when desktop virtual file is destroyed");
+	}
+
+	g_hash_table_destroy (desktop_file->details->callbacks);
+	g_hash_table_destroy (desktop_file->details->monitors);
+
+	nautilus_file_unref (desktop_file->details->real_dir_file);
+
+	g_free (desktop_file->details);
+
+	nautilus_directory_unref (NAUTILUS_DIRECTORY (desktop_directory));
+
+	EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
+}
+
+static void
+nautilus_desktop_directory_file_class_init (gpointer klass)
+{
+	GObjectClass *object_class;
+	NautilusFileClass *file_class;
+
+	object_class = G_OBJECT_CLASS (klass);
+	file_class = NAUTILUS_FILE_CLASS (klass);
+	
+	object_class->finalize = desktop_finalize;
+
+	file_class->monitor_add = desktop_directory_file_monitor_add;
+	file_class->monitor_remove = desktop_directory_file_monitor_remove;
+	file_class->call_when_ready = desktop_directory_file_call_when_ready;
+	file_class->cancel_call_when_ready = desktop_directory_file_cancel_call_when_ready;
+	file_class->check_if_ready = desktop_directory_file_check_if_ready;
+	file_class->get_file_type = desktop_directory_file_get_file_type;
+	file_class->get_item_count = desktop_directory_file_get_item_count;
+	file_class->get_deep_counts = desktop_directory_file_get_deep_counts;
+	file_class->get_date = desktop_directory_file_get_date;
+	file_class->get_where_string = desktop_directory_file_get_where_string;
+}
Index: libnautilus-private/nautilus-desktop-directory-file.h
===================================================================
RCS file: libnautilus-private/nautilus-desktop-directory-file.h
diff -N libnautilus-private/nautilus-desktop-directory-file.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libnautilus-private/nautilus-desktop-directory-file.h	15 May 2003 17:08:04 -0000
@@ -0,0 +1,55 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+   nautilus-desktop-directory-file.h: Subclass of NautilusFile to implement the
+   the case of the desktop directory
+ 
+   Copyright (C) 2003 Red Hat, Inc.
+  
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+  
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+  
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+  
+   Author: Alexander Larsson <alexl redhat com>
+*/
+
+#ifndef NAUTILUS_DESKTOP_DIRECTORY_FILE_H
+#define NAUTILUS_DESKTOP_DIRECTORY_FILE_H
+
+#include <libnautilus-private/nautilus-file.h>
+
+#define NAUTILUS_TYPE_DESKTOP_DIRECTORY_FILE \
+	(nautilus_desktop_directory_file_get_type ())
+#define NAUTILUS_DESKTOP_DIRECTORY_FILE(obj) \
+	(GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_DESKTOP_DIRECTORY_FILE, NautilusDesktopDirectoryFile))
+#define NAUTILUS_DESKTOP_DIRECTORY_FILE_CLASS(klass) \
+	(GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_DESKTOP_DIRECTORY_FILE, NautilusDesktopDirectoryFileClass))
+#define NAUTILUS_IS_DESKTOP_DIRECTORY_FILE(obj) \
+	(GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_DESKTOP_DIRECTORY_FILE))
+#define NAUTILUS_IS_DESKTOP_DIRECTORY_FILE_CLASS(klass) \
+	(GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_DESKTOP_DIRECTORY_FILE))
+
+typedef struct NautilusDesktopDirectoryFileDetails NautilusDesktopDirectoryFileDetails;
+
+typedef struct {
+	NautilusFile parent_slot;
+	NautilusDesktopDirectoryFileDetails *details;
+} NautilusDesktopDirectoryFile;
+
+typedef struct {
+	NautilusFileClass parent_slot;
+} NautilusDesktopDirectoryFileClass;
+
+GType   nautilus_desktop_directory_file_get_type (void);
+
+#endif /* NAUTILUS_DESKTOP_DIRECTORY_FILE_H */
Index: libnautilus-private/nautilus-desktop-directory.c
===================================================================
RCS file: libnautilus-private/nautilus-desktop-directory.c
diff -N libnautilus-private/nautilus-desktop-directory.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libnautilus-private/nautilus-desktop-directory.c	15 May 2003 17:08:04 -0000
@@ -0,0 +1,496 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+   nautilus-desktop-directory.c: Subclass of NautilusDirectory to implement
+   a virtual directory consisting of the desktop directory and the desktop
+   icons
+ 
+   Copyright (C) 2003 Red Hat, Inc.
+  
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+  
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+  
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+  
+   Author: Alexander Larsson <alexl redhat com>
+*/
+
+#include <config.h>
+#include "nautilus-desktop-directory.h"
+
+#include "nautilus-directory-private.h"
+#include "nautilus-file.h"
+#include "nautilus-file-private.h"
+#include "nautilus-file-utilities.h"
+#include <eel/eel-glib-extensions.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+#include <gtk/gtksignal.h>
+#include <libgnome/gnome-macros.h>
+
+struct NautilusDesktopDirectoryDetails {
+	NautilusDirectory *real_directory;
+	GHashTable *callbacks;
+	GHashTable *monitors;
+};
+
+typedef struct {
+	NautilusDesktopDirectory *desktop_dir;
+	NautilusDirectoryCallback callback;
+	gpointer callback_data;
+
+	NautilusFileAttributes wait_for_attributes;
+	gboolean wait_for_file_list;
+
+	GList *non_ready_directories;
+	GList *merged_file_list;
+} MergedCallback;
+
+
+typedef struct {
+	NautilusDesktopDirectory *desktop_dir;
+
+	gboolean monitor_hidden_files;
+	gboolean monitor_backup_files;
+	NautilusFileAttributes monitor_attributes;
+} MergedMonitor;
+
+
+GNOME_CLASS_BOILERPLATE (NautilusDesktopDirectory, nautilus_desktop_directory,
+			 NautilusDirectory, NAUTILUS_TYPE_DIRECTORY)
+
+
+static gboolean
+desktop_contains_file (NautilusDirectory *directory,
+		       NautilusFile *file)
+{
+	NautilusDesktopDirectory *desktop;
+
+	desktop = NAUTILUS_DESKTOP_DIRECTORY (directory);
+
+	if (nautilus_directory_contains_file (desktop->details->real_directory, file)) {
+		return TRUE;
+	}
+
+	return file->details->directory == directory;
+}
+
+static guint
+merged_callback_hash (gconstpointer merged_callback_as_pointer)
+{
+	const MergedCallback *merged_callback;
+
+	merged_callback = merged_callback_as_pointer;
+	return GPOINTER_TO_UINT (merged_callback->callback)
+		^ GPOINTER_TO_UINT (merged_callback->callback_data);
+}
+
+static gboolean
+merged_callback_equal (gconstpointer merged_callback_as_pointer,
+		       gconstpointer merged_callback_as_pointer_2)
+{
+	const MergedCallback *merged_callback, *merged_callback_2;
+
+	merged_callback = merged_callback_as_pointer;
+	merged_callback_2 = merged_callback_as_pointer_2;
+
+	return merged_callback->callback == merged_callback_2->callback
+		&& merged_callback->callback_data == merged_callback_2->callback_data;
+}
+
+static void
+merged_callback_destroy (MergedCallback *merged_callback)
+{
+	g_assert (merged_callback != NULL);
+	g_assert (NAUTILUS_IS_DESKTOP_DIRECTORY (merged_callback->desktop_dir));
+
+	g_list_free (merged_callback->non_ready_directories);
+	nautilus_file_list_free (merged_callback->merged_file_list);
+	g_free (merged_callback);
+}
+
+static void
+merged_callback_check_done (MergedCallback *merged_callback)
+{
+	/* Check if we are ready. */
+	if (merged_callback->non_ready_directories != NULL) {
+		return;
+	}
+
+	/* Remove from the hash table before sending it. */
+	g_hash_table_steal (merged_callback->desktop_dir->details->callbacks, merged_callback);
+
+	/* We are ready, so do the real callback. */
+	(* merged_callback->callback) (NAUTILUS_DIRECTORY (merged_callback->desktop_dir),
+				       merged_callback->merged_file_list,
+				       merged_callback->callback_data);
+
+	/* And we are done. */
+	merged_callback_destroy (merged_callback);
+}
+
+static void
+merged_callback_remove_directory (MergedCallback *merged_callback,
+				  NautilusDirectory *directory)
+{
+	merged_callback->non_ready_directories = g_list_remove
+		(merged_callback->non_ready_directories, directory);
+	merged_callback_check_done (merged_callback);
+}
+
+static void
+directory_ready_callback (NautilusDirectory *directory,
+			  GList *files,
+			  gpointer callback_data)
+{
+	MergedCallback *merged_callback;
+
+	g_assert (NAUTILUS_IS_DIRECTORY (directory));
+	g_assert (callback_data != NULL);
+
+	merged_callback = callback_data;
+	g_assert (g_list_find (merged_callback->non_ready_directories, directory) != NULL);
+
+	/* Update based on this call. */
+	merged_callback->merged_file_list = g_list_concat
+		(merged_callback->merged_file_list,
+		 nautilus_file_list_copy (files));
+
+	/* Check if we are ready. */
+	merged_callback_remove_directory (merged_callback, directory);
+}
+
+static void
+desktop_call_when_ready (NautilusDirectory *directory,
+			 NautilusFileAttributes file_attributes,
+			 gboolean wait_for_file_list,
+			 NautilusDirectoryCallback callback,
+			 gpointer callback_data)
+{
+	NautilusDesktopDirectory *desktop;
+	MergedCallback search_key, *merged_callback;
+
+	desktop = NAUTILUS_DESKTOP_DIRECTORY (directory);
+
+	/* Check to be sure we aren't overwriting. */
+	search_key.callback = callback;
+	search_key.callback_data = callback_data;
+	if (g_hash_table_lookup (desktop->details->callbacks, &search_key) != NULL) {
+		g_warning ("tried to add a new callback while an old one was pending");
+		return;
+	}
+
+	/* Create a merged_callback record. */
+	merged_callback = g_new0 (MergedCallback, 1);
+	merged_callback->desktop_dir = desktop;
+	merged_callback->callback = callback;
+	merged_callback->callback_data = callback_data;
+	merged_callback->wait_for_attributes = file_attributes;
+	merged_callback->wait_for_file_list = wait_for_file_list;
+	merged_callback->non_ready_directories = g_list_prepend
+			(merged_callback->non_ready_directories, directory);
+	merged_callback->non_ready_directories = g_list_prepend
+			(merged_callback->non_ready_directories, desktop->details->real_directory);
+
+
+	merged_callback->merged_file_list = g_list_concat (NULL,
+							   nautilus_file_list_copy (directory->details->file_list));
+
+	/* Put it in the hash table. */
+	g_hash_table_insert (desktop->details->callbacks,
+			     merged_callback, merged_callback);
+
+	/* Now tell all the directories about it. */
+	nautilus_directory_call_when_ready
+		(desktop->details->real_directory,
+		 merged_callback->wait_for_attributes,
+		 merged_callback->wait_for_file_list,
+		 directory_ready_callback, merged_callback);
+	nautilus_directory_call_when_ready_internal
+		(directory,
+		 NULL,
+		 merged_callback->wait_for_attributes,
+		 merged_callback->wait_for_file_list,
+		 directory_ready_callback,
+		 NULL,
+		 merged_callback);
+	
+}
+
+static void
+desktop_cancel_callback (NautilusDirectory *directory,
+			NautilusDirectoryCallback callback,
+			gpointer callback_data)
+{
+	NautilusDesktopDirectory *desktop;
+	MergedCallback search_key, *merged_callback;
+	GList *node;
+
+	desktop = NAUTILUS_DESKTOP_DIRECTORY (directory);
+
+	/* Find the entry in the table. */
+	search_key.callback = callback;
+	search_key.callback_data = callback_data;
+	merged_callback = g_hash_table_lookup (desktop->details->callbacks, &search_key);
+	if (merged_callback == NULL) {
+		return;
+	}
+
+	/* Remove from the hash table before working with it. */
+	g_hash_table_steal (merged_callback->desktop_dir->details->callbacks, merged_callback);
+
+	/* Tell all the directories to cancel the call. */
+	for (node = merged_callback->non_ready_directories; node != NULL; node = node->next) {
+		nautilus_directory_cancel_callback
+			(node->data,
+			 directory_ready_callback, merged_callback);
+	}
+	merged_callback_destroy (merged_callback);
+}
+
+static void
+merged_monitor_destroy (MergedMonitor *monitor)
+{
+	NautilusDesktopDirectory *desktop;
+
+	desktop = monitor->desktop_dir;
+	
+	/* Call through to the real directory remove calls. */
+	nautilus_directory_file_monitor_remove (desktop->details->real_directory, monitor);
+
+	nautilus_directory_monitor_remove_internal (NAUTILUS_DIRECTORY (desktop), NULL, monitor);
+	
+	g_free (monitor);
+}
+
+static void
+build_merged_callback_list (NautilusDirectory *directory,
+			    GList *file_list,
+			    gpointer callback_data)
+{
+	GList **merged_list;
+
+	merged_list = callback_data;
+	*merged_list = g_list_concat (*merged_list,
+				      nautilus_file_list_copy (file_list));
+}
+
+static void
+desktop_monitor_add (NautilusDirectory *directory,
+		    gconstpointer client,
+		    gboolean monitor_hidden_files,
+		    gboolean monitor_backup_files,
+		    NautilusFileAttributes file_attributes,
+		    NautilusDirectoryCallback callback,
+		    gpointer callback_data)
+{
+	NautilusDesktopDirectory *desktop;
+	MergedMonitor *monitor;
+	GList *merged_callback_list;
+
+	desktop = NAUTILUS_DESKTOP_DIRECTORY (directory);
+
+	/* Map the client to a unique value so this doesn't interfere
+	 * with direct monitoring of the directory by the same client.
+	 */
+	monitor = g_hash_table_lookup (desktop->details->monitors, client);
+	if (monitor != NULL) {
+		g_assert (monitor->desktop_dir == desktop);
+	} else {
+		monitor = g_new0 (MergedMonitor, 1);
+		monitor->desktop_dir = desktop;
+		g_hash_table_insert (desktop->details->monitors,
+				     (gpointer) client, monitor);
+	}
+	monitor->monitor_hidden_files = monitor_hidden_files;
+	monitor->monitor_backup_files = monitor_backup_files;
+	monitor->monitor_attributes = file_attributes;
+	
+	/* Call through to the real directory add calls. */
+	merged_callback_list = NULL;
+
+	/* Call up to real dir */
+	nautilus_directory_file_monitor_add
+		(desktop->details->real_directory, monitor,
+		 monitor_hidden_files, monitor_backup_files,
+		 file_attributes,
+		 build_merged_callback_list, &merged_callback_list);
+	
+	/* Handle the desktop part */
+	merged_callback_list = g_list_concat (merged_callback_list,
+					      nautilus_file_list_copy (directory->details->file_list));
+
+	
+	if (callback != NULL) {
+		(* callback) (directory, merged_callback_list, callback_data);
+	}
+	nautilus_file_list_free (merged_callback_list);
+}
+
+static void
+desktop_monitor_remove (NautilusDirectory *directory,
+		       gconstpointer client)
+{
+	NautilusDesktopDirectory *desktop;
+	MergedMonitor *monitor;
+	
+	desktop = NAUTILUS_DESKTOP_DIRECTORY (directory);
+
+	monitor = g_hash_table_lookup (desktop->details->monitors, client);
+	if (monitor == NULL) {
+		return;
+	}
+	
+	g_hash_table_remove (desktop->details->monitors, client);
+}
+
+static void
+desktop_force_reload (NautilusDirectory *directory)
+{
+	NautilusDesktopDirectory *desktop;
+
+	desktop = NAUTILUS_DESKTOP_DIRECTORY (directory);
+
+	nautilus_directory_force_reload (desktop->details->real_directory);
+
+	/* We don't invalidate the files in desktop, since they are always
+	   up to date. (And we don't ever want to mark them invalid.) */
+}
+
+static gboolean
+desktop_are_all_files_seen (NautilusDirectory *directory)
+{
+	NautilusDesktopDirectory *desktop;
+
+	desktop = NAUTILUS_DESKTOP_DIRECTORY (directory);
+
+	if (!nautilus_directory_are_all_files_seen (desktop->details->real_directory)) {
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean
+desktop_is_not_empty (NautilusDirectory *directory)
+{
+	NautilusDesktopDirectory *desktop;
+
+	desktop = NAUTILUS_DESKTOP_DIRECTORY (directory);
+
+	if (nautilus_directory_is_not_empty (desktop->details->real_directory)) {
+		return TRUE;
+	}
+
+	return directory->details->file_list != NULL;
+}
+
+NautilusDirectory *
+nautilus_desktop_directory_get_real_directory (NautilusDesktopDirectory *desktop)
+{
+	nautilus_directory_ref (desktop->details->real_directory);
+	return desktop->details->real_directory;
+}
+
+
+static void
+desktop_finalize (GObject *object)
+{
+	NautilusDesktopDirectory *desktop;
+
+	desktop = NAUTILUS_DESKTOP_DIRECTORY (object);
+
+	nautilus_directory_unref (desktop->details->real_directory);
+	g_free (desktop->details);
+
+	g_hash_table_destroy (desktop->details->callbacks);
+	g_hash_table_destroy (desktop->details->monitors);
+	
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+done_loading_callback (NautilusDirectory *real_directory,
+		       NautilusDesktopDirectory *desktop)
+{
+     nautilus_directory_emit_done_loading (NAUTILUS_DIRECTORY (desktop));
+}
+
+
+static void
+forward_files_added_cover (NautilusDirectory *real_directory,
+			   GList *files,
+			   gpointer callback_data)
+{
+	nautilus_directory_emit_files_added (NAUTILUS_DIRECTORY (callback_data), files);
+}
+
+static void
+forward_files_changed_cover (NautilusDirectory *real_directory,
+			     GList *files,
+			     gpointer callback_data)
+{
+	nautilus_directory_emit_files_changed (NAUTILUS_DIRECTORY (callback_data), files);
+}
+
+
+static void
+nautilus_desktop_directory_instance_init (NautilusDesktopDirectory *desktop)
+{
+	char *desktop_path;
+	char *desktop_uri;
+	NautilusDirectory *real_directory;
+	
+	desktop->details = g_new0 (NautilusDesktopDirectoryDetails, 1);
+
+	desktop_path = nautilus_get_desktop_directory ();
+	desktop_uri = gnome_vfs_get_uri_from_local_path (desktop_path);
+	desktop->details->real_directory = nautilus_directory_get (desktop_uri);
+	g_free (desktop_uri);
+	g_free (desktop_path);
+
+	desktop->details->callbacks = g_hash_table_new_full
+		(merged_callback_hash, merged_callback_equal,
+		 NULL, (GDestroyNotify)merged_callback_destroy);
+	desktop->details->monitors = g_hash_table_new_full (NULL, NULL,
+							    NULL, (GDestroyNotify)merged_monitor_destroy);
+
+	real_directory = desktop->details->real_directory;
+	
+	g_signal_connect_object (real_directory, "done_loading",
+				 G_CALLBACK (done_loading_callback), desktop, 0);
+
+	g_signal_connect_object (real_directory, "files_added",
+				 G_CALLBACK (forward_files_added_cover), desktop, 0);
+	g_signal_connect_object (real_directory, "files_changed",
+				 G_CALLBACK (forward_files_changed_cover), desktop, 0);
+
+}
+
+static void
+nautilus_desktop_directory_class_init (NautilusDesktopDirectoryClass *class)
+{
+	NautilusDirectoryClass *directory_class;
+
+	directory_class = NAUTILUS_DIRECTORY_CLASS (class);
+	
+	G_OBJECT_CLASS (class)->finalize = desktop_finalize;
+
+	directory_class->contains_file = desktop_contains_file;
+	directory_class->call_when_ready = desktop_call_when_ready;
+	directory_class->cancel_callback = desktop_cancel_callback;
+	directory_class->file_monitor_add = desktop_monitor_add;
+	directory_class->file_monitor_remove = desktop_monitor_remove;
+	directory_class->force_reload = desktop_force_reload;
+ 	directory_class->are_all_files_seen = desktop_are_all_files_seen;
+	directory_class->is_not_empty = desktop_is_not_empty;
+}
+     
Index: libnautilus-private/nautilus-desktop-directory.h
===================================================================
RCS file: libnautilus-private/nautilus-desktop-directory.h
diff -N libnautilus-private/nautilus-desktop-directory.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libnautilus-private/nautilus-desktop-directory.h	15 May 2003 17:08:04 -0000
@@ -0,0 +1,58 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+   nautilus-desktop-directory.h: Subclass of NautilusDirectory to implement
+   a virtual directory consisting of the desktop directory and the desktop
+   icons
+ 
+   Copyright (C) 2003 Red Hat, Inc.
+  
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+  
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+  
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+  
+   Author: Alexander Larsson <alexl redhat com>
+*/
+
+#ifndef NAUTILUS_DESKTOP_DIRECTORY_H
+#define NAUTILUS_DESKTOP_DIRECTORY_H
+
+#include <libnautilus-private/nautilus-directory.h>
+
+#define NAUTILUS_TYPE_DESKTOP_DIRECTORY \
+	(nautilus_desktop_directory_get_type ())
+#define NAUTILUS_DESKTOP_DIRECTORY(obj) \
+	(GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_DESKTOP_DIRECTORY, NautilusDesktopDirectory))
+#define NAUTILUS_DESKTOP_DIRECTORY_CLASS(klass) \
+	(GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_DESKTOP_DIRECTORY, NautilusDesktopDirectoryClass))
+#define NAUTILUS_IS_DESKTOP_DIRECTORY(obj) \
+	(GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_DESKTOP_DIRECTORY))
+#define NAUTILUS_IS_DESKTOP_DIRECTORY_CLASS(klass) \
+	(GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_DESKTOP_DIRECTORY))
+
+typedef struct NautilusDesktopDirectoryDetails NautilusDesktopDirectoryDetails;
+
+typedef struct {
+	NautilusDirectory parent_slot;
+	NautilusDesktopDirectoryDetails *details;
+} NautilusDesktopDirectory;
+
+typedef struct {
+	NautilusDirectoryClass parent_slot;
+
+} NautilusDesktopDirectoryClass;
+
+GType   nautilus_desktop_directory_get_type             (void);
+NautilusDirectory * nautilus_desktop_directory_get_real_directory   (NautilusDesktopDirectory *desktop_directory);
+
+#endif /* NAUTILUS_DESKTOP_DIRECTORY_H */
Index: libnautilus-private/nautilus-desktop-icon-file.c
===================================================================
RCS file: libnautilus-private/nautilus-desktop-icon-file.c
diff -N libnautilus-private/nautilus-desktop-icon-file.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libnautilus-private/nautilus-desktop-icon-file.c	15 May 2003 17:08:04 -0000
@@ -0,0 +1,344 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+   nautilus-desktop-icon-file.c: Subclass of NautilusFile to help implement the
+   virtual desktop icons.
+ 
+   Copyright (C) 2003 Red Hat, Inc.
+  
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+  
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+  
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+  
+   Author: Alexander Larsson <alexl redhat com>
+*/
+
+#include <config.h>
+#include "nautilus-desktop-icon-file.h"
+
+#include "nautilus-directory-notify.h"
+#include "nautilus-directory-private.h"
+#include "nautilus-file-attributes.h"
+#include "nautilus-file-private.h"
+#include "nautilus-file-utilities.h"
+#include <eel/eel-glib-extensions.h>
+#include <eel/eel-gtk-macros.h>
+#include "nautilus-desktop-directory.h"
+#include <gtk/gtksignal.h>
+#include <libgnome/gnome-i18n.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <string.h>
+
+struct NautilusDesktopIconFileDetails {
+	NautilusDesktopLink *link;
+};
+
+static void nautilus_desktop_icon_file_init       (gpointer   object,
+						   gpointer   klass);
+static void nautilus_desktop_icon_file_class_init (gpointer   klass);
+
+EEL_CLASS_BOILERPLATE (NautilusDesktopIconFile,
+		       nautilus_desktop_icon_file,
+		       NAUTILUS_TYPE_FILE)
+
+static void
+desktop_icon_file_monitor_add (NautilusFile *file,
+			       gconstpointer client,
+			       NautilusFileAttributes attributes)
+{
+	nautilus_directory_monitor_add_internal
+		(file->details->directory, file,
+		 client, TRUE, TRUE, attributes, NULL, NULL);
+}
+
+static void
+desktop_icon_file_monitor_remove (NautilusFile *file,
+				  gconstpointer client)
+{
+	nautilus_directory_monitor_remove_internal
+		(file->details->directory, file, client);
+}
+
+
+static void
+desktop_icon_file_call_when_ready (NautilusFile *file,
+				   NautilusFileAttributes attributes,
+				   NautilusFileCallback callback,
+				   gpointer callback_data)
+
+{
+	nautilus_directory_call_when_ready_internal
+		(file->details->directory, file,
+		 attributes, FALSE, NULL, callback, callback_data);
+}
+
+static void
+desktop_icon_file_cancel_call_when_ready (NautilusFile *file,
+					  NautilusFileCallback callback,
+					  gpointer callback_data)
+{
+	nautilus_directory_cancel_callback_internal
+		(file->details->directory, file,
+		 NULL, callback, callback_data);
+}
+
+static gboolean
+desktop_icon_file_check_if_ready (NautilusFile *file,
+				  NautilusFileAttributes attributes)
+{
+	return nautilus_directory_check_if_ready_internal
+		(file->details->directory, file,
+		 attributes);
+}
+
+static GnomeVFSFileType
+desktop_icon_file_get_file_type (NautilusFile *file)
+{
+	return GNOME_VFS_FILE_TYPE_REGULAR;
+}			      
+
+static gboolean
+desktop_icon_file_get_item_count (NautilusFile *file, 
+				  guint *count,
+				  gboolean *count_unreadable)
+{
+	if (count != NULL) {
+		*count = 0;
+	}
+	if (count_unreadable != NULL) {
+		*count_unreadable = FALSE;
+	}
+	return TRUE;
+}
+
+static NautilusRequestStatus
+desktop_icon_file_get_deep_counts (NautilusFile *file,
+				   guint *directory_count,
+				   guint *file_count,
+				   guint *unreadable_directory_count,
+				   GnomeVFSFileSize *total_size)
+{
+	if (directory_count != NULL) {
+		*directory_count = 0;
+	}
+	if (file_count != NULL) {
+		*file_count = 0;
+	}
+	if (unreadable_directory_count != NULL) {
+		*unreadable_directory_count = 0;
+	}
+	if (total_size != NULL) {
+		*total_size = 0;
+	}
+
+	return NAUTILUS_REQUEST_DONE;
+}
+
+static gboolean
+desktop_icon_file_get_date (NautilusFile *file,
+			    NautilusDateType date_type,
+			    time_t *date)
+{
+	NautilusDesktopIconFile *desktop_file;
+
+	desktop_file = NAUTILUS_DESKTOP_ICON_FILE (file);
+
+	return nautilus_desktop_link_get_date (desktop_file->details->link,
+					       date_type, date);
+}
+
+static char *
+desktop_icon_file_get_where_string (NautilusFile *file)
+{
+	return g_strdup (_("on the desktop"));
+}
+
+static void
+nautilus_desktop_icon_file_init (gpointer object, gpointer klass)
+{
+	NautilusDesktopIconFile *desktop_file;
+
+	desktop_file = NAUTILUS_DESKTOP_ICON_FILE (object);
+
+	desktop_file->details = g_new0 (NautilusDesktopIconFileDetails, 1);
+}	
+
+static void
+update_info_from_link (NautilusDesktopIconFile *icon_file)
+{
+	NautilusFile *file;
+	GnomeVFSFileInfo *file_info;
+	NautilusDesktopLink *link;
+	
+	file = NAUTILUS_FILE (icon_file);
+	
+	link = icon_file->details->link;
+
+	if (link == NULL) {
+		return;
+	}
+	
+	file_info = file->details->info;
+
+	gnome_vfs_file_info_clear (file_info);
+
+	file_info->name = nautilus_desktop_link_get_file_name (link);
+	file_info->mime_type = g_strdup ("application/x-nautilus-link");
+	file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
+	file_info->flags = GNOME_VFS_FILE_FLAGS_NONE;
+	file_info->link_count = 1;
+	file_info->size = 0;
+	
+	file_info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
+		GNOME_VFS_FILE_INFO_FIELDS_FLAGS |
+		GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE |
+		GNOME_VFS_FILE_INFO_FIELDS_SIZE |
+		GNOME_VFS_FILE_INFO_FIELDS_LINK_COUNT;
+	
+	file->details->file_info_is_up_to_date = TRUE;
+
+	g_free (file->details->display_name);
+	file->details->display_name = nautilus_desktop_link_get_display_name (link);
+	g_free (file->details->custom_icon);
+	file->details->custom_icon = nautilus_desktop_link_get_icon (link);
+	g_free (file->details->activation_uri);
+	file->details->activation_uri = nautilus_desktop_link_get_activation_uri (link);
+	file->details->got_link_info = TRUE;
+	file->details->link_info_is_up_to_date = TRUE;
+
+	file->details->directory_count = 0;
+	file->details->got_directory_count = TRUE;
+	file->details->directory_count_is_up_to_date = TRUE;
+}
+
+void
+nautilus_desktop_icon_file_update (NautilusDesktopIconFile *icon_file)
+{
+	NautilusFile *file;
+	
+	update_info_from_link (icon_file);
+	file = NAUTILUS_FILE (icon_file);
+	nautilus_file_clear_cached_display_name (file);
+	nautilus_file_changed (file);
+}
+
+void
+nautilus_desktop_icon_file_remove (NautilusDesktopIconFile *icon_file)
+{
+	NautilusFile *file;
+	GList list;
+
+	icon_file->details->link = NULL;
+
+	file = NAUTILUS_FILE (icon_file);
+	
+	/* ref here because we might be removing the last ref when we
+	 * mark the file gone below, but we need to keep a ref at
+	 * least long enough to send the change notification. 
+	 */
+	nautilus_file_ref (file);
+	
+	file->details->is_gone = TRUE;
+	
+	list.data = file;
+	list.next = NULL;
+	list.prev = NULL;
+	
+	nautilus_directory_remove_file (file->details->directory, file);
+	nautilus_directory_emit_change_signals (file->details->directory, &list);
+	
+	nautilus_file_unref (file);
+}
+
+
+NautilusDesktopIconFile *
+nautilus_desktop_icon_file_new (NautilusDesktopLink *link)
+{
+	NautilusFile *file;
+	NautilusDirectory *directory;
+	NautilusDesktopIconFile *icon_file;
+	char *name;
+	GList list;
+	
+	directory = nautilus_directory_get (EEL_DESKTOP_URI);
+
+	file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_DESKTOP_ICON_FILE, NULL));
+
+#ifdef NAUTILUS_FILE_DEBUG_REF
+	printf("%10p ref'd\n", file);
+	eazel_dump_stack_trace ("\t", 10);
+#endif
+
+	nautilus_directory_ref (directory);
+	file->details->directory = directory;
+
+	icon_file = NAUTILUS_DESKTOP_ICON_FILE (file);
+	icon_file->details->link = link;
+
+	file->details->info = gnome_vfs_file_info_new ();
+	name = nautilus_desktop_link_get_file_name (link);
+	file->details->relative_uri = gnome_vfs_escape_string (name);
+	g_free (name);
+
+	update_info_from_link (icon_file);
+	
+	nautilus_directory_add_file (directory, file);
+
+	list.data = file;
+	list.next = NULL;
+	list.prev = NULL;
+	nautilus_directory_emit_files_added (directory, &list);
+
+	return icon_file;
+}
+
+NautilusDesktopLink *
+nautilus_desktop_icon_file_get_link (NautilusDesktopIconFile *icon_file)
+{
+	return g_object_ref (icon_file->details->link);
+}
+
+static void
+desktop_finalize (GObject *object)
+{
+	NautilusDesktopIconFile *desktop_file;
+
+	desktop_file = NAUTILUS_DESKTOP_ICON_FILE (object);
+
+	g_free (desktop_file->details);
+
+	EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
+}
+
+static void
+nautilus_desktop_icon_file_class_init (gpointer klass)
+{
+	GObjectClass *object_class;
+	NautilusFileClass *file_class;
+
+	object_class = G_OBJECT_CLASS (klass);
+	file_class = NAUTILUS_FILE_CLASS (klass);
+	
+	object_class->finalize = desktop_finalize;
+
+	file_class->monitor_add = desktop_icon_file_monitor_add;
+	file_class->monitor_remove = desktop_icon_file_monitor_remove;
+	file_class->call_when_ready = desktop_icon_file_call_when_ready;
+	file_class->cancel_call_when_ready = desktop_icon_file_cancel_call_when_ready;
+	file_class->check_if_ready = desktop_icon_file_check_if_ready;
+	file_class->get_file_type = desktop_icon_file_get_file_type;
+	file_class->get_item_count = desktop_icon_file_get_item_count;
+	file_class->get_deep_counts = desktop_icon_file_get_deep_counts;
+	file_class->get_date = desktop_icon_file_get_date;
+	file_class->get_where_string = desktop_icon_file_get_where_string;
+}
Index: libnautilus-private/nautilus-desktop-icon-file.h
===================================================================
RCS file: libnautilus-private/nautilus-desktop-icon-file.h
diff -N libnautilus-private/nautilus-desktop-icon-file.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libnautilus-private/nautilus-desktop-icon-file.h	15 May 2003 17:08:04 -0000
@@ -0,0 +1,61 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+   nautilus-desktop-file.h: Subclass of NautilusFile to implement the
+   the case of a desktop icon file
+ 
+   Copyright (C) 2003 Red Hat, Inc.
+  
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+  
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+  
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+  
+   Author: Alexander Larsson <alexl redhat com>
+*/
+
+#ifndef NAUTILUS_DESKTOP_ICON_FILE_H
+#define NAUTILUS_DESKTOP_ICON_FILE_H
+
+#include <libnautilus-private/nautilus-file.h>
+#include <libnautilus-private/nautilus-desktop-link.h>
+
+#define NAUTILUS_TYPE_DESKTOP_ICON_FILE \
+	(nautilus_desktop_icon_file_get_type ())
+#define NAUTILUS_DESKTOP_ICON_FILE(obj) \
+	(GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_DESKTOP_ICON_FILE, NautilusDesktopIconFile))
+#define NAUTILUS_DESKTOP_ICON_FILE_CLASS(klass) \
+	(GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_DESKTOP_ICON_FILE, NautilusDesktopIconFileClass))
+#define NAUTILUS_IS_DESKTOP_ICON_FILE(obj) \
+	(GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_DESKTOP_ICON_FILE))
+#define NAUTILUS_IS_DESKTOP_ICON_FILE_CLASS(klass) \
+	(GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_DESKTOP_ICON_FILE))
+
+typedef struct NautilusDesktopIconFileDetails NautilusDesktopIconFileDetails;
+
+typedef struct {
+	NautilusFile parent_slot;
+	NautilusDesktopIconFileDetails *details;
+} NautilusDesktopIconFile;
+
+typedef struct {
+	NautilusFileClass parent_slot;
+} NautilusDesktopIconFileClass;
+
+GType   nautilus_desktop_icon_file_get_type (void);
+
+NautilusDesktopIconFile *nautilus_desktop_icon_file_new      (NautilusDesktopLink     *link);
+void                     nautilus_desktop_icon_file_update   (NautilusDesktopIconFile *icon_file);
+void                     nautilus_desktop_icon_file_remove   (NautilusDesktopIconFile *icon_file);
+NautilusDesktopLink     *nautilus_desktop_icon_file_get_link (NautilusDesktopIconFile *icon_file);
+
+#endif /* NAUTILUS_DESKTOP_ICON_FILE_H */
Index: libnautilus-private/nautilus-desktop-link-monitor.c
===================================================================
RCS file: libnautilus-private/nautilus-desktop-link-monitor.c
diff -N libnautilus-private/nautilus-desktop-link-monitor.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libnautilus-private/nautilus-desktop-link-monitor.c	15 May 2003 17:08:04 -0000
@@ -0,0 +1,354 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+   nautilus-desktop-link-monitor.c: singleton thatn manages the links
+    
+   Copyright (C) 2003 Red Hat, Inc.
+  
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+  
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+  
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+  
+   Author: Alexander Larsson <alexl redhat com>
+*/
+
+#include <config.h>
+#include "nautilus-desktop-link-monitor.h"
+#include "nautilus-desktop-link.h"
+#include "nautilus-desktop-icon-file.h"
+#include "nautilus-directory.h"
+#include "nautilus-desktop-directory.h"
+#include "nautilus-global-preferences.h"
+
+#include <eel/eel-gtk-macros.h>
+#include <eel/eel-glib-extensions.h>
+#include <eel/eel-vfs-extensions.h>
+#include <eel/eel-stock-dialogs.h>
+#include <gtk/gtksignal.h>
+#include <gtk/gtkstock.h>
+#include <libgnome/gnome-i18n.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <libnautilus-private/nautilus-trash-monitor.h>
+#include <string.h>
+
+struct NautilusDesktopLinkMonitorDetails {
+	NautilusDirectory *desktop_dir;
+	
+	NautilusDesktopLink *home_link;
+	NautilusDesktopLink *trash_link;
+
+	GList *volume_links;
+
+	GList *mount_black_list;
+};
+
+
+static void nautilus_desktop_link_monitor_init       (gpointer              object,
+						      gpointer              klass);
+static void nautilus_desktop_link_monitor_class_init (gpointer              klass);
+
+EEL_CLASS_BOILERPLATE (NautilusDesktopLinkMonitor,
+		       nautilus_desktop_link_monitor,
+		       G_TYPE_OBJECT)
+
+static NautilusDesktopLinkMonitor *link_monitor = NULL;
+     
+NautilusDesktopLinkMonitor *
+nautilus_desktop_link_monitor_get (void)
+{
+	if (link_monitor == NULL) {
+		link_monitor = NAUTILUS_DESKTOP_LINK_MONITOR (g_object_new (NAUTILUS_TYPE_DESKTOP_LINK_MONITOR, NULL));
+	}
+	return link_monitor;
+}
+
+void
+nautilus_desktop_link_monitor_delete_link (NautilusDesktopLinkMonitor *monitor,
+					   NautilusDesktopLink *link,
+					   GtkWidget *parent_view)
+{
+	/* FIXME: Is this right? How to get them back?
+	 * Do we disallow this, or add a prefs ui to get them back? */
+	
+	switch (nautilus_desktop_link_get_link_type (link)) {
+	case NAUTILUS_DESKTOP_LINK_HOME:
+		eel_preferences_set_boolean (NAUTILUS_PREFERENCES_DESKTOP_HOME_VISIBLE, FALSE);
+		break;
+	case NAUTILUS_DESKTOP_LINK_TRASH:
+		eel_preferences_set_boolean (NAUTILUS_PREFERENCES_DESKTOP_TRASH_VISIBLE, FALSE);
+		break;
+	default:
+		eel_run_simple_dialog
+			(parent_view, 
+			 FALSE,
+			 _("You cannot delete a volume icon. If you want to eject "
+			   "the volume, please use Eject in the right-click menu of "
+			   "the volume."), 
+			 _("Can't delete volume"),
+			 GTK_STOCK_OK, NULL);
+		break;
+	}
+}
+
+
+static gboolean
+volume_in_black_list (NautilusDesktopLinkMonitor *monitor,
+		      const NautilusVolume *volume)
+{
+	GList *p;
+	
+	g_return_val_if_fail (NAUTILUS_IS_DESKTOP_LINK_MONITOR (monitor), TRUE);
+
+	for (p = monitor->details->mount_black_list; p != NULL; p = p->next) {
+		if (strcmp ((char *) p->data, nautilus_volume_get_mount_path (volume)) == 0) {
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
+static gboolean
+volume_name_exists (NautilusDesktopLinkMonitor *monitor,
+		    const char *name)
+{
+	GList *l;
+	char *other_name;
+	
+	for (l = monitor->details->volume_links; l != NULL; l = l->next) {
+		other_name = nautilus_desktop_link_get_display_name (l->data);
+		if (strcmp (name, other_name) == 0) {
+			g_free (other_name);
+			return TRUE;
+		}
+		g_free (other_name);
+	}
+	return FALSE;
+}
+
+static void
+create_volume_link (NautilusDesktopLinkMonitor *monitor,
+		    const NautilusVolume *volume)
+{
+	NautilusDesktopLink *link;
+	char *volume_name;
+	char *unique_name;
+	int index;
+	
+	if (volume_in_black_list (monitor, volume)) {
+		return;
+	}
+
+	/* FIXME bugzilla.gnome.org 45412: Design a comprehensive desktop mounting strategy */
+	if (!nautilus_volume_is_removable (volume)) {
+		return;
+	}
+
+	volume_name = nautilus_volume_get_name (volume);
+	index = 1;
+
+	unique_name = g_strdup (volume_name);
+	while (volume_name_exists (monitor, volume_name)) {
+		g_free (unique_name);
+		unique_name = g_strdup_printf ("%s (%d)", volume_name, index);
+	}
+
+	if (index != 1) {
+		nautilus_volume_monitor_set_volume_name (nautilus_volume_monitor_get (),
+							 volume, unique_name);
+	}
+	g_free (volume_name);
+	g_free (unique_name);
+	
+	link = nautilus_desktop_link_new_from_volume (volume);
+	monitor->details->volume_links = g_list_prepend (monitor->details->volume_links, link);
+}
+
+static gboolean
+create_one_volume_link (const NautilusVolume *volume, gpointer callback_data)
+{
+	create_volume_link (NAUTILUS_DESKTOP_LINK_MONITOR (callback_data),
+			    volume);
+	return TRUE;
+}
+
+
+static void
+volume_mounted_callback (NautilusVolumeMonitor *volume_monitor,
+			 NautilusVolume *volume, 
+			 NautilusDesktopLinkMonitor *monitor)
+{
+	create_volume_link (monitor, volume);
+}
+
+
+static void
+volume_unmounted_callback (NautilusVolumeMonitor *volume_monitor,
+			   NautilusVolume *volume, 
+			   NautilusDesktopLinkMonitor *monitor)
+{
+	GList *l;
+	NautilusDesktopLink *link;
+	char *mount_path;
+
+	link = NULL;
+	for (l = monitor->details->volume_links; l != NULL; l = l->next) {
+		mount_path = nautilus_desktop_link_get_mount_path (l->data);
+		
+		if (strcmp (mount_path, nautilus_volume_get_mount_path (volume)) == 0) {
+			link = l->data;
+			g_free (mount_path);
+			break;
+		}
+		g_free (mount_path);
+	}
+
+	if (link) {
+		g_object_unref (link);
+		monitor->details->volume_links = g_list_remove (monitor->details->volume_links, link);
+	}
+}
+
+
+static void
+desktop_home_visible_changed (gpointer callback_data)
+{
+	NautilusDesktopLinkMonitor *monitor;
+
+	monitor = NAUTILUS_DESKTOP_LINK_MONITOR (callback_data);
+
+	if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_HOME_VISIBLE)) {
+		if (monitor->details->home_link == NULL) {
+			monitor->details->home_link = nautilus_desktop_link_new (NAUTILUS_DESKTOP_LINK_HOME);
+		}
+	} else {
+		if (monitor->details->home_link != NULL) {
+			g_object_unref (monitor->details->home_link);
+			monitor->details->home_link = NULL;
+		}
+	}
+}
+
+static void
+desktop_trash_visible_changed (gpointer callback_data)
+{
+	NautilusDesktopLinkMonitor *monitor;
+
+	monitor = NAUTILUS_DESKTOP_LINK_MONITOR (callback_data);
+
+	if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_TRASH_VISIBLE)) {
+		if (monitor->details->trash_link == NULL) {
+			monitor->details->trash_link = nautilus_desktop_link_new (NAUTILUS_DESKTOP_LINK_TRASH);
+		}
+	} else {
+		if (monitor->details->trash_link != NULL) {
+			g_object_unref (monitor->details->trash_link);
+			monitor->details->trash_link = NULL;
+		}
+	}
+}
+
+static void
+nautilus_desktop_link_monitor_init (gpointer object, gpointer klass)
+{
+	NautilusDesktopLinkMonitor *monitor;
+	GList *list;
+
+	monitor = NAUTILUS_DESKTOP_LINK_MONITOR (object);
+
+	monitor->details = g_new0 (NautilusDesktopLinkMonitorDetails, 1);
+
+	/* Set up default mount black list */
+	list = g_list_prepend (NULL, g_strdup ("/proc"));
+	list = g_list_prepend (list, g_strdup ("/boot"));
+	monitor->details->mount_black_list = list;
+
+	/* We keep around a ref to the desktop dir */
+	monitor->details->desktop_dir = nautilus_directory_get (EEL_DESKTOP_URI);
+
+	if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_HOME_VISIBLE)) {
+		monitor->details->home_link = nautilus_desktop_link_new (NAUTILUS_DESKTOP_LINK_HOME);
+	}
+	
+	if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_TRASH_VISIBLE)) {
+		monitor->details->trash_link = nautilus_desktop_link_new (NAUTILUS_DESKTOP_LINK_TRASH);
+	}
+
+	nautilus_volume_monitor_each_mounted_volume (nautilus_volume_monitor_get (),
+					     	     create_one_volume_link,
+						     monitor);
+
+	eel_preferences_add_callback (NAUTILUS_PREFERENCES_DESKTOP_HOME_VISIBLE,
+				      desktop_home_visible_changed,
+				      monitor);
+	eel_preferences_add_callback (NAUTILUS_PREFERENCES_DESKTOP_TRASH_VISIBLE,
+				      desktop_trash_visible_changed,
+				      monitor);
+
+	
+	g_signal_connect_object (nautilus_volume_monitor_get (), "volume_mounted",
+				 G_CALLBACK (volume_mounted_callback), monitor, 0);
+	g_signal_connect_object (nautilus_volume_monitor_get (), "volume_unmounted",
+				 G_CALLBACK (volume_unmounted_callback), monitor, 0);
+
+}	
+
+static void
+desktop_link_monitor_finalize (GObject *object)
+{
+	NautilusDesktopLinkMonitor *monitor;
+
+	monitor = NAUTILUS_DESKTOP_LINK_MONITOR (object);
+
+	if (monitor->details->home_link != NULL) {
+		g_object_unref (monitor->details->home_link);
+		monitor->details->home_link = NULL;
+	}
+
+	if (monitor->details->trash_link != NULL) {
+		g_object_unref (monitor->details->home_link);
+		monitor->details->trash_link = NULL;
+	}
+
+	g_list_foreach (monitor->details->volume_links, (GFunc)g_object_unref, NULL);
+	g_list_free (monitor->details->volume_links);
+	monitor->details->volume_links = NULL;
+		
+	nautilus_directory_unref (monitor->details->desktop_dir);
+	monitor->details->desktop_dir = NULL;
+
+	eel_g_list_free_deep (monitor->details->mount_black_list);
+	monitor->details->mount_black_list = NULL;
+
+	eel_preferences_remove_callback (NAUTILUS_PREFERENCES_DESKTOP_HOME_VISIBLE,
+					 desktop_home_visible_changed,
+					 monitor);
+	eel_preferences_remove_callback (NAUTILUS_PREFERENCES_DESKTOP_TRASH_VISIBLE,
+					 desktop_trash_visible_changed,
+					 monitor);
+	
+	g_free (monitor->details);
+
+	EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
+}
+
+static void
+nautilus_desktop_link_monitor_class_init (gpointer klass)
+{
+	GObjectClass *object_class;
+
+	object_class = G_OBJECT_CLASS (klass);
+	
+	object_class->finalize = desktop_link_monitor_finalize;
+
+}
Index: libnautilus-private/nautilus-desktop-link-monitor.h
===================================================================
RCS file: libnautilus-private/nautilus-desktop-link-monitor.h
diff -N libnautilus-private/nautilus-desktop-link-monitor.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libnautilus-private/nautilus-desktop-link-monitor.h	15 May 2003 17:08:04 -0000
@@ -0,0 +1,60 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+   nautilus-desktop-link-monitor.h: singleton thatn manages the links
+    
+   Copyright (C) 2003 Red Hat, Inc.
+  
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+  
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+  
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+  
+   Author: Alexander Larsson <alexl redhat com>
+*/
+
+#ifndef NAUTILUS_DESKTOP_LINK_MONITOR_H
+#define NAUTILUS_DESKTOP_LINK_MONITOR_H
+
+#include <gtk/gtkwidget.h>
+#include <libnautilus-private/nautilus-desktop-link.h>
+
+#define NAUTILUS_TYPE_DESKTOP_LINK_MONITOR \
+	(nautilus_desktop_link_monitor_get_type ())
+#define NAUTILUS_DESKTOP_LINK_MONITOR(obj) \
+	(GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_DESKTOP_LINK_MONITOR, NautilusDesktopLinkMonitor))
+#define NAUTILUS_DESKTOP_LINK_MONITOR_CLASS(klass) \
+	(GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_DESKTOP_LINK_MONITOR, NautilusDesktopLinkMonitor))
+#define NAUTILUS_IS_DESKTOP_LINK_MONITOR(obj) \
+	(GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_DESKTOP_LINK_MONITOR))
+#define NAUTILUS_IS_DESKTOP_LINK_MONITOR_CLASS(klass) \
+	(GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_DESKTOP_LINK_MONITOR))
+
+typedef struct NautilusDesktopLinkMonitorDetails NautilusDesktopLinkMonitorDetails;
+
+typedef struct {
+	GObject parent_slot;
+	NautilusDesktopLinkMonitorDetails *details;
+} NautilusDesktopLinkMonitor;
+
+typedef struct {
+	GObjectClass parent_slot;
+} NautilusDesktopLinkMonitorClass;
+
+GType   nautilus_desktop_link_monitor_get_type (void);
+
+NautilusDesktopLinkMonitor *   nautilus_desktop_link_monitor_get (void);
+void nautilus_desktop_link_monitor_delete_link (NautilusDesktopLinkMonitor *monitor,
+						NautilusDesktopLink *link,
+						GtkWidget *parent_view);
+
+#endif /* NAUTILUS_DESKTOP_LINK_MONITOR_H */
Index: libnautilus-private/nautilus-desktop-link.c
===================================================================
RCS file: libnautilus-private/nautilus-desktop-link.c
diff -N libnautilus-private/nautilus-desktop-link.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libnautilus-private/nautilus-desktop-link.c	15 May 2003 17:08:04 -0000
@@ -0,0 +1,428 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+   nautilus-desktop-link.c: Class that handles the links on the desktop
+    
+   Copyright (C) 2003 Red Hat, Inc.
+  
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+  
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+  
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+  
+   Author: Alexander Larsson <alexl redhat com>
+*/
+
+#include <config.h>
+#include "nautilus-desktop-link.h"
+#include "nautilus-desktop-icon-file.h"
+#include "nautilus-directory-private.h"
+#include "nautilus-desktop-directory.h"
+
+#include <eel/eel-gtk-macros.h>
+#include <eel/eel-vfs-extensions.h>
+#include <gtk/gtksignal.h>
+#include <libgnome/gnome-i18n.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <libnautilus-private/nautilus-trash-monitor.h>
+#include <libnautilus-private/nautilus-global-preferences.h>
+#include <string.h>
+
+#define TRASH_EMPTY_ICON "gnome-fs-trash-empty"
+#define TRASH_FULL_ICON "gnome-fs-trash-full"
+
+struct NautilusDesktopLinkDetails {
+	NautilusDesktopLinkType type;
+        char *filename;
+	char *display_name;
+	char *activation_uri;
+	char *icon;
+
+	NautilusDesktopIconFile *icon_file;
+	
+	/* Just for trash icons: */
+	gulong trash_state_handler;
+
+	/* Just for volume icons: */
+	char *mount_path;
+};
+
+static void nautilus_desktop_link_init       (gpointer              object,
+					      gpointer              klass);
+static void nautilus_desktop_link_class_init (gpointer              klass);
+static void trash_state_changed_callback     (NautilusTrashMonitor *trash_monitor,
+					      gboolean              state,
+					      gpointer              callback_data);
+static void nautilus_desktop_link_changed    (NautilusDesktopLink  *link);
+static void home_uri_changed                 (gpointer              callback_data);
+
+EEL_CLASS_BOILERPLATE (NautilusDesktopLink,
+		       nautilus_desktop_link,
+		       G_TYPE_OBJECT)
+
+static void
+create_icon_file (NautilusDesktopLink *link)
+{
+	link->details->icon_file = nautilus_desktop_icon_file_new (link);
+}
+
+static void
+home_name_changed (gpointer callback_data)
+{
+	NautilusDesktopLink *link;
+
+	link = NAUTILUS_DESKTOP_LINK (callback_data);
+	g_assert (link->details->type == NAUTILUS_DESKTOP_LINK_HOME);
+
+	g_free (link->details->display_name);
+	link->details->display_name = eel_preferences_get (NAUTILUS_PREFERENCES_DESKTOP_HOME_NAME);
+	
+	nautilus_desktop_link_changed (link);
+}
+
+static void
+trash_name_changed (gpointer callback_data)
+{
+	NautilusDesktopLink *link;
+
+	link = NAUTILUS_DESKTOP_LINK (callback_data);
+	g_assert (link->details->type == NAUTILUS_DESKTOP_LINK_TRASH);
+
+	
+	g_free (link->details->display_name);
+	link->details->display_name = eel_preferences_get (NAUTILUS_PREFERENCES_DESKTOP_TRASH_NAME);
+	nautilus_desktop_link_changed (link);
+}
+
+
+
+NautilusDesktopLink *
+nautilus_desktop_link_new (NautilusDesktopLinkType type)
+{
+	NautilusDesktopLink *link;
+
+	link = NAUTILUS_DESKTOP_LINK (g_object_new (NAUTILUS_TYPE_DESKTOP_LINK, NULL));
+
+	link->details->type = type;
+	switch (type) {
+	case NAUTILUS_DESKTOP_LINK_HOME:
+		link->details->filename = g_strdup ("home");
+
+		link->details->display_name = eel_preferences_get (NAUTILUS_PREFERENCES_DESKTOP_HOME_NAME);
+		
+#ifdef WEB_NAVIGATION_ENABLED
+		link->details->activation_uri = eel_preferences_get (NAUTILUS_PREFERENCES_HOME_URI);
+#else
+		link->details->activation_uri = gnome_vfs_get_uri_from_local_path (g_get_home_dir ());
+#endif
+		link->details->icon = g_strdup ("gnome-fs-home");
+
+		eel_preferences_add_callback (NAUTILUS_PREFERENCES_HOME_URI,
+					      home_uri_changed,
+					      link);
+		eel_preferences_add_callback (NAUTILUS_PREFERENCES_DESKTOP_HOME_NAME,
+					      home_name_changed,
+					      link);
+		
+		break;
+	case NAUTILUS_DESKTOP_LINK_TRASH:
+		link->details->filename = g_strdup ("trash");
+		link->details->display_name = g_strdup (_("Trash"));
+		link->details->activation_uri = g_strdup (EEL_TRASH_URI);
+		if (nautilus_trash_monitor_is_empty ()) {
+			link->details->icon = g_strdup (TRASH_EMPTY_ICON);
+		} else {
+			link->details->icon = g_strdup (TRASH_FULL_ICON);
+		}
+		
+		eel_preferences_add_callback (NAUTILUS_PREFERENCES_DESKTOP_TRASH_NAME,
+					      trash_name_changed,
+					      link);
+		link->details->trash_state_handler =
+			g_signal_connect_object (nautilus_trash_monitor_get (), "trash_state_changed",
+						 G_CALLBACK (trash_state_changed_callback), link, 0);	
+		break;
+	default:
+	case NAUTILUS_DESKTOP_LINK_VOLUME:
+		g_assert_not_reached();
+	}
+
+	create_icon_file (link);
+
+	return link;
+}
+
+static char *
+get_icon_for_volume (const NautilusVolume *volume)
+{
+	char *icon_name;
+	
+	icon_name = "gnome-dev-harddisk";
+	switch (nautilus_volume_get_device_type (volume)) {
+	case NAUTILUS_DEVICE_AUDIO_CD:
+	case NAUTILUS_DEVICE_CDROM_DRIVE:
+		icon_name = "gnome-dev-cdrom";
+		break;
+
+	case NAUTILUS_DEVICE_FLOPPY_DRIVE:
+		icon_name = "gnome-dev-floppy";
+		break;
+
+	case NAUTILUS_DEVICE_JAZ_DRIVE:
+		icon_name = "gnome-dev-jazdisk";
+		break;
+
+	case NAUTILUS_DEVICE_MEMORY_STICK:
+		icon_name = "gnome-dev-memory";
+		break;
+	
+	case NAUTILUS_DEVICE_NFS:
+		icon_name = "gnome-fs-nfs";
+		break;
+
+	case NAUTILUS_DEVICE_SMB:
+		icon_name = "gnome-fs-smb";
+		break;
+	
+	case NAUTILUS_DEVICE_ZIP_DRIVE:
+		icon_name = "gnome-dev-zipdisk";
+		break;
+
+	case NAUTILUS_DEVICE_APPLE:
+	case NAUTILUS_DEVICE_WINDOWS:
+	case NAUTILUS_DEVICE_CAMERA:
+	case NAUTILUS_DEVICE_UNKNOWN:
+		break;
+	}
+
+	return g_strdup (icon_name);
+}
+
+NautilusDesktopLink *
+nautilus_desktop_link_new_from_volume (const NautilusVolume *volume)
+{
+	NautilusDesktopLink *link;
+	const char *mount_path;
+	char *underscore_mount_path, *p;
+
+	link = NAUTILUS_DESKTOP_LINK (g_object_new (NAUTILUS_TYPE_DESKTOP_LINK, NULL));
+	
+	link->details->type = NAUTILUS_DESKTOP_LINK_VOLUME;
+
+	mount_path = nautilus_volume_get_mount_path (volume);
+	link->details->mount_path = g_strdup (mount_path);
+	
+	/* Convert slashes in the mount path to underscores and skip
+	   first slash */
+	while (*mount_path == '/') {
+		mount_path ++;
+	}
+	underscore_mount_path = g_strdup (mount_path);
+	for (p = underscore_mount_path; *p != 0; p++) {
+		if (*p == '/') {
+			*p = '_';
+		}
+	}
+
+	link->details->filename = g_strconcat ("mount_", underscore_mount_path, NULL);
+	g_free (underscore_mount_path);
+	
+	link->details->display_name = nautilus_volume_get_name (volume);
+	
+	link->details->activation_uri = nautilus_volume_get_target_uri (volume);
+	link->details->icon = get_icon_for_volume (volume);
+	
+	create_icon_file (link);
+
+	return link;
+}
+
+char *
+nautilus_desktop_link_get_mount_path (NautilusDesktopLink *link)
+{
+	g_assert (link->details->type == NAUTILUS_DESKTOP_LINK_VOLUME);
+	return g_strdup (link->details->mount_path);
+}
+
+
+NautilusDesktopLinkType
+nautilus_desktop_link_get_link_type  (NautilusDesktopLink *link)
+{
+  return link->details->type;
+}
+
+char *
+nautilus_desktop_link_get_file_name (NautilusDesktopLink *link)
+{
+	return g_strdup (link->details->filename);
+}
+
+char *
+nautilus_desktop_link_get_display_name (NautilusDesktopLink *link)
+{
+	return g_strdup (link->details->display_name);
+}
+
+char *
+nautilus_desktop_link_get_icon (NautilusDesktopLink *link)
+{
+	return g_strdup (link->details->icon);
+}
+
+char *
+nautilus_desktop_link_get_activation_uri (NautilusDesktopLink *link)
+{
+	return g_strdup (link->details->activation_uri);
+}
+
+gboolean
+nautilus_desktop_link_get_date (NautilusDesktopLink *link,
+				NautilusDateType     date_type,
+				time_t               *date)
+{
+	return FALSE;
+}
+
+static void
+nautilus_desktop_link_changed (NautilusDesktopLink *link)
+{
+	if (link->details->icon_file != NULL) {
+		nautilus_desktop_icon_file_update (link->details->icon_file);
+	}
+}
+
+static void
+trash_state_changed_callback (NautilusTrashMonitor *trash_monitor,
+			      gboolean state,
+			      gpointer callback_data)
+{
+	NautilusDesktopLink *link;
+
+	link = NAUTILUS_DESKTOP_LINK (callback_data);
+	g_assert (link->details->type == NAUTILUS_DESKTOP_LINK_TRASH);
+
+	g_free (link->details->icon);
+	
+	if (state) {
+		link->details->icon = g_strdup (TRASH_EMPTY_ICON);
+	} else {
+		link->details->icon = g_strdup (TRASH_FULL_ICON);
+	}
+
+	nautilus_desktop_link_changed (link);
+}
+
+static void
+home_uri_changed (gpointer callback_data)
+{
+	NautilusDesktopLink *link;
+
+	link = NAUTILUS_DESKTOP_LINK (callback_data);
+
+	g_free (link->details->activation_uri);
+#ifdef WEB_NAVIGATION_ENABLED
+	link->details->activation_uri = eel_preferences_get (NAUTILUS_PREFERENCES_HOME_URI);
+#else
+	link->details->activation_uri = gnome_vfs_get_uri_from_local_path (g_get_home_dir ());
+#endif
+	
+	nautilus_desktop_link_changed (link);
+}
+
+
+gboolean
+nautilus_desktop_link_can_rename (NautilusDesktopLink     *link)
+{
+	return (link->details->type == NAUTILUS_DESKTOP_LINK_HOME ||
+		link->details->type == NAUTILUS_DESKTOP_LINK_TRASH);
+}
+
+gboolean
+nautilus_desktop_link_rename (NautilusDesktopLink     *link,
+			      const char              *name)
+{
+	switch (link->details->type) {
+	case NAUTILUS_DESKTOP_LINK_HOME:
+		eel_preferences_set (NAUTILUS_PREFERENCES_DESKTOP_HOME_NAME,
+				     name);
+		break;
+	case NAUTILUS_DESKTOP_LINK_TRASH:
+		eel_preferences_set (NAUTILUS_PREFERENCES_DESKTOP_HOME_NAME,
+				     name);
+		break;
+	default:
+		g_assert_not_reached ();
+		/* FIXME: Do we want volume renaming?
+		 * We didn't support that before. */
+		break;
+	}
+	
+	return TRUE;
+}
+
+
+static void
+nautilus_desktop_link_init (gpointer object, gpointer klass)
+{
+	NautilusDesktopLink *link;
+
+	link = NAUTILUS_DESKTOP_LINK (object);
+
+	link->details = g_new0 (NautilusDesktopLinkDetails, 1);
+}	
+
+static void
+desktop_link_finalize (GObject *object)
+{
+	NautilusDesktopLink *link;
+
+	link = NAUTILUS_DESKTOP_LINK (object);
+
+	if (link->details->trash_state_handler != 0) {
+		g_signal_handler_disconnect (nautilus_trash_monitor_get (),
+					     link->details->trash_state_handler);
+	}
+
+	if (link->details->icon_file != NULL) {
+		nautilus_desktop_icon_file_remove (link->details->icon_file);
+	}
+
+	if (link->details->type == NAUTILUS_DESKTOP_LINK_HOME) {
+		eel_preferences_remove_callback (NAUTILUS_PREFERENCES_HOME_URI,
+						 home_uri_changed,
+						 link);
+		eel_preferences_remove_callback (NAUTILUS_PREFERENCES_DESKTOP_HOME_NAME,
+						 home_name_changed,
+						 link);
+	}
+	
+	if (link->details->type == NAUTILUS_DESKTOP_LINK_TRASH) {
+		eel_preferences_remove_callback (NAUTILUS_PREFERENCES_DESKTOP_TRASH_NAME,
+						 trash_name_changed,
+						 link);
+	}
+	
+	g_free (link->details);
+
+	EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
+}
+
+static void
+nautilus_desktop_link_class_init (gpointer klass)
+{
+	GObjectClass *object_class;
+
+	object_class = G_OBJECT_CLASS (klass);
+	
+	object_class->finalize = desktop_link_finalize;
+
+}
Index: libnautilus-private/nautilus-desktop-link.h
===================================================================
RCS file: libnautilus-private/nautilus-desktop-link.h
diff -N libnautilus-private/nautilus-desktop-link.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libnautilus-private/nautilus-desktop-link.h	15 May 2003 17:08:04 -0000
@@ -0,0 +1,77 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+   nautilus-desktop-link.h: Class that handles the links on the desktop
+    
+   Copyright (C) 2003 Red Hat, Inc.
+  
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+  
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+  
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+  
+   Author: Alexander Larsson <alexl redhat com>
+*/
+
+#ifndef NAUTILUS_DESKTOP_LINK_H
+#define NAUTILUS_DESKTOP_LINK_H
+
+#include <libnautilus-private/nautilus-file.h>
+#include <libnautilus-private/nautilus-volume-monitor.h>
+
+#define NAUTILUS_TYPE_DESKTOP_LINK \
+	(nautilus_desktop_link_get_type ())
+#define NAUTILUS_DESKTOP_LINK(obj) \
+	(GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_DESKTOP_LINK, NautilusDesktopLink))
+#define NAUTILUS_DESKTOP_LINK_CLASS(klass) \
+	(GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_DESKTOP_LINK, NautilusDesktopLink))
+#define NAUTILUS_IS_DESKTOP_LINK(obj) \
+	(GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_DESKTOP_LINK))
+#define NAUTILUS_IS_DESKTOP_LINK_CLASS(klass) \
+	(GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_DESKTOP_LINK))
+
+typedef struct NautilusDesktopLinkDetails NautilusDesktopLinkDetails;
+
+typedef struct {
+	GObject parent_slot;
+	NautilusDesktopLinkDetails *details;
+} NautilusDesktopLink;
+
+typedef struct {
+	GObjectClass parent_slot;
+} NautilusDesktopLinkClass;
+
+typedef enum {
+	NAUTILUS_DESKTOP_LINK_HOME,
+	NAUTILUS_DESKTOP_LINK_TRASH,
+	NAUTILUS_DESKTOP_LINK_VOLUME
+} NautilusDesktopLinkType;
+
+GType   nautilus_desktop_link_get_type (void);
+
+NautilusDesktopLink *   nautilus_desktop_link_new                (NautilusDesktopLinkType  type);
+NautilusDesktopLink *   nautilus_desktop_link_new_from_volume    (const NautilusVolume    *volume);
+NautilusDesktopLinkType nautilus_desktop_link_get_link_type      (NautilusDesktopLink     *link);
+char *                  nautilus_desktop_link_get_file_name      (NautilusDesktopLink     *link);
+char *                  nautilus_desktop_link_get_display_name   (NautilusDesktopLink     *link);
+char *                  nautilus_desktop_link_get_icon           (NautilusDesktopLink     *link);
+char *                  nautilus_desktop_link_get_activation_uri (NautilusDesktopLink     *link);
+gboolean                nautilus_desktop_link_get_date           (NautilusDesktopLink     *link,
+								  NautilusDateType         date_type,
+								  time_t                  *date);
+char *                  nautilus_desktop_link_get_mount_path     (NautilusDesktopLink     *link);
+
+gboolean                nautilus_desktop_link_can_rename         (NautilusDesktopLink     *link);
+gboolean                nautilus_desktop_link_rename             (NautilusDesktopLink     *link,
+								  const char              *name);
+
+#endif /* NAUTILUS_DESKTOP_LINK_H */
Index: libnautilus-private/nautilus-directory-async.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-directory-async.c,v
retrieving revision 1.198
diff -u -p -r1.198 nautilus-directory-async.c
--- libnautilus-private/nautilus-directory-async.c	2 Apr 2003 11:50:52 -0000	1.198
+++ libnautilus-private/nautilus-directory-async.c	15 May 2003 17:08:05 -0000
@@ -3305,7 +3305,7 @@ nautilus_directory_add_file_to_work_queu
 	}
 
 	nautilus_file_queue_enqueue (directory->details->high_priority_queue,
-				    file);
+				     file);
 }
 
 
Index: libnautilus-private/nautilus-directory.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-directory.c,v
retrieving revision 1.246
diff -u -p -r1.246 nautilus-directory.c
--- libnautilus-private/nautilus-directory.c	2 Apr 2003 11:50:53 -0000	1.246
+++ libnautilus-private/nautilus-directory.c	15 May 2003 17:08:05 -0000
@@ -34,6 +34,7 @@
 #include "nautilus-lib-self-check-functions.h"
 #include "nautilus-metadata.h"
 #include "nautilus-metafile.h"
+#include "nautilus-desktop-directory.h"
 #include "nautilus-trash-directory.h"
 #include "nautilus-vfs-directory.h"
 #include <eel/eel-glib-extensions.h>
@@ -501,6 +502,8 @@ nautilus_directory_new (const char *uri)
 
 	if (eel_uri_is_trash (uri)) {
 		directory = NAUTILUS_DIRECTORY (g_object_new (NAUTILUS_TYPE_TRASH_DIRECTORY, NULL));
+	} else if (eel_uri_is_desktop (uri)) {
+		directory = NAUTILUS_DIRECTORY (g_object_new (NAUTILUS_TYPE_DESKTOP_DIRECTORY, NULL));
 	} else {
 		directory = NAUTILUS_DIRECTORY (g_object_new (NAUTILUS_TYPE_VFS_DIRECTORY, NULL));
 	}
Index: libnautilus-private/nautilus-dnd.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-dnd.c,v
retrieving revision 1.15
diff -u -p -r1.15 nautilus-dnd.c
--- libnautilus-private/nautilus-dnd.c	27 Mar 2003 16:01:19 -0000	1.15
+++ libnautilus-private/nautilus-dnd.c	15 May 2003 17:08:05 -0000
@@ -44,6 +44,7 @@
 #include <libgnomevfs/gnome-vfs-types.h>
 #include <libgnomevfs/gnome-vfs-uri.h>
 #include <libgnomevfs/gnome-vfs-utils.h>
+#include <libnautilus-private/nautilus-file-utilities.h>
 #include <stdio.h>
 #include <string.h>
 
@@ -219,12 +220,19 @@ nautilus_drag_items_local (const char *t
 
 	target_uri = gnome_vfs_uri_new (target_uri_string);
 
-	/* get the parent URI of the first item in the selection */
-	item_uri = gnome_vfs_uri_new (((NautilusDragSelectionItem *)selection_list->data)->uri);
-	result = gnome_vfs_uri_is_parent (target_uri, item_uri, FALSE);
-	
-	gnome_vfs_uri_unref (item_uri);
-	gnome_vfs_uri_unref (target_uri);
+	if (target_uri != NULL) {
+		/* get the parent URI of the first item in the selection */
+		item_uri = gnome_vfs_uri_new (((NautilusDragSelectionItem *)selection_list->data)->uri);
+		
+		if (item_uri != NULL) {
+			result = gnome_vfs_uri_is_parent (target_uri, item_uri, FALSE);
+			
+			gnome_vfs_uri_unref (item_uri);
+		}
+		
+		gnome_vfs_uri_unref (target_uri);
+	}
+		
 	
 	return result;
 }
@@ -240,6 +248,39 @@ nautilus_drag_items_in_trash (const GLis
 	return eel_uri_is_in_trash (((NautilusDragSelectionItem *)selection_list->data)->uri);
 }
 
+gboolean
+nautilus_drag_items_on_desktop (const GList *selection_list)
+{
+	char *uri;
+	GnomeVFSURI *vfs_uri, *desktop_vfs_uri;
+	char *desktop_uri;
+	gboolean result;
+	
+	/* check if the first item on the list is in trash.
+	 * FIXME:
+	 * we should really test each item but that would be slow for large selections
+	 * and currently dropped items can only be from the same container
+	 */
+	uri = ((NautilusDragSelectionItem *)selection_list->data)->uri;
+	if (eel_uri_is_desktop (uri)) {
+		return TRUE;
+	}
+
+	vfs_uri = gnome_vfs_uri_new (uri);
+	desktop_uri = nautilus_get_desktop_directory_uri ();
+	desktop_vfs_uri = gnome_vfs_uri_new (desktop_uri);
+	g_free (desktop_uri);
+	
+	result = gnome_vfs_uri_is_parent (desktop_vfs_uri, vfs_uri, FALSE);
+	
+	gnome_vfs_uri_unref (desktop_vfs_uri);
+	gnome_vfs_uri_unref (vfs_uri);
+	
+	return result;
+	
+}
+
+
 void
 nautilus_drag_default_drop_action_for_icons (GdkDragContext *context,
 	const char *target_uri_string, const GList *items,
@@ -293,10 +334,17 @@ nautilus_drag_default_drop_action_for_ic
 
 		return;
 
-	} else if (eel_str_has_prefix (target_uri_string, NAUTILUS_COMMAND_SPECIFIER)
-			|| eel_str_has_prefix (target_uri_string, NAUTILUS_DESKTOP_COMMAND_SPECIFIER)) {
+	} else if (g_str_has_prefix (target_uri_string, NAUTILUS_COMMAND_SPECIFIER)
+			|| g_str_has_prefix (target_uri_string, NAUTILUS_DESKTOP_COMMAND_SPECIFIER)) {
+		if (actions & GDK_ACTION_MOVE) {
+			*action = GDK_ACTION_MOVE;
+		}
+		return;
+	} else if (eel_uri_is_desktop (target_uri_string)) {
 		if (actions & GDK_ACTION_MOVE) {
 			*action = GDK_ACTION_MOVE;
+		} else {
+			*action = context->suggested_action;
 		}
 		return;
 	} else {
@@ -312,8 +360,10 @@ nautilus_drag_default_drop_action_for_ic
 	dropped_uri = gnome_vfs_uri_new (((NautilusDragSelectionItem *)items->data)->uri);
 	same_fs = TRUE;
 
-	gnome_vfs_check_same_fs_uris (dropped_uri, target_uri, &same_fs);
-	gnome_vfs_uri_unref (dropped_uri);
+	if (dropped_uri != NULL) {
+		gnome_vfs_check_same_fs_uris (dropped_uri, target_uri, &same_fs);
+		gnome_vfs_uri_unref (dropped_uri);
+	}
 	gnome_vfs_uri_unref (target_uri);
 	
 	if (same_fs) {
@@ -790,36 +840,15 @@ gboolean
 nautilus_drag_selection_includes_special_link (GList *selection_list)
 {
 	GList *node;
-	char *uri, *local_path;
-	gboolean link_in_selection;
-	GnomeVFSFileInfo *info;
-
-	link_in_selection = FALSE;
+	char *uri;
 
 	for (node = selection_list; node != NULL; node = node->next) {
 		uri = ((NautilusDragSelectionItem *) node->data)->uri;
 
-		/* FIXME bugzilla.gnome.org 43020: This does sync. I/O and works only locally. */
-		local_path = gnome_vfs_get_local_path_from_uri (uri);
-
-		if (local_path) {
-			info = gnome_vfs_file_info_new ();
-			gnome_vfs_get_file_info
-				(local_path, info, 
-				 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
-				 GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
-			/* assume info is blank on failure */
-			link_in_selection = (nautilus_link_local_is_trash_link (local_path, info) ||
-					     nautilus_link_local_is_home_link (local_path, info) ||
-					     nautilus_link_local_is_volume_link (local_path, info));
-			gnome_vfs_file_info_unref (info);
-			g_free (local_path);
-		}
-		
-		if (link_in_selection) {
-			break;
+		if (eel_uri_is_desktop (uri)) {
+			return TRUE;
 		}
 	}
 	
-	return link_in_selection;
+	return FALSE;
 }
Index: libnautilus-private/nautilus-dnd.h
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-dnd.h,v
retrieving revision 1.8
diff -u -p -r1.8 nautilus-dnd.h
--- libnautilus-private/nautilus-dnd.h	8 Feb 2003 22:19:24 -0000	1.8
+++ libnautilus-private/nautilus-dnd.h	15 May 2003 17:08:05 -0000
@@ -114,6 +114,7 @@ GList 		           *nautilus_drag_build_
 gboolean                    nautilus_drag_items_local                   (const char                           *target_uri,
 									 const GList                          *selection_list);
 gboolean                    nautilus_drag_items_in_trash                (const GList                          *selection_list);
+gboolean                    nautilus_drag_items_on_desktop              (const GList                          *selection_list);
 void                        nautilus_drag_default_drop_action_for_icons (GdkDragContext                       *context,
 									 const char                           *target_uri,
 									 const GList                          *items,
Index: libnautilus-private/nautilus-file-operations.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-file-operations.c,v
retrieving revision 1.163
diff -u -p -r1.163 nautilus-file-operations.c
--- libnautilus-private/nautilus-file-operations.c	3 Feb 2003 16:16:52 -0000	1.163
+++ libnautilus-private/nautilus-file-operations.c	15 May 2003 17:08:05 -0000
@@ -46,6 +46,9 @@
 #include <libgnomevfs/gnome-vfs-uri.h>
 #include <libgnomevfs/gnome-vfs-utils.h>
 #include "nautilus-file-changes-queue.h"
+#include "nautilus-file-private.h"
+#include "nautilus-desktop-icon-file.h"
+#include "nautilus-desktop-link-monitor.h"
 #include "nautilus-global-preferences.h"
 #include "nautilus-link.h"
 #include "nautilus-trash-monitor.h"
@@ -991,17 +994,8 @@ handle_transfer_vfs_error (const GnomeVF
 static gboolean
 is_special_link (const char *uri)
 {
-	char *local_path;
-	gboolean is_special;
 
-	local_path = gnome_vfs_get_local_path_from_uri (uri);
-	if (local_path == NULL) {
-		return FALSE;
-	}
-	is_special = nautilus_link_local_is_special_link (local_path);
-	g_free (local_path);
-
-	return is_special;
+	return eel_uri_is_desktop (uri);
 }
 
 static int
@@ -1691,19 +1685,6 @@ append_basename (const GnomeVFSURI *targ
 	return gnome_vfs_uri_dup (target_directory);
 }
 
-static gboolean 
-vfs_uri_is_special_link (GnomeVFSURI *vfs_uri)
-{
-	char *uri;
-	gboolean is_special;
-
-	uri = gnome_vfs_uri_to_string (vfs_uri, GNOME_VFS_URI_HIDE_NONE);
-	is_special = is_special_link (uri);
-	g_free (uri);
-
-	return is_special;
-}
-
 void
 nautilus_file_operations_copy_move (const GList *item_uris,
 				    GArray *relative_item_points,
@@ -1725,7 +1706,6 @@ nautilus_file_operations_copy_move (cons
 	SyncTransferInfo *sync_transfer_info;
 	GnomeVFSResult result;
 	gboolean target_is_trash;
-	gboolean is_desktop_trash_link;
 	gboolean duplicate;
 	gboolean target_is_mapping;
 	gboolean have_nonlocal_source;
@@ -1945,21 +1925,13 @@ nautilus_file_operations_copy_move (cons
 			    	/* Distinguish Trash file on desktop from other trash folders for
 			    	 * message purposes.
 			    	 */
-				/* FIXME: is_special_link finds more than just trash links,
-				 * so these messages are wrong. 
-				 */
-			    	is_desktop_trash_link = vfs_uri_is_special_link (uri);
 
 				eel_run_simple_dialog
 					(parent_view,
 					 FALSE,
 					 ((move_options & GNOME_VFS_XFER_REMOVESOURCE) != 0)
-						 ? (is_desktop_trash_link
-						    ? _("The Trash must remain on the desktop.")
-						    : _("You cannot move this trash folder."))
-						 : (is_desktop_trash_link
-						    ? _("You cannot copy the Trash.")
-						    : _("You cannot copy this trash folder.")),
+						 ? _("You cannot move this trash folder.")
+						 : _("You cannot copy this trash folder."),
 					 ((move_options & GNOME_VFS_XFER_REMOVESOURCE) != 0)
 						 ? _("Can't Change Trash Location")
 						 : _("Can't Copy Trash"),
@@ -2176,14 +2148,40 @@ nautilus_file_operations_delete (const G
 {
 	GList *uri_list;
 	const GList *p;
+	const char *item_uri;
+	NautilusFile *file;
 	TransferInfo *transfer_info;
 
 	uri_list = NULL;
 	for (p = item_uris; p != NULL; p = p->next) {
-		uri_list = g_list_prepend (uri_list, 
-					   gnome_vfs_uri_new ((const char *) p->data));
+		item_uri = (const char *) p->data;
+
+		if (eel_uri_is_desktop (item_uri)) {
+			file = nautilus_file_get_existing (item_uri);
+			if (file != NULL) {
+				if (NAUTILUS_IS_DESKTOP_ICON_FILE (file)) {
+					NautilusDesktopLink *link;
+
+					link = nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (file));
+
+					nautilus_desktop_link_monitor_delete_link (nautilus_desktop_link_monitor_get (),
+										   link,
+										   parent_view);
+					
+					g_object_unref (link);
+				}
+				nautilus_file_unref (file);
+			}
+		} else {
+			uri_list = g_list_prepend (uri_list, 
+						   gnome_vfs_uri_new (item_uri));
+		}
 	}
 	uri_list = g_list_reverse (uri_list);
+
+	if (uri_list == NULL) {
+		return;
+	}
 
 	transfer_info = transfer_info_new (parent_view);
 
Index: libnautilus-private/nautilus-file-utilities.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-file-utilities.c,v
retrieving revision 1.109
diff -u -p -r1.109 nautilus-file-utilities.c
--- libnautilus-private/nautilus-file-utilities.c	8 Jul 2002 15:32:06 -0000	1.109
+++ libnautilus-private/nautilus-file-utilities.c	15 May 2003 17:08:05 -0000
@@ -40,7 +40,8 @@
 #define NAUTILUS_USER_DIRECTORY_NAME ".nautilus"
 #define DEFAULT_NAUTILUS_DIRECTORY_MODE (0755)
 
-#define DESKTOP_DIRECTORY_NAME ".gnome-desktop"
+#define DESKTOP_DIRECTORY_NAME "Desktop"
+#define LEGACY_DESKTOP_DIRECTORY_NAME ".gnome-desktop"
 #define DEFAULT_DESKTOP_DIRECTORY_MODE (0755)
 
 gboolean
@@ -74,7 +75,7 @@ nautilus_get_user_directory (void)
 	user_directory = g_build_filename (g_get_home_dir (),
 					   NAUTILUS_USER_DIRECTORY_NAME,
 					   NULL);
-
+	
 	if (!g_file_test (user_directory, G_FILE_TEST_EXISTS)) {
 		mkdir (user_directory, DEFAULT_NAUTILUS_DIRECTORY_MODE);
 		/* FIXME bugzilla.gnome.org 41286: 
@@ -104,7 +105,7 @@ nautilus_get_desktop_directory (void)
 	if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_IS_HOME_DIR)) {
 		desktop_directory = g_strdup (g_get_home_dir());
 	} else {
-		desktop_directory = nautilus_get_gmc_desktop_directory ();
+		desktop_directory = g_build_filename (g_get_home_dir (), DESKTOP_DIRECTORY_NAME, NULL);
 		if (!g_file_test (desktop_directory, G_FILE_TEST_EXISTS)) {
 			mkdir (desktop_directory, DEFAULT_DESKTOP_DIRECTORY_MODE);
 			/* FIXME bugzilla.gnome.org 41286: 
@@ -120,6 +121,28 @@ nautilus_get_desktop_directory (void)
 	return desktop_directory;
 }
 
+
+/**
+ * nautilus_get_desktop_directory_uri:
+ * 
+ * Get the uri for the directory containing files on the desktop.
+ *
+ * Return value: the directory path.
+ **/
+char *
+nautilus_get_desktop_directory_uri (void)
+{
+	char *desktop_path;
+	char *desktop_uri;
+	
+	desktop_path = nautilus_get_desktop_directory ();
+	desktop_uri = gnome_vfs_get_uri_from_local_path (desktop_path);
+	g_free (desktop_path);
+
+	return desktop_uri;
+}
+
+
 /**
  * nautilus_get_gmc_desktop_directory:
  * 
@@ -130,7 +153,7 @@ nautilus_get_desktop_directory (void)
 char *
 nautilus_get_gmc_desktop_directory (void)
 {
-	return g_build_filename (g_get_home_dir (), DESKTOP_DIRECTORY_NAME, NULL);
+	return g_build_filename (g_get_home_dir (), LEGACY_DESKTOP_DIRECTORY_NAME, NULL);
 }
 
 /**
Index: libnautilus-private/nautilus-file-utilities.h
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-file-utilities.h,v
retrieving revision 1.46
diff -u -p -r1.46 nautilus-file-utilities.h
--- libnautilus-private/nautilus-file-utilities.h	8 Jul 2002 15:32:06 -0000	1.46
+++ libnautilus-private/nautilus-file-utilities.h	15 May 2003 17:08:05 -0000
@@ -36,6 +36,7 @@ gboolean nautilus_file_name_matches_back
  */
 char *   nautilus_get_user_directory                 (void);
 char *   nautilus_get_desktop_directory              (void);
+char *   nautilus_get_desktop_directory_uri          (void);
 char *   nautilus_get_gmc_desktop_directory          (void);
 char *   nautilus_get_pixmap_directory               (void);
 
Index: libnautilus-private/nautilus-file.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-file.c,v
retrieving revision 1.316
diff -u -p -r1.316 nautilus-file.c
--- libnautilus-private/nautilus-file.c	2 Apr 2003 11:50:54 -0000	1.316
+++ libnautilus-private/nautilus-file.c	15 May 2003 17:08:06 -0000
@@ -28,6 +28,9 @@
 #include "nautilus-directory-metafile.h"
 #include "nautilus-directory-notify.h"
 #include "nautilus-directory-private.h"
+#include "nautilus-desktop-directory.h"
+#include "nautilus-desktop-directory-file.h"
+#include "nautilus-desktop-icon-file.h"
 #include "nautilus-file-attributes.h"
 #include "nautilus-file-private.h"
 #include "nautilus-file-utilities.h"
@@ -136,6 +139,13 @@ nautilus_file_new_from_relative_uri (Nau
 
 	if (self_owned && NAUTILUS_IS_TRASH_DIRECTORY (directory)) {
 		file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_TRASH_FILE, NULL));
+	} else if (NAUTILUS_IS_DESKTOP_DIRECTORY (directory)) {
+		if (self_owned) {
+			file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_DESKTOP_DIRECTORY_FILE, NULL));
+		} else {
+			file = NULL;
+			g_assert_not_reached ();
+		}
 	} else {
 		file = NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_VFS_FILE, NULL));
 	}
@@ -272,6 +282,7 @@ static NautilusFile *
 nautilus_file_get_internal (const char *uri, gboolean create)
 {
 	char *canonical_uri, *directory_uri, *relative_uri, *file_name;
+	const char *relative_uri_tmp;
 	gboolean self_owned;
 	GnomeVFSURI *vfs_uri, *directory_vfs_uri;
 	NautilusDirectory *directory;
@@ -302,24 +313,29 @@ nautilus_file_get_internal (const char *
 		}
 	}
 
+	self_owned = FALSE;
+	directory_uri = NULL;
+	
 	/* Make VFS version of directory URI. */
 	if (vfs_uri == NULL) {
-		directory_vfs_uri = NULL;
+		if (eel_uri_is_desktop (uri) &&
+		    strcmp (uri, EEL_DESKTOP_URI) != 0) {
+			directory_uri = g_strdup (EEL_DESKTOP_URI);
+		}
 	} else {
 		directory_vfs_uri = gnome_vfs_uri_get_parent (vfs_uri);
+		if (directory_vfs_uri != NULL) {
+			directory_uri = gnome_vfs_uri_to_string
+				(directory_vfs_uri,
+				 GNOME_VFS_URI_HIDE_NONE);
+			gnome_vfs_uri_unref (directory_vfs_uri);
+		} 
 		gnome_vfs_uri_unref (vfs_uri);
 	}
-
-	self_owned = directory_vfs_uri == NULL;
-	if (self_owned) {
-		/* Use the item itself if we have no parent. */
+	
+	if (directory_uri == NULL) {
+		self_owned = TRUE;
 		directory_uri = g_strdup (canonical_uri);
-	} else {
-		/* Make text version of directory URI. */
-		directory_uri = gnome_vfs_uri_to_string
-			(directory_vfs_uri,
-			 GNOME_VFS_URI_HIDE_NONE);
-		gnome_vfs_uri_unref (directory_vfs_uri);
 	}
 
 	/* Get object that represents the directory. */
@@ -328,11 +344,19 @@ nautilus_file_get_internal (const char *
 
 	/* Get the name for the file. */
 	if (vfs_uri == NULL) {
-		g_assert (self_owned);
-		if (directory != NULL) {
+		if (self_owned && directory != NULL) {
 			file_name = nautilus_directory_get_name_for_self_as_new_file (directory);
 			relative_uri = gnome_vfs_escape_string (file_name);
 			g_free (file_name);
+		} else if (eel_uri_is_desktop (uri)) {
+			/* Special case desktop files here. They have no vfs_uri */
+			relative_uri_tmp = uri + strlen (EEL_DESKTOP_URI);
+			while (*relative_uri_tmp == '/') {
+				relative_uri_tmp++;
+			}
+			relative_uri = strdup (relative_uri_tmp);
+		} else {
+			g_assert_not_reached ();
 		}
 	}
 
@@ -746,7 +770,7 @@ nautilus_file_can_rename (NautilusFile *
 {
 	NautilusFile *parent;
 	gboolean can_rename;
-	char *uri, *path;
+	char *uri;
 	
 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
 
@@ -767,23 +791,15 @@ nautilus_file_can_rename (NautilusFile *
 	
 	can_rename = TRUE;
 	uri = nautilus_file_get_uri (file);
-	path = gnome_vfs_get_local_path_from_uri (uri);
 
 	/* Certain types of links can't be renamed */
-	if (path != NULL && nautilus_file_is_nautilus_link (file)) {
-		/* FIXME: This reads the link file every time -- seems
-		 * bad to do that even though it's known to be local.
-		 */
-		switch (nautilus_link_local_get_link_type (path, file->details->info)) {
-		case NAUTILUS_LINK_TRASH:
-		case NAUTILUS_LINK_MOUNT:
-			can_rename = FALSE;
-			break;
-
-		case NAUTILUS_LINK_HOME:
-		case NAUTILUS_LINK_GENERIC:
-			break;
-		}
+	if (NAUTILUS_IS_DESKTOP_ICON_FILE (file)) {
+		NautilusDesktopLink *link;
+
+		link = nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (file));
+
+		can_rename = nautilus_desktop_link_can_rename (link);
+		g_object_unref (link);
 	}
 	
 	/* Nautilus trash directories cannot be renamed */
@@ -792,7 +808,6 @@ nautilus_file_can_rename (NautilusFile *
 	}
 
 	g_free (uri);
-	g_free (path);
 
 	if (!can_rename) {
 		return FALSE;
@@ -1047,6 +1062,22 @@ rename_guts (NautilusFile *file,
 		(* callback) (file, GNOME_VFS_ERROR_NOT_SUPPORTED, callback_data);
 		return;
 	}
+
+
+	if (NAUTILUS_IS_DESKTOP_ICON_FILE (file)) {
+		NautilusDesktopLink *link;
+
+		link = nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (file));
+
+		if (nautilus_desktop_link_rename (link, new_name)) {
+			(* callback) (file, GNOME_VFS_OK, callback_data);
+		} else {
+			(* callback) (file, GNOME_VFS_ERROR_GENERIC, callback_data);
+		}
+		
+		g_object_unref (link);
+		return;
+	}
 	
 	if (is_local_desktop_file) {
 		/* Don't actually change the name if the new name is the same.
@@ -2069,7 +2100,7 @@ nautilus_file_is_in_desktop (NautilusFil
 	/* This handles visiting other people's desktops, but it can arguably
 	 * be said that this might break and that we should lookup the passwd table.
 	 */
-	return strstr (file->details->directory->details->uri, "/.gnome-desktop") != NULL;
+	return strstr (file->details->directory->details->uri, "/Desktop") != NULL;
 }
 
 static gboolean
@@ -2451,11 +2482,22 @@ char *
 nautilus_file_get_drop_target_uri (NautilusFile *file)
 {
 	char *uri, *target_uri;
+	NautilusDesktopLink *link;
 	
 	g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
 
+	if (NAUTILUS_IS_DESKTOP_ICON_FILE (file)) {
+		link = nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (file));
+		
+		uri = nautilus_desktop_link_get_activation_uri (link);
+		g_object_unref (link);
+		if (uri != NULL) {
+			return uri;
+		}
+	}
+	
 	uri = nautilus_file_get_uri (file);
-
+	
 	/* Check for Nautilus link */
 	if (nautilus_file_is_nautilus_link (file)) {
 		/* FIXME bugzilla.gnome.org 43020: This does sync. I/O and works only locally. */
@@ -2512,7 +2554,6 @@ nautilus_file_get_uri (NautilusFile *fil
 	}
 
 	return g_strconcat (file->details->directory->details->uri,
-			    "/",
 			    file->details->relative_uri,
 			    NULL);
 }
Index: libnautilus-private/nautilus-global-preferences.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-global-preferences.c,v
retrieving revision 1.208
diff -u -p -r1.208 nautilus-global-preferences.c
--- libnautilus-private/nautilus-global-preferences.c	14 Mar 2003 17:48:44 -0000	1.208
+++ libnautilus-private/nautilus-global-preferences.c	15 May 2003 17:08:06 -0000
@@ -55,6 +55,8 @@ static gpointer default_font_callback   
 static gpointer default_home_location_callback           (void);
 static gpointer default_default_folder_viewer_callback	 (void);
 static void     import_old_preferences_if_needed         (void);
+static gpointer default_home_link_name                   (void);
+static gpointer default_trash_link_name                  (void);
 
 /* An enumeration used for installing type specific preferences defaults. */
 typedef enum
@@ -491,6 +493,29 @@ static const PreferenceDefault preferenc
 	  "default_zoom_level"
 	},
 
+	/* Desktop Preferences */
+	{ NAUTILUS_PREFERENCES_DESKTOP_HOME_VISIBLE,
+	  PREFERENCE_BOOLEAN,
+	  GINT_TO_POINTER (TRUE)
+	},
+	
+	{ NAUTILUS_PREFERENCES_DESKTOP_HOME_NAME,
+	  PREFERENCE_STRING,
+	  NULL,
+	  default_home_link_name, g_free,
+	},
+	
+	{ NAUTILUS_PREFERENCES_DESKTOP_TRASH_VISIBLE,
+	  PREFERENCE_BOOLEAN,
+	  GINT_TO_POINTER (TRUE)
+	},
+	
+	{ NAUTILUS_PREFERENCES_DESKTOP_TRASH_NAME,
+	  PREFERENCE_STRING,
+	  NULL,
+	  default_trash_link_name, g_free,
+	},
+	
 	/* non-visible preferences */
 	{ NAUTILUS_PREFERENCES_ADD_TO_SESSION,
 	  PREFERENCE_BOOLEAN,
@@ -499,6 +524,28 @@ static const PreferenceDefault preferenc
 
 	{ NULL }
 };
+
+static gpointer
+default_home_link_name (void)
+{
+	/* Note to translators: If it's hard to compose a good home
+	 * icon name from the user name, you can use a string without
+	 * an "%s" here, in which case the home icon name will not
+	 * include the user's name, which should be fine. To avoid a
+	 * warning, put "%.0s" somewhere in the string, which will
+	 * match the user name string passed by the C code, but not
+	 * put the user name in the final string.
+	 */
+	return g_strdup_printf (_("%s's Home"), g_get_user_name ());
+}
+
+static gpointer
+default_trash_link_name (void)
+{
+	return g_strdup (_("Trash"));
+}
+
+
 
 /**
  * global_preferences_register_enumerations
Index: libnautilus-private/nautilus-global-preferences.h
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-global-preferences.h,v
retrieving revision 1.116
diff -u -p -r1.116 nautilus-global-preferences.h
--- libnautilus-private/nautilus-global-preferences.h	2 Mar 2003 02:34:52 -0000	1.116
+++ libnautilus-private/nautilus-global-preferences.h	15 May 2003 17:08:06 -0000
@@ -167,6 +167,11 @@ typedef enum
 /* Gnome session management */
 #define NAUTILUS_PREFERENCES_ADD_TO_SESSION		   "preferences/add_to_session"
 
+#define NAUTILUS_PREFERENCES_DESKTOP_HOME_VISIBLE          "desktop/home_icon_visible"
+#define NAUTILUS_PREFERENCES_DESKTOP_HOME_NAME             "desktop/home_icon_name"
+#define NAUTILUS_PREFERENCES_DESKTOP_TRASH_VISIBLE         "desktop/trash_icon_visible"
+#define NAUTILUS_PREFERENCES_DESKTOP_TRASH_NAME            "desktop/trash_icon_name"
+
 void nautilus_global_preferences_init                      (void);
 void nautilus_global_preferences_init_with_folder_browsing (void);
 void nautilus_global_preferences_set_default_folder_viewer (const char *iid);
Index: libnautilus-private/nautilus-icon-container.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-icon-container.c,v
retrieving revision 1.340
diff -u -p -r1.340 nautilus-icon-container.c
--- libnautilus-private/nautilus-icon-container.c	3 May 2003 23:23:30 -0000	1.340
+++ libnautilus-private/nautilus-icon-container.c	15 May 2003 17:08:07 -0000
@@ -1477,7 +1477,9 @@ lay_down_icons_tblr (NautilusIconContain
 				}
 				
 				/* Check and see if we need to move to a new column */
-				if (y != DESKTOP_PAD_VERTICAL && y > height - icon_height) {
+				if (y != DESKTOP_PAD_VERTICAL && y > height - icon_height &&
+				    /* Make sure we lay out at least one icon per column, to make progress */
+				    p != icons) {
 					x += column_width + DESKTOP_PAD_HORIZONTAL;
 					break;
 				}
Index: libnautilus-private/nautilus-icon-dnd.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-icon-dnd.c,v
retrieving revision 1.131
diff -u -p -r1.131 nautilus-icon-dnd.c
--- libnautilus-private/nautilus-icon-dnd.c	3 May 2003 23:23:30 -0000	1.131
+++ libnautilus-private/nautilus-icon-dnd.c	15 May 2003 17:08:07 -0000
@@ -57,6 +57,7 @@
 #include <libgnomevfs/gnome-vfs-uri.h>
 #include <libgnomevfs/gnome-vfs-utils.h>
 #include <libgnomevfs/gnome-vfs-mime-utils.h>
+#include <libnautilus-private/nautilus-file-utilities.h>
 #include <stdio.h>
 #include <string.h>
 
@@ -513,6 +514,8 @@ nautilus_icon_container_selection_items_
 		 * would not work for it.
 		 */
 		result = nautilus_drag_items_in_trash (items);
+	} else if (eel_uri_is_desktop (container_uri_string)) {
+		result = nautilus_drag_items_on_desktop (items);
 	} else {
 		result = nautilus_drag_items_local (container_uri_string, items);
 	}
@@ -831,6 +834,7 @@ handle_nonlocal_move (NautilusIconContai
 {
 	GList *source_uris, *p;
 	GArray *source_item_locations;
+	gboolean free_target_uri;
 	int index;
 
 	if (container->details->dnd_info->drag_info.selection_list == NULL) {
@@ -860,7 +864,14 @@ handle_nonlocal_move (NautilusIconContai
 				((NautilusDragSelectionItem *)p->data)->icon_y;
 		}
 	}
-		
+
+	free_target_uri = FALSE;
+ 	/* Rewrite internal desktop URIs to the normal target uri */
+	if (eel_uri_is_desktop (target_uri)) {
+		target_uri = nautilus_get_desktop_directory_uri ();
+		free_target_uri = TRUE;
+	}
+	
 	/* start the copy */
 	g_signal_emit_by_name (container, "move_copy_items",
 				 source_uris,
@@ -868,6 +879,10 @@ handle_nonlocal_move (NautilusIconContai
 				 target_uri,
 				 context->action,
 				 x, y);
+
+	if (free_target_uri) {
+		g_free ((char *)target_uri);
+	}
 
 	g_list_free (source_uris);
 	g_array_free (source_item_locations, TRUE);
Index: src/Nautilus_shell.server.in
===================================================================
RCS file: /cvs/gnome/nautilus/src/Nautilus_shell.server.in,v
retrieving revision 1.22
diff -u -p -r1.22 Nautilus_shell.server.in
--- src/Nautilus_shell.server.in	14 Jan 2003 18:29:45 -0000	1.22
+++ src/Nautilus_shell.server.in	15 May 2003 17:08:07 -0000
@@ -25,6 +25,7 @@
   <oaf_attribute name="bonobo:additional_uri_schemes" type="stringv">
     <item value="gnome-trash"/>
     <item value="trash"/>
+    <item value="x-nautilus-desktop"/>
   </oaf_attribute>
   <oaf_attribute name="nautilus:view_as_name" type="string" _value="Icons"/>
   <oaf_attribute name="nautilus:view_as_label" type="string" _value="View as Icons"/>
@@ -41,6 +42,9 @@
   </oaf_attribute>
   <oaf_attribute name="name" type="string" _value="Nautilus file manager desktop icon view"/>
   <oaf_attribute name="description" type="string" _value="Nautilus file manager component that shows icons on the desktop"/>
+  <oaf_attribute name="bonobo:additional_uri_schemes" type="stringv">
+    <item value="x-nautilus-desktop"/>
+  </oaf_attribute>
 </oaf_server>
 
 <oaf_server iid="OAFIID:Nautilus_File_Manager_List_View" type="factory" location="OAFIID:Nautilus_Factory">
Index: src/nautilus-application.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-application.c,v
retrieving revision 1.197
diff -u -p -r1.197 nautilus-application.c
--- src/nautilus-application.c	2 Oct 2002 05:36:51 -0000	1.197
+++ src/nautilus-application.c	15 May 2003 17:08:07 -0000
@@ -66,6 +66,7 @@
 #include <libnautilus-private/nautilus-undo-manager.h>
 #include <libnautilus-private/nautilus-volume-monitor.h>
 #include <libnautilus-private/nautilus-authn-manager.h>
+#include <libnautilus-private/nautilus-desktop-link-monitor.h>
 #include <bonobo-activation/bonobo-activation.h>
 
 /* Needed for the is_kdesktop_present check */
@@ -372,6 +373,9 @@ finish_startup (NautilusApplication *app
 
 	/* Make the desktop work with old Nautilus. */
 	migrate_old_nautilus_files ();
+
+	/* Initialize the desktop link monitor singleton */
+	nautilus_desktop_link_monitor_get ();
 }
 
 void
Index: src/nautilus-desktop-window.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-desktop-window.c,v
retrieving revision 1.55
diff -u -p -r1.55 nautilus-desktop-window.c
--- src/nautilus-desktop-window.c	31 Oct 2002 08:37:30 -0000	1.55
+++ src/nautilus-desktop-window.c	15 May 2003 17:08:07 -0000
@@ -28,6 +28,7 @@
 #include <X11/Xatom.h>
 #include <gdk/gdkx.h>
 #include <gtk/gtklayout.h>
+#include <eel/eel-vfs-extensions.h>
 #include <libgnome/gnome-macros.h>
 #include <libgnomevfs/gnome-vfs-utils.h>
 #include <libnautilus-private/nautilus-file-utilities.h>
@@ -65,18 +66,10 @@ nautilus_desktop_window_delete_event (Na
 void
 nautilus_desktop_window_update_directory (NautilusDesktopWindow *window)
 {
-	char *desktop_directory_path;
-	char *desktop_directory_uri;
-
 	g_assert (NAUTILUS_IS_DESKTOP_WINDOW (window));
-
-	desktop_directory_path = nautilus_get_desktop_directory ();
 	
-	desktop_directory_uri = gnome_vfs_get_uri_from_local_path (desktop_directory_path);
-	g_free (desktop_directory_path);
 	window->affect_desktop_on_next_location_change = TRUE;
-	nautilus_window_go_to (NAUTILUS_WINDOW (window), desktop_directory_uri);
-	g_free (desktop_directory_uri);
+	nautilus_window_go_to (NAUTILUS_WINDOW (window), EEL_DESKTOP_URI);
 }
 
 static void
Index: src/file-manager/fm-desktop-icon-view.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-desktop-icon-view.c,v
retrieving revision 1.203
diff -u -p -r1.203 fm-desktop-icon-view.c
--- src/file-manager/fm-desktop-icon-view.c	3 May 2003 23:23:31 -0000	1.203
+++ src/file-manager/fm-desktop-icon-view.c	15 May 2003 17:08:08 -0000
@@ -47,6 +47,7 @@
 #include <libgnomevfs/gnome-vfs.h>
 #include <libegg/egg-screen-exec.h>
 #include <libnautilus-private/nautilus-bonobo-extensions.h>
+#include <libnautilus-private/nautilus-desktop-icon-file.h>
 #include <libnautilus-private/nautilus-directory-background.h>
 #include <libnautilus-private/nautilus-directory-notify.h>
 #include <libnautilus-private/nautilus-file-changes-queue.h>
@@ -68,9 +69,6 @@
 #include <unistd.h>
 #include <gtk/gtkmessagedialog.h>
 
-static const char untranslated_trash_link_name[] = N_("Trash");
-#define TRASH_LINK_NAME _(untranslated_trash_link_name)
-
 #define DESKTOP_COMMAND_EMPTY_TRASH_CONDITIONAL		"/commands/Empty Trash Conditional"
 #define DESKTOP_COMMAND_UNMOUNT_VOLUME_CONDITIONAL	"/commands/Unmount Volume Conditional"
 #define DESKTOP_COMMAND_PROTECT_VOLUME_CONDITIONAL      "/commands/Protect Conditional"
@@ -85,7 +83,6 @@ static const char untranslated_trash_lin
 struct FMDesktopIconViewDetails
 {
 	BonoboUIComponent *ui;
-	GList *mount_black_list;
 	GdkWindow *root_window;
 
 	/* For the desktop rescanning
@@ -100,40 +97,22 @@ typedef struct {
 	char *mount_path;
 } MountParameters;
 
-typedef enum {
-	DELETE_MOUNT_LINKS = 1<<0,
-	UPDATE_HOME_LINK   = 1<<1,
-	UPDATE_TRASH_LINK  = 1<<2
-} UpdateType;
-
 static void     fm_desktop_icon_view_init                   (FMDesktopIconView      *desktop_icon_view);
 static void     fm_desktop_icon_view_class_init             (FMDesktopIconViewClass *klass);
-static void     fm_desktop_icon_view_trash_state_changed_callback (NautilusTrashMonitor   *trash,
-								   gboolean                state,
-								   gpointer                callback_data);
-static void     home_uri_changed                                  (gpointer                user_data);
 static void     default_zoom_level_changed                        (gpointer                user_data);
-static void     volume_mounted_callback                           (NautilusVolumeMonitor  *monitor,
-								   NautilusVolume         *volume,
-								   FMDesktopIconView      *icon_view);
-static void     volume_unmounted_callback                         (NautilusVolumeMonitor  *monitor,
-								   NautilusVolume         *volume,
-								   FMDesktopIconView      *icon_view);
-static void     update_desktop_directory                          (UpdateType              type);
 static gboolean real_supports_auto_layout                         (FMIconView             *view);
 static gboolean real_supports_keep_aligned                        (FMIconView             *view);
 static void     real_merge_menus                                  (FMDirectoryView        *view);
 static void     real_update_menus                                 (FMDirectoryView        *view);
 static gboolean real_supports_zooming                             (FMDirectoryView        *view);
 static void     update_disks_menu                                 (FMDesktopIconView      *view);
-static void     free_volume_black_list                            (FMDesktopIconView      *view);
 static gboolean	volume_link_is_selection 			  (FMDirectoryView 	  *view);
 static NautilusDeviceType volume_link_device_type                 (FMDirectoryView        *view);
 static void     fm_desktop_icon_view_update_icon_container_fonts  (FMDesktopIconView      *view);
 
 EEL_CLASS_BOILERPLATE (FMDesktopIconView,
-			      fm_desktop_icon_view,
-			      FM_TYPE_ICON_VIEW)
+		       fm_desktop_icon_view,
+		       FM_TYPE_ICON_VIEW)
 
 static char *desktop_directory;
 static time_t desktop_dir_modify_time;
@@ -267,12 +246,6 @@ fm_desktop_icon_view_finalize (GObject *
 		g_source_remove (icon_view->details->reload_desktop_timeout);
 	}
 
-	/* Delete all of the link files. */
-	update_desktop_directory (DELETE_MOUNT_LINKS);
-	
-	eel_preferences_remove_callback (NAUTILUS_PREFERENCES_HOME_URI,
-					 home_uri_changed,
-					 icon_view);
 	eel_preferences_remove_callback (NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_ZOOM_LEVEL,
 					 default_zoom_level_changed,
 					 icon_view);
@@ -284,8 +257,6 @@ fm_desktop_icon_view_finalize (GObject *
 		icon_view->details->ui = NULL;
 	}
 	
-	free_volume_black_list (icon_view);
-	
 	g_free (icon_view->details);
 
 	G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -344,156 +315,6 @@ fm_desktop_icon_view_handle_middle_click
 }
 
 static void
-free_volume_black_list (FMDesktopIconView *icon_view)
-{
-	eel_g_list_free_deep (icon_view->details->mount_black_list);
-	icon_view->details->mount_black_list = NULL;
-}
-
-static gboolean
-volume_in_black_list (FMDesktopIconView *icon_view,
-		      const NautilusVolume *volume)
-{
-	GList *p;
-	
-	g_return_val_if_fail (FM_IS_DESKTOP_ICON_VIEW (icon_view), TRUE);
-
-	for (p = icon_view->details->mount_black_list; p != NULL; p = p->next) {
-		if (strcmp ((char *) p->data, nautilus_volume_get_mount_path (volume)) == 0) {
-			return TRUE;
-		}
-	}
-
-	return FALSE;
-}
-
-
-static char *
-create_unique_volume_name (const NautilusVolume *volume)
-{
-	GnomeVFSURI *uri;
-	char *uri_path, *new_name;
-	int index;
-	char *volume_name, *original_volume_name;
-	
-	new_name = NULL;
-
-	/* Start with an index of one. If we collide, the file collided with will be the actual
-	 * number one. We will rename with the next available number.
-	 */	   
-	index = 1;
-			
-	volume_name = nautilus_volume_get_name (volume);	
-		
-	uri_path = g_strdup_printf ("%s/%s", desktop_directory, volume_name);		
-	uri = gnome_vfs_uri_new (uri_path);
-	
-	/* Check for existing filename and create a unique name. */
-	while (gnome_vfs_uri_exists (uri)) {
-		gnome_vfs_uri_unref (uri);
-		g_free (uri_path);
-		
-		index++;
-		
-		g_free (new_name);
-		new_name = g_strdup_printf ("%s (%d)", volume_name, index);
-		
-		uri_path = g_strdup_printf ("%s/%s", desktop_directory, new_name);
-		uri = gnome_vfs_uri_new (uri_path);		
-	}
-	
-	if (new_name != NULL) {
-		g_free (volume_name);
-		volume_name = new_name;	
-	}
-	
-	original_volume_name = nautilus_volume_get_name (volume);
-	if (strcmp (volume_name, original_volume_name) != 0) {
-		nautilus_volume_monitor_set_volume_name (nautilus_volume_monitor_get (),
-							 volume, volume_name);
-	}
-	g_free (original_volume_name);
-
-	gnome_vfs_uri_unref (uri);
-	g_free (uri_path);
-	
-	return volume_name;
-}
-
-static void
-create_mount_link (FMDesktopIconView *icon_view,
-		   const NautilusVolume *volume)
-{
-	char *target_uri, *volume_name;
-	const char *icon_name;
-
-	if (volume_in_black_list (icon_view, volume)) {
-		return;
-	}
-	
-	/* FIXME bugzilla.gnome.org 45412: Design a comprehensive desktop mounting strategy */
-	if (!nautilus_volume_is_removable (volume)) {
-		return;
-	}
-
-	/* Get icon type */
-	icon_name = "gnome-dev-harddisk";
-	switch (nautilus_volume_get_device_type (volume)) {
-	case NAUTILUS_DEVICE_AUDIO_CD:
-	case NAUTILUS_DEVICE_CDROM_DRIVE:
-		icon_name = "gnome-dev-cdrom";
-		break;
-
-	case NAUTILUS_DEVICE_FLOPPY_DRIVE:
-		icon_name = "gnome-dev-floppy";
-		break;
-
-	case NAUTILUS_DEVICE_JAZ_DRIVE:
-		icon_name = "gnome-dev-jazdisk";
-		break;
-
-	case NAUTILUS_DEVICE_MEMORY_STICK:
-		icon_name = "gnome-dev-memory";
-		break;
-	
-	case NAUTILUS_DEVICE_NFS:
-		icon_name = "gnome-fs-nfs";
-		break;
-
-	case NAUTILUS_DEVICE_SMB:
-		icon_name = "gnome-fs-smb";
-		break;
-	
-	case NAUTILUS_DEVICE_ZIP_DRIVE:
-		icon_name = "gnome-dev-zipdisk";
-		break;
-
-	case NAUTILUS_DEVICE_APPLE:
-	case NAUTILUS_DEVICE_WINDOWS:
-	case NAUTILUS_DEVICE_CAMERA:
-	case NAUTILUS_DEVICE_UNKNOWN:
-		break;
-	}
-
-	target_uri = nautilus_volume_get_target_uri (volume);
-
-	volume_name = create_unique_volume_name (volume);
-
-	/* Create link */
-	nautilus_link_local_create (desktop_directory, volume_name, icon_name, target_uri, NULL, NAUTILUS_LINK_MOUNT);
-
-	g_free (target_uri);
-	g_free (volume_name);
-}
-
-static gboolean
-create_one_mount_link (const NautilusVolume *volume, gpointer callback_data)
-{
-	create_mount_link (FM_DESKTOP_ICON_VIEW (callback_data), volume);
-	return TRUE;
-}
-
-static void
 unrealized_callback (GtkWidget *widget, FMDesktopIconView *desktop_icon_view)
 {
 	g_return_if_fail (desktop_icon_view->details->root_window != NULL);
@@ -554,13 +375,6 @@ default_zoom_level_changed (gpointer use
 						new_level);
 }
 
-/* Update home link to point to new home uri */
-static void
-home_uri_changed (gpointer callback_data)
-{
-	update_desktop_directory (UPDATE_HOME_LINK);
-}
-
 static gboolean
 do_desktop_rescan (gpointer data)
 {
@@ -650,7 +464,6 @@ fm_desktop_icon_view_update_icon_contain
 static void
 fm_desktop_icon_view_init (FMDesktopIconView *desktop_icon_view)
 {
-	GList *list;
 	NautilusIconContainer *icon_container;
 	GtkAllocation *allocation;
 	GtkAdjustment *hadj, *vadj;
@@ -682,11 +495,6 @@ fm_desktop_icon_view_init (FMDesktopIcon
 	nautilus_icon_container_set_is_fixed_size (icon_container, TRUE);
 	nautilus_icon_container_set_is_desktop (icon_container, TRUE);
 
-	/* Set up default mount black list */
-	list = g_list_prepend (NULL, g_strdup ("/proc"));
-	list = g_list_prepend (list, g_strdup ("/boot"));
-	desktop_icon_view->details->mount_black_list = list;
-
 	/* Set allocation to be at 0, 0 */
 	allocation = &GTK_WIDGET (icon_container)->allocation;
 	allocation->x = 0;
@@ -707,30 +515,13 @@ fm_desktop_icon_view_init (FMDesktopIcon
 	nautilus_icon_container_set_layout_mode (icon_container,
 						 NAUTILUS_ICON_LAYOUT_T_B_L_R);
 
-	update_desktop_directory (DELETE_MOUNT_LINKS | UPDATE_HOME_LINK | UPDATE_TRASH_LINK);
-
-	/* Create initial mount links */
-	nautilus_volume_monitor_each_mounted_volume (nautilus_volume_monitor_get (),
-					     	     create_one_mount_link,
-						     desktop_icon_view);
-	
 	g_signal_connect_object (icon_container, "middle_click",
 				 G_CALLBACK (fm_desktop_icon_view_handle_middle_click), desktop_icon_view, 0);
-	g_signal_connect_object (nautilus_trash_monitor_get (), "trash_state_changed",
-				 G_CALLBACK (fm_desktop_icon_view_trash_state_changed_callback), desktop_icon_view, 0);	
-	g_signal_connect_object (nautilus_volume_monitor_get (), "volume_mounted",
-				 G_CALLBACK (volume_mounted_callback), desktop_icon_view, 0);
-	g_signal_connect_object (nautilus_volume_monitor_get (), "volume_unmounted",
-				 G_CALLBACK (volume_unmounted_callback), desktop_icon_view, 0);
 	g_signal_connect_object (desktop_icon_view, "realize",
 				 G_CALLBACK (realized_callback), desktop_icon_view, 0);
 	g_signal_connect_object (desktop_icon_view, "unrealize",
 				 G_CALLBACK (unrealized_callback), desktop_icon_view, 0);
 	
-	eel_preferences_add_callback (NAUTILUS_PREFERENCES_HOME_URI,
-				      home_uri_changed,
-				      desktop_icon_view);
-
 	eel_preferences_add_callback (NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_ZOOM_LEVEL,
 				      default_zoom_level_changed,
 				      desktop_icon_view);
@@ -852,8 +643,7 @@ static void
 volume_ops_callback (BonoboUIComponent *component, gpointer data, const char *verb)
 {
         FMDirectoryView *view;
-	NautilusFile *file;
-	char *uri, *mount_uri, *mount_path;
+	char *mount_path;
 	GList *selection;
 	char *command;
 	const char *device_path;
@@ -864,6 +654,7 @@ volume_ops_callback (BonoboUIComponent *
 	GError *error;
 	GtkWidget *dialog;
 	GdkScreen *screen;
+	NautilusDesktopLink *link;
 
         g_assert (FM_IS_DIRECTORY_VIEW (data));
         
@@ -874,25 +665,16 @@ volume_ops_callback (BonoboUIComponent *
 	}
               
 	selection = fm_directory_view_get_selection (view);
+
+	link = nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (selection->data));
+	mount_path = nautilus_desktop_link_get_mount_path (link);
+	g_object_unref (link);
 	
-	file = NAUTILUS_FILE (selection->data);
-	
-	uri = nautilus_file_get_uri (file);
-	if (!eel_str_has_prefix (uri, "file:")) {
-		/* Don't allow volume ops on remote uris */
-		g_free (uri);
-		nautilus_file_list_free (selection);
-		return;
-	}
-	
-	mount_uri = nautilus_link_local_get_link_uri (uri);
-	mount_path = gnome_vfs_get_local_path_from_uri (mount_uri);
-	g_free (uri);
-	g_free (mount_uri);
 	if (mount_path == NULL) {
 		nautilus_file_list_free (selection);
 		return;
 	}
+	
 
 	volume = nautilus_volume_monitor_get_volume_for_path (nautilus_volume_monitor_get (), mount_path);
 	device_path = nautilus_volume_get_device_path (volume);
@@ -976,23 +758,20 @@ static gboolean
 trash_link_is_selection (FMDirectoryView *view)
 {
 	GList *selection;
+	NautilusDesktopLink *link;
 	gboolean result;
-	char *uri;
 
 	result = FALSE;
 	
 	selection = fm_directory_view_get_selection (view);
 
-	if (eel_g_list_exactly_one_item (selection)
-	    && nautilus_file_is_nautilus_link (NAUTILUS_FILE (selection->data))) {
-		uri = nautilus_file_get_uri (NAUTILUS_FILE (selection->data));
-		/* It's probably OK that this only works for local
-		 * items, since the trash we care about is on the desktop.
-		 */
-		if (nautilus_link_local_is_trash_link (uri, NULL)) {
+	if (eel_g_list_exactly_one_item (selection) &&
+	    NAUTILUS_IS_DESKTOP_ICON_FILE (selection->data)) {
+		link = nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (selection->data));
+		if (nautilus_desktop_link_get_link_type (link) == NAUTILUS_DESKTOP_LINK_TRASH) {
 			result = TRUE;
 		}
-		g_free (uri);
+		g_object_unref (link);
 	}
 	
 	nautilus_file_list_free (selection);
@@ -1004,23 +783,20 @@ static gboolean
 volume_link_is_selection (FMDirectoryView *view)
 {
 	GList *selection;
+	NautilusDesktopLink *link;
 	gboolean result;
-	char *uri;
 
 	result = FALSE;
 	
 	selection = fm_directory_view_get_selection (view);
 
-	if (eel_g_list_exactly_one_item (selection)
-	    && nautilus_file_is_nautilus_link (NAUTILUS_FILE (selection->data))) {
-		uri = nautilus_file_get_uri (NAUTILUS_FILE (selection->data));
-		/* It's probably OK that this only works for local
-		 * items, since the volume we care about is on the desktop.
-		 */
-		if (nautilus_link_local_is_volume_link (uri, NULL)) {
+	if (eel_g_list_exactly_one_item (selection) &&
+	    NAUTILUS_IS_DESKTOP_ICON_FILE (selection->data)) {
+		link = nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (selection->data));
+		if (nautilus_desktop_link_get_link_type (link) == NAUTILUS_DESKTOP_LINK_VOLUME) {
 			result = TRUE;
 		}
-		g_free (uri);
+		g_object_unref (link);
 	}
 	
 	nautilus_file_list_free (selection);
@@ -1036,8 +812,9 @@ static NautilusDeviceType
 volume_link_device_type (FMDirectoryView *view)
 {
 	GList *selection;
-	gchar *uri, *mount_uri, *mount_path;
+	gchar *mount_path;
 	NautilusVolume *volume;
+	NautilusDesktopLink *link;
 
 	selection = fm_directory_view_get_selection (view);
 
@@ -1045,18 +822,12 @@ volume_link_device_type (FMDirectoryView
 		return NAUTILUS_DEVICE_UNKNOWN;
 	}
 
-	volume = NULL;
-	
-	uri = nautilus_file_get_uri (NAUTILUS_FILE (selection->data));
-	mount_uri = nautilus_link_local_get_link_uri (uri);
-	mount_path = gnome_vfs_get_local_path_from_uri (mount_uri);
-	if(mount_path != NULL) {
-		volume = nautilus_volume_monitor_get_volume_for_path (nautilus_volume_monitor_get (), mount_path);
-		g_free (mount_path);
-	}
-	g_free (mount_uri);
-	g_free (uri);
+	link = nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (selection->data));
+	mount_path = nautilus_desktop_link_get_mount_path (link);
+	volume = nautilus_volume_monitor_get_volume_for_path (nautilus_volume_monitor_get (), mount_path);
+	g_free (mount_path);
 	nautilus_file_list_free (selection);
+	g_object_unref (link);
 
 	if (volume != NULL)
 		return nautilus_volume_get_device_type (volume);
@@ -1064,72 +835,6 @@ volume_link_device_type (FMDirectoryView
 	return NAUTILUS_DEVICE_UNKNOWN;
 }
 
-
-static void
-fm_desktop_icon_view_trash_state_changed_callback (NautilusTrashMonitor *trash_monitor,
-						   gboolean state,
-						   gpointer callback_data)
-{
-	char *path;
-
-	path = g_build_filename (desktop_directory, TRASH_LINK_NAME, NULL);
-
-	nautilus_link_local_set_icon (path, state ? "gnome-fs-trash-empty" : "gnome-fs-trash-full");
-
-	g_free (path);
-}
-
-static void
-volume_mounted_callback (NautilusVolumeMonitor *monitor,
-			 NautilusVolume *volume, 
-			 FMDesktopIconView *icon_view)
-{
-	create_mount_link (icon_view, volume);
-}
-
-static void
-unlink_and_notify (const char *path)
-{
-	char *uri, *unescaped_uri;
-	GList one_item_list;
-
-	unlink (path);
-
-	uri = gnome_vfs_get_uri_from_local_path (path);
-	if (uri == NULL) {
-		return;
-	}
- 
-	unescaped_uri = gnome_vfs_unescape_string (uri, NULL);
-	g_free (uri);
-
-	one_item_list.data = unescaped_uri;
-	one_item_list.next = NULL;
-	one_item_list.prev = NULL;
-	nautilus_directory_notify_files_removed (&one_item_list);
-}
-
-static void
-volume_unmounted_callback (NautilusVolumeMonitor *monitor,
-			   NautilusVolume *volume, 
-			   FMDesktopIconView *icon_view)
-{
-	char *link_path, *volume_name;
-
-	g_assert (volume != NULL);
-	
-	volume_name = nautilus_volume_get_name (volume);
-	if (volume_name == NULL) {
-		return;
-	}
-	
-	link_path = g_build_filename (desktop_directory, volume_name, NULL);
-	unlink_and_notify (link_path);
-
-	g_free (volume_name);
-	g_free (link_path);
-}
-
 static MountParameters *
 mount_parameters_new (FMDesktopIconView *view, const char *mount_path)
 {
@@ -1488,128 +1193,3 @@ real_supports_zooming (FMDirectoryView *
 	 */
 	return FALSE;
 }
-
-/* update_desktop_directory
- *
- * Look for a particular type of link on the desktop. If the right
- * link is there, update its target URI. Delete any extra links of
- * that type.
- */
-static void
-update_desktop_directory (UpdateType type)
-{
-	char *link_path;
-	GnomeVFSResult result;
-	GList *desktop_files, *l;
-	GnomeVFSFileInfo *info;
-
-	char *home_uri = NULL;
-	char *home_link_name = NULL;
-	gboolean found_home_link;
-	gboolean found_trash_link;
-
-	if (type & UPDATE_HOME_LINK) {
-		/* Note to translators: If it's hard to compose a good home
-		 * icon name from the user name, you can use a string without
-		 * an "%s" here, in which case the home icon name will not
-		 * include the user's name, which should be fine. To avoid a
-		 * warning, put "%.0s" somewhere in the string, which will
-		 * match the user name string passed by the C code, but not
-		 * put the user name in the final string.
-		 */
-		home_link_name = g_strdup_printf (_("%s's Home"), g_get_user_name ());
-	
-#ifdef WEB_NAVIGATION_ENABLED
-		home_uri = eel_preferences_get (NAUTILUS_PREFERENCES_HOME_URI);
-#else
-		home_uri = gnome_vfs_get_uri_from_local_path (g_get_home_dir ());
-#endif
-	}
-
-	result = gnome_vfs_directory_list_load
-		(&desktop_files, desktop_directory,
-		 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
-		 GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
-
-	found_home_link = found_trash_link = FALSE;
-
-	if (result != GNOME_VFS_OK) {
-		desktop_files = NULL;
-	}
-
-	for (l = desktop_files; l; l = l->next) {
-		info = l->data;
-
-		if (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE &&
-		    info->type != GNOME_VFS_FILE_TYPE_REGULAR &&
-		    info->type != GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK) {
-			continue;
-		}
-		
-		link_path = g_build_filename (desktop_directory, info->name, NULL);
-
-
-		if (type & DELETE_MOUNT_LINKS &&
-		    nautilus_link_local_is_volume_link (link_path, info)) {
-			unlink_and_notify (link_path);
-		}
-
-
-		if (type & UPDATE_HOME_LINK &&
-		    nautilus_link_local_is_home_link (link_path, info)) {
-			if (!found_home_link &&
-			    nautilus_link_local_is_utf8 (link_path, info)) {
-				nautilus_link_local_set_link_uri (link_path, home_uri);
-				nautilus_link_local_set_icon (link_path, "gnome-fs-home");
-				found_home_link = TRUE;
-			} else {
-				unlink_and_notify (link_path); /* kill duplicates */
-			}
-		}
-
-		if (type & UPDATE_TRASH_LINK &&
-		    nautilus_link_local_is_trash_link (link_path, info)) {
-			if (!found_trash_link &&
-			    nautilus_link_local_is_utf8 (link_path, info) &&
-			    !strcmp (TRASH_LINK_NAME, info->name)) {
-				nautilus_link_local_set_link_uri (link_path, EEL_TRASH_URI);
-				found_trash_link = TRUE;
-			} else {
-				unlink_and_notify (link_path); /* kill duplicates */
-			}
-		}
-		g_free (link_path);
-	}
-
-	gnome_vfs_file_info_list_free (desktop_files);
-
-	if (type & UPDATE_HOME_LINK && !found_home_link &&
-	    !eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_IS_HOME_DIR)) {
-		nautilus_link_local_create (desktop_directory,
-					    home_link_name,
-					    "gnome-fs-home", 
-					    home_uri,
-					    NULL,
-					    NAUTILUS_LINK_HOME);
-	}
-	       
-	if (type & UPDATE_TRASH_LINK) {
-		if (!found_trash_link) {
-			nautilus_link_local_create (desktop_directory,
-						    TRASH_LINK_NAME,
-						    "gnome-fs-trash-empty", 
-						    EEL_TRASH_URI,
-						    NULL,
-						    NAUTILUS_LINK_TRASH);
-		}
-
-		/* Make sure link represents current trash state */
-		fm_desktop_icon_view_trash_state_changed_callback (nautilus_trash_monitor_get (),
-								   nautilus_trash_monitor_is_empty (),
-								   NULL);
-	}
-
-	g_free (home_link_name);
-	g_free (home_uri);
-}
-
Index: src/file-manager/fm-directory-view.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-directory-view.c,v
retrieving revision 1.574
diff -u -p -r1.574 fm-directory-view.c
--- src/file-manager/fm-directory-view.c	29 Apr 2003 07:30:19 -0000	1.574
+++ src/file-manager/fm-directory-view.c	15 May 2003 17:08:09 -0000
@@ -68,6 +68,8 @@
 #include <libnautilus-private/nautilus-recent.h>
 #include <libegg/egg-screen-exec.h>
 #include <libnautilus-private/nautilus-bonobo-extensions.h>
+#include <libnautilus-private/nautilus-desktop-icon-file.h>
+#include <libnautilus-private/nautilus-desktop-directory.h>
 #include <libnautilus-private/nautilus-directory-background.h>
 #include <libnautilus-private/nautilus-directory.h>
 #include <libnautilus-private/nautilus-file-attributes.h>
@@ -992,7 +994,7 @@ new_launcher_callback (BonoboUIComponent
 
 	view = FM_DIRECTORY_VIEW (callback_data);
 
-	parent_uri = fm_directory_view_get_uri (view);
+	parent_uri = fm_directory_view_get_backing_uri (view);
 
 	nautilus_launch_application_from_command (gtk_widget_get_screen (GTK_WIDGET (view)),
 						  "gnome-desktop-item-edit", 
@@ -2314,7 +2316,7 @@ display_pending_idle_callback (gpointer 
 {
 	gboolean ret;
 	FMDirectoryView *view;
-		
+
 	view = FM_DIRECTORY_VIEW (data);
 
 	g_object_ref (G_OBJECT (view));
@@ -2474,7 +2476,7 @@ done_loading_callback (NautilusDirectory
 		       gpointer callback_data)
 {
 	FMDirectoryView *view;
-	
+
 	view = FM_DIRECTORY_VIEW (callback_data);
 	
 	process_new_files (view);
@@ -2946,7 +2948,7 @@ fm_directory_view_duplicate_selection (F
  * 
  * Return TRUE if one of our special links is in the selection.
  * Special links include the following: 
- *	 NAUTILUS_LINK_TRASH, NAUTILUS_LINK_HOME, NAUTILUS_LINK_MOUNT
+ *	 NAUTILUS_DESKTOP_LINK_TRASH, NAUTILUS_DESKTOP_LINK_HOME, NAUTILUS_DESKTOP_LINK_MOUNT
  */
  
 static gboolean
@@ -2955,7 +2957,6 @@ special_link_in_selection (FMDirectoryVi
 	gboolean saw_link;
 	GList *selection, *node;
 	NautilusFile *file;
-	char *uri;
 
 	g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE);
 
@@ -2966,14 +2967,7 @@ special_link_in_selection (FMDirectoryVi
 	for (node = selection; node != NULL; node = node->next) {
 		file = NAUTILUS_FILE (node->data);
 
-		uri = nautilus_file_get_uri (file);
-
-		/* FIXME: This reads the link file every single time. */
-		saw_link = nautilus_file_is_local (file)
-			&& nautilus_file_is_nautilus_link (file)
-			&& nautilus_link_local_is_special_link (uri);
-		
-		g_free (uri);
+		saw_link = NAUTILUS_IS_DESKTOP_ICON_FILE (file);
 		
 		if (saw_link) {
 			break;
@@ -2999,7 +2993,9 @@ can_move_uri_to_trash (FMDirectoryView *
 
 	file_uri = gnome_vfs_uri_new (file_uri_string);
 
-	g_return_val_if_fail (file_uri != NULL, FALSE);
+	if (file_uri == NULL) {
+		return FALSE;
+	}
 
 	/* FIXME: Why can't we just pass file_uri to gnome_vfs_find_directory? */
 	directory_uri = gnome_vfs_uri_get_parent (file_uri);
@@ -3273,7 +3269,7 @@ fm_directory_view_new_folder (FMDirector
 {
 	char *parent_uri;
 
-	parent_uri = fm_directory_view_get_uri (directory_view);
+	parent_uri = fm_directory_view_get_backing_uri (directory_view);
 	nautilus_file_operations_new_folder (GTK_WIDGET (directory_view),
 					     parent_uri,
 					     new_folder_done, directory_view);
@@ -4406,6 +4402,14 @@ clear_clipboard_callback (GtkClipboard *
 	g_free (user_data_or_owner);
 }
 
+static GtkClipboard *
+get_clipboard (FMDirectoryView *view)
+{
+	return gtk_clipboard_get_for_display (gtk_widget_get_display (GTK_WIDGET (view)),
+					      GDK_SELECTION_CLIPBOARD);
+}
+
+
 static void
 copy_or_cut_files (FMDirectoryView *view,
 		   gboolean cut)
@@ -4419,7 +4423,7 @@ copy_or_cut_files (FMDirectoryView *view
 
 	clipboard_string = convert_file_list_to_string (clipboard_contents, cut);
 	
-	gtk_clipboard_set_with_data (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
+	gtk_clipboard_set_with_data (get_clipboard (view),
 				     clipboard_targets, G_N_ELEMENTS (clipboard_targets),
 				     get_clipboard_callback, clear_clipboard_callback,
 				     clipboard_string);
@@ -4525,7 +4529,7 @@ clipboard_received_callback (GtkClipboar
 		g_strfreev (lines);
 	}
 
-	view_uri = fm_directory_view_get_uri (view);
+	view_uri = fm_directory_view_get_backing_uri (view);
 
 	if (item_uris == NULL|| view_uri == NULL) {
 		nautilus_view_report_status (view->details->nautilus_view,
@@ -4543,7 +4547,11 @@ paste_files_callback (BonoboUIComponent 
 		      gpointer callback_data,
 		      const char *verb)
 {
-	gtk_clipboard_request_contents (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
+	FMDirectoryView *view;
+
+	view = FM_DIRECTORY_VIEW (callback_data);
+	
+	gtk_clipboard_request_contents (get_clipboard (view),
 					copied_files_atom,
 					clipboard_received_callback,
 					callback_data);
@@ -4626,6 +4634,7 @@ clipboard_targets_received (GtkClipboard
 	int n_targets;
 	int i;
 
+	
 	view = FM_DIRECTORY_VIEW (user_data);
 	can_paste = FALSE;
 
@@ -4832,7 +4841,7 @@ real_update_menus (FMDirectoryView *view
 	} else {
 		/* Ask the clipboard */
 		g_object_ref (view); /* Need to keep the object alive until we get the reply */
-		gtk_clipboard_request_contents (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
+		gtk_clipboard_request_contents (get_clipboard (view),
 						gdk_atom_intern ("TARGETS", FALSE),
 						clipboard_targets_received,
 						view);
@@ -5960,6 +5969,34 @@ fm_directory_view_get_uri (FMDirectoryVi
 	return nautilus_directory_get_uri (view->details->model);
 }
 
+/* Get the real directory where files will be stored and created */
+char *
+fm_directory_view_get_backing_uri (FMDirectoryView *view)
+{
+	NautilusDirectory *directory;
+	char *uri;
+	
+	g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), NULL);
+
+	if (view->details->model == NULL) {
+		return NULL;
+	}
+	
+	directory = view->details->model;
+	
+	if (NAUTILUS_IS_DESKTOP_DIRECTORY (directory)) {
+		directory = nautilus_desktop_directory_get_real_directory (NAUTILUS_DESKTOP_DIRECTORY (directory));
+	} else {
+		nautilus_directory_ref (directory);
+	}
+	
+	uri = nautilus_directory_get_uri (directory);
+
+	nautilus_directory_unref (directory);
+
+	return uri;
+}
+
 void
 fm_directory_view_move_copy_items (const GList *item_uris,
 				   GArray *relative_item_points,
@@ -6004,7 +6041,7 @@ fm_directory_view_move_copy_items (const
 		
 		return;
 	}
-	
+
 	if (eel_uri_is_trash (target_uri) && copy_action == GDK_ACTION_MOVE) {
 		trash_or_delete_files_common (view, item_uris, relative_item_points, FALSE);
 	} else {
Index: src/file-manager/fm-directory-view.h
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-directory-view.h,v
retrieving revision 1.128
diff -u -p -r1.128 fm-directory-view.h
--- src/file-manager/fm-directory-view.h	7 Apr 2003 11:56:04 -0000	1.128
+++ src/file-manager/fm-directory-view.h	15 May 2003 17:08:09 -0000
@@ -292,6 +292,7 @@ NautilusView *      fm_directory_view_ge
 
 /* Functions callable from the user interface and elsewhere. */
 char *              fm_directory_view_get_uri                          (FMDirectoryView  *view);
+char *              fm_directory_view_get_backing_uri                  (FMDirectoryView  *view);
 gboolean            fm_directory_view_can_accept_item                  (NautilusFile     *target_item,
 									const char       *item_uri,
 									FMDirectoryView  *view);
Index: src/file-manager/fm-icon-container.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-icon-container.c,v
retrieving revision 1.9
diff -u -p -r1.9 fm-icon-container.c
--- src/file-manager/fm-icon-container.c	2 Apr 2003 11:51:14 -0000	1.9
+++ src/file-manager/fm-icon-container.c	15 May 2003 17:08:09 -0000
@@ -31,6 +31,7 @@
 #include <libnautilus-private/nautilus-global-preferences.h>
 #include <libnautilus-private/nautilus-file-attributes.h>
 #include <libnautilus-private/nautilus-thumbnails.h>
+#include <libnautilus-private/nautilus-desktop-icon-file.h>
 
 #include "fm-icon-container.h"
 
@@ -248,6 +249,13 @@ fm_icon_container_get_icon_text (Nautilu
 		*editable_text = nautilus_file_get_display_name (file);
 	}
 
+	if (NAUTILUS_IS_DESKTOP_ICON_FILE (file)) {
+		/* Don't show the normal extra information for desktop icons, it doesn't
+		 * make sense. */
+ 		*additional_text = NULL;
+		return;
+	}
+	
 	/* Handle link files specially. */
 	if (nautilus_file_is_nautilus_link (file)) {
 		/* FIXME bugzilla.gnome.org 42531: Does sync. I/O and works only locally. */
@@ -318,34 +326,30 @@ typedef enum {
 static SortCategory
 get_sort_category (NautilusFile *file)
 {
-	char *uri;
+	NautilusDesktopLink *link;
 	SortCategory category;
 
-	if (!nautilus_file_is_nautilus_link (file)) {
-		category = SORT_OTHER;
-	} else {
-		if (!nautilus_file_is_local (file))
-			return SORT_OTHER;
-
-		uri = nautilus_file_get_uri (file);
+	if (NAUTILUS_IS_DESKTOP_ICON_FILE (file)) {
+		link = nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (file));
 		
-		switch (nautilus_link_local_get_link_type (uri, NULL)) {
-		case NAUTILUS_LINK_HOME:
+		switch (nautilus_desktop_link_get_link_type (link)) {
+		case NAUTILUS_DESKTOP_LINK_HOME:
 			category = SORT_HOME_LINK;
 			break;
-		case NAUTILUS_LINK_MOUNT:
+		case NAUTILUS_DESKTOP_LINK_VOLUME:
 			category = SORT_MOUNT_LINK;
 			break;
-		case NAUTILUS_LINK_TRASH:
+		case NAUTILUS_DESKTOP_LINK_TRASH:
 			category = SORT_TRASH_LINK;
 			break;
 		default:
 			category = SORT_OTHER;
 			break;
 		}
-		
-		g_free (uri);
-	}
+		g_object_unref (link);
+	} else {
+		category = SORT_OTHER;
+	} 
 	
 	return category;
 }
Index: src/file-manager/fm-icon-view.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-icon-view.c,v
retrieving revision 1.279
diff -u -p -r1.279 fm-icon-view.c
--- src/file-manager/fm-icon-view.c	3 May 2003 23:23:31 -0000	1.279
+++ src/file-manager/fm-icon-view.c	15 May 2003 17:08:09 -0000
@@ -2413,7 +2413,7 @@ icon_view_handle_uri_list (NautilusIconC
 		return;
 	}
 
-	container_uri = fm_directory_view_get_uri (FM_DIRECTORY_VIEW (view));
+	container_uri = fm_directory_view_get_backing_uri (FM_DIRECTORY_VIEW (view));
 	g_return_if_fail (container_uri != NULL);
 
 	if (eel_vfs_has_capability (container_uri,
Index: src/file-manager/fm-properties-window.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-properties-window.c,v
retrieving revision 1.170
diff -u -p -r1.170 fm-properties-window.c
--- src/file-manager/fm-properties-window.c	23 Apr 2003 18:29:13 -0000	1.170
+++ src/file-manager/fm-properties-window.c	15 May 2003 17:08:10 -0000
@@ -63,6 +63,7 @@
 #include <libnautilus-private/nautilus-customization-data.h>
 #include <libnautilus-private/nautilus-entry.h>
 #include <libnautilus-private/nautilus-file-attributes.h>
+#include <libnautilus-private/nautilus-desktop-icon-file.h>
 #include <libnautilus-private/nautilus-global-preferences.h>
 #include <libnautilus-private/nautilus-icon-factory.h>
 #include <libnautilus-private/nautilus-emblem-utils.h>
@@ -2479,34 +2480,21 @@ static NautilusFile *
 get_target_file (NautilusFile *file)
 {
 	NautilusFile *target_file;
-	char *uri;
 	char *uri_to_display;
+	NautilusDesktopLink *link;
 
 	target_file = NULL;
-	if (nautilus_file_is_nautilus_link (file)) {
-		/* Note: This will only work on local files. For now
-		 * that seems fine since the links we care about are
-		 * all on the desktop.
-		 */
-		if (nautilus_file_is_local (file)) {
-			uri = nautilus_file_get_uri (file);
-
-			switch (nautilus_link_local_get_link_type (uri, NULL)) {
-			case NAUTILUS_LINK_MOUNT:
-			case NAUTILUS_LINK_TRASH:
-			case NAUTILUS_LINK_HOME:
-				/* map to linked URI for these types of links */
-				uri_to_display = nautilus_link_local_get_link_uri (uri);
-				target_file = nautilus_file_get (uri_to_display);
-				g_free (uri_to_display);
-				break;
-			case NAUTILUS_LINK_GENERIC:
-				/* don't for these types */
-				break;
-			}
-			
-			g_free (uri);
+	if (NAUTILUS_IS_DESKTOP_ICON_FILE (file)) {
+		link = nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (file));
+		
+		/* map to linked URI for these types of links */
+		uri_to_display = nautilus_desktop_link_get_activation_uri (link);
+		if (uri_to_display) {
+			target_file = nautilus_file_get (uri_to_display);
+			g_free (uri_to_display);
 		}
+		
+		g_object_unref (link);
 	}
 
 	if (target_file != NULL) {


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