diff options
Diffstat (limited to 'shell/main.c')
-rw-r--r-- | shell/main.c | 444 |
1 files changed, 257 insertions, 187 deletions
diff --git a/shell/main.c b/shell/main.c index 2abd30eec1..bf0a8c47c6 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 @@ -184,6 +168,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 @@ -286,123 +300,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 (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; + e_shell_create_shell_window (shell, requested_view); - 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 another Evolution process is running, we're done. */ + if (unique_app_is_running (UNIQUE_APP (shell))) + gtk_main_quit (); - } - - 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); - - 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 (!disable_eplugin) { + /* 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 */ + else if (uris == NULL && !disable_eplugin) e_plugin_load_plugins_with_missing_symbols (); - } return FALSE; } @@ -464,27 +390,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 @@ -547,19 +461,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; + 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) +{ + 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) { @@ -571,10 +644,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)); @@ -583,21 +654,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) { @@ -611,15 +680,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); @@ -628,11 +696,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); @@ -654,34 +721,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 (); } @@ -699,18 +761,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; } |