Index: src/nautilus-application.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-application.c,v
retrieving revision 1.227
diff -p -u -r1.227 nautilus-application.c
--- src/nautilus-application.c	22 Nov 2004 15:24:37 -0000	1.227
+++ src/nautilus-application.c	13 Feb 2005 20:20:55 -0000
@@ -452,6 +452,7 @@ nautilus_application_startup (NautilusAp
 			      gboolean no_desktop,
 			      gboolean do_first_time_druid_check,
 			      gboolean browser_window,
+			      const char *startup_id,
 			      const char *geometry,
 			      const char *urls[])
 {
@@ -461,6 +462,7 @@ nautilus_application_startup (NautilusAp
 	const char *message, *detailed_message;
 	GtkDialog *dialog;
 	Nautilus_URIList *url_list;
+	const CORBA_char *corba_startup_id;
 	const CORBA_char *corba_geometry;
 	int num_failures;
 
@@ -610,15 +612,16 @@ nautilus_application_startup (NautilusAp
 
 		/* CORBA C mapping doesn't allow NULL to be passed
 		   for string parameters */
-		corba_geometry = (geometry != NULL) ? geometry : "";
+		corba_geometry   = (geometry   != NULL) ? geometry   : "";
+		corba_startup_id = (startup_id != NULL) ? startup_id : "";
 
 	  	/* Create the other windows. */
 		if (urls != NULL) {
 			url_list = nautilus_make_uri_list_from_shell_strv (urls);
-			Nautilus_Shell_open_windows (shell, url_list, corba_geometry, browser_window, &ev);
+			Nautilus_Shell_open_windows (shell, url_list, corba_startup_id, corba_geometry, browser_window, &ev);
 			CORBA_free (url_list);
 		} else if (!no_default_window) {
-			Nautilus_Shell_open_default_window (shell, corba_geometry, browser_window, &ev);
+			Nautilus_Shell_open_default_window (shell, corba_startup_id, corba_geometry, browser_window, &ev);
 		}
 		
 		/* Add ourselves to the session */
@@ -980,7 +983,7 @@ NautilusWindow *
 nautilus_application_present_spatial_window_with_selection (NautilusApplication *application,
 							    NautilusWindow      *requesting_window,
 							    const char          *location,
-							    GList		 *new_selection,
+							    GList		*new_selection,
 							    GdkScreen           *screen)
 {
 	NautilusWindow *window;
Index: src/nautilus-application.h
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-application.h,v
retrieving revision 1.38
diff -p -u -r1.38 nautilus-application.h
--- src/nautilus-application.h	18 Oct 2004 21:36:11 -0000	1.38
+++ src/nautilus-application.h	13 Feb 2005 20:20:55 -0000
@@ -67,6 +67,7 @@ void                 nautilus_applicatio
 							     gboolean             no_desktop,
 							     gboolean             do_first_time_druid_check,
 							     gboolean             browser_window,
+							     const char          *startup_id,
 							     const char          *default_geometry,
 							     const char          *urls[]);
 GList *              nautilus_application_get_window_list           (void);
Index: src/nautilus-main.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-main.c,v
retrieving revision 1.143
diff -p -u -r1.143 nautilus-main.c
--- src/nautilus-main.c	27 Jan 2005 19:10:45 -0000	1.143
+++ src/nautilus-main.c	13 Feb 2005 20:20:55 -0000
@@ -196,6 +196,8 @@ main (int argc, char *argv[])
 	gboolean no_default_window;
 	gboolean browser_window;
 	gboolean no_desktop;
+	const char *startup_id;
+	char *startup_id_copy;
 	char *geometry;
 	gboolean perform_self_check;
 	poptContext popt_context;
@@ -246,6 +248,17 @@ main (int argc, char *argv[])
 	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 	textdomain (GETTEXT_PACKAGE);
 
+	startup_id = g_getenv ("DESKTOP_STARTUP_ID");
+	startup_id_copy = NULL;
+	if (startup_id != NULL && *startup_id != '\0') {
+		/* Clear the DESKTOP_STARTUP_ID, but make sure to copy it first */
+		startup_id_copy = g_strdup (startup_id);
+		putenv ("DESKTOP_STARTUP_ID=");
+	}
+
+	/* we'll do it ourselves due to complicated factory setup */
+	gtk_window_set_auto_startup_notification (FALSE);
+
 	/* Get parameters. */
 	geometry = NULL;
 	kill_shell = FALSE;
@@ -349,6 +362,7 @@ main (int argc, char *argv[])
 			 kill_shell, restart_shell, no_default_window, no_desktop,
 			 !(kill_shell || restart_shell),
 			 browser_window,
+			 startup_id_copy,
 			 geometry,
 			 args);
 		if (is_event_loop_needed ()) {
Index: src/nautilus-shell-interface.idl
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-shell-interface.idl,v
retrieving revision 1.7
diff -p -u -r1.7 nautilus-shell-interface.idl
--- src/nautilus-shell-interface.idl	22 Nov 2004 15:24:37 -0000	1.7
+++ src/nautilus-shell-interface.idl	13 Feb 2005 20:20:55 -0000
@@ -10,8 +10,8 @@ module Nautilus {
 	typedef sequence<URI> URIList;
 
 	interface Shell : ::Bonobo::Unknown {
-		void open_windows (in URIList uris, in string geometry, in boolean browser_window);
-		void open_default_window (in string geometry, in boolean browser_window);
+		void open_windows (in URIList uris, in string startup_id, in string geometry, in boolean browser_window);
+		void open_default_window (in string startup_id, in string geometry, in boolean browser_window);
 		void start_desktop ();
 		void stop_desktop ();
 		void quit ();
Index: src/nautilus-shell.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-shell.c,v
retrieving revision 1.58
diff -p -u -r1.58 nautilus-shell.c
--- src/nautilus-shell.c	22 Nov 2004 15:24:37 -0000	1.58
+++ src/nautilus-shell.c	13 Feb 2005 20:20:55 -0000
@@ -42,12 +42,15 @@
 #include <gtk/gtklabel.h>
 #include <gtk/gtkmain.h>
 #include <gtk/gtksignal.h>
+#include <gdk/gdkx.h>
 #include <libgnome/gnome-i18n.h>
 #include <libgnomeui/gnome-stock-icons.h>
 #include <libgnomeui/gnome-uidefs.h>
 #include <libgnomevfs/gnome-vfs-utils.h>
 #include <libnautilus-private/nautilus-file-utilities.h>
 #include <libnautilus-private/nautilus-global-preferences.h>
+#define SN_API_NOT_YET_FROZEN Yes_i_know_DO_IT
+#include <libsn/sn-launchee.h>
 #include <stdlib.h>
 
 /* Keep window from shrinking down ridiculously small; numbers are somewhat arbitrary */
@@ -63,10 +66,12 @@ struct NautilusShellDetails {
 static void     finalize                         (GObject              *shell);
 static void     corba_open_windows              (PortableServer_Servant  servant,
 						 const Nautilus_URIList *list,
+						 const CORBA_char       *startup_id,
 						 const CORBA_char       *geometry,
 						 CORBA_boolean           browser_window,
 						 CORBA_Environment      *ev);
 static void     corba_open_default_window       (PortableServer_Servant  servant,
+						 const CORBA_char       *startup_id,
 						 const CORBA_char       *geometry,
 						 CORBA_boolean           browser_window,
 						 CORBA_Environment      *ev);
@@ -125,8 +130,73 @@ nautilus_shell_new (NautilusApplication 
 }
 
 static void
-open_window (NautilusShell *shell, const char *uri, const char *geometry,
-	     gboolean browser_window)
+sn_error_trap_push (SnDisplay *display,
+                    Display   *xdisplay)
+{
+  gdk_error_trap_push ();
+}
+
+static void
+sn_error_trap_pop (SnDisplay *display,
+                   Display   *xdisplay)
+{
+  gdk_error_trap_pop ();
+}
+
+static void
+handle_startup_id (GtkWidget *widget, GdkScreen *screen, const char *startup_id)
+{
+	SnDisplay *sn_display;
+	SnLauncheeContext *context;
+	GdkDisplay *display;
+
+	g_return_if_fail (startup_id != NULL);
+  
+	if (!GTK_WIDGET_REALIZED (widget))
+		gtk_widget_realize (widget);
+  
+	context = NULL;
+	sn_display = NULL;
+
+	/* Set up window for launch notification */
+	/* FIXME In principle all transient children of this
+	 * window should get the same startup_id
+	 */
+      
+	display = gdk_screen_get_display (screen);
+      
+	sn_display = sn_display_new (gdk_x11_display_get_xdisplay (display),
+				     sn_error_trap_push,
+				     sn_error_trap_pop);
+      
+	context = sn_launchee_context_new (sn_display,
+					   gdk_screen_get_number (screen),
+					   startup_id);
+	sn_launchee_context_setup_window (context,
+					  GDK_WINDOW_XWINDOW (widget->window));
+
+	/* Now, set the _NET_WM_USER_TIME for the new window to the timestamp
+	 * that caused the window to be launched.
+	 */
+	if (sn_launchee_context_get_id_has_timestamp (context)) {
+		gulong timestamp;
+
+		timestamp = sn_launchee_context_get_timestamp (context);
+		gdk_x11_window_set_user_time (widget->window, timestamp);
+        } else {
+		g_warning ("Launched by a non-compliant or obsolete startup "
+			   "notification launcher.  Focus-stealing-prevention "
+			   "may fail.\n");
+        }
+  
+	sn_launchee_context_complete (context);
+	sn_launchee_context_unref (context);
+	sn_display_unref (sn_display);
+}
+
+static void
+open_window (NautilusShell *shell, const char *uri, const char *startup_id,
+	     const char *geometry, gboolean browser_window)
 {
 	char *home_uri;
 	NautilusWindow *window;
@@ -154,18 +224,21 @@ open_window (NautilusShell *shell, const
 		g_free (home_uri);
 	}
 	
-	if (geometry != NULL && !GTK_WIDGET_VISIBLE (window)) {
-		eel_gtk_window_set_initial_geometry_from_string (GTK_WINDOW (window),
-								 geometry,
-								 APPLICATION_WINDOW_MIN_WIDTH,
-								 APPLICATION_WINDOW_MIN_HEIGHT,
-								 FALSE);
+	if (!GTK_WIDGET_VISIBLE (window)) {
+		handle_startup_id (GTK_WIDGET (window), gdk_screen_get_default (), startup_id);
+		if (geometry != NULL)
+			eel_gtk_window_set_initial_geometry_from_string (GTK_WINDOW (window),
+									 geometry,
+									 APPLICATION_WINDOW_MIN_WIDTH,
+									 APPLICATION_WINDOW_MIN_HEIGHT,
+									 FALSE);
 	}
 }
 
 static void
 corba_open_windows (PortableServer_Servant servant,
 		    const Nautilus_URIList *list,
+		    const CORBA_char *startup_id,
 		    const CORBA_char *geometry,
 		    CORBA_boolean browser_window,
 		    CORBA_Environment *ev)
@@ -178,12 +251,13 @@ corba_open_windows (PortableServer_Serva
 	/* Open windows at each requested location. */
 	for (i = 0; i < list->_length; i++) {
 		g_assert (list->_buffer[i] != NULL);
-		open_window (shell, list->_buffer[i], geometry, browser_window);
+		open_window (shell, list->_buffer[i], startup_id, geometry, browser_window);
 	}
 }
 
 static void
 corba_open_default_window (PortableServer_Servant servant,
+			   const CORBA_char *startup_id,
 			   const CORBA_char *geometry,
 			   CORBA_boolean browser_window,
 			   CORBA_Environment *ev)
@@ -194,7 +268,7 @@ corba_open_default_window (PortableServe
 
 	if (!restore_window_states (shell)) {
 		/* Open a window pointing at the default location. */
-		open_window (shell, NULL, geometry, browser_window);
+		open_window (shell, NULL, startup_id, geometry, browser_window);
 	}
 }
 
Index: src/nautilus-window.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-window.c,v
retrieving revision 1.440
diff -p -u -r1.440 nautilus-window.c
--- src/nautilus-window.c	1 Feb 2005 16:44:47 -0000	1.440
+++ src/nautilus-window.c	13 Feb 2005 20:20:56 -0000
@@ -463,7 +463,7 @@ nautilus_window_constructed (NautilusWin
 static void
 nautilus_window_set_property (GObject *object,
 			      guint arg_id,
-		      const GValue *value,
+			      const GValue *value,
 			      GParamSpec *pspec)
 {
 	NautilusWindow *window;
