aboutsummaryrefslogtreecommitdiffstats
path: root/shell/main.c
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@src.gnome.org>2009-01-29 01:19:34 +0800
committerMatthew Barnes <mbarnes@src.gnome.org>2009-01-29 01:19:34 +0800
commit533d59e2cd30ba79a99a71907ffdda65505e633a (patch)
treeba6f611ce6a1bb9d3dfb98a6a6a670cf99a55b9d /shell/main.c
parent3e339d5ecc63d912840c6f885460c58f60eb85e0 (diff)
downloadgsoc2013-evolution-533d59e2cd30ba79a99a71907ffdda65505e633a.tar
gsoc2013-evolution-533d59e2cd30ba79a99a71907ffdda65505e633a.tar.gz
gsoc2013-evolution-533d59e2cd30ba79a99a71907ffdda65505e633a.tar.bz2
gsoc2013-evolution-533d59e2cd30ba79a99a71907ffdda65505e633a.tar.lz
gsoc2013-evolution-533d59e2cd30ba79a99a71907ffdda65505e633a.tar.xz
gsoc2013-evolution-533d59e2cd30ba79a99a71907ffdda65505e633a.tar.zst
gsoc2013-evolution-533d59e2cd30ba79a99a71907ffdda65505e633a.zip
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. svn path=/branches/kill-bonobo/; revision=37147
Diffstat (limited to 'shell/main.c')
-rw-r--r--shell/main.c165
1 files changed, 111 insertions, 54 deletions
diff --git a/shell/main.c b/shell/main.c
index 0cf8c77d8c..670b24d1a2 100644
--- a/shell/main.c
+++ b/shell/main.c
@@ -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_eplugin = FALSE;
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 @@ destroy_config (GConfClient *client)
#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;
+ /* 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);
- 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);
+ if (unique_app_is_running (UNIQUE_APP (shell))) {
+ gtk_main_quit ();
+ return FALSE;
}
- shell_window = e_shell_create_shell_window (shell);
-
-#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 ();
- }
-#endif
+ /* 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 */
- /* 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 */
-
- if (!disable_eplugin) {
+ if (uris == NULL && !disable_eplugin)
e_plugin_load_plugins_with_missing_symbols ();
- }
return FALSE;
}
@@ -530,6 +497,84 @@ master_client_die_cb (GnomeClient *client,
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 @@ create_default_shell (void)
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 @@ create_default_shell (void)
}
}
- 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 @@ main (int argc, char **argv)
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 @@ main (int argc, char **argv)
link_shutdown ();
#endif
- /* Indicates a clean shut down to the next session. */
- e_file_lock_destroy ();
-
return 0;
}