diff --git a/ChangeLog b/ChangeLog index 8ef789df63..1df523a4d9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2002-12-05 Michael Natterer + + Cleaned up the exit process: + + * app/core/gimp.[ch]: added an "exit" signal which carries a + "gboolean kill_it" parameter and has a boolean return value. + Added gimp_boolean_handled_accumulator() so the emission of "exit" + can be stopped by returning TRUE from a callback. Removed + gimp_shutdown() from the public API and made it "exit"'s default + implementation. Addec gimp_exit() to emit the signal. + + * app/core/gimpmarshal.list: added BOOLEAN__BOOLEAN marshaller. + + * app/gui/gui.[ch]: Replaced public functions gui_shutdown() and + gui_exit() by "exit" callbacks. g_signal_connect_after() the + latter so the shutdown order is correct. + + * app/app_procs.[ch]: removed app_exit() and connect to "exit". + Split the exit stuff into normal and connect_after callbacks as + above. + + * app/batch.c + * app/gui/file-commands.c + * tools/pdbgen/pdb/misc.pdb + * app/widgets/gimptoolbox.c: call gimp_exit() instead of + app_exit(). Don't #include "app_procs.h". + + * app/pdb/misc_cmds.c: regenerated. + 2002-12-05 Sven Neumann * app/core/gimpbrushpipe.c: use the same string as in diff --git a/app/actions/file-commands.c b/app/actions/file-commands.c index ee46f7ff8a..bd9bf56e3d 100644 --- a/app/actions/file-commands.c +++ b/app/actions/file-commands.c @@ -45,7 +45,6 @@ #include "file-open-dialog.h" #include "file-save-dialog.h" -#include "app_procs.h" #include "undo.h" #include "libgimp/gimpintl.h" @@ -286,7 +285,7 @@ file_quit_cmd_callback (GtkWidget *widget, gpointer data, guint action) { - app_exit (FALSE); + gimp_exit (GIMP (data), FALSE); } diff --git a/app/app_procs.c b/app/app_procs.c index 22d8f6f8de..fc4cdddf53 100644 --- a/app/app_procs.c +++ b/app/app_procs.c @@ -41,7 +41,6 @@ #include "config/gimprc.h" #include "core/gimp.h" -#include "core/gimpdatafactory.h" #include "core/gimpunits.h" #include "plug-in/plug-ins.h" @@ -49,8 +48,6 @@ #include "file/file-open.h" #include "file/file-utils.h" -#include "display/gimpdisplay-foreach.h" - #include "tools/tool_manager.h" #include "gui/gui.h" @@ -60,17 +57,19 @@ #include "appenv.h" #include "app_procs.h" #include "batch.h" -#include "undo.h" #include "libgimp/gimpintl.h" /* local prototypes */ -static void app_init_update_status (const gchar *text1, - const gchar *text2, - gdouble percentage); -static void app_exit_finish (void); +static void app_init_update_status (const gchar *text1, + const gchar *text2, + gdouble percentage); +static gboolean app_exit_callback (Gimp *gimp, + gboolean kill_it); +static gboolean app_exit_finish_callback (Gimp *gimp, + gboolean kill_it); /* gimprc debugging code, to be removed */ static void gimprc_notify_callback (GObject *object, @@ -189,6 +188,16 @@ app_init (gint gimp_argc, gui_restore (the_gimp, restore_session); } + /* connext our "exit" callbacks after gui_restore() so they are + * invoked after the GUI's "exit" callbacks + */ + g_signal_connect (G_OBJECT (the_gimp), "exit", + G_CALLBACK (app_exit_callback), + NULL); + g_signal_connect_after (G_OBJECT (the_gimp), "exit", + G_CALLBACK (app_exit_finish_callback), + NULL); + /* Parse the rest of the command line arguments as images to load */ if (gimp_argc > 0) @@ -233,16 +242,6 @@ app_init (gint gimp_argc, gimp_main_loop (the_gimp); } -void -app_exit (gboolean kill_it) -{ - /* If it's the user's perogative, and there are dirty images */ - if (! kill_it && gimp_displays_dirty (the_gimp) && ! no_interface) - gui_really_quit_dialog (G_CALLBACK (app_exit_finish)); - else - app_exit_finish (); -} - /* private functions */ @@ -257,26 +256,29 @@ app_init_update_status (const gchar *text1, } } -static void -app_exit_finish (void) +static gboolean +app_exit_callback (Gimp *gimp, + gboolean kill_it) { - if (! no_interface) - { - gui_shutdown (the_gimp); - } + g_print ("EXIT: app_exit_callback(%s)\n", + kill_it ? "TRUE" : "FALSE"); - plug_ins_exit (the_gimp); + plug_ins_exit (gimp); if (! no_interface) - { - tool_manager_exit (the_gimp); + tool_manager_exit (gimp); - gui_exit (the_gimp); - } + return FALSE; /* continue exiting */ +} - gimp_shutdown (the_gimp); +static gboolean +app_exit_finish_callback (Gimp *gimp, + gboolean kill_it) +{ + g_print ("EXIT: app_exit_finish_callback(%s)\n", + kill_it ? "TRUE" : "FALSE"); - g_object_unref (G_OBJECT (the_gimp)); + g_object_unref (G_OBJECT (gimp)); the_gimp = NULL; base_exit (); @@ -285,6 +287,8 @@ app_exit_finish (void) * that foo_main() was never called before we reach this point. --Sven */ exit (0); + + return FALSE; } diff --git a/app/app_procs.h b/app/app_procs.h index 6e43737613..7a2244aa29 100644 --- a/app/app_procs.h +++ b/app/app_procs.h @@ -29,9 +29,8 @@ extern Gimp *the_gimp; -void app_init (gint gimp_argc, - gchar **gimp_argv); -void app_exit (gboolean kill_it); +void app_init (gint gimp_argc, + gchar **gimp_argv); #endif /* __APP_PROCS_H__ */ diff --git a/app/batch.c b/app/batch.c index d91d292f37..ca12cb3faa 100644 --- a/app/batch.c +++ b/app/batch.c @@ -30,7 +30,8 @@ #include "core/core-types.h" -#include "app_procs.h" +#include "core/gimp.h" + #include "batch.h" #include "pdb/procedural_db.h" @@ -97,7 +98,7 @@ batch_init (Gimp *gimp, batch_run_cmd (gimp, batch_cmds[i]); if (read_from_stdin) - app_exit (FALSE); + gimp_exit (gimp, FALSE); } } @@ -112,7 +113,7 @@ batch_run_cmd (Gimp *gimp, if (g_ascii_strcasecmp (cmd, "(gimp-quit 0)") == 0) { - app_exit (FALSE); + gimp_exit (gimp, FALSE); exit (0); } diff --git a/app/core/gimp.c b/app/core/gimp.c index d4ddd2331f..a1548925af 100644 --- a/app/core/gimp.c +++ b/app/core/gimp.c @@ -54,6 +54,7 @@ #include "gimpimage-new.h" #include "gimpimagefile.h" #include "gimplist.h" +#include "gimpmarshal.h" #include "gimpmodules.h" #include "gimppalette.h" #include "gimppattern.h" @@ -64,24 +65,36 @@ #include "libgimp/gimpintl.h" -static void gimp_class_init (GimpClass *klass); -static void gimp_init (Gimp *gimp); +enum +{ + EXIT, + LAST_SIGNAL +}; -static void gimp_dispose (GObject *object); -static void gimp_finalize (GObject *object); -static gsize gimp_get_memsize (GimpObject *object); +static void gimp_class_init (GimpClass *klass); +static void gimp_init (Gimp *gimp); -static void gimp_global_config_notify (GObject *global_config, - GParamSpec *param_spec, - GObject *edit_config); -static void gimp_edit_config_notify (GObject *edit_config, - GParamSpec *param_spec, - GObject *global_config); +static void gimp_dispose (GObject *object); +static void gimp_finalize (GObject *object); + +static gsize gimp_get_memsize (GimpObject *object); + +static gboolean gimp_real_exit (Gimp *gimp, + gboolean kill_it); + +static void gimp_global_config_notify (GObject *global_config, + GParamSpec *param_spec, + GObject *edit_config); +static void gimp_edit_config_notify (GObject *edit_config, + GParamSpec *param_spec, + GObject *global_config); static GimpObjectClass *parent_class = NULL; +static guint gimp_signals[LAST_SIGNAL] = { 0, }; + GType gimp_get_type (void) @@ -111,6 +124,22 @@ gimp_get_type (void) return object_type; } +gboolean +gimp_boolean_handled_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer dummy) +{ + gboolean continue_emission; + gboolean signal_handled; + + signal_handled = g_value_get_boolean (handler_return); + g_value_set_boolean (return_accu, signal_handled); + continue_emission = ! signal_handled; + + return continue_emission; +} + static void gimp_class_init (GimpClass *klass) { @@ -122,10 +151,22 @@ gimp_class_init (GimpClass *klass) parent_class = g_type_class_peek_parent (klass); + gimp_signals[EXIT] = + g_signal_new ("exit", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GimpClass, exit), + gimp_boolean_handled_accumulator, NULL, + gimp_marshal_BOOLEAN__BOOLEAN, + G_TYPE_BOOLEAN, 1, + G_TYPE_BOOLEAN); + object_class->dispose = gimp_dispose; object_class->finalize = gimp_finalize; gimp_object_class->get_memsize = gimp_get_memsize; + + klass->exit = gimp_real_exit; } static void @@ -423,6 +464,25 @@ gimp_get_memsize (GimpObject *object) return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object); } +static gboolean +gimp_real_exit (Gimp *gimp, + gboolean kill_it) +{ + g_print ("EXIT: gimp_real_exit(%s)\n", + kill_it ? "TRUE" : "FALSE"); + + gimp_modules_unload (gimp); + gimp_data_factory_data_save (gimp->brush_factory); + gimp_data_factory_data_save (gimp->pattern_factory); + gimp_data_factory_data_save (gimp->gradient_factory); + gimp_data_factory_data_save (gimp->palette_factory); + gimp_documents_save (gimp); + gimp_parasiterc_save (gimp); + gimp_unitrc_save (gimp); + + return FALSE; /* continue exiting */ +} + Gimp * gimp_new (gboolean be_verbose, gboolean no_data, @@ -696,18 +756,16 @@ gimp_restore (Gimp *gimp, } void -gimp_shutdown (Gimp *gimp) +gimp_exit (Gimp *gimp, + gboolean kill_it) { + gboolean handled; + g_return_if_fail (GIMP_IS_GIMP (gimp)); - gimp_modules_unload (gimp); - gimp_data_factory_data_save (gimp->brush_factory); - gimp_data_factory_data_save (gimp->pattern_factory); - gimp_data_factory_data_save (gimp->gradient_factory); - gimp_data_factory_data_save (gimp->palette_factory); - gimp_documents_save (gimp); - gimp_parasiterc_save (gimp); - gimp_unitrc_save (gimp); + g_signal_emit (G_OBJECT (gimp), gimp_signals[EXIT], 0, + kill_it ? TRUE : FALSE, + &handled); } void diff --git a/app/core/gimp.h b/app/core/gimp.h index ff61fe5ab0..d371980bf4 100644 --- a/app/core/gimp.h +++ b/app/core/gimp.h @@ -136,6 +136,9 @@ struct _Gimp struct _GimpClass { GimpObjectClass parent_class; + + gboolean (* exit) (Gimp *gimp, + gboolean kill_it); }; @@ -149,14 +152,14 @@ Gimp * gimp_new (gboolean be_verbose, void gimp_set_config (Gimp *gimp, GimpCoreConfig *core_config); - void gimp_initialize (Gimp *gimp, GimpInitStatusFunc status_callback); - void gimp_restore (Gimp *gimp, GimpInitStatusFunc status_callback, gboolean no_data); -void gimp_shutdown (Gimp *gimp); + +void gimp_exit (Gimp *gimp, + gboolean kill_it); void gimp_main_loop (Gimp *gimp); void gimp_main_loop_quit (Gimp *gimp); diff --git a/app/core/gimpmarshal.list b/app/core/gimpmarshal.list index be6e644aae..4872cb8cc5 100644 --- a/app/core/gimpmarshal.list +++ b/app/core/gimpmarshal.list @@ -22,6 +22,7 @@ # NONE deprecated alias for VOID # BOOL deprecated alias for BOOLEAN +BOOLEAN: BOOLEAN BOOLEAN: OBJECT BOOLEAN: POINTER BOOLEAN: VOID diff --git a/app/gui/file-commands.c b/app/gui/file-commands.c index ee46f7ff8a..bd9bf56e3d 100644 --- a/app/gui/file-commands.c +++ b/app/gui/file-commands.c @@ -45,7 +45,6 @@ #include "file-open-dialog.h" #include "file-save-dialog.h" -#include "app_procs.h" #include "undo.h" #include "libgimp/gimpintl.h" @@ -286,7 +285,7 @@ file_quit_cmd_callback (GtkWidget *widget, gpointer data, guint action) { - app_exit (FALSE); + gimp_exit (GIMP (data), FALSE); } diff --git a/app/gui/gui.c b/app/gui/gui.c index 42740d5e67..8f5ed7add1 100644 --- a/app/gui/gui.c +++ b/app/gui/gui.c @@ -76,10 +76,14 @@ static void gui_themes_dir_foreach_func (GimpDatafileData *file_data static gint gui_rotate_the_shield_harmonics (GtkWidget *widget, GdkEvent *eevent, gpointer data); + +static gboolean gui_exit_callback (Gimp *gimp, + gboolean kill_it); +static gboolean gui_exit_finish_callback (Gimp *gimp, + gboolean kill_it); static void gui_really_quit_callback (GtkWidget *button, gboolean quit, gpointer data); - static void gui_show_tooltips_notify (GObject *config, GParamSpec *param_spec, Gimp *gimp); @@ -283,6 +287,13 @@ gui_restore (Gimp *gimp, session_restore (gimp); dialogs_show_toolbox (); + + g_signal_connect (G_OBJECT (gimp), "exit", + G_CALLBACK (gui_exit_callback), + NULL); + g_signal_connect_after (G_OBJECT (gimp), "exit", + G_CALLBACK (gui_exit_finish_callback), + NULL); } void @@ -297,50 +308,6 @@ gui_post_init (Gimp *gimp) } } -void -gui_shutdown (Gimp *gimp) -{ - g_return_if_fail (GIMP_IS_GIMP (gimp)); - - gimp->message_handler = GIMP_CONSOLE; - - session_save (gimp); - - if (GIMP_GUI_CONFIG (gimp->config)->save_device_status) - gimp_devices_save (gimp); - - gimp_displays_delete (gimp); -} - -void -gui_exit (Gimp *gimp) -{ - g_return_if_fail (GIMP_IS_GIMP (gimp)); - - menus_exit (gimp); - render_exit (gimp); - - dialogs_exit (gimp); - gimp_devices_exit (gimp); - - gimp_help_free (); - - g_signal_handlers_disconnect_by_func (G_OBJECT (gimp->config), - gui_show_tooltips_notify, - gimp); - - gimp_container_remove_handler (gimp->images, image_disconnect_handler_id); - image_disconnect_handler_id = 0; - - if (themes_hash) - { - g_hash_table_destroy (themes_hash); - themes_hash = NULL; - } - - g_type_class_unref (g_type_class_peek (GIMP_TYPE_COLOR_SELECT)); -} - void gui_get_screen_resolution (gdouble *xres, gdouble *yres) @@ -389,32 +356,6 @@ gui_get_screen_resolution (gdouble *xres, *yres = y; } -void -gui_really_quit_dialog (GCallback quit_func) -{ - GtkItemFactory *item_factory; - GtkWidget *dialog; - - item_factory = GTK_ITEM_FACTORY (gimp_item_factory_from_path ("")); - gimp_item_factory_set_sensitive (item_factory, "/File/Quit", FALSE); - - item_factory = GTK_ITEM_FACTORY (gimp_item_factory_from_path ("")); - gimp_item_factory_set_sensitive (item_factory, "/File/Quit", FALSE); - - dialog = gimp_query_boolean_box (_("Quit The GIMP?"), - gimp_standard_help_func, - "dialogs/really_quit.html", - GIMP_STOCK_WILBER_EEK, - _("Some files are unsaved.\n" - "\nReally quit The GIMP?"), - GTK_STOCK_QUIT, GTK_STOCK_CANCEL, - NULL, NULL, - gui_really_quit_callback, - quit_func); - - gtk_widget_show (dialog); -} - /* private functions */ @@ -561,18 +502,97 @@ gui_rotate_the_shield_harmonics (GtkWidget *widget, return FALSE; } +static gboolean +gui_exit_callback (Gimp *gimp, + gboolean kill_it) +{ + g_print ("EXIT: gui_exit_callback(%s)\n", + kill_it ? "TRUE" : "FALSE"); + + if (! kill_it && gimp_displays_dirty (gimp)) + { + GtkItemFactory *item_factory; + GtkWidget *dialog; + + item_factory = GTK_ITEM_FACTORY (gimp_item_factory_from_path ("")); + gimp_item_factory_set_sensitive (item_factory, "/File/Quit", FALSE); + + item_factory = GTK_ITEM_FACTORY (gimp_item_factory_from_path ("")); + gimp_item_factory_set_sensitive (item_factory, "/File/Quit", FALSE); + + dialog = gimp_query_boolean_box (_("Quit The GIMP?"), + gimp_standard_help_func, + "dialogs/really_quit.html", + GIMP_STOCK_WILBER_EEK, + _("Some files are unsaved.\n" + "\nReally quit The GIMP?"), + GTK_STOCK_QUIT, GTK_STOCK_CANCEL, + NULL, NULL, + gui_really_quit_callback, + gimp); + + gtk_widget_show (dialog); + + return TRUE; /* stop exit for now */ + } + + gimp->message_handler = GIMP_CONSOLE; + + session_save (gimp); + + if (GIMP_GUI_CONFIG (gimp->config)->save_device_status) + gimp_devices_save (gimp); + + gimp_displays_delete (gimp); + + return FALSE; /* continue exiting */ +} + +static gboolean +gui_exit_finish_callback (Gimp *gimp, + gboolean kill_it) +{ + g_print ("EXIT: gui_exit_finish_callback(%s)\n", + kill_it ? "TRUE" : "FALSE"); + + menus_exit (gimp); + render_exit (gimp); + + dialogs_exit (gimp); + gimp_devices_exit (gimp); + + gimp_help_free (); + + g_signal_handlers_disconnect_by_func (G_OBJECT (gimp->config), + gui_show_tooltips_notify, + gimp); + + gimp_container_remove_handler (gimp->images, image_disconnect_handler_id); + image_disconnect_handler_id = 0; + + if (themes_hash) + { + g_hash_table_destroy (themes_hash); + themes_hash = NULL; + } + + g_type_class_unref (g_type_class_peek (GIMP_TYPE_COLOR_SELECT)); + + return FALSE; /* continue exiting */ +} + static void gui_really_quit_callback (GtkWidget *button, gboolean quit, gpointer data) { - GCallback quit_func; + Gimp *gimp; - quit_func = G_CALLBACK (data); + gimp = GIMP (data); if (quit) { - (* quit_func) (); + gimp_exit (gimp, TRUE); } else { @@ -586,7 +606,6 @@ gui_really_quit_callback (GtkWidget *button, } } - static void gui_show_tooltips_notify (GObject *config, GParamSpec *param_spec, diff --git a/app/gui/gui.h b/app/gui/gui.h index 4a1c921c72..5e6e7874c1 100644 --- a/app/gui/gui.h +++ b/app/gui/gui.h @@ -33,13 +33,8 @@ void gui_restore (Gimp *gimp, gboolean restore_session); void gui_post_init (Gimp *gimp); -void gui_shutdown (Gimp *gimp); -void gui_exit (Gimp *gimp); - void gui_get_screen_resolution (gdouble *xres, gdouble *yres); -void gui_really_quit_dialog (GCallback quit_func); - #endif /* __GUI_H__ */ diff --git a/app/pdb/misc_cmds.c b/app/pdb/misc_cmds.c index 4daeb62e68..1970a23ce9 100644 --- a/app/pdb/misc_cmds.c +++ b/app/pdb/misc_cmds.c @@ -28,7 +28,7 @@ #include "pdb-types.h" #include "procedural_db.h" -#include "app_procs.h" +#include "core/gimp.h" #include "libgimpbase/gimpbase.h" @@ -87,7 +87,7 @@ quit_invoker (Gimp *gimp, kill_it = args[0].value.pdb_int ? TRUE : FALSE; - app_exit (kill_it); + gimp_exit (gimp, kill_it); return procedural_db_return_args (&quit_proc, TRUE); } diff --git a/app/widgets/gimptoolbox.c b/app/widgets/gimptoolbox.c index 48ce84e4e0..2ec984b145 100644 --- a/app/widgets/gimptoolbox.c +++ b/app/widgets/gimptoolbox.c @@ -46,8 +46,6 @@ #include "gimptoolbox-indicator-area.h" #include "gtkhwrapbox.h" -#include "app_procs.h" - #include "libgimp/gimpintl.h" @@ -216,7 +214,7 @@ static gboolean gimp_toolbox_delete_event (GtkWidget *widget, GdkEventAny *event) { - app_exit (FALSE); + gimp_exit (GIMP_DOCK (widget)->context->gimp, FALSE); return TRUE; } diff --git a/tools/pdbgen/pdb/misc.pdb b/tools/pdbgen/pdb/misc.pdb index c593bff3b0..7d2d1c14bd 100644 --- a/tools/pdbgen/pdb/misc.pdb +++ b/tools/pdbgen/pdb/misc.pdb @@ -56,8 +56,8 @@ HELP ); %invoke = ( - headers => [ qw("app_procs.h") ], - code => 'app_exit (kill_it);' + headers => [ qw("core/gimp.h") ], + code => 'gimp_exit (gimp, kill_it);' ); } @@ -67,4 +67,3 @@ HELP $desc = 'Miscellaneous'; 1; -