diff options
-rw-r--r-- | addressbook/gui/contact-editor/eab-editor.c | 11 | ||||
-rw-r--r-- | doc/reference/shell/tmpl/e-shell.sgml | 2 | ||||
-rw-r--r-- | glib-gen.mak | 42 | ||||
-rw-r--r-- | mail/e-mail-backend.c | 5 | ||||
-rw-r--r-- | shell/Makefile.am | 13 | ||||
-rw-r--r-- | shell/e-shell-window-actions.c | 2 | ||||
-rw-r--r-- | shell/e-shell.c | 116 | ||||
-rw-r--r-- | shell/e-shell.h | 33 | ||||
-rw-r--r-- | shell/main.c | 16 |
9 files changed, 170 insertions, 70 deletions
diff --git a/addressbook/gui/contact-editor/eab-editor.c b/addressbook/gui/contact-editor/eab-editor.c index 17ac1c391c..f53ecc30cd 100644 --- a/addressbook/gui/contact-editor/eab-editor.c +++ b/addressbook/gui/contact-editor/eab-editor.c @@ -57,11 +57,16 @@ static gpointer parent_class; static guint signals[LAST_SIGNAL]; static void -eab_editor_quit_requested_cb (EABEditor *editor, - EShell *shell) +eab_editor_quit_requested_cb (EShell *shell, + EShellQuitReason reason, + EABEditor *editor) { GtkWindow *window; + /* Quit immediately if another Evolution process asked us to. */ + if (reason == E_SHELL_QUIT_REMOTE_REQUEST) + return; + window = eab_editor_get_window (editor); eab_editor_raise (editor); @@ -78,7 +83,7 @@ eab_editor_set_shell (EABEditor *editor, editor->priv->shell = g_object_ref (shell); - g_signal_connect_swapped ( + g_signal_connect ( shell, "quit-requested", G_CALLBACK (eab_editor_quit_requested_cb), editor); } diff --git a/doc/reference/shell/tmpl/e-shell.sgml b/doc/reference/shell/tmpl/e-shell.sgml index 2287392fee..5505f3e03f 100644 --- a/doc/reference/shell/tmpl/e-shell.sgml +++ b/doc/reference/shell/tmpl/e-shell.sgml @@ -73,6 +73,7 @@ EShell </para> @eshell: the object which received the signal. +@Param2: <!-- ##### SIGNAL EShell::send-receive ##### --> <para> @@ -339,6 +340,7 @@ EShell </para> @shell: +@reason: @Returns: diff --git a/glib-gen.mak b/glib-gen.mak new file mode 100644 index 0000000000..7aae596e15 --- /dev/null +++ b/glib-gen.mak @@ -0,0 +1,42 @@ +# these are the variables your Makefile.am should set +# the example is based on the colorbalance interface + +#glib_enum_headers=$(colorbalance_headers) +#glib_enum_define=GST_COLOR_BALANCE +#glib_enum_prefix=gst_color_balance + +# these are all the rules generating the relevant files +%-marshal.h: %-marshal.list + glib-genmarshal --header --prefix=$(glib_enum_prefix)_marshal $^ > $*-marshal.h.tmp + mv $*-marshal.h.tmp $*-marshal.h + +%-marshal.c: %-marshal.list + echo "#include \"$*-marshal.h\"" >> $*-marshal.c.tmp + glib-genmarshal --body --prefix=$(glib_enum_prefix)_marshal $^ >> $*-marshal.c.tmp + mv $*-marshal.c.tmp $*-marshal.c + +%-enumtypes.h: $(glib_enum_headers) + glib-mkenums \ + --fhead "#ifndef __$(glib_enum_define)_ENUM_TYPES_H__\n#define __$(glib_enum_define)_ENUM_TYPES_H__\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \ + --fprod "/* enumerations from \"@filename@\" */\n" \ + --vhead "GType @enum_name@_get_type (void);\n#define E_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ + --ftail "G_END_DECLS\n\n#endif /* __$(glib_enum_define)_ENUM_TYPES_H__ */" \ + $^ > $@ + +%-enumtypes.c: $(glib_enum_headers) + @if test "x$(glib_enum_headers)" == "x"; then echo "ERROR: glib_enum_headers is empty, please fix Makefile"; exit 1; fi + glib-mkenums \ + --fhead "#include <$*.h>\n#include \"$*-enumtypes.h\"" \ + --fprod "\n/* enumerations from \"@filename@\" */" \ + --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \ + --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@VALUENAME@\" }," \ + --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \ + $^ > $@ + +# a hack rule to make sure .Plo files exist because they get include'd +# from Makefile's +.deps/%-marshal.Plo: + touch $@ + +.deps/%-enumtypes.Plo: + touch $@ diff --git a/mail/e-mail-backend.c b/mail/e-mail-backend.c index 7f62c466ad..a0453a963d 100644 --- a/mail/e-mail-backend.c +++ b/mail/e-mail-backend.c @@ -260,6 +260,7 @@ mail_backend_prepare_for_quit_cb (EShell *shell, static void mail_backend_quit_requested_cb (EShell *shell, + EShellQuitReason reason, EShellBackend *shell_backend) { CamelFolder *folder; @@ -272,6 +273,10 @@ mail_backend_quit_requested_cb (EShell *shell, if (!e_shell_get_online (shell)) return; + /* Or if another Evolution process asked us to. */ + if (reason == E_SHELL_QUIT_REMOTE_REQUEST) + return; + /* In express mode, don't raise mail request in non mail window. */ if (e_shell_get_express_mode(shell) && strcmp(e_shell_window_get_active_view((EShellWindow *)window), "mail") != 0) diff --git a/shell/Makefile.am b/shell/Makefile.am index 567059e0f1..2f044e420e 100644 --- a/shell/Makefile.am +++ b/shell/Makefile.am @@ -6,15 +6,23 @@ endif bin_PROGRAMS = evolution # Shell library -privsolib_LTLIBRARIES = libeshell.la +privsolib_LTLIBRARIES = libeshell.la eshellincludedir = $(privincludedir)/shell +include $(top_srcdir)/glib-gen.mak +glib_enum_headers=e-shell.h +glib_enum_define=E_SHELL +glib_enum_prefix=e_shell + +ENUM_GENERATED = e-shell-enumtypes.h e-shell-enumtypes.c + eshellinclude_HEADERS = \ e-shell.h \ e-shell-backend.h \ e-shell-common.h \ e-shell-content.h \ + e-shell-enumtypes.h \ e-shell-searchbar.h \ e-shell-settings.h \ e-shell-sidebar.h \ @@ -58,6 +66,7 @@ libeshell_la_SOURCES = \ e-shell.c \ e-shell-backend.c \ e-shell-content.c \ + e-shell-enumtypes.c \ e-shell-meego.c \ e-shell-meego.h \ e-shell-searchbar.c \ @@ -217,7 +226,7 @@ evolution.pure: evolution endif -BUILT_SOURCES = $(error_DATA) +BUILT_SOURCES = $(error_DATA) $(ENUM_GENERATED) CLEANFILES = $(BUILT_SOURCES) DISTCLEANFILES = $(schema_DATA) diff --git a/shell/e-shell-window-actions.c b/shell/e-shell-window-actions.c index 606f125f33..480b99da2b 100644 --- a/shell/e-shell-window-actions.c +++ b/shell/e-shell-window-actions.c @@ -1012,7 +1012,7 @@ action_quit_cb (GtkAction *action, EShell *shell; shell = e_shell_window_get_shell (shell_window); - e_shell_quit (shell); + e_shell_quit (shell, E_SHELL_QUIT_ACTION); } /** diff --git a/shell/e-shell.c b/shell/e-shell.c index f82931cec0..21bf16e0c8 100644 --- a/shell/e-shell.c +++ b/shell/e-shell.c @@ -38,6 +38,7 @@ #include "widgets/misc/e-preferences-window.h" #include "e-shell-backend.h" +#include "e-shell-enumtypes.h" #include "e-shell-window.h" #include "e-shell-utils.h" @@ -65,6 +66,7 @@ struct _EShellPrivate { gchar *startup_view; guint auto_reconnect : 1; + guint modules_loaded : 1; guint network_available : 1; guint online : 1; guint quit_cancelled : 1; @@ -145,7 +147,7 @@ shell_window_delete_event_cb (EShell *shell, return FALSE; /* Otherwise we initiate application quit. */ - e_shell_quit (shell); + e_shell_quit (shell, E_SHELL_QUIT_LAST_WINDOW); return TRUE; } @@ -311,15 +313,6 @@ shell_ready_for_quit (EShell *shell, /* Finalize the activity. */ g_object_ref (activity); - /* This handles a strange corner case where --quit is given on - * the command-line but no other Evolution process is running. - * We bring all the shell backends up and then immediately run - * the shutdown procedure, which gets us here. But because no - * windows have been shown yet, the usual "main loop ends when - * the last window is destroyed" trick won't work. */ - if (e_shell_get_watched_windows (shell) == NULL) - gtk_main_quit (); - /* Destroy all watched windows. Note, we iterate over a -copy- * of the watched windows list because the act of destroying a * watched window will modify the watched windows list, which @@ -362,7 +355,8 @@ shell_prepare_for_quit (EShell *shell) } static gboolean -shell_request_quit (EShell *shell) +shell_request_quit (EShell *shell, + EShellQuitReason reason) { /* Are preparations already in progress? */ if (shell->priv->preparing_for_quit != NULL) @@ -370,28 +364,11 @@ shell_request_quit (EShell *shell) /* Give the application a chance to cancel quit. */ shell->priv->quit_cancelled = FALSE; - g_signal_emit (shell, signals[QUIT_REQUESTED], 0); + g_signal_emit (shell, signals[QUIT_REQUESTED], 0, reason); return !shell->priv->quit_cancelled; } -static void -shell_load_modules (EShell *shell) -{ - const gchar *module_directory; - GList *modules = NULL; - - /* Load all shared library modules. */ - - module_directory = e_shell_get_module_directory (shell); - g_return_if_fail (module_directory != NULL); - - modules = e_module_load_all_in_directory (module_directory); - - g_list_foreach (modules, (GFunc) g_type_module_unuse, NULL); - g_list_free (modules); -} - /* Helper for shell_add_backend() */ static void shell_split_and_insert_items (GHashTable *hash_table, @@ -443,12 +420,13 @@ static void shell_sm_quit_requested_cb (EShell *shell, EggSMClient *sm_client) { + EShellQuitReason reason = E_SHELL_QUIT_SESSION_REQUEST; gboolean will_quit; /* If preparations are already in progress then we have already * committed ourselves to quitting, and can answer 'yes'. */ if (shell->priv->preparing_for_quit == NULL) - will_quit = shell_request_quit (shell); + will_quit = shell_request_quit (shell, reason); else will_quit = TRUE; @@ -675,34 +653,14 @@ shell_finalize (GObject *object) static void shell_constructed (GObject *object) { - EShellPrivate *priv; - GList *list; - - priv = E_SHELL_GET_PRIVATE (object); - /* The first EShell instance is the default. */ if (default_shell == NULL) { default_shell = object; g_object_add_weak_pointer (object, &default_shell); } - /* 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; - - e_file_lock_create (); - - shell_load_modules (E_SHELL (object)); - - /* Process shell backends. */ - list = g_list_sort ( - e_extensible_list_extensions ( - E_EXTENSIBLE (object), E_TYPE_SHELL_BACKEND), - (GCompareFunc) e_shell_backend_compare); - g_list_foreach (list, (GFunc) shell_process_backend, object); - priv->loaded_backends = list; + if (!unique_app_is_running (UNIQUE_APP (object))) + e_file_lock_create (); } static UniqueResponse @@ -753,7 +711,7 @@ shell_message_handle_close (EShell *shell, { UniqueResponse response; - if (e_shell_quit (shell)) + if (e_shell_quit (shell, E_SHELL_QUIT_REMOTE_REQUEST)) response = UNIQUE_RESPONSE_OK; else response = UNIQUE_RESPONSE_CANCEL; @@ -1070,6 +1028,7 @@ e_shell_class_init (EShellClass *class) /** * EShell::quit-requested * @shell: the #EShell which emitted the signal + * @reason: the reason for quitting * * Emitted when the user elects to quit the application, before * #EShell::prepare-for-quit. @@ -1086,8 +1045,9 @@ e_shell_class_init (EShellClass *class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (EShellClass, quit_requested), NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + g_cclosure_marshal_VOID__ENUM, + G_TYPE_NONE, 1, + E_TYPE_SHELL_QUIT_REASON); /** * EShell::send-receive @@ -1245,6 +1205,46 @@ e_shell_get_default (void) } /** + * e_shell_load_modules: + * @shell: an #EShell + * + * Loads all installed modules and performs some internal bookkeeping. + * This function should be called after creating the #EShell instance + * but before initiating migration or starting the main loop. + **/ +void +e_shell_load_modules (EShell *shell) +{ + const gchar *module_directory; + GList *list; + + g_return_if_fail (E_IS_SHELL (shell)); + + if (shell->priv->modules_loaded) + return; + + /* Load all shared library modules. */ + + module_directory = e_shell_get_module_directory (shell); + g_return_if_fail (module_directory != NULL); + + list = e_module_load_all_in_directory (module_directory); + g_list_foreach (list, (GFunc) g_type_module_unuse, NULL); + g_list_free (list); + + /* Process shell backends. */ + + list = g_list_sort ( + e_extensible_list_extensions ( + E_EXTENSIBLE (shell), E_TYPE_SHELL_BACKEND), + (GCompareFunc) e_shell_backend_compare); + g_list_foreach (list, (GFunc) shell_process_backend, shell); + shell->priv->loaded_backends = list; + + shell->priv->modules_loaded = TRUE; +} + +/** * e_shell_get_shell_backends: * @shell: an #EShell * @@ -1846,6 +1846,7 @@ e_shell_event (EShell *shell, /** * e_shell_quit: * @shell: an #EShell + * @reason: the reason for quitting * * Requests an application shutdown. This happens in two phases: the * first is synchronous, the second is asynchronous. @@ -1866,7 +1867,8 @@ e_shell_event (EShell *shell, * Returns: %TRUE if shutdown is underway, %FALSE if it was cancelled **/ gboolean -e_shell_quit (EShell *shell) +e_shell_quit (EShell *shell, + EShellQuitReason reason) { UniqueApp *app; UniqueResponse response; @@ -1878,7 +1880,7 @@ e_shell_quit (EShell *shell) if (unique_app_is_running (app)) goto unique; - if (!shell_request_quit (shell)) + if (!shell_request_quit (shell, reason)) return FALSE; shell_prepare_for_quit (shell); diff --git a/shell/e-shell.h b/shell/e-shell.h index f1d76b9ea6..6962ff6d0f 100644 --- a/shell/e-shell.h +++ b/shell/e-shell.h @@ -57,6 +57,32 @@ typedef struct _EShellClass EShellClass; typedef struct _EShellPrivate EShellPrivate; /** + * EShellQuitReason: + * + * @E_SHELL_QUIT_ACTION: + * @E_SHELL_WINDOW_ACTION_QUIT was activated. + * @E_SHELL_QUIT_LAST_WINDOW: + * The last watched window has been destroyed. + * @E_SHELL_QUIT_OPTION: + * The program was invoked with --quit. Extensions will never + * see this value because they are not loaded when --quit is given. + * @E_SHELL_QUIT_REMOTE_REQUEST: + * Another Evolution process requested we quit. + * @E_SHELL_QUIT_SESSION_REQUEST: + * The desktop session requested we quit. + * + * These values are passed in the #EShell::quit-requested signal to + * indicate why the shell is requesting to shut down. + **/ +typedef enum { + E_SHELL_QUIT_ACTION, + E_SHELL_QUIT_LAST_WINDOW, + E_SHELL_QUIT_OPTION, + E_SHELL_QUIT_REMOTE_REQUEST, + E_SHELL_QUIT_SESSION_REQUEST +} EShellQuitReason; + +/** * EShell: * * Contains only private data that should be read and manipulated using the @@ -78,7 +104,8 @@ struct _EShellClass { EActivity *activity); void (*prepare_for_quit) (EShell *shell, EActivity *activity); - void (*quit_requested) (EShell *shell); + void (*quit_requested) (EShell *shell, + EShellQuitReason reason); void (*send_receive) (EShell *shell, GtkWindow *parent); void (*window_created) (EShell *shell, @@ -88,6 +115,7 @@ struct _EShellClass { GType e_shell_get_type (void); EShell * e_shell_get_default (void); +void e_shell_load_modules (EShell *shell); GList * e_shell_get_shell_backends (EShell *shell); const gchar * e_shell_get_canonical_name (EShell *shell, const gchar *name); @@ -122,7 +150,8 @@ GtkWidget * e_shell_get_preferences_window (EShell *shell); void e_shell_event (EShell *shell, const gchar *event_name, gpointer event_data); -gboolean e_shell_quit (EShell *shell); +gboolean e_shell_quit (EShell *shell, + EShellQuitReason reason); void e_shell_cancel_quit (EShell *shell); void e_shell_adapt_window_size (EShell *shell, diff --git a/shell/main.c b/shell/main.c index cac04dd0bd..7e58d97aa6 100644 --- a/shell/main.c +++ b/shell/main.c @@ -232,9 +232,7 @@ idle_cb (gchar **uris) /* These calls do the right thing when another Evolution * process is running. */ - if (quit) - e_shell_quit (shell); - else if (uris != NULL && *uris != NULL) { + if (uris != NULL && *uris != NULL) { if (e_shell_handle_uris (shell, uris, import_uris) == 0) gtk_main_quit (); } else { @@ -578,6 +576,13 @@ main (gint argc, gchar **argv) shell = create_default_shell (); + if (quit) { + e_shell_quit (shell, E_SHELL_QUIT_OPTION); + goto exit; + } + + e_shell_load_modules (shell); + if (!disable_eplugin) { /* Register built-in plugin hook types. */ es_event_hook_get_type (); @@ -593,9 +598,9 @@ main (gint argc, gchar **argv) } if (requested_view) - e_shell_set_startup_view(shell, requested_view); + e_shell_set_startup_view (shell, requested_view); else if (express_mode) - e_shell_set_startup_view(shell, "mail"); + e_shell_set_startup_view (shell, "mail"); /* Attempt migration -after- loading all modules and plugins, * as both shell backends and certain plugins hook into this. */ @@ -608,6 +613,7 @@ main (gint argc, gchar **argv) gtk_main (); +exit: /* Drop what should be the last reference to the shell. * That will cause e_shell_get_default() to henceforth * return NULL. Use that to check for reference leaks. */ |