Index: src/file-manager/fm-icon-container.c
===================================================================
--- src/file-manager/fm-icon-container.c	(revision 14701)
+++ src/file-manager/fm-icon-container.c	(working copy)
@@ -402,6 +402,7 @@ get_sort_category (NautilusFile *file)
 				category = SORT_HOME_LINK;
 				break;
 			case NAUTILUS_DESKTOP_LINK_MOUNT:
+			case NAUTILUS_DESKTOP_LINK_VOLUME:
 				category = SORT_MOUNT_LINK;
 				break;
 			case NAUTILUS_DESKTOP_LINK_TRASH:
Index: src/nautilus-places-sidebar.c
===================================================================
--- src/nautilus-places-sidebar.c	(revision 14701)
+++ src/nautilus-places-sidebar.c	(working copy)
@@ -257,6 +257,36 @@ add_place (NautilusPlacesSidebar *sidebar,
 	return child_iter;
 }
 
+static gboolean
+mount_referenced_by_volume_activation_root (GList *volumes, GMount *mount)
+{
+	GList *l;
+	GFile *mount_root;
+	gboolean ret;
+
+	ret = FALSE;
+
+	mount_root = g_mount_get_root (mount);
+
+	for (l = volumes; l != NULL; l = l->next) {
+		GVolume *volume = G_VOLUME (l->data);
+		GFile *volume_activation_root;
+
+		volume_activation_root = g_volume_get_activation_root (volume);
+		if (volume_activation_root != NULL) {
+			if (g_file_has_prefix (volume_activation_root, mount_root)) {
+				ret = TRUE;
+				g_object_unref (volume_activation_root);
+				break;
+			}
+			g_object_unref (volume_activation_root);
+		}
+	}
+
+	g_object_unref (mount_root);
+	return ret;
+}
+
 static void
 update_places (NautilusPlacesSidebar *sidebar)
 {
@@ -412,7 +442,6 @@ update_places (NautilusPlacesSidebar *sidebar)
 		volume = l->data;
 		drive = g_volume_get_drive (volume);
 		if (drive != NULL) {
-		    	g_object_unref (volume);
 			g_object_unref (drive);
 			continue;
 		}
@@ -443,17 +472,17 @@ update_places (NautilusPlacesSidebar *sidebar)
 			g_object_unref (icon);
 			g_free (name);
 		}
-		g_object_unref (volume);
 	}
-	g_list_free (volumes);
 
 	/* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
 	mounts = g_volume_monitor_get_mounts (volume_monitor);
 	for (l = mounts; l != NULL; l = l->next) {
 		mount = l->data;
+		if (mount_referenced_by_volume_activation_root (volumes, mount))
+			continue;
 		volume = g_mount_get_volume (mount);
 		if (volume != NULL) {
-		    	g_object_unref (volume);
+		        g_object_unref (volume);
 			g_object_unref (mount);
 			continue;
 		}
@@ -475,6 +504,9 @@ update_places (NautilusPlacesSidebar *sidebar)
 	}
 	g_list_free (mounts);
 
+	g_list_foreach (volumes, (GFunc) g_object_unref, NULL);
+	g_list_free (volumes);
+
 	mount_uri = "trash:///"; /* No need to strdup */
 	icon = nautilus_trash_monitor_get_icon ();
 	last_iter = add_place (sidebar, PLACES_BUILT_IN,
Index: configure.in
===================================================================
--- configure.in	(revision 14701)
+++ configure.in	(working copy)
@@ -3,7 +3,7 @@ AC_PREREQ(2.54)
 dnl ===========================================================================
 
 m4_define(eel_minver,                  2.24.0)
-m4_define(glib_minver,                 2.17.5)
+m4_define(glib_minver,                 2.19.0)
 m4_define(gnome_desktop_minver,        2.9.91)
 m4_define(gnome_minver,                2.14.0)
 m4_define(gnome_ui_minver,             2.6.0)
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 14701)
+++ ChangeLog	(working copy)
@@ -1,3 +1,31 @@
+2008-10-07  David Zeuthen  <davidz@redhat.com>
+
+	The nautilus bits of the "connected server" feature (#555333).  No
+	UI enhancements (such as a reworked "Connect to Server" dialog)
+	are included; that's for a future patch in the 2.25 series.
+
+	* configure.in:
+	Bump gio/glib dependency to 2.19.0 for the
+	G_VOLUME_IDENTIFIER_KIND_CONNECTED_SERVER_PATH symbol.
+
+	* libnautilus-private/apps_nautilus_preferences.schemas.in:
+	* libnautilus-private/nautilus-global-preferences.[ch]:
+	* libnautilus-private/nautilus-global-preferences.h:
+	Add new /apps/nautilus/desktop/connected_servers_visible
+	preference.
+
+	* libnautilus-private/nautilus-desktop-link-monitor.c:
+	* libnautilus-private/nautilus-desktop-link.[ch]:
+	Also monitor volumes. Always show volumes for connected servers on
+	the desktop even if they are not mounted.
+
+	* src/file-manager/fm-icon-container.c:
+	Also use NAUTILUS_DESKTOP_LINK_VOLUME for sorting right.
+
+	* src/nautilus-places-sidebar.c:
+	Don't show unanchored mounts that are referenced from volumes
+	using shadow mounts.
+
 2008-10-07  Alexander Larsson  <alexl@redhat.com>
 
         * src/nautilus-property-browser.c:
Index: libnautilus-private/nautilus-desktop-link.c
===================================================================
--- libnautilus-private/nautilus-desktop-link.c	(revision 14701)
+++ libnautilus-private/nautilus-desktop-link.c	(working copy)
@@ -48,7 +48,8 @@ struct NautilusDesktopLinkDetails {
 	GObject *signal_handler_obj;
 	gulong signal_handler;
 
-	/* Just for mount icons: */
+	/* for volume/mount icons: */
+	GVolume *volume;
 	GMount *mount;
 };
 
@@ -69,8 +70,11 @@ nautilus_desktop_link_changed (NautilusDesktopLink
 }
 
 static void
-mount_changed_callback (GMount *mount, NautilusDesktopLink *link)
+volume_update_details (NautilusDesktopLink *link, GVolume *volume)
 {
+	GMount *mount;
+	GFile *activation_root;
+
 	g_free (link->details->display_name);
 	if (link->details->activation_location) {
 		g_object_unref (link->details->activation_location);
@@ -78,15 +82,72 @@ static void
 	if (link->details->icon) {
 		g_object_unref (link->details->icon);
 	}
-	
+
+	mount = g_volume_get_mount (volume);
+	activation_root = g_volume_get_activation_root (volume);
+
+	if (activation_root != NULL) {
+			link->details->display_name = g_volume_get_name (volume);
+			link->details->activation_location = g_object_ref (activation_root);
+			link->details->icon = g_volume_get_icon (volume);
+	} else {
+		if (mount != NULL) {
+			link->details->display_name = g_mount_get_name (mount);
+			link->details->activation_location = g_mount_get_root (mount);
+			link->details->icon = g_mount_get_icon (mount);
+		} else {
+			/* this only happens for unmounted volumes without an activation URI;
+			 * these shouldn't be shown due to the logic in the desktop monitor..
+			 *
+			 * However, handle such an error gracefully instead of crashing.
+			 */
+			link->details->display_name = g_volume_get_name (volume);
+			link->details->activation_location = g_file_new_for_uri ("file:///");
+			link->details->icon = g_volume_get_icon (volume);
+
+			g_warning ("Shouldn't display unmounted volume '%s' without an activation URI",
+				   link->details->display_name);
+		}
+	}
+
+	if (activation_root != NULL)
+		g_object_unref (activation_root);
+	if (mount != NULL)
+		g_object_unref (mount);
+}
+
+static void
+mount_update_details (NautilusDesktopLink *link, GMount *mount)
+{
+	g_free (link->details->display_name);
+	if (link->details->activation_location) {
+		g_object_unref (link->details->activation_location);
+	}
+	if (link->details->icon) {
+		g_object_unref (link->details->icon);
+	}
+
 	link->details->display_name = g_mount_get_name (mount);
 	link->details->activation_location = g_mount_get_root (mount);
 	link->details->icon = g_mount_get_icon (mount);
-	
+}
+
+
+static void
+volume_changed_callback (GVolume *volume, NautilusDesktopLink *link)
+{
+	volume_update_details (link, volume);
 	nautilus_desktop_link_changed (link);
 }
 
 static void
+mount_changed_callback (GMount *mount, NautilusDesktopLink *link)
+{
+	mount_update_details (link, mount);
+	nautilus_desktop_link_changed (link);
+}
+
+static void
 trash_state_changed_callback (NautilusTrashMonitor *trash_monitor,
 			      gboolean state,
 			      gpointer callback_data)
@@ -220,6 +281,7 @@ nautilus_desktop_link_new (NautilusDesktopLinkType
 
 	default:
 	case NAUTILUS_DESKTOP_LINK_MOUNT:
+	case NAUTILUS_DESKTOP_LINK_VOLUME:
 		g_assert_not_reached();
 	}
 
@@ -229,10 +291,43 @@ nautilus_desktop_link_new (NautilusDesktopLinkType
 }
 
 NautilusDesktopLink *
+nautilus_desktop_link_new_from_volume (GVolume *volume)
+{
+	NautilusDesktopLink *link;
+	char *name, *filename;
+
+	link = NAUTILUS_DESKTOP_LINK (g_object_new (NAUTILUS_TYPE_DESKTOP_LINK, NULL));
+	
+	link->details->type = NAUTILUS_DESKTOP_LINK_VOLUME;
+
+	link->details->volume = g_object_ref (volume);
+
+	name = g_volume_get_name (volume);
+
+	/* Replace slashes in name */
+	filename = g_strconcat (g_strdelimit (name, "/", '-'), ".volume", NULL);
+	link->details->filename =
+		nautilus_desktop_link_monitor_make_filename_unique (nautilus_desktop_link_monitor_get (),
+								    filename);
+	g_free (filename);
+	g_free (name);
+	
+	volume_update_details (link, volume);
+	
+	link->details->signal_handler_obj = G_OBJECT (volume);
+	link->details->signal_handler =
+		g_signal_connect (volume, "changed",
+				  G_CALLBACK (volume_changed_callback), link);
+	
+	create_icon_file (link);
+
+	return link;
+}
+
+NautilusDesktopLink *
 nautilus_desktop_link_new_from_mount (GMount *mount)
 {
 	NautilusDesktopLink *link;
-	GVolume *volume;
 	char *name, *filename;
 
 	link = NAUTILUS_DESKTOP_LINK (g_object_new (NAUTILUS_TYPE_DESKTOP_LINK, NULL));
@@ -241,29 +336,20 @@ nautilus_desktop_link_new_from_mount (GMount *moun
 
 	link->details->mount = g_object_ref (mount);
 
-	/* We try to use the drive name to get somewhat stable filenames
-	   for metadata */
-	volume = g_mount_get_volume (mount);
-	if (volume != NULL) {
-		name = g_volume_get_name (volume);
-		g_object_unref (volume);
-	} else {
-		name = g_mount_get_name (mount);
-	}
+	/* can't get better name for metadata (there is no volume, if there were, the
+	 * desktop monitor would have called new_from_volume() instead) */
+	name = g_mount_get_name (mount);
 
 	/* Replace slashes in name */
-	filename = g_strconcat (g_strdelimit (name, "/", '-'), ".volume", NULL);
+	filename = g_strconcat (g_strdelimit (name, "/", '-'), ".mount", NULL);
 	link->details->filename =
 		nautilus_desktop_link_monitor_make_filename_unique (nautilus_desktop_link_monitor_get (),
 								    filename);
 	g_free (filename);
 	g_free (name);
 	
-	link->details->display_name = g_mount_get_name (mount);
+	mount_update_details (link, mount);
 	
-	link->details->activation_location = g_mount_get_root (mount);
-	link->details->icon = g_mount_get_icon (mount);
-	
 	link->details->signal_handler_obj = G_OBJECT (mount);
 	link->details->signal_handler =
 		g_signal_connect (mount, "changed",
@@ -274,11 +360,22 @@ nautilus_desktop_link_new_from_mount (GMount *moun
 	return link;
 }
 
+GVolume *
+nautilus_desktop_link_get_volume (NautilusDesktopLink *link)
+{
+	if (link->details->volume) {
+		return g_object_ref (link->details->volume);
+	}
+	return NULL;
+}
+
 GMount *
 nautilus_desktop_link_get_mount (NautilusDesktopLink *link)
 {
-	if (link->details->mount) {
+	if (link->details->mount != NULL) {
 		return g_object_ref (link->details->mount);
+	} else if (link->details->volume != NULL) {
+		return g_volume_get_mount (link->details->volume);
 	}
 	return NULL;
 }
@@ -417,6 +514,10 @@ desktop_link_finalize (GObject *object)
 						 link);
 	}
 
+	if (link->details->type == NAUTILUS_DESKTOP_LINK_VOLUME) {
+		g_object_unref (link->details->volume);
+	}
+
 	if (link->details->type == NAUTILUS_DESKTOP_LINK_MOUNT) {
 		g_object_unref (link->details->mount);
 	}
Index: libnautilus-private/nautilus-desktop-link.h
===================================================================
--- libnautilus-private/nautilus-desktop-link.h	(revision 14701)
+++ libnautilus-private/nautilus-desktop-link.h	(working copy)
@@ -54,6 +54,7 @@ typedef enum {
 	NAUTILUS_DESKTOP_LINK_HOME,
 	NAUTILUS_DESKTOP_LINK_COMPUTER,
 	NAUTILUS_DESKTOP_LINK_TRASH,
+	NAUTILUS_DESKTOP_LINK_VOLUME,
 	NAUTILUS_DESKTOP_LINK_MOUNT,
 	NAUTILUS_DESKTOP_LINK_NETWORK
 } NautilusDesktopLinkType;
@@ -61,7 +62,8 @@ typedef enum {
 GType   nautilus_desktop_link_get_type (void);
 
 NautilusDesktopLink *   nautilus_desktop_link_new                     (NautilusDesktopLinkType  type);
-NautilusDesktopLink *   nautilus_desktop_link_new_from_mount          (GMount                 *mount);
+NautilusDesktopLink *   nautilus_desktop_link_new_from_volume         (GVolume                 *volume);
+NautilusDesktopLink *   nautilus_desktop_link_new_from_mount          (GMount                  *mount);
 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);
@@ -70,6 +72,7 @@ GFile *                 nautilus_desktop_link_get_
 gboolean                nautilus_desktop_link_get_date                (NautilusDesktopLink     *link,
 								       NautilusDateType         date_type,
 								       time_t                  *date);
+GVolume *               nautilus_desktop_link_get_volume              (NautilusDesktopLink     *link);
 GMount *                nautilus_desktop_link_get_mount               (NautilusDesktopLink     *link);
 gboolean                nautilus_desktop_link_can_rename              (NautilusDesktopLink     *link);
 gboolean                nautilus_desktop_link_rename                  (NautilusDesktopLink     *link,
Index: libnautilus-private/apps_nautilus_preferences.schemas.in
===================================================================
--- libnautilus-private/apps_nautilus_preferences.schemas.in	(revision 14701)
+++ libnautilus-private/apps_nautilus_preferences.schemas.in	(working copy)
@@ -1019,6 +1019,21 @@ most cases, this should be left alone. -->Sans 10<
     </schema>
 
     <schema>
+      <key>/schemas/apps/nautilus/desktop/connected_servers_visible</key>
+      <applyto>/apps/nautilus/desktop/connected_servers_visible</applyto>
+      <owner>nautilus</owner>
+      <type>bool</type>
+      <default>true</default>
+      <locale name="C">
+      	<short>Show connected servers on the desktop</short>
+	<long>
+	  If this is set to true, icons linking to connected
+	  servers will be put on the desktop.
+	</long>
+      </locale>
+    </schema>
+
+    <schema>
       <key>/schemas/apps/nautilus/desktop/network_icon_visible</key>
       <applyto>/apps/nautilus/desktop/network_icon_visible</applyto>
       <owner>nautilus</owner>
Index: libnautilus-private/nautilus-desktop-link-monitor.c
===================================================================
--- libnautilus-private/nautilus-desktop-link-monitor.c	(revision 14701)
+++ libnautilus-private/nautilus-desktop-link-monitor.c	(working copy)
@@ -50,10 +50,15 @@ struct NautilusDesktopLinkMonitorDetails {
 	NautilusDesktopLink *trash_link;
 	NautilusDesktopLink *network_link;
 
-	gulong mount_id;
-	gulong unmount_id;
-	gulong changed_id;
+	gulong volume_added_id;
+	gulong volume_removed_id;
+	gulong volume_changed_id;
+
+	gulong mount_added_id;
+	gulong mount_removed_id;
+	gulong mount_changed_id;
 	
+	GList *volume_links;
 	GList *mount_links;
 };
 
@@ -66,6 +71,8 @@ EEL_CLASS_BOILERPLATE (NautilusDesktopLinkMonitor,
 		       nautilus_desktop_link_monitor,
 		       G_TYPE_OBJECT)
 
+static void recompute_volume_and_mount_links (NautilusDesktopLinkMonitor *monitor);
+
 static NautilusDesktopLinkMonitor *the_link_monitor = NULL;
 
 static void
@@ -110,7 +117,7 @@ volume_delete_dialog (GtkWidget *parent_view,
 				 dialog_str,
 				 _("If you want to eject the volume, please use \"Eject\" in the "
 				   "popup menu of the volume."),
-				 GTK_STOCK_OK, NULL);
+					 GTK_STOCK_OK, NULL);
 		} else {
 			eel_run_simple_dialog
 				(parent_view, 
@@ -153,7 +160,7 @@ volume_file_name_used (NautilusDesktopLinkMonitor
 	char *other_name;
 	gboolean same;
 
-	for (l = monitor->details->mount_links; l != NULL; l = l->next) {
+	for (l = monitor->details->volume_links; l != NULL; l = l->next) {
 		other_name = nautilus_desktop_link_get_file_name (l->data);
 		same = strcmp (name, other_name) == 0;
 		g_free (other_name);
@@ -182,63 +189,168 @@ nautilus_desktop_link_monitor_make_filename_unique
 	return unique_name;
 }
 
+static gboolean
+should_display_link_for_volume (GVolume *volume)
+{
+	gboolean ret;
+	GMount *mount;
+	char *connected_server_path;
+
+	ret = FALSE;
+
+	mount = g_volume_get_mount (volume);
+	connected_server_path = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_CONNECTED_SERVER_PATH);
+
+	if (connected_server_path != NULL) {
+		/* connected server, show (according to preferences) even if not mounted */
+		if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_CONNECTED_SERVERS_VISIBLE))
+			ret = TRUE;
+	} else {
+		/* regular volume, show (according to preferences) only if mounted */
+		if (mount != NULL && eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE))
+			ret = TRUE;
+	}
+
+	g_free (connected_server_path);
+	if (mount != NULL)
+		g_object_unref (mount);
+
+	return ret;
+}
+
 static void
+create_volume_link (NautilusDesktopLinkMonitor *monitor,
+		    GVolume *volume)
+{
+	NautilusDesktopLink *link;
+
+	if (should_display_link_for_volume (volume)) {
+		link = nautilus_desktop_link_new_from_volume (volume);
+		monitor->details->volume_links = g_list_prepend (monitor->details->volume_links, link);
+	}
+}
+
+static gboolean
+mount_referenced_by_volume_activation_root (GList *volumes, GMount *mount)
+{
+	GList *l;
+	GFile *mount_root;
+	gboolean ret;
+
+	ret = FALSE;
+
+	mount_root = g_mount_get_root (mount);
+
+	for (l = volumes; l != NULL; l = l->next) {
+		GVolume *volume = G_VOLUME (l->data);
+		GFile *volume_activation_root;
+
+		volume_activation_root = g_volume_get_activation_root (volume);
+		if (volume_activation_root != NULL) {
+			if (g_file_has_prefix (volume_activation_root, mount_root)) {
+				ret = TRUE;
+				g_object_unref (volume_activation_root);
+				break;
+			}
+			g_object_unref (volume_activation_root);
+		}
+	}
+
+	g_object_unref (mount_root);
+	return ret;
+}
+
+static gboolean
+should_display_link_for_mount (NautilusDesktopLinkMonitor *monitor, GMount *mount)
+{
+	gboolean ret;
+	GVolume *volume;
+	GList *volumes;
+
+	ret = TRUE;
+
+	/* if the mount has a volume, we've processed it already as a GVolume so hide this */
+	volume = g_mount_get_volume (mount);
+	if (volume != NULL) {
+		ret = FALSE;
+		g_object_unref (volume);
+		goto out;
+	}
+
+	/* if there's exists one or more volumes with an activation root inside the mount,
+	 * don't display the mount
+	 */
+	volumes = g_volume_monitor_get_volumes (monitor->details->volume_monitor);
+	if (mount_referenced_by_volume_activation_root (volumes, mount))
+		ret = FALSE;
+	g_list_foreach (volumes, (GFunc) g_object_unref, NULL);
+	g_list_free (volumes);
+
+out:
+	return ret;
+}
+
+
+static void
 create_mount_link (NautilusDesktopLinkMonitor *monitor,
 		   GMount *mount)
 {
 	NautilusDesktopLink *link;
 
-	link = NULL;
-
-	if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE)) {
+	if (should_display_link_for_mount (monitor, mount)) {
 		link = nautilus_desktop_link_new_from_mount (mount);
 		monitor->details->mount_links = g_list_prepend (monitor->details->mount_links, link);
 	}
 }
 
+static void
+volume_added_callback (GVolumeMonitor *volume_monitor,
+		       GVolume *volume,
+		       NautilusDesktopLinkMonitor *monitor)
+{
+	recompute_volume_and_mount_links (monitor);
+}
 
 
 static void
+volume_removed_callback (GVolumeMonitor *volume_monitor,
+			 GVolume *volume,
+			 NautilusDesktopLinkMonitor *monitor)
+{
+	recompute_volume_and_mount_links (monitor);
+}
+
+static void
+volume_changed_callback (GVolumeMonitor *volume_monitor,
+			 GVolume *volume,
+			 NautilusDesktopLinkMonitor *monitor)
+{
+	recompute_volume_and_mount_links (monitor);
+}
+
+static void
 mount_added_callback (GVolumeMonitor *volume_monitor,
-		      GMount *mount, 
+		      GMount *mount,
 		      NautilusDesktopLinkMonitor *monitor)
 {
-	create_mount_link (monitor, mount);
+	recompute_volume_and_mount_links (monitor);
 }
 
 
 static void
 mount_removed_callback (GVolumeMonitor *volume_monitor,
-			GMount *mount, 
+			GMount *mount,
 			NautilusDesktopLinkMonitor *monitor)
 {
-	GList *l;
-	NautilusDesktopLink *link;
-	GMount *other_mount;
-
-	link = NULL;
-	for (l = monitor->details->mount_links; l != NULL; l = l->next) {
-		other_mount = nautilus_desktop_link_get_mount (l->data);
-		if (mount == other_mount) {
-			g_object_unref (other_mount);
-			link = l->data;
-			break;
-		}
-		g_object_unref (other_mount);
-	}
-
-	if (link) {
-		monitor->details->mount_links = g_list_remove (monitor->details->mount_links, link);
-		g_object_unref (link);
-	}
+	recompute_volume_and_mount_links (monitor);
 }
 
 static void
 mount_changed_callback (GVolumeMonitor *volume_monitor,
-			GMount *mount, 
+			GMount *mount,
 			NautilusDesktopLinkMonitor *monitor)
 {
-	/* TODO: update the mount */
+	recompute_volume_and_mount_links (monitor);
 }
 
 static void
@@ -312,30 +424,280 @@ desktop_network_visible_changed (gpointer callback
 }
 
 static void
-desktop_volumes_visible_changed (gpointer callback_data)
+delete_all_volume_links (NautilusDesktopLinkMonitor *monitor)
 {
-	NautilusDesktopLinkMonitor *monitor;
+	g_list_foreach (monitor->details->volume_links, (GFunc)g_object_unref, NULL);
+	g_list_free (monitor->details->volume_links);
+	monitor->details->volume_links = NULL;
+}
+
+static void
+delete_all_mount_links (NautilusDesktopLinkMonitor *monitor)
+{
+	g_list_foreach (monitor->details->mount_links, (GFunc)g_object_unref, NULL);
+	g_list_free (monitor->details->mount_links);
+	monitor->details->mount_links = NULL;
+}
+
+static void
+add_all_volume_links (NautilusDesktopLinkMonitor *monitor)
+{
+	GList *l, *volumes;
+	GVolume *volume;
+
+	volumes = g_volume_monitor_get_volumes (monitor->details->volume_monitor);
+	for (l = volumes; l != NULL; l = l->next) {
+		volume = G_VOLUME (l->data);
+		create_volume_link (monitor, volume);
+		g_object_unref (volume);
+	}
+	g_list_free (volumes);
+}
+
+static void
+add_all_mount_links (NautilusDesktopLinkMonitor *monitor)
+{
 	GList *l, *mounts;
-	
-	monitor = NAUTILUS_DESKTOP_LINK_MONITOR (callback_data);
+	GMount *mount;
 
-	if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE)) {
-		if (monitor->details->mount_links == NULL) {
-			mounts = g_volume_monitor_get_mounts (monitor->details->volume_monitor);
-			for (l = mounts; l != NULL; l = l->next) {
-				create_mount_link (monitor, l->data);
-				g_object_unref (l->data);
-			}
-			g_list_free (mounts);
+	mounts = g_volume_monitor_get_mounts (monitor->details->volume_monitor);
+	for (l = mounts; l != NULL; l = l->next) {
+		mount = G_MOUNT (l->data);
+		create_mount_link (monitor, mount);
+		g_object_unref (mount);
+	}
+	g_list_free (mounts);
+}
+
+static void
+desktop_volumes_visible_changed (gpointer callback_data)
+{
+	NautilusDesktopLinkMonitor *monitor = NAUTILUS_DESKTOP_LINK_MONITOR (callback_data);
+
+	recompute_volume_and_mount_links (monitor);
+}
+
+static void
+connected_servers_visible_changed (gpointer callback_data)
+{
+	NautilusDesktopLinkMonitor *monitor = NAUTILUS_DESKTOP_LINK_MONITOR (callback_data);
+
+	recompute_volume_and_mount_links (monitor);
+}
+
+static void
+diff_sorted_lists (GList         *list1,
+                   GList         *list2,
+                   GCompareFunc   compare,
+                   GList        **added,
+                   GList        **removed)
+{
+  int order;
+
+  *added = *removed = NULL;
+
+  while (list1 != NULL &&
+         list2 != NULL)
+    {
+      order = (*compare) (list1->data, list2->data);
+      if (order < 0)
+        {
+          *removed = g_list_prepend (*removed, list1->data);
+          list1 = list1->next;
+        }
+      else if (order > 0)
+        {
+          *added = g_list_prepend (*added, list2->data);
+          list2 = list2->next;
+        }
+      else
+        { /* same item */
+          list1 = list1->next;
+          list2 = list2->next;
+        }
+    }
+
+  while (list1 != NULL)
+    {
+      *removed = g_list_prepend (*removed, list1->data);
+      list1 = list1->next;
+    }
+  while (list2 != NULL)
+    {
+      *added = g_list_prepend (*added, list2->data);
+      list2 = list2->next;
+    }
+}
+
+static gint
+pointer_cmp (gconstpointer a, gconstpointer b)
+{
+	if (a > b)
+		return 1;
+	else if (a < b)
+		return -1;
+	else
+		return 0;
+}
+
+static void
+delete_link_for_volume (NautilusDesktopLinkMonitor *monitor, GVolume *volume)
+{
+	GList *l;
+	for (l = monitor->details->volume_links; l != NULL; l = l->next) {
+		NautilusDesktopLink *link = NAUTILUS_DESKTOP_LINK (l->data);
+		GVolume *link_volume;
+
+		link_volume = nautilus_desktop_link_get_volume (link);
+		if (link_volume == volume) {
+			monitor->details->volume_links = g_list_delete_link (monitor->details->volume_links, l);
+			g_object_unref (link);
+			g_object_unref (link_volume);
+			goto out;
 		}
-	} else {
-		g_list_foreach (monitor->details->mount_links, (GFunc)g_object_unref, NULL);
-		g_list_free (monitor->details->mount_links);
-		monitor->details->mount_links = NULL;
+		g_object_unref (link_volume);
 	}
+out:
+	;
 }
 
 static void
+delete_link_for_mount (NautilusDesktopLinkMonitor *monitor, GMount *mount)
+{
+	GList *l;
+	for (l = monitor->details->mount_links; l != NULL; l = l->next) {
+		NautilusDesktopLink *link = NAUTILUS_DESKTOP_LINK (l->data);
+		GMount *link_mount;
+
+		link_mount = nautilus_desktop_link_get_mount (link);
+		if (link_mount == mount) {
+			monitor->details->mount_links = g_list_delete_link (monitor->details->mount_links, l);
+			g_object_unref (link);
+			g_object_unref (link_mount);
+			goto out;
+		}
+		g_object_unref (link_mount);
+	}
+out:
+	;
+}
+
+static void
+recompute_volume_and_mount_links (NautilusDesktopLinkMonitor *monitor)
+{
+	GList *volumes;
+	GList *mounts;
+	GList *volumes_we_have;
+	GList *mounts_we_have;
+	GList *volumes_we_want;
+	GList *mounts_we_want;
+	GList *added_volumes;
+	GList *removed_volumes;
+	GList *added_mounts;
+	GList *removed_mounts;
+	GList *l;
+
+	volumes_we_have = NULL;
+	mounts_we_have = NULL;
+	volumes_we_want = NULL;
+	mounts_we_want = NULL;
+
+	/* first build lists of volumes/mounts we have */
+
+	for (l = monitor->details->volume_links; l != NULL; l = l->next) {
+		NautilusDesktopLink *link = NAUTILUS_DESKTOP_LINK (l->data);
+		volumes_we_have = g_list_prepend (volumes_we_have, nautilus_desktop_link_get_volume (link));
+	}
+
+	for (l = monitor->details->mount_links; l != NULL; l = l->next) {
+		NautilusDesktopLink *link = NAUTILUS_DESKTOP_LINK (l->data);
+		mounts_we_have = g_list_prepend (mounts_we_have, nautilus_desktop_link_get_mount (link));
+	}
+
+	/* then compute what volumes/mount we want */
+
+	volumes = g_volume_monitor_get_volumes (monitor->details->volume_monitor);
+	mounts = g_volume_monitor_get_mounts (monitor->details->volume_monitor);
+
+	for (l = volumes; l != NULL; l = l->next) {
+		GVolume *volume = G_VOLUME (l->data);
+		if (should_display_link_for_volume (volume))
+			volumes_we_want = g_list_prepend (volumes_we_want, volume);
+	}
+
+	for (l = mounts; l != NULL; l = l->next) {
+		GMount *mount = G_MOUNT (l->data);
+		if (should_display_link_for_mount (monitor, mount))
+			mounts_we_want = g_list_prepend (mounts_we_want, mount);
+	}
+
+	/* compute the differences */
+
+	volumes_we_have = g_list_sort (volumes_we_have, pointer_cmp);
+	volumes_we_want = g_list_sort (volumes_we_want, pointer_cmp);
+
+	mounts_we_have = g_list_sort (mounts_we_have, pointer_cmp);
+	mounts_we_want = g_list_sort (mounts_we_want, pointer_cmp);
+
+	diff_sorted_lists (volumes_we_have,
+			   volumes_we_want,
+			   pointer_cmp,
+			   &added_volumes,
+			   &removed_volumes);
+
+	diff_sorted_lists (mounts_we_have,
+			   mounts_we_want,
+			   pointer_cmp,
+			   &added_mounts,
+			   &removed_mounts);
+
+	/* and then deal with the differences */
+
+	for (l = removed_volumes; l != NULL; l = l->next) {
+		GVolume *volume = G_VOLUME (l->data);
+		delete_link_for_volume (monitor, volume);
+	}
+
+	for (l = removed_mounts; l != NULL; l = l->next) {
+		GMount *mount = G_MOUNT (l->data);
+		delete_link_for_mount (monitor, mount);
+	}
+
+	for (l = added_volumes; l != NULL; l = l->next) {
+		GVolume *volume = G_VOLUME (l->data);
+		create_volume_link (monitor, volume);
+	}
+
+	for (l = added_mounts; l != NULL; l = l->next) {
+		GMount *mount = G_MOUNT (l->data);
+		create_mount_link (monitor, mount);
+	}
+
+	/* cleanup */
+
+	g_list_foreach (volumes_we_have, (GFunc) g_object_unref, NULL);
+	g_list_free (volumes_we_have);
+
+	g_list_foreach (mounts_we_have, (GFunc) g_object_unref, NULL);
+	g_list_free (mounts_we_have);
+
+	g_list_free (volumes_we_want);
+	g_list_free (mounts_we_want);
+
+	g_list_foreach (volumes, (GFunc) g_object_unref, NULL);
+	g_list_free (volumes);
+
+	g_list_foreach (mounts, (GFunc) g_object_unref, NULL);
+	g_list_free (mounts);
+
+	g_list_free (added_volumes);
+	g_list_free (removed_volumes);
+
+	g_list_free (added_mounts);
+	g_list_free (removed_mounts);
+}
+
+static void
 create_link_and_add_preference (NautilusDesktopLink   **link_ref,
 				NautilusDesktopLinkType link_type,
 				const char             *preference_key,
@@ -353,8 +715,6 @@ static void
 nautilus_desktop_link_monitor_init (gpointer object, gpointer klass)
 {
 	NautilusDesktopLinkMonitor *monitor;
-	GList *l, *mounts;
-	GMount *mount;
 
 	monitor = NAUTILUS_DESKTOP_LINK_MONITOR (object);
 
@@ -393,27 +753,35 @@ nautilus_desktop_link_monitor_init (gpointer objec
 					desktop_network_visible_changed,
 					monitor);
 
-	/* Mount links */
+	/* Volume and mount links */
+	add_all_volume_links (monitor);
+	add_all_mount_links (monitor);
 
-	mounts = g_volume_monitor_get_mounts (monitor->details->volume_monitor);
-	for (l = mounts; l != NULL; l = l->next) {
-		mount = l->data;
-		create_mount_link (monitor, mount);
-		g_object_unref (mount);
-	}
-	g_list_free (mounts);
-
 	eel_preferences_add_callback (NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE,
 				      desktop_volumes_visible_changed,
 				      monitor);
 
-	monitor->details->mount_id =
+	eel_preferences_add_callback (NAUTILUS_PREFERENCES_DESKTOP_CONNECTED_SERVERS_VISIBLE,
+				      connected_servers_visible_changed,
+				      monitor);
+
+	monitor->details->volume_added_id =
+		g_signal_connect_object (monitor->details->volume_monitor, "volume_added",
+					 G_CALLBACK (volume_added_callback), monitor, 0);
+	monitor->details->volume_removed_id =
+		g_signal_connect_object (monitor->details->volume_monitor, "volume_removed",
+					 G_CALLBACK (volume_removed_callback), monitor, 0);
+	monitor->details->volume_changed_id =
+		g_signal_connect_object (monitor->details->volume_monitor, "volume_changed",
+					 G_CALLBACK (volume_changed_callback), monitor, 0);
+
+	monitor->details->mount_added_id =
 		g_signal_connect_object (monitor->details->volume_monitor, "mount_added",
 					 G_CALLBACK (mount_added_callback), monitor, 0);
-	monitor->details->unmount_id =
+	monitor->details->mount_removed_id =
 		g_signal_connect_object (monitor->details->volume_monitor, "mount_removed",
 					 G_CALLBACK (mount_removed_callback), monitor, 0);
-	monitor->details->changed_id =
+	monitor->details->mount_changed_id =
 		g_signal_connect_object (monitor->details->volume_monitor, "mount_changed",
 					 G_CALLBACK (mount_changed_callback), monitor, 0);
 
@@ -464,11 +832,10 @@ desktop_link_monitor_finalize (GObject *object)
 				    desktop_network_visible_changed,
 				    monitor);
 
-	/* Mounts */
+	/* Volumes and mounts */
 
-	g_list_foreach (monitor->details->mount_links, (GFunc)g_object_unref, NULL);
-	g_list_free (monitor->details->mount_links);
-	monitor->details->mount_links = NULL;
+	delete_all_volume_links (monitor);
+	delete_all_mount_links (monitor);
 		
 	nautilus_directory_unref (monitor->details->desktop_dir);
 	monitor->details->desktop_dir = NULL;
@@ -477,15 +844,25 @@ desktop_link_monitor_finalize (GObject *object)
 					 desktop_volumes_visible_changed,
 					 monitor);
 
-	if (monitor->details->mount_id != 0) {
-		g_source_remove (monitor->details->mount_id);
+	if (monitor->details->volume_added_id != 0) {
+		g_source_remove (monitor->details->volume_added_id);
 	}
-	if (monitor->details->unmount_id != 0) {
-		g_source_remove (monitor->details->unmount_id);
+	if (monitor->details->volume_removed_id != 0) {
+		g_source_remove (monitor->details->volume_removed_id);
 	}
-	if (monitor->details->changed_id != 0) {
-		g_source_remove (monitor->details->changed_id);
+	if (monitor->details->volume_changed_id != 0) {
+		g_source_remove (monitor->details->volume_changed_id);
 	}
+
+	if (monitor->details->mount_added_id != 0) {
+		g_source_remove (monitor->details->mount_added_id);
+	}
+	if (monitor->details->mount_removed_id != 0) {
+		g_source_remove (monitor->details->mount_removed_id);
+	}
+	if (monitor->details->mount_changed_id != 0) {
+		g_source_remove (monitor->details->mount_changed_id);
+	}
 	
 	g_free (monitor->details);
 
Index: libnautilus-private/nautilus-global-preferences.c
===================================================================
--- libnautilus-private/nautilus-global-preferences.c	(revision 14701)
+++ libnautilus-private/nautilus-global-preferences.c	(working copy)
@@ -502,6 +502,11 @@ static const PreferenceDefault preference_defaults
 	  GINT_TO_POINTER (TRUE)
 	},
 
+	{ NAUTILUS_PREFERENCES_DESKTOP_CONNECTED_SERVERS_VISIBLE,
+	  PREFERENCE_BOOLEAN,
+	  GINT_TO_POINTER (TRUE)
+	},
+
 	{ NAUTILUS_PREFERENCES_DESKTOP_NETWORK_VISIBLE,
 	  PREFERENCE_BOOLEAN,
 	  GINT_TO_POINTER (FALSE)
Index: libnautilus-private/nautilus-global-preferences.h
===================================================================
--- libnautilus-private/nautilus-global-preferences.h	(revision 14701)
+++ libnautilus-private/nautilus-global-preferences.h	(working copy)
@@ -214,6 +214,7 @@ typedef enum
 #define NAUTILUS_PREFERENCES_DESKTOP_TRASH_VISIBLE         "desktop/trash_icon_visible"
 #define NAUTILUS_PREFERENCES_DESKTOP_TRASH_NAME            "desktop/trash_icon_name"
 #define NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE	   "desktop/volumes_visible"
+#define NAUTILUS_PREFERENCES_DESKTOP_CONNECTED_SERVERS_VISIBLE "desktop/connected_servers_visible"
 #define NAUTILUS_PREFERENCES_DESKTOP_NETWORK_VISIBLE       "desktop/network_icon_visible"
 #define NAUTILUS_PREFERENCES_DESKTOP_NETWORK_NAME          "desktop/network_icon_name"
 
