? GE.cpp
? P
? p
Index: idl/EphyAutomation.idl
===================================================================
RCS file: /cvs/gnome/epiphany/idl/EphyAutomation.idl,v
retrieving revision 1.8
diff -p -u -u -p -r1.8 EphyAutomation.idl
--- idl/EphyAutomation.idl	13 Nov 2003 14:02:03 -0000	1.8
+++ idl/EphyAutomation.idl	30 Jan 2005 23:08:29 -0000
@@ -15,6 +15,17 @@ module GNOME {
 		void loadSession (in string filename);
 
 		void openBookmarksEditor ();
+
+		void loadUrlWithStartupId (in string  url, 
+					   in boolean fullscreen,
+					   in boolean open_in_existing_tab,
+					   in boolean open_in_new_tab,
+					   in string startup_id);
+		
+		void loadSessionWithStartupId (in string filename,
+					       in string startup_id);
+		
+		void openBookmarksEditorWithStartupId (in string startup_id);
 	};
 };
 
Index: src/ephy-automation.c
===================================================================
RCS file: /cvs/gnome/epiphany/src/ephy-automation.c,v
retrieving revision 1.22
diff -p -u -u -p -r1.22 ephy-automation.c
--- src/ephy-automation.c	2 Nov 2004 20:57:20 -0000	1.22
+++ src/ephy-automation.c	30 Jan 2005 23:08:30 -0000
@@ -33,25 +33,60 @@
 #include "eel-gconf-extensions.h"
 #include "ephy-prefs.h"
 
+#include <errno.h>
 #include <string.h>
 #include <bonobo/bonobo-main.h>
 #include <bonobo/bonobo-context.h>
+#include <gdk/gdkx.h>
 
 static void ephy_automation_class_init (EphyAutomationClass *klass);
 
 static GObjectClass *parent_class = NULL;
 
-static void
-impl_ephy_automation_loadurl (PortableServer_Servant _servant,
-			      const CORBA_char *url,
-			      const CORBA_boolean fullscreen,
-			      const CORBA_boolean open_in_existing_tab,
-			      const CORBA_boolean open_in_new_tab,
-                              CORBA_Environment *ev)
+/* adapted from gtk+/gdk/x11/gdkdisplay-x11.c */
+static guint32
+parse_startup_id (const char *startup_id)
+{
+	const char *time_str;
+	guint32 retval = 0;
+
+	/* Find the launch time from the startup_id, if it's there.  Newer spec
+	* states that the startup_id is of the form <unique>_TIME<timestamp>
+	*/
+	time_str = g_strrstr (startup_id, "_TIME");
+	if (time_str != NULL)
+	{
+		gulong value;
+		gchar *end;
+		errno = 0;
+	
+		/* Skip past the "_TIME" part */
+		time_str += 5;
+	
+		value = strtoul (time_str, &end, 0);
+		if (end != time_str && errno == 0)
+		{
+			retval = (guint32) value;
+		}
+	}
+
+	return retval;
+}
+static void
+impl_ephy_automation_loadUrlWithStartupId (PortableServer_Servant _servant,
+					   const CORBA_char *url,
+					   const CORBA_boolean fullscreen,
+					   const CORBA_boolean open_in_existing_tab,
+					   const CORBA_boolean open_in_new_tab,
+					   const CORBA_char *startup_id,
+					   CORBA_Environment *ev)
 {
 	EphyNewTabFlags flags = 0;
 	EphyWindow *window;
 	EphySession *session;
+	guint32 user_time;
+
+	user_time = parse_startup_id (startup_id);
 
 	session = EPHY_SESSION (ephy_shell_get_session (ephy_shell));
 	g_return_if_fail (session != NULL);
@@ -61,7 +96,7 @@ impl_ephy_automation_loadurl (PortableSe
 		url = "";
 	}
 
-	if (ephy_session_autoresume (session) && *url == '\0')
+	if (ephy_session_autoresume (session, user_time) && *url == '\0')
 	{
 		/* no need to open the homepage,
 		* we did already open session windows */
@@ -72,6 +107,16 @@ impl_ephy_automation_loadurl (PortableSe
 
 	if (open_in_existing_tab && window != NULL)
 	{
+		/* update user time */
+		if (user_time != 0)
+		{
+			GtkWidget *widget = GTK_WIDGET (window);
+
+			gtk_widget_realize (widget);
+			gdk_x11_window_set_user_time (widget->window,
+						      user_time);
+		}
+
 		ephy_window_load_url (window, url);
 		return;
 	}
@@ -100,51 +145,101 @@ impl_ephy_automation_loadurl (PortableSe
 		flags |= EPHY_NEW_TAB_FULLSCREEN_MODE;
 	}
 
-	ephy_shell_new_tab (ephy_shell, window, NULL, url, flags);
+	ephy_shell_new_tab_full (ephy_shell, window, NULL, url, flags,
+				 user_time);
+}
+
+static void
+impl_ephy_automation_loadurl (PortableServer_Servant _servant,
+			      const CORBA_char *url,
+			      const CORBA_boolean fullscreen,
+			      const CORBA_boolean open_in_existing_tab,
+			      const CORBA_boolean open_in_new_tab,
+                              CORBA_Environment *ev)
+{
+	impl_ephy_automation_loadUrlWithStartupId (_servant,
+						   url,
+						   fullscreen,
+						   open_in_existing_tab,
+						   open_in_new_tab,
+						   "", /* no startup ID */
+						   ev);
 }
 
 static void
-impl_ephy_automation_add_bookmark (PortableServer_Servant _servant,
-				   const CORBA_char * url,
-				   CORBA_Environment * ev)
+impl_ephy_automation_addBookmark (PortableServer_Servant _servant,
+				  const CORBA_char * url,
+				  CORBA_Environment * ev)
 {
 	ephy_bookmarks_add (ephy_shell_get_bookmarks (ephy_shell),
 			    url /* title */, url);
 }
 
 static void
-impl_ephy_automation_import_bookmarks (PortableServer_Servant _servant,
-				       const CORBA_char * filename,
-				       CORBA_Environment * ev)
+impl_ephy_automation_importBookmarks (PortableServer_Servant _servant,
+				      const CORBA_char *filename,
+				      CORBA_Environment *ev)
 {
 	ephy_bookmarks_import (ephy_shell_get_bookmarks (ephy_shell),
 			       filename);
 }
 
 static void
-impl_ephy_automation_load_session (PortableServer_Servant _servant,
-				   const CORBA_char * filename,
-				   CORBA_Environment * ev)
+impl_ephy_automation_loadSessionWithStartupId (PortableServer_Servant _servant,
+					       const CORBA_char *filename,
+					       const CORBA_char *startup_id,
+					       CORBA_Environment *ev)
 {
 	EphySession *session;
+	guint32 user_time;
 
+	user_time = parse_startup_id (startup_id);
 	session = EPHY_SESSION (ephy_shell_get_session (ephy_shell));
-	ephy_session_load (session, filename);
+	ephy_session_load (session, filename, user_time);
+}
+
+static void
+impl_ephy_automation_loadSession (PortableServer_Servant _servant,
+				   const CORBA_char *filename,
+				   CORBA_Environment *ev)
+{
+	impl_ephy_automation_loadSessionWithStartupId (_servant,
+						       filename,
+						       "", /* no startup ID */
+						       ev);
 }
 
 static void
-impl_ephy_automation_open_bookmarks_editor (PortableServer_Servant _servant,
-					    CORBA_Environment * ev)
+impl_ephy_automation_openBookmarksEditorWithStartupId (PortableServer_Servant _servant,
+						       const CORBA_char *startup_id,
+						       CORBA_Environment *ev)
 {
 	GtkWidget *editor;
+	guint32 user_time;
 
 	if (eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_BOOKMARK_EDITING)) return;
 	editor = ephy_shell_get_bookmarks_editor (ephy_shell);
 
+	user_time = parse_startup_id (startup_id);
+	if (user_time != 0)
+	{
+		gtk_widget_realize (editor);
+		gdk_x11_window_set_user_time (editor->window, user_time);
+	}
+
 	gtk_window_present (GTK_WINDOW (editor));
 }
 
 static void
+impl_ephy_automation_openBookmarksEditor (PortableServer_Servant _servant,
+					  CORBA_Environment *ev)
+{
+	impl_ephy_automation_openBookmarksEditorWithStartupId (_servant,
+							       "", /* no startup ID */
+							       ev);
+}
+
+static void
 ephy_automation_init (EphyAutomation *c)
 {
 }
@@ -158,10 +253,13 @@ ephy_automation_class_init (EphyAutomati
 
 	/* connect implementation callbacks */
 	epv->loadurl = impl_ephy_automation_loadurl;
-	epv->addBookmark = impl_ephy_automation_add_bookmark;
-	epv->importBookmarks = impl_ephy_automation_import_bookmarks;
-	epv->loadSession = impl_ephy_automation_load_session;
-	epv->openBookmarksEditor = impl_ephy_automation_open_bookmarks_editor;
+	epv->addBookmark = impl_ephy_automation_addBookmark;
+	epv->importBookmarks = impl_ephy_automation_importBookmarks;
+	epv->loadSession = impl_ephy_automation_loadSession;
+	epv->openBookmarksEditor = impl_ephy_automation_openBookmarksEditor;
+	epv->loadUrlWithStartupId = impl_ephy_automation_loadUrlWithStartupId;
+	epv->loadSessionWithStartupId = impl_ephy_automation_loadSessionWithStartupId;
+	epv->openBookmarksEditorWithStartupId = impl_ephy_automation_openBookmarksEditorWithStartupId;
 }
 
 BONOBO_TYPE_FUNC_FULL (
Index: src/ephy-main.c
===================================================================
RCS file: /cvs/gnome/epiphany/src/ephy-main.c,v
retrieving revision 1.33
diff -p -u -u -p -r1.33 ephy-main.c
--- src/ephy-main.c	17 Dec 2004 21:49:55 -0000	1.33
+++ src/ephy-main.c	30 Jan 2005 23:08:30 -0000
@@ -48,6 +48,8 @@ static const char *session_filename = NU
 static const char *bookmark_url = NULL;
 static const char *bookmarks_file = NULL;
 
+char *main_startup_id = NULL;
+
 static struct poptOption popt_options[] =
 {
 	{ "new-tab", 'n', POPT_ARG_NONE, &open_in_new_tab, 0,
@@ -113,7 +115,7 @@ main (int argc, char *argv[])
         GValue context_as_value = { 0 };
 	GnomeProgram *program;
 	EphyShellStartupFlags startup_flags;
-	const char **args, *string_arg;
+	const char **args, *string_arg, *startup_id;
 	gboolean new_instance;
 	GError *err = NULL;
 
@@ -129,6 +131,10 @@ main (int argc, char *argv[])
 	 */
 	LIBXML_TEST_VERSION
 
+	/* save the startup ID, since gdk will unset it */
+	startup_id = g_getenv ("DESKTOP_STARTUP_ID");
+	main_startup_id = g_strdup (startup_id ? startup_id : "");
+
 	program = gnome_program_init (PACKAGE, VERSION,
                                       LIBGNOMEUI_MODULE, argc, argv,
                                       GNOME_PARAM_POPT_TABLE, popt_options,
@@ -225,6 +231,7 @@ main (int argc, char *argv[])
 	gnome_vfs_shutdown ();
 	xmlCleanupParser ();
 	poptFreeContext (context);
+	g_free (main_startup_id);
 
 	return 0;
 }
Index: src/ephy-session.c
===================================================================
RCS file: /cvs/gnome/epiphany/src/ephy-session.c,v
retrieving revision 1.35
diff -p -u -u -p -r1.35 ephy-session.c
--- src/ephy-session.c	28 Jan 2005 22:24:46 -0000	1.35
+++ src/ephy-session.c	30 Jan 2005 23:08:30 -0000
@@ -38,6 +38,7 @@
 #include <errno.h>
 #include <string.h>
 #include <stdlib.h>
+#include <gdk/gdkx.h>
 #include <gtk/gtkimage.h>
 #include <gtk/gtklabel.h>
 #include <gtk/gtkstock.h>
@@ -357,7 +358,8 @@ ephy_session_class_init (EphySessionClas
 }
 
 static gboolean
-offer_to_resume (EphySession *session)
+offer_to_resume (EphySession *session,
+		 guint32 user_time)
 {
 	GtkWidget *dialog;
 	int response;
@@ -385,6 +387,13 @@ offer_to_resume (EphySession *session)
 
 	session->priv->resume_dialog = dialog;
 
+	/* set user time */
+	if (user_time != 0)
+	{
+		gtk_widget_realize (dialog);
+		gdk_x11_window_set_user_time (dialog->window, user_time);
+	}
+
 	response = gtk_dialog_run (GTK_DIALOG (dialog));
 
 	gtk_widget_destroy (dialog);
@@ -397,6 +406,7 @@ offer_to_resume (EphySession *session)
 /**
  * ephy_session_autoresume:
  * @session: a #EphySession
+ * @user_time: a timestamp, or 0
  *
  * Resume a crashed session when necessary (interactive)
  *
@@ -405,28 +415,39 @@ offer_to_resume (EphySession *session)
  * has been re-presented to the user.
  **/
 gboolean
-ephy_session_autoresume (EphySession *session)
+ephy_session_autoresume (EphySession *session,
+			 guint32 user_time)
 {
+	EphySessionPrivate *priv = session->priv;
 	char *saved_session;
 	gboolean retval = FALSE;
 
 	LOG ("ephy_session_autoresume");
 
-	if (session->priv->windows != NULL || session->priv->tool_windows != NULL) return FALSE;
+	if (priv->windows != NULL || priv->tool_windows != NULL) return FALSE;
 
-	if (session->priv->resume_dialog)
+	if (priv->resume_dialog)
 	{
-		gtk_window_present (GTK_WINDOW (session->priv->resume_dialog));
+		/* update user time */
+		if (user_time != 0)
+		{
+			gtk_widget_realize (priv->resume_dialog);
+			gdk_x11_window_set_user_time (priv->resume_dialog->window,
+						      user_time);
+		}
+
+		gtk_window_present (GTK_WINDOW (priv->resume_dialog));
 		return TRUE;
 	}
 
 	saved_session = get_session_filename (SESSION_CRASHED);
 
 	if (g_file_test (saved_session, G_FILE_TEST_EXISTS)
-	    && offer_to_resume (session))
+	    && offer_to_resume (session, user_time))
 	{
 		session->priv->dont_save = TRUE;
-		retval = ephy_session_load (session, saved_session);
+		retval = ephy_session_load (session, saved_session,
+					    user_time);
 		session->priv->dont_save = FALSE;
 		ephy_session_save (session, SESSION_CRASHED);
 	}
@@ -738,6 +759,7 @@ restore_geometry (GtkWindow *window,
  * ephy_session_load:
  * @session: a #EphySession
  * @filename: the path of the source file
+ * @user_time: a timestamp, or 0
  *
  * Load a session from disk, restoring the windows and their state
  *
@@ -745,7 +767,8 @@ restore_geometry (GtkWindow *window,
  **/
 gboolean
 ephy_session_load (EphySession *session,
-		   const char *filename)
+		   const char *filename,
+		   guint32 user_time)
 {
 	xmlDocPtr doc;
         xmlNodePtr child;
@@ -776,6 +799,15 @@ ephy_session_load (EphySession *session,
 			widget = GTK_WIDGET (ephy_window_new ());
 			restore_geometry (GTK_WINDOW (widget), child);
 			parse_embed (child->children, EPHY_WINDOW (widget));
+
+			/* set user time */
+			if (user_time != 0)
+			{
+				gtk_widget_realize (widget);
+				gdk_x11_window_set_user_time (widget->window,
+							      user_time);
+			}
+
 			gtk_window_present (GTK_WINDOW (widget));
 		}
 		else if (xmlStrEqual (child->name, (const xmlChar *) "toolwindow"))
@@ -800,6 +832,14 @@ ephy_session_load (EphySession *session,
 			}
 
 			restore_geometry (GTK_WINDOW (widget), child);
+
+			/* update user time */
+			if (user_time != 0)
+			{
+				gtk_widget_realize (widget);
+				gdk_x11_window_set_user_time (widget->window, user_time);
+			}
+
 			gtk_window_present (GTK_WINDOW (widget));
 		}
 
Index: src/ephy-session.h
===================================================================
RCS file: /cvs/gnome/epiphany/src/ephy-session.h,v
retrieving revision 1.3
diff -p -u -u -p -r1.3 ephy-session.h
--- src/ephy-session.h	8 Jan 2005 16:40:45 -0000	1.3
+++ src/ephy-session.h	30 Jan 2005 23:08:30 -0000
@@ -63,9 +63,11 @@ gboolean	 ephy_session_save		(EphySessio
 						 const char *filename);
 
 gboolean	 ephy_session_load		(EphySession *session,
-						 const char *filename);
+						 const char *filename,
+						 guint32 user_time);
 
-gboolean	 ephy_session_autoresume	(EphySession *session);
+gboolean	 ephy_session_autoresume	(EphySession *session,
+						 guint32 user_time);
 
 void		 ephy_session_close		(EphySession *session);
 
Index: src/ephy-shell.c
===================================================================
RCS file: /cvs/gnome/epiphany/src/ephy-shell.c,v
retrieving revision 1.114
diff -p -u -u -p -r1.114 ephy-shell.c
--- src/ephy-shell.c	30 Jan 2005 15:20:36 -0000	1.114
+++ src/ephy-shell.c	30 Jan 2005 23:08:30 -0000
@@ -54,6 +54,7 @@
 #include <string.h>
 #include <bonobo/bonobo-main.h>
 #include <glib/gi18n.h>
+#include <gdk/gdkx.h>
 #include <gtk/gtksignal.h>
 #include <gtk/gtkmain.h>
 #include <gtk/gtkmessagedialog.h>
@@ -86,6 +87,8 @@ struct _EphyShellPrivate
 	gboolean embed_single_connected;
 };
 
+extern char *main_startup_id;
+
 EphyShell *ephy_shell = NULL;
 
 static void ephy_shell_class_init	(EphyShellClass *klass);
@@ -308,8 +311,10 @@ path_from_command_line_arg (const char *
 
 static void
 open_urls (GNOME_EphyAutomation automation,
-	   const char **args, CORBA_Environment *ev,
-	   gboolean new_tab, gboolean existing_window,
+	   const char **args,
+	   CORBA_Environment *ev,
+	   gboolean new_tab,
+	   gboolean existing_window,
 	   gboolean fullscreen)
 {
 	int i;
@@ -317,9 +322,9 @@ open_urls (GNOME_EphyAutomation automati
 	if (args == NULL)
 	{
 		/* Homepage or resume */
-		GNOME_EphyAutomation_loadurl
+		GNOME_EphyAutomation_loadUrlWithStartupId
 			(automation, "", fullscreen,
-			 existing_window, new_tab, ev);
+			 existing_window, new_tab, main_startup_id, ev);
 	}
 	else
 	{
@@ -329,9 +334,9 @@ open_urls (GNOME_EphyAutomation automati
 
 			path = path_from_command_line_arg (args[i]);
 
-			GNOME_EphyAutomation_loadurl
+			GNOME_EphyAutomation_loadUrlWithStartupId
 				(automation, path, fullscreen,
-				 existing_window, new_tab, ev);
+				 existing_window, new_tab, main_startup_id, ev);
 
 			g_free (path);
 		}
@@ -465,13 +470,13 @@ ephy_shell_startup (EphyShell *shell,
 		}
 		else if (flags & EPHY_SHELL_STARTUP_BOOKMARKS_EDITOR)
 		{
-			GNOME_EphyAutomation_openBookmarksEditor
-				(automation, &ev);
+			GNOME_EphyAutomation_openBookmarksEditorWithStartupId
+				(automation, main_startup_id, &ev);
 		}
 		else if (flags & EPHY_SHELL_STARTUP_SESSION)
 		{
-			GNOME_EphyAutomation_loadSession
-				(automation, string_arg, &ev);
+			GNOME_EphyAutomation_loadSessionWithStartupId
+				(automation, string_arg, main_startup_id, &ev);
 		}
 		else if (flags & EPHY_SHELL_STARTUP_IMPORT_BOOKMARKS)
 		{
@@ -638,11 +643,12 @@ load_homepage (EphyEmbed *embed)
 }
 
 /**
- * ephy_shell_new_tab:
+ * ephy_shell_new_tab_full:
  * @shell: a #EphyShell
  * @parent_window: the target #EphyWindow or %NULL
  * @previous_tab: the referrer tab or %NULL
  * @url: an url to load or %NULL
+ * @user_time: a timestamp, or 0
  *
  * Create a new tab and the parent window when necessary.
  * Use this function to open urls in new window/tabs.
@@ -650,11 +656,12 @@ load_homepage (EphyEmbed *embed)
  * ReturnValue: the created #EphyTab
  **/
 EphyTab *
-ephy_shell_new_tab (EphyShell *shell,
-		    EphyWindow *parent_window,
-		    EphyTab *previous_tab,
-		    const char *url,
-		    EphyNewTabFlags flags)
+ephy_shell_new_tab_full (EphyShell *shell,
+			 EphyWindow *parent_window,
+			 EphyTab *previous_tab,
+			 const char *url,
+			 EphyNewTabFlags flags,
+			 guint32 user_time)
 {
 	EphyWindow *window;
 	EphyTab *tab;
@@ -704,6 +711,16 @@ ephy_shell_new_tab (EphyShell *shell,
 	embed = ephy_tab_get_embed (tab);
 
 	ephy_window_add_tab (window, tab, position, jump_to);
+
+	/* update user time */
+	if (user_time != 0)
+	{
+		GtkWidget *widget = GTK_WIDGET (window);
+
+		gtk_widget_realize (widget);
+		gdk_x11_window_set_user_time (widget->window, user_time);
+	}
+
 	gtk_widget_show (GTK_WIDGET (window));
 
 	if (flags & EPHY_NEW_TAB_HOME_PAGE ||
@@ -725,6 +742,29 @@ ephy_shell_new_tab (EphyShell *shell,
 	}
 
 	return tab;
+}
+
+/**
+ * ephy_shell_new_tab:
+ * @shell: a #EphyShell
+ * @parent_window: the target #EphyWindow or %NULL
+ * @previous_tab: the referrer tab or %NULL
+ * @url: an url to load or %NULL
+ *
+ * Create a new tab and the parent window when necessary.
+ * Use this function to open urls in new window/tabs.
+ *
+ * ReturnValue: the created #EphyTab
+ **/
+EphyTab *
+ephy_shell_new_tab (EphyShell *shell,
+		    EphyWindow *parent_window,
+		    EphyTab *previous_tab,
+		    const char *url,
+		    EphyNewTabFlags flags)
+{
+	return ephy_shell_new_tab_full (shell, parent_window,
+					previous_tab, url, flags, 0);
 }
 
 /**
Index: src/ephy-shell.h
===================================================================
RCS file: /cvs/gnome/epiphany/src/ephy-shell.h,v
retrieving revision 1.32
diff -p -u -u -p -r1.32 ephy-shell.h
--- src/ephy-shell.h	15 Jan 2005 16:47:39 -0000	1.32
+++ src/ephy-shell.h	30 Jan 2005 23:08:30 -0000
@@ -122,6 +122,13 @@ EphyTab	       *ephy_shell_new_tab			(Ep
 							 const char *url,
 							 EphyNewTabFlags flags);
 
+EphyTab	       *ephy_shell_new_tab_full			(EphyShell *shell,
+							 EphyWindow *parent_window,
+							 EphyTab *previous_tab,
+							 const char *url,
+							 EphyNewTabFlags flags,
+							 guint32 user_time);
+
 GObject	       *ephy_shell_get_session			(EphyShell *shell);
 
 EphyBookmarks  *ephy_shell_get_bookmarks		(EphyShell *shell);
Index: src/bookmarks/ephy-bookmarks.c
===================================================================
RCS file: /cvs/gnome/epiphany/src/bookmarks/ephy-bookmarks.c,v
retrieving revision 1.102
diff -p -u -u -p -r1.102 ephy-bookmarks.c
--- src/bookmarks/ephy-bookmarks.c	30 Jan 2005 20:09:59 -0000	1.102
+++ src/bookmarks/ephy-bookmarks.c	30 Jan 2005 23:08:31 -0000
@@ -564,6 +564,9 @@ redirect_cb (EphyHistory *history,
 					 (EphyNodeCallback) update_bookmark_destroy_cb,
 					 G_OBJECT (dialog));
 
+	/* this dialogue is unexpected */
+	gtk_window_set_focus_on_map (GTK_WINDOW (dialog), FALSE);
+
 	gtk_window_present (GTK_WINDOW (dialog));
 }
 
