aboutsummaryrefslogtreecommitdiffstats
path: root/shell/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell/main.c')
-rw-r--r--shell/main.c445
1 files changed, 257 insertions, 188 deletions
diff --git a/shell/main.c b/shell/main.c
index c6959d7663..928a321e61 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
@@ -34,12 +35,10 @@
#include "e-util/e-bconf-map.h"
#include <e-util/e-icon-factory.h>
-#include "e-shell-constants.h"
#include "e-util/e-profile-event.h"
#include "e-util/e-util.h"
#include "e-shell.h"
-#include "es-menu.h"
#include "es-event.h"
#include "e-util/e-util-private.h"
@@ -55,12 +54,11 @@
#include <libgnomeui/gnome-ui-init.h>
#include <libgnomeui/gnome-client.h>
-#include <bonobo/bonobo-main.h>
-#include <bonobo/bonobo-moniker-util.h>
#include <bonobo/bonobo-exception.h>
#include <bonobo-activation/bonobo-activation.h>
+#include <libedataserver/e-categories.h>
#include <libedataserverui/e-passwords.h>
#include <glade/glade.h>
@@ -92,13 +90,11 @@
#define DEVELOPMENT 1
#endif
-static EShell *shell = NULL;
-
/* Command-line options. */
static gboolean start_online = FALSE;
static gboolean start_offline = FALSE;
static gboolean setup_only = FALSE;
-static gboolean killev = FALSE;
+static gboolean force_shutdown = FALSE;
#ifdef DEVELOPMENT
static gboolean force_migrate = FALSE;
#endif
@@ -106,24 +102,12 @@ static gboolean disable_eplugin = FALSE;
static gboolean disable_preview = FALSE;
static gboolean idle_cb (gchar **uris);
-static char *default_component_id = NULL;
-static char *evolution_debug_log = NULL;
+static gchar *requested_view = NULL;
+static gchar *evolution_debug_log = NULL;
static gchar **remaining_args;
-static void
-no_windows_left_cb (EShell *shell, gpointer data)
-{
- bonobo_object_unref (BONOBO_OBJECT (shell));
- bonobo_main_quit ();
-}
-
-static void
-shell_weak_notify (void *data,
- GObject *where_the_object_was)
-{
- bonobo_main_quit ();
-}
-
+/* Defined in <e-shell.h> */
+extern EShell *default_shell;
#ifdef KILL_PROCESS_CMD
@@ -185,6 +169,36 @@ kill_old_dataserver (void)
}
#endif
+static void
+categories_icon_theme_hack (void)
+{
+ GtkIconTheme *icon_theme;
+ const gchar *category_name;
+ const gchar *filename;
+ gchar *dirname;
+
+ /* XXX Allow the category icons to be referenced as named
+ * icons, since GtkAction does not support GdkPixbufs. */
+
+ /* Get the icon file for some default category. Doesn't matter
+ * which, so long as it has an icon. We're just interested in
+ * the directory components. */
+ category_name = _("Birthday");
+ filename = e_categories_get_icon_file_for (category_name);
+ g_return_if_fail (filename != NULL && *filename != '\0');
+
+ /* Extract the directory components. */
+ dirname = g_path_get_dirname (filename);
+
+ /* Add it to the icon theme's search path. This relies on
+ * GtkIconTheme's legacy feature of using image files found
+ * directly in the search path. */
+ icon_theme = gtk_icon_theme_get_default ();
+ gtk_icon_theme_append_search_path (icon_theme, dirname);
+
+ g_free (dirname);
+}
+
#ifdef DEVELOPMENT
@@ -287,124 +301,35 @@ destroy_config (GConfClient *client)
#endif /* DEVELOPMENT */
-static void
-open_uris (GNOME_Evolution_Shell corba_shell, gchar **uris)
-{
- CORBA_Environment ev;
- guint n_uris, ii;
-
- g_return_if_fail (uris != NULL);
- n_uris = g_strv_length (uris);
-
- CORBA_exception_init (&ev);
-
- for (ii = 0; ii < n_uris; ii++) {
- GNOME_Evolution_Shell_handleURI (corba_shell, uris[ii], &ev);
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("Invalid URI: %s", uris[ii]);
- CORBA_exception_free (&ev);
- }
- }
-
- CORBA_exception_free (&ev);
-}
-
/* This is for doing stuff that requires the GTK+ loop to be running already. */
static gboolean
idle_cb (gchar **uris)
{
- GNOME_Evolution_Shell corba_shell;
- CORBA_Environment ev;
- EShellConstructResult result;
- EShellStartupLineMode startup_line_mode;
-
- g_return_val_if_fail (uris == NULL || g_strv_length (uris) > 0, FALSE);
+ EShell *shell;
#ifdef KILL_PROCESS_CMD
kill_old_dataserver ();
#endif
- CORBA_exception_init (&ev);
+ shell = e_shell_get_default ();
- if (! start_online && ! start_offline)
- startup_line_mode = E_SHELL_STARTUP_LINE_MODE_CONFIG;
- else if (start_online)
- startup_line_mode = E_SHELL_STARTUP_LINE_MODE_ONLINE;
+ /* These calls do the right thing when another Evolution
+ * process is running. */
+ if (uris != NULL && *uris != NULL)
+ e_shell_handle_uris (shell, uris);
else
- startup_line_mode = E_SHELL_STARTUP_LINE_MODE_OFFLINE;
-
- shell = e_shell_new (startup_line_mode, &result);
-
- switch (result) {
- case E_SHELL_CONSTRUCT_RESULT_OK:
- e_shell_set_crash_recovery (shell, e_file_lock_exists ());
- g_signal_connect (shell, "no_windows_left", G_CALLBACK (no_windows_left_cb), NULL);
- g_object_weak_ref (G_OBJECT (shell), shell_weak_notify, NULL);
- corba_shell = bonobo_object_corba_objref (BONOBO_OBJECT (shell));
- corba_shell = CORBA_Object_duplicate (corba_shell, &ev);
- break;
-
- case E_SHELL_CONSTRUCT_RESULT_CANNOTREGISTER:
- corba_shell = bonobo_activation_activate_from_id (
- (Bonobo_ActivationID) E_SHELL_OAFIID, 0, NULL, &ev);
- if (ev._major != CORBA_NO_EXCEPTION || corba_shell == CORBA_OBJECT_NIL) {
- e_error_run(NULL, "shell:noshell", NULL);
- CORBA_exception_free (&ev);
- bonobo_main_quit ();
- return FALSE;
- }
- break;
-
- default:
- e_error_run(NULL, "shell:noshell-reason",
- e_shell_construct_result_to_string(result), NULL);
- CORBA_exception_free (&ev);
- bonobo_main_quit ();
- return FALSE;
-
- }
-
- if (shell != NULL) {
- if (uris != NULL)
- open_uris (corba_shell, uris);
- else {
- e_file_lock_create ();
- e_shell_create_window (shell, default_component_id, NULL);
- }
- } else {
- CORBA_Environment ev;
-
- CORBA_exception_init (&ev);
- if (uris != NULL)
- open_uris (corba_shell, uris);
- else
- if (default_component_id == NULL)
- GNOME_Evolution_Shell_createNewWindow (corba_shell, "", &ev);
- else
- GNOME_Evolution_Shell_createNewWindow (corba_shell, default_component_id, &ev);
-
- CORBA_exception_free (&ev);
- }
-
- CORBA_Object_release (corba_shell, &ev);
-
- CORBA_exception_free (&ev);
+ e_shell_create_shell_window (shell, requested_view);
- 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 ();
- }
-
- /* 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 another Evolution process is running, we're done. */
+ if (unique_app_is_running (UNIQUE_APP (shell)))
+ gtk_main_quit ();
- if (!disable_eplugin) {
+ /* This must be done after EShell has loaded all the backends.
+ * For example the mail backend makes the global variable `session`
+ * which is being used by several EPlugins */
+ else if (uris == NULL && !disable_eplugin)
e_plugin_load_plugins_with_missing_symbols ();
- }
return FALSE;
}
@@ -466,27 +391,15 @@ setup_segv_redirect (void)
#define setup_segv_redirect() (void)0
#endif
-static gint
-gnome_master_client_save_yourself_cb (GnomeClient *client, GnomeSaveStyle save_style, gint shutdown, GnomeInteractStyle interact_style, gint fast, gpointer user_data)
-{
- return !shell || e_shell_can_quit (shell);
-}
-
-static void
-gnome_master_client_die_cb (GnomeClient *client)
-{
- e_shell_do_quit (shell);
-}
-
-static const GOptionEntry options[] = {
- { "component", 'c', 0, G_OPTION_ARG_STRING, &default_component_id,
+static GOptionEntry entries[] = {
+ { "component", 'c', 0, G_OPTION_ARG_STRING, &requested_view,
N_("Start Evolution activating the specified component"), NULL },
{ "offline", '\0', 0, G_OPTION_ARG_NONE, &start_offline,
N_("Start in offline mode"), NULL },
{ "online", '\0', 0, G_OPTION_ARG_NONE, &start_online,
N_("Start in online mode"), NULL },
#ifdef KILL_PROCESS_CMD
- { "force-shutdown", '\0', 0, G_OPTION_ARG_NONE, &killev,
+ { "force-shutdown", '\0', 0, G_OPTION_ARG_NONE, &force_shutdown,
N_("Forcibly shut down all Evolution components"), NULL },
#endif
#ifdef DEVELOPMENT
@@ -549,19 +462,178 @@ set_paths (void)
g_free (exe_folder_utf8);
g_free (components_folder_utf8);
- /* Set BONOBO_ACTIVATION_PATH */
- if (g_getenv ("BONOBO_ACTIVATION_PATH" ) == NULL) {
- path = g_build_filename (top_folder_utf8,
- "lib/bonobo/servers",
- NULL);
- if (!g_setenv ("BONOBO_ACTIVATION_PATH", path, TRUE))
- g_warning ("Could not set BONOBO_ACTIVATION_PATH");
- g_free (path);
- }
g_free (top_folder_utf8);
}
#endif
+static void
+shell_window_destroyed_cb (EShell *shell)
+{
+ if (e_shell_get_watched_windows (shell) == NULL)
+ gtk_main_quit ();
+}
+
+static gint
+master_client_save_yourself_cb (GnomeClient *client,
+ GnomeSaveStyle save_style,
+ gint shutdown,
+ GnomeInteractStyle interact_style,
+ gint fast,
+ gpointer user_data)
+{
+ EShell *shell = user_data;
+
+ return !e_shell_is_busy (shell);
+}
+
+static void
+master_client_die_cb (GnomeClient *client,
+ gpointer user_data)
+{
+ EShell *shell = user_data;
+
+ 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;
+ const gchar *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)
+{
+ EShell *shell;
+ GConfClient *conf_client;
+ GnomeClient *master_client;
+ gboolean online = TRUE;
+ gchar *startup_id;
+ GError *error = NULL;
+
+ conf_client = gconf_client_get_default ();
+ master_client = gnome_master_client ();
+
+ if (start_online)
+ online = TRUE;
+ else if (start_offline)
+ online = FALSE;
+ else {
+ const gchar *key;
+ gboolean value;
+
+ key = "/apps/evolution/shell/start_offline";
+ value = gconf_client_get_bool (conf_client, key, &error);
+ if (error == NULL)
+ online = !value;
+ else {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+ }
+
+ startup_id = pick_startup_id ();
+
+ shell = g_object_new (
+ E_TYPE_SHELL,
+ "name", "org.gnome.evolution",
+ "online", online,
+ "startup-id", startup_id,
+ NULL);
+
+ g_free (startup_id);
+
+ g_signal_connect (
+ shell, "window-destroyed",
+ G_CALLBACK (shell_window_destroyed_cb), NULL);
+
+ if (master_client != NULL) {
+ g_signal_connect (
+ master_client, "save_yourself",
+ G_CALLBACK (master_client_save_yourself_cb), shell);
+
+ g_signal_connect (
+ master_client, "die",
+ G_CALLBACK (master_client_die_cb), shell);
+ }
+
+ g_object_unref (conf_client);
+
+ default_shell = shell;
+}
+
int
main (int argc, char **argv)
{
@@ -573,10 +645,8 @@ main (int argc, char **argv)
#ifdef DEVELOPMENT
gboolean skip_warning_dialog;
#endif
- GnomeProgram *program;
- GnomeClient *master_client;
- GOptionContext *context;
- char *filename;
+ gchar *filename;
+ GError *error = NULL;
/* Make ElectricFence work. */
free (malloc (10));
@@ -585,21 +655,19 @@ main (int argc, char **argv)
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
- context = g_option_context_new (_("- The Evolution PIM and Email Client"));
-
- g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE);
-
- g_option_context_set_translation_domain(context, GETTEXT_PACKAGE);
-
#ifdef G_OS_WIN32
set_paths ();
#endif
- program = gnome_program_init (PACKAGE, VERSION, LIBGNOMEUI_MODULE, argc, argv,
- GNOME_PROGRAM_STANDARD_PROPERTIES,
- GNOME_PARAM_GOPTION_CONTEXT, context,
- GNOME_PARAM_HUMAN_READABLE_NAME, _("Evolution"),
- NULL);
+ gtk_init_with_args (
+ &argc, &argv,
+ _("- The Evolution PIM and Email Client"),
+ entries, GETTEXT_PACKAGE, &error);
+ if (error != NULL) {
+ g_printerr ("%s\n", error->message);
+ g_error_free (error);
+ exit (1);
+ }
#ifdef G_OS_WIN32
if (strcmp (gettext (""), "") == 0) {
@@ -613,15 +681,14 @@ main (int argc, char **argv)
}
#endif
if (start_online && start_offline) {
- fprintf (stderr, _("%s: --online and --offline cannot be used together.\n Use %s --help for more information.\n"),
+ g_printerr (_("%s: --online and --offline cannot be used together.\n Use %s --help for more information.\n"),
argv[0], argv[0]);
exit (1);
}
- if (killev) {
- filename = g_build_filename (EVOLUTION_TOOLSDIR,
- "killev",
- NULL);
+ if (force_shutdown) {
+ filename = g_build_filename (
+ EVOLUTION_TOOLSDIR, "killev", NULL);
execl (filename, "killev", NULL);
/* Not reached */
exit (0);
@@ -630,11 +697,10 @@ main (int argc, char **argv)
client = gconf_client_get_default ();
#ifdef DEVELOPMENT
-
- if (force_migrate) {
+ if (force_migrate)
destroy_config (client);
- }
#endif
+
if (disable_preview) {
gconf_client_set_bool (client, "/apps/evolution/mail/display/show_preview", FALSE, NULL);
gconf_client_set_bool (client, "/apps/evolution/mail/display/safe_list", TRUE, NULL);
@@ -656,34 +722,29 @@ main (int argc, char **argv)
g_warning ("Could not set up debugging output file.");
}
- master_client = gnome_master_client ();
-
- g_signal_connect (G_OBJECT (master_client), "save_yourself", G_CALLBACK (gnome_master_client_save_yourself_cb), NULL);
- g_signal_connect (G_OBJECT (master_client), "die", G_CALLBACK (gnome_master_client_die_cb), NULL);
-
glade_init ();
e_cursors_init ();
e_icon_factory_init ();
- e_passwords_init();
+ e_passwords_init ();
gtk_window_set_default_icon_name ("evolution");
if (setup_only)
exit (0);
+ categories_icon_theme_hack ();
gnome_sound_init ("localhost");
gtk_accel_map_load (e_get_accels_filename ());
if (!disable_eplugin) {
- e_plugin_register_type(e_plugin_lib_get_type());
- e_plugin_hook_register_type(es_menu_hook_get_type());
- e_plugin_hook_register_type(es_event_hook_get_type());
+ e_plugin_register_type (e_plugin_lib_get_type ());
+ e_plugin_hook_register_type (es_event_hook_get_type ());
#ifdef ENABLE_PROFILING
- e_plugin_hook_register_type(e_profile_event_hook_get_type());
+ e_plugin_hook_register_type (e_profile_event_hook_get_type ());
#endif
- e_plugin_hook_register_type(e_plugin_type_hook_get_type());
- e_plugin_hook_register_type(e_import_hook_get_type());
- e_plugin_hook_register_type(E_TYPE_PLUGIN_UI_HOOK);
+ e_plugin_hook_register_type (e_plugin_type_hook_get_type ());
+ e_plugin_hook_register_type (e_import_hook_get_type ());
+ e_plugin_hook_register_type (E_TYPE_PLUGIN_UI_HOOK);
e_plugin_load_plugins ();
}
@@ -701,18 +762,26 @@ main (int argc, char **argv)
#else
g_idle_add ((GSourceFunc) idle_cb, remaining_args);
#endif
+
g_object_unref (client);
- bonobo_main ();
+ create_default_shell ();
+
+ 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 ();
- g_object_unref (program);
gnome_sound_shutdown ();
e_cursors_shutdown ();
#ifdef G_OS_WIN32
link_shutdown ();
#endif
+
return 0;
}