Commit b2c3f018 authored by Michael Natterer's avatar Michael Natterer 😴 Committed by Michael Natterer
Browse files

Cleaned up the exit process:

2002-12-05  Michael Natterer  <mitch@gimp.org>

	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.
parent bb7ff29e
2002-12-05 Michael Natterer <mitch@gimp.org>
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 <sven@gimp.org>
 
* app/core/gimpbrushpipe.c: use the same string as in
......
......@@ -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);
}
......
......@@ -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;
}
......
......@@ -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__ */
......@@ -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);
}
......
......@@ -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_class_init (GimpClass *klass);
static void gimp_init (Gimp *gimp);
static void gimp_dispose (GObject *object);
static void gimp_finalize (GObject *object);
static void gimp_dispose (GObject *object);
static void gimp_finalize (GObject *object);
static gsize gimp_get_memsize (GimpObject *object);
static gsize gimp_get_memsize (GimpObject *object);
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 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
......
......@@ -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);
......
......@@ -22,6 +22,7 @@
# NONE deprecated alias for VOID
# BOOL deprecated alias for BOOLEAN
BOOLEAN: BOOLEAN
BOOLEAN: OBJECT
BOOLEAN: POINTER
BOOLEAN: VOID
......
......@@ -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);
}
......
......@@ -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 ("<Toolbox>"));
gimp_item_factory_set_sensitive (item_factory, "/File/Quit", FALSE);
item_factory = GTK_ITEM_FACTORY (gimp_item_factory_from_path ("<Image>"));
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 ("<Toolbox>"));
gimp_item_factory_set_sensitive (item_factory, "/File/Quit", FALSE);
item_factory = GTK_ITEM_FACTORY (gimp_item_factory_from_path ("<Image>"));
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);
}