evolution r37147 - in branches/kill-bonobo: . mail shell widgets/misc



Author: mbarnes
Date: Wed Jan 28 17:19:34 2009
New Revision: 37147
URL: http://svn.gnome.org/viewvc/evolution?rev=37147&view=rev

Log:
Add unique-1.0 requirement (blessed external dependency).

Make EShell a subclass of UniqueApp and handle single-instance negotiation.

When another Evolution process is running:

  - Running "evolution" will simply present the existing windows.

  - Running "evolution -c <view>" will open a shell window set to <view>.

  - Running "evolution <uri>" will open an appropriate window for <uri>.

The second process will then terminate immediately.



Modified:
   branches/kill-bonobo/configure.in
   branches/kill-bonobo/evolution-shell.pc.in
   branches/kill-bonobo/mail/em-mailer-prefs.c
   branches/kill-bonobo/mail/em-mailer-prefs.h
   branches/kill-bonobo/shell/e-shell-module.c
   branches/kill-bonobo/shell/e-shell-window-actions.c
   branches/kill-bonobo/shell/e-shell-window-private.c
   branches/kill-bonobo/shell/e-shell-window-private.h
   branches/kill-bonobo/shell/e-shell-window.c
   branches/kill-bonobo/shell/e-shell.c
   branches/kill-bonobo/shell/e-shell.h
   branches/kill-bonobo/shell/main.c
   branches/kill-bonobo/widgets/misc/e-activity-proxy.c

Modified: branches/kill-bonobo/configure.in
==============================================================================
--- branches/kill-bonobo/configure.in	(original)
+++ branches/kill-bonobo/configure.in	Wed Jan 28 17:19:34 2009
@@ -34,6 +34,7 @@
 m4_define([libgnomeui_minimum_version], [2.0.0])        # XXX Just a Guess
 m4_define([libxml_minimum_version], [2.0.0])            # XXX Just a Guess
 m4_define([shared_mime_info_minimum_version], [0.22])
+m4_define([unique_minimum_version], [1.0])              # XXX Just a Guess
 
 # Optional Packages
 #
@@ -181,7 +182,8 @@
          libgnomecanvas-2.0 >= libgnomecanvas_minimum_version
          libgnomeui-2.0 >= libgnomeui_minimum_version
          libxml-2.0 >= libxml_minimum_version
-	 shared-mime-info >= shared_mime_info_minimum_version])
+         shared-mime-info >= shared_mime_info_minimum_version
+         unique-1.0 >= unique_minimum_version])
 AC_SUBST(GNOME_PLATFORM_CFLAGS)
 AC_SUBST(GNOME_PLATFORM_LIBS)
 
@@ -195,9 +197,8 @@
 	 libgdata-$EDS_PACKAGE >= eds_minimum_version
 	 libgdata-google-$EDS_PACKAGE >= eds_minimum_version])
 
-
 dnl ******************
-dnl User documentation
+dnl User Documentation
 dnl ******************
 AC_MSG_CHECKING([whether to build user documentation])
 AC_ARG_WITH([help],
@@ -1558,14 +1559,14 @@
 AM_CONDITIONAL(NM_SUPPORT, test x$NM_SUPPORT = xyes)
 
 
-EVO_SET_COMPILE_FLAGS(SHELL, libgnomeui-2.0 libbonoboui-2.0 libglade-2.0 gio-2.0 gconf-2.0 gobject-2.0 libgtkhtml-$GTKHTML_PACKAGE $NM_SUPPORT_PACKAGES)   
+EVO_SET_COMPILE_FLAGS(SHELL, libgnomeui-2.0 libbonoboui-2.0 libglade-2.0 gio-2.0 gconf-2.0 gobject-2.0 libgtkhtml-$GTKHTML_PACKAGE $NM_SUPPORT_PACKAGES unique-1.0)
 
 AC_SUBST(SHELL_CFLAGS)
 AC_SUBST(SHELL_LIBS)
 
 dnl --- evolution-addressbook flags
 
-EVOLUTION_ADDRESSBOOK_DEPS="libbonoboui-2.0 libglade-2.0 libgnomeui-2.0 gio-2.0 gconf-2.0 gobject-2.0 libgtkhtml-$GTKHTML_PACKAGE libebook-$EDS_PACKAGE libedataserverui-$EDS_PACKAGE camel-$EDS_PACKAGE gtkhtml-editor"
+EVOLUTION_ADDRESSBOOK_DEPS="libbonoboui-2.0 libglade-2.0 libgnomeui-2.0 gio-2.0 gconf-2.0 gobject-2.0 libgtkhtml-$GTKHTML_PACKAGE libebook-$EDS_PACKAGE libedataserverui-$EDS_PACKAGE camel-$EDS_PACKAGE gtkhtml-editor unique-1.0"
 
 EVO_SET_COMPILE_FLAGS(EVOLUTION_ADDRESSBOOK, $EVOLUTION_ADDRESSBOOK_DEPS)
 AC_SUBST(EVOLUTION_ADDRESSBOOK_CFLAGS)
@@ -1594,7 +1595,7 @@
 AC_SUBST(LIBSOUP_CFLAGS)
 AC_SUBST(LIBSOUP_LIBS)
 
-EVO_SET_COMPILE_FLAGS(EVOLUTION_CALENDAR, libgnomeui-2.0 libbonoboui-2.0 libglade-2.0 gio-2.0 gconf-2.0 gobject-2.0 libgtkhtml-$GTKHTML_PACKAGE libebook-$EDS_PACKAGE libecal-$EDS_PACKAGE libedataserverui-$EDS_PACKAGE libebackend-$EDS_PACKAGE $HAL_REQUIREMENT $libnotify gtkhtml-editor libgdata-$EDS_PACKAGE libgdata-google-$EDS_PACKAGE)
+EVO_SET_COMPILE_FLAGS(EVOLUTION_CALENDAR, libgnomeui-2.0 libbonoboui-2.0 libglade-2.0 gio-2.0 gconf-2.0 gobject-2.0 libgtkhtml-$GTKHTML_PACKAGE libebook-$EDS_PACKAGE libecal-$EDS_PACKAGE libedataserverui-$EDS_PACKAGE libebackend-$EDS_PACKAGE $HAL_REQUIREMENT $libnotify gtkhtml-editor libgdata-$EDS_PACKAGE libgdata-google-$EDS_PACKAGE unique-1.0)
 AC_SUBST(EVOLUTION_CALENDAR_CFLAGS)
 AC_SUBST(EVOLUTION_CALENDAR_LIBS)
 
@@ -1606,7 +1607,7 @@
 
 dnl --- evolution-mail flags
 
-EVO_SET_COMPILE_FLAGS(EVOLUTION_MAIL, camel-provider-$EDS_PACKAGE libgnomeui-2.0 libbonoboui-2.0 libglade-2.0 gio-2.0 gconf-2.0 gobject-2.0 libgtkhtml-$GTKHTML_PACKAGE gtkhtml-editor bonobo-activation-2.0 $mozilla_nss libebook-$EDS_PACKAGE libedataserverui-$EDS_PACKAGE)
+EVO_SET_COMPILE_FLAGS(EVOLUTION_MAIL, camel-provider-$EDS_PACKAGE libgnomeui-2.0 libbonoboui-2.0 libglade-2.0 gio-2.0 gconf-2.0 gobject-2.0 libgtkhtml-$GTKHTML_PACKAGE gtkhtml-editor bonobo-activation-2.0 $mozilla_nss libebook-$EDS_PACKAGE libedataserverui-$EDS_PACKAGE unique-1.0)
 AC_SUBST(EVOLUTION_MAIL_CFLAGS)
 AC_SUBST(EVOLUTION_MAIL_LIBS)
 

Modified: branches/kill-bonobo/evolution-shell.pc.in
==============================================================================
--- branches/kill-bonobo/evolution-shell.pc.in	(original)
+++ branches/kill-bonobo/evolution-shell.pc.in	Wed Jan 28 17:19:34 2009
@@ -22,6 +22,6 @@
 Name: evolution-shell
 Description: libraries needed for Evolution shell components
 Version: @VERSION@
-Requires: libgnome-2.0 libgnomeui-2.0 libbonoboui-2.0 >= @BONOBOUI_REQUIRED@
+Requires: libgnome-2.0 libgnomeui-2.0 libbonoboui-2.0 >= @BONOBOUI_REQUIRED@ unique-1.0
 Libs: -L${privlibdir} -leshell -Wl,-R${privlibdir}
 Cflags: -I${privincludedir}

Modified: branches/kill-bonobo/mail/em-mailer-prefs.c
==============================================================================
--- branches/kill-bonobo/mail/em-mailer-prefs.c	(original)
+++ branches/kill-bonobo/mail/em-mailer-prefs.c	Wed Jan 28 17:19:34 2009
@@ -52,7 +52,6 @@
 
 static void em_mailer_prefs_class_init (EMMailerPrefsClass *class);
 static void em_mailer_prefs_init       (EMMailerPrefs *dialog);
-static void em_mailer_prefs_dispose    (GObject *object);
 static void em_mailer_prefs_finalize   (GObject *object);
 
 static GtkVBoxClass *parent_class = NULL;
@@ -129,7 +128,6 @@
 	object_class = (GObjectClass *) klass;
 	parent_class = g_type_class_ref (gtk_vbox_get_type ());
 
-	object_class->dispose = em_mailer_prefs_dispose;
 	object_class->finalize = em_mailer_prefs_finalize;
 }
 
@@ -140,20 +138,6 @@
 }
 
 static void
-em_mailer_prefs_dispose (GObject *object)
-{
-	EMMailerPrefs *prefs = (EMMailerPrefs *) object;
-
-	if (prefs->shell != NULL) {
-		g_object_unref (prefs->shell);
-		prefs->shell = NULL;
-	}
-
-	/* Chain up to parent's dispose() method. */
-	G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
 em_mailer_prefs_finalize (GObject *obj)
 {
 	EMMailerPrefs *prefs = (EMMailerPrefs *) obj;
@@ -1107,7 +1091,6 @@
 	GSList *l;
 	char *gladefile;
 
-	prefs->shell = g_object_ref (shell);
 	shell_settings = e_shell_get_shell_settings (shell);
 
 	gladefile = g_build_filename (EVOLUTION_GLADEDIR,

Modified: branches/kill-bonobo/mail/em-mailer-prefs.h
==============================================================================
--- branches/kill-bonobo/mail/em-mailer-prefs.h	(original)
+++ branches/kill-bonobo/mail/em-mailer-prefs.h	Wed Jan 28 17:19:34 2009
@@ -62,7 +62,6 @@
 struct _EMMailerPrefs {
 	GtkVBox parent_object;
 
-	EShell *shell;
 	GladeXML *gui;
 	GConfClient *gconf;
 

Modified: branches/kill-bonobo/shell/e-shell-module.c
==============================================================================
--- branches/kill-bonobo/shell/e-shell-module.c	(original)
+++ branches/kill-bonobo/shell/e-shell-module.c	Wed Jan 28 17:19:34 2009
@@ -44,7 +44,7 @@
 	GModule *module;
 	gchar *filename;
 
-	EShell *shell;
+	gpointer shell;  /* weak pointer */
 	gchar *config_dir;
 	gchar *data_dir;
 
@@ -82,7 +82,12 @@
                         EShell *shell)
 {
 	g_return_if_fail (shell_module->priv->shell == NULL);
-	shell_module->priv->shell = g_object_ref (shell);
+
+	shell_module->priv->shell = shell;
+
+	g_object_add_weak_pointer (
+		G_OBJECT (shell_module),
+		&shell_module->priv->shell);
 }
 
 static void
@@ -132,22 +137,6 @@
 }
 
 static void
-shell_module_dispose (GObject *object)
-{
-	EShellModulePrivate *priv;
-
-	priv = E_SHELL_MODULE_GET_PRIVATE (object);
-
-	if (priv->shell != NULL) {
-		g_object_unref (priv->shell);
-		priv->shell = NULL;
-	}
-
-	/* Chain up to parent's dispose() method. */
-	G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
 shell_module_finalize (GObject *object)
 {
 	EShellModulePrivate *priv;
@@ -217,7 +206,6 @@
 	object_class = G_OBJECT_CLASS (class);
 	object_class->set_property = shell_module_set_property;
 	object_class->get_property = shell_module_get_property;
-	object_class->dispose = shell_module_dispose;
 	object_class->finalize = shell_module_finalize;
 
 	type_module_class = G_TYPE_MODULE_CLASS (class);
@@ -420,7 +408,7 @@
 {
 	g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), NULL);
 
-	return shell_module->priv->shell;
+	return E_SHELL (shell_module->priv->shell);
 }
 
 /**

Modified: branches/kill-bonobo/shell/e-shell-window-actions.c
==============================================================================
--- branches/kill-bonobo/shell/e-shell-window-actions.c	(original)
+++ branches/kill-bonobo/shell/e-shell-window-actions.c	Wed Jan 28 17:19:34 2009
@@ -853,9 +853,12 @@
                       EShellWindow *shell_window)
 {
 	EShell *shell;
+	const gchar *view_name;
 
 	shell = e_shell_window_get_shell (shell_window);
-	e_shell_create_shell_window (shell);
+	view_name = e_shell_window_get_active_view (shell_window);
+
+	e_shell_create_shell_window (shell, view_name);
 }
 
 /**

Modified: branches/kill-bonobo/shell/e-shell-window-private.c
==============================================================================
--- branches/kill-bonobo/shell/e-shell-window-private.c	(original)
+++ branches/kill-bonobo/shell/e-shell-window-private.c	Wed Jan 28 17:19:34 2009
@@ -420,7 +420,6 @@
 		priv->signal_handler_ids = NULL;
 	}
 
-	DISPOSE (priv->shell);
 	DISPOSE (priv->ui_manager);
 
 	g_hash_table_remove_all (priv->loaded_views);

Modified: branches/kill-bonobo/shell/e-shell-window-private.h
==============================================================================
--- branches/kill-bonobo/shell/e-shell-window-private.h	(original)
+++ branches/kill-bonobo/shell/e-shell-window-private.h	Wed Jan 28 17:19:34 2009
@@ -65,7 +65,7 @@
 
 struct _EShellWindowPrivate {
 
-	EShell *shell;
+	gpointer shell;  /* weak pointer */
 
 	/*** UI Management ***/
 

Modified: branches/kill-bonobo/shell/e-shell-window.c
==============================================================================
--- branches/kill-bonobo/shell/e-shell-window.c	(original)
+++ branches/kill-bonobo/shell/e-shell-window.c	Wed Jan 28 17:19:34 2009
@@ -153,7 +153,12 @@
 	gulong handler_id;
 
 	g_return_if_fail (shell_window->priv->shell == NULL);
-	shell_window->priv->shell = g_object_ref (shell);
+
+	shell_window->priv->shell = shell;
+
+	g_object_add_weak_pointer (
+		G_OBJECT (shell_window),
+		&shell_window->priv->shell);
 
 	/* Need to disconnect these when the window is closing. */
 
@@ -435,7 +440,7 @@
 {
 	g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL);
 
-	return shell_window->priv->shell;
+	return E_SHELL (shell_window->priv->shell);
 }
 
 /**

Modified: branches/kill-bonobo/shell/e-shell.c
==============================================================================
--- branches/kill-bonobo/shell/e-shell.c	(original)
+++ branches/kill-bonobo/shell/e-shell.c	Wed Jan 28 17:19:34 2009
@@ -316,6 +316,37 @@
 			modules_by_scheme, string, shell_module);
 }
 
+static void
+shell_load_modules (EShell *shell)
+{
+	GDir *dir;
+	const gchar *dirname;
+	const gchar *basename;
+	GError *error = NULL;
+
+	dirname = EVOLUTION_MODULEDIR;
+
+	dir = g_dir_open (dirname, 0, &error);
+	if (dir == NULL) {
+		g_critical ("%s", error->message);
+		g_error_free (error);
+		return;
+	}
+
+	while ((basename = g_dir_read_name (dir)) != NULL) {
+		gchar *filename;
+
+		if (!g_str_has_suffix (basename, "." G_MODULE_SUFFIX))
+			continue;
+
+		filename = g_build_filename (dirname, basename, NULL);
+		shell_query_module (shell, filename);
+		g_free (filename);
+	}
+
+	g_dir_close (dir);
+}
+
 static gboolean
 shell_shutdown_timeout (EShell *shell)
 {
@@ -448,6 +479,10 @@
 	g_hash_table_destroy (priv->modules_by_name);
 	g_hash_table_destroy (priv->modules_by_scheme);
 
+	/* Indicates a clean shut down to the next session. */
+	if (!unique_app_is_running (UNIQUE_APP (object)))
+		e_file_lock_destroy ();
+
 	/* Chain up to parent's finalize() method. */
 	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -455,42 +490,94 @@
 static void
 shell_constructed (GObject *object)
 {
-	GDir *dir;
-	EShell *shell;
-	const gchar *dirname;
-	const gchar *basename;
-	GError *error = NULL;
+	/* UniqueApp will have by this point determined whether we're
+	 * the only Evolution process running.  If so, proceed normally.
+	 * Otherwise we just issue commands to the other process. */
+	if (unique_app_is_running (UNIQUE_APP (object)))
+		return;
 
-	shell = E_SHELL (object);
-	dirname = EVOLUTION_MODULEDIR;
+	e_file_lock_create ();
 
-	dir = g_dir_open (dirname, 0, &error);
-	if (dir == NULL) {
-		g_critical ("%s", error->message);
-		g_error_free (error);
-		return;
-	}
+	shell_load_modules (E_SHELL (object));
+	e_shell_migrate_attempt (E_SHELL (object));
+}
 
-	while ((basename = g_dir_read_name (dir)) != NULL) {
-		gchar *filename;
+static gboolean
+shell_message_handle_new (EShell *shell,
+                          UniqueMessageData *data)
+{
+	gchar *view_name;
 
-		if (!g_str_has_suffix (basename, "." G_MODULE_SUFFIX))
-			continue;
+	view_name = unique_message_data_get_text (data);
+	e_shell_create_shell_window (shell, view_name);
+	g_free (view_name);
 
-		filename = g_build_filename (dirname, basename, NULL);
-		shell_query_module (shell, filename);
-		g_free (filename);
-	}
+	return TRUE;
+}
 
-	g_dir_close (dir);
+static gboolean
+shell_message_handle_open (EShell *shell,
+                           UniqueMessageData *data)
+{
+	gchar **uris;
+
+	uris = unique_message_data_get_uris (data);
+	e_shell_handle_uris (shell, uris);
+	g_strfreev (uris);
+
+	return TRUE;
+}
+
+static gboolean
+shell_message_handle_close (EShell *shell,
+                            UniqueMessageData *data)
+{
+	e_shell_quit (shell);
+
+	return TRUE;
+}
+
+static UniqueResponse
+shell_message_received (UniqueApp *app,
+                        gint command,
+                        UniqueMessageData *data,
+                        guint time_)
+{
+	EShell *shell = E_SHELL (app);
+
+	switch (command) {
+		case UNIQUE_ACTIVATE:
+			break;  /* use the default behavior */
+
+		case UNIQUE_NEW:
+			if (shell_message_handle_new (shell, data))
+				return UNIQUE_RESPONSE_OK;
+			break;
+
+		case UNIQUE_OPEN:
+			if (shell_message_handle_open (shell, data))
+				return UNIQUE_RESPONSE_OK;
+			break;
+
+		case UNIQUE_CLOSE:
+			if (shell_message_handle_close (shell, data))
+				return UNIQUE_RESPONSE_OK;
+			break;
+
+		default:
+			break;
+	}
 
-	e_shell_migrate_attempt (shell);
+	/* Chain up to parent's message_received() method. */
+	return UNIQUE_APP_CLASS (parent_class)->
+		message_received (app, command, data, time_);
 }
 
 static void
 shell_class_init (EShellClass *class)
 {
 	GObjectClass *object_class;
+	UniqueAppClass *unique_app_class;
 
 	parent_class = g_type_class_peek_parent (class);
 	g_type_class_add_private (class, sizeof (EShellPrivate));
@@ -502,6 +589,9 @@
 	object_class->finalize = shell_finalize;
 	object_class->constructed = shell_constructed;
 
+	unique_app_class = UNIQUE_APP_CLASS (class);
+	unique_app_class->message_received = shell_message_received;
+
 	/**
 	 * EShell:network-available
 	 *
@@ -748,8 +838,6 @@
 	e_shell_dbus_initialize (shell);
 #endif
 
-	e_file_lock_create ();
-
 	shell_parse_debug_string (shell);
 
 	g_signal_connect (
@@ -797,7 +885,7 @@
 		};
 
 		type = g_type_register_static (
-			G_TYPE_OBJECT, "EShell", &type_info, 0);
+			UNIQUE_TYPE_APP, "EShell", &type_info, 0);
 	}
 
 	return type;
@@ -864,8 +952,6 @@
  * Returns the canonical name for the #EShellModule whose name or alias
  * is @name.
  *
- * XXX Not sure this function is worth keeping around.
- *
  * Returns: the canonical #EShellModule name
  **/
 const gchar *
@@ -954,6 +1040,7 @@
 /**
  * e_shell_create_shell_window:
  * @shell: an #EShell
+ * @view_name: name of the initial shell view, or %NULL
  *
  * Creates a new #EShellWindow and emits the #EShell::window-created
  * signal.  Use this function instead of e_shell_window_new() so that
@@ -962,14 +1049,43 @@
  * Returns: a new #EShellWindow
  **/
 GtkWidget *
-e_shell_create_shell_window (EShell *shell)
+e_shell_create_shell_window (EShell *shell,
+                             const gchar *view_name)
 {
 	GList *active_windows;
 	GtkWidget *shell_window;
+	UniqueMessageData *data;
+	UniqueApp *app;
 
 	g_return_val_if_fail (E_IS_SHELL (shell), NULL);
 
+	app = UNIQUE_APP (shell);
+
+	if (unique_app_is_running (app))
+		goto unique;
+
+	view_name = e_shell_get_canonical_name (shell, view_name);
+
+	/* EShellWindow initializes its active view from a GConf key,
+	 * so set the key ahead of time to control the intial view. */
+	if (view_name != NULL) {
+		GConfClient *client;
+		const gchar *key;
+		GError *error = NULL;
+
+		client = gconf_client_get_default ();
+		key = "/apps/evolution/shell/view_defaults/component_id";
+		gconf_client_set_string (client, key, view_name, &error);
+		g_object_unref (client);
+
+		if (error != NULL) {
+			g_warning ("%s", error->message);
+			g_error_free (error);
+		}
+	}
+
 	shell_window = e_shell_window_new (shell, shell->priv->safe_mode);
+	unique_app_watch_window (app, GTK_WINDOW (shell_window));
 
 	active_windows = shell->priv->active_windows;
 	active_windows = g_list_prepend (active_windows, shell_window);
@@ -992,29 +1108,70 @@
 	gtk_widget_show (shell_window);
 
 	return shell_window;
+
+unique:  /* Send a message to the other Evolution process. */
+
+	/* XXX Do something with UniqueResponse? */
+
+	if (view_name != NULL) {
+		data = unique_message_data_new ();
+		unique_message_data_set_text (data, view_name, -1);
+		unique_app_send_message (app, UNIQUE_NEW, data);
+		unique_message_data_free (data);
+	} else
+		unique_app_send_message (app, UNIQUE_ACTIVATE, NULL);
+
+	return NULL;
 }
 
 /**
- * e_shell_handle_uri:
+ * e_shell_handle_uris:
  * @shell: an #EShell
- * @uri: the URI to be handled
+ * @uris: %NULL-terminated list of URIs
  *
- * Emits the #EShell::handle-uri signal.
+ * Emits the #EShell::handle-uri signal for each URI.
  *
- * Returns: %TRUE if the URI was handled, %FALSE otherwise
+ * Returns: the number of URIs successfully handled
  **/
-gboolean
-e_shell_handle_uri (EShell *shell,
-                    const gchar *uri)
-{
-	gboolean handled;
+guint
+e_shell_handle_uris (EShell *shell,
+                     const gchar **uris)
+{
+	UniqueApp *app;
+	UniqueMessageData *data;
+	guint n_handled = 0;
+	gint ii;
 
 	g_return_val_if_fail (E_IS_SHELL (shell), FALSE);
-	g_return_val_if_fail (uri != NULL, FALSE);
+	g_return_val_if_fail (uris != NULL, FALSE);
+
+	app = UNIQUE_APP (shell);
+
+	if (unique_app_is_running (app))
+		goto unique;
+
+	for (ii = 0; uris[ii] != NULL; ii++) {
+		gboolean handled;
+
+		g_signal_emit (
+			shell, signals[HANDLE_URI],
+			0, uris[ii], &handled);
+		n_handled += handled ? 1 : 0;
+	}
+
+	return n_handled;
+
+unique:  /* Send a message to the other Evolution process. */
+
+	/* XXX Do something with UniqueResponse?
+	 * XXX set_uris() should take a "const" URI list. */
 
-	g_signal_emit (shell, signals[HANDLE_URI], 0, uri, &handled);
+	data = unique_message_data_new ();
+	unique_message_data_set_uris (data, (gchar **) uris);
+	unique_app_send_message (app, UNIQUE_OPEN, data);
+	unique_message_data_free (data);
 
-	return handled;
+	return 0;
 }
 
 /**

Modified: branches/kill-bonobo/shell/e-shell.h
==============================================================================
--- branches/kill-bonobo/shell/e-shell.h	(original)
+++ branches/kill-bonobo/shell/e-shell.h	Wed Jan 28 17:19:34 2009
@@ -28,6 +28,7 @@
 #ifndef E_SHELL_H
 #define E_SHELL_H
 
+#include <unique/unique.h>
 #include <shell/e-shell-common.h>
 #include <shell/e-shell-module.h>
 #include <shell/e-shell-settings.h>
@@ -66,12 +67,12 @@
  * functions below.
  **/
 struct _EShell {
-	GObject parent;
+	UniqueApp parent;
 	EShellPrivate *priv;
 };
 
 struct _EShellClass {
-	GObjectClass parent_class;
+	UniqueAppClass parent_class;
 };
 
 GType		e_shell_get_type		(void);
@@ -85,9 +86,10 @@
 EShellModule *	e_shell_get_module_by_scheme	(EShell *shell,
 						 const gchar *scheme);
 EShellSettings *e_shell_get_shell_settings	(EShell *shell);
-GtkWidget *	e_shell_create_shell_window	(EShell *shell);
-gboolean	e_shell_handle_uri		(EShell *shell,
-                                                 const gchar *uri);
+GtkWidget *	e_shell_create_shell_window	(EShell *shell,
+						 const gchar *view_name);
+guint		e_shell_handle_uris		(EShell *shell,
+                                                 const gchar **uris);
 void		e_shell_send_receive		(EShell *shell,
 						 GtkWindow *parent);
 gboolean	e_shell_get_network_available	(EShell *shell);

Modified: branches/kill-bonobo/shell/main.c
==============================================================================
--- branches/kill-bonobo/shell/main.c	(original)
+++ branches/kill-bonobo/shell/main.c	Wed Jan 28 17:19:34 2009
@@ -23,6 +23,7 @@
 #include <config.h>
 
 #include <gtk/gtk.h>
+#include <gdk/gdkx.h>  /* for copied UniqueApp code */
 #include <glib/gstdio.h>
 
 #ifdef G_OS_WIN32
@@ -101,8 +102,8 @@
 static gboolean disable_preview = FALSE;
 static gboolean idle_cb (gchar **uris);
 
-static char *requested_view = NULL;
-static char *evolution_debug_log = NULL;
+static gchar *requested_view = NULL;
+static gchar *evolution_debug_log = NULL;
 static gchar **remaining_args;
 
 /* Defined in <e-shell.h> */
@@ -299,72 +300,38 @@
 
 #endif /* DEVELOPMENT */
 
-static void
-open_uris (gchar **uris)
-{
-	EShell *shell;
-	guint ii;
-
-	g_return_if_fail (uris != NULL);
-
-	shell = e_shell_get_default ();
-
-	for (ii = 0; uris[ii] != NULL; ii++)
-		if (!e_shell_handle_uri (shell, uris[ii]))
-			g_warning ("Invalid URI: %s", uris[ii]);
-}
-
 /* This is for doing stuff that requires the GTK+ loop to be running already.  */
 
 static gboolean
 idle_cb (gchar **uris)
 {
 	EShell *shell;
-	GtkWidget *shell_window;
-	const gchar *initial_view;
-
-	g_return_val_if_fail (uris == NULL || g_strv_length (uris) > 0, FALSE);
+	guint ii;
 
 #ifdef KILL_PROCESS_CMD
 	kill_old_dataserver ();
 #endif
 
-	if (uris != NULL) {
-		open_uris (uris);
-		return FALSE;
-	}
-
 	shell = e_shell_get_default ();
-	initial_view = e_shell_get_canonical_name (shell, requested_view);
-
-	if (initial_view != NULL) {
-		GConfClient *client;
-		const gchar *key;
 
-		client = gconf_client_get_default ();
-		key = "/apps/evolution/shell/view_defaults/component_id";
-		gconf_client_set_string (client, key, initial_view, NULL);
-		g_object_unref (client);
-	}
-
-	shell_window = e_shell_create_shell_window (shell);
+	/* These calls do the right thing when there's another
+	 * Evolution process running. */
+	if (uris != NULL && *uris != NULL)
+		e_shell_handle_uris (shell, uris);
+	else
+		e_shell_create_shell_window (shell, requested_view);
 
-#if 0  /* MBARNES */
-	if (shell == NULL) {
-		/*there is another instance but because we don't open any windows
-		we must notify the startup was complete manually*/
-		gdk_notify_startup_complete ();
-		bonobo_main_quit ();
+	if (unique_app_is_running (UNIQUE_APP (shell))) {
+		gtk_main_quit ();
+		return FALSE;
 	}
-#endif
 
-	/* This must be done after Bonobo has created all the components. For 
-	 * example the mail component makes the global variable `session` which
-	 * is being used by several EPlugins */
+	/* This must be done after EShell has loaded all the modules.
+	 * For example the mail module makes the global variable `session`
+	 * which is being used by several EPlugins */
 
-	if (!disable_eplugin) {
+	if (uris == NULL && !disable_eplugin)
 		e_plugin_load_plugins_with_missing_symbols ();
-	}
 
 	return FALSE;
 }
@@ -530,6 +497,84 @@
 	e_shell_do_quit (shell);
 }
 
+/* taken from nautilus */
+static guint32
+slowly_and_stupidly_obtain_timestamp (GdkDisplay *display)
+{
+	Display *xdisplay;
+	Window xwindow;
+	XEvent event;
+	XSetWindowAttributes attrs;
+	Atom atom_name;
+	Atom atom_type;
+	char *name;
+
+	xdisplay = GDK_DISPLAY_XDISPLAY (display);
+
+	attrs.override_redirect = True;
+	attrs.event_mask = PropertyChangeMask | StructureNotifyMask;
+
+	xwindow = XCreateWindow (
+		xdisplay, RootWindow (xdisplay, 0),
+		-100, -100, 1, 1,
+		0,
+		CopyFromParent,
+		CopyFromParent,
+		CopyFromParent,
+		CWOverrideRedirect | CWEventMask,
+		&attrs);
+
+	atom_name = XInternAtom (xdisplay, "WM_NAME", TRUE);
+	g_assert (atom_name != None);
+
+	atom_type = XInternAtom (xdisplay, "STRING", TRUE);
+	g_assert (atom_type != None);
+
+	name = "Fake Window";
+	XChangeProperty (
+		xdisplay, xwindow, atom_name, atom_type,
+		8, PropModeReplace, (unsigned char *) name,
+		strlen (name));
+
+	XWindowEvent (
+		xdisplay, xwindow, PropertyChangeMask, &event);
+
+	XDestroyWindow (xdisplay, xwindow);
+
+	return event.xproperty.time;
+}
+
+static gchar *
+pick_startup_id (void)
+{
+	GdkDisplay *display;
+	const gchar *startup_id;
+	gchar *id;
+
+	/* XXX This copies logic from unique_app_new(), which we can't use
+	 *     because we're subclassing UniqueApp.  I already sent ebassi
+	 *     a patch to fix this. */
+
+	display = gdk_display_get_default ();
+
+	/* Try and get the startup notification ID from GDK, the
+	 * environment or, if everything else failed, fake one. */
+	startup_id = gdk_x11_display_get_startup_notification_id (display);
+
+	if (!startup_id || startup_id[0] == '\0')
+		startup_id = g_getenv ("DESKTOP_STARTUP_ID");
+
+	if (!startup_id || startup_id[0] == '\0') {
+		guint32 timestamp;
+
+		timestamp = slowly_and_stupidly_obtain_timestamp (display);
+		id = g_strdup_printf ("_TIME%lu", (gulong) timestamp);
+	} else
+		id = g_strdup (startup_id);
+
+	return id;
+}
+
 static void
 create_default_shell (void)
 {
@@ -537,6 +582,7 @@
 	GConfClient *conf_client;
 	GnomeClient *master_client;
 	gboolean online_mode = TRUE;
+	gchar *startup_id;
 	GError *error = NULL;
 
 	conf_client = gconf_client_get_default ();
@@ -560,7 +606,16 @@
 		}
 	}
 
-	shell = g_object_new (E_TYPE_SHELL, "online-mode", online_mode, NULL);
+	startup_id = pick_startup_id ();
+
+	shell = g_object_new (
+		E_TYPE_SHELL,
+		"name", "org.gnome.evolution",
+		"online-mode", online_mode,
+		"startup-id", startup_id,
+		NULL);
+
+	g_free (startup_id);
 
 	g_signal_connect (
 		shell, "window-destroyed",
@@ -718,6 +773,11 @@
 
 	gtk_main ();
 
+	/* Emit a warning if the shell is not finalized. */
+	g_object_unref (default_shell);
+	if (E_IS_SHELL (default_shell))
+		g_warning ("Shell not finalized on exit");
+
 	gtk_accel_map_save (e_get_accels_filename ());
 
 	e_icon_factory_shutdown ();
@@ -728,8 +788,5 @@
 	link_shutdown ();
 #endif
 
-	/* Indicates a clean shut down to the next session. */
-	e_file_lock_destroy ();
-
 	return 0;
 }

Modified: branches/kill-bonobo/widgets/misc/e-activity-proxy.c
==============================================================================
--- branches/kill-bonobo/widgets/misc/e-activity-proxy.c	(original)
+++ branches/kill-bonobo/widgets/misc/e-activity-proxy.c	Wed Jan 28 17:19:34 2009
@@ -160,7 +160,7 @@
 
 	if (priv->button != NULL) {
 		g_object_unref (priv->button);
-		priv->image = NULL;
+		priv->button = NULL;
 	}
 
 	if (priv->image != NULL) {



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