From 3e24bb610d970255ffcf99597021f5913d5d7cc6 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 26 Nov 2017 19:59:24 +0000 Subject: [PATCH] Make connection_fatal() nonmodal. This change requires me to break up the general cleanups in delete_inst() into two halves: one runs when the error message box is created, and cleans up the network connection and all the stuff associated with it, and the other runs when the error message is dismissed and the window can actually close. --- unix/gtkdlg.c | 7 ----- unix/gtkwin.c | 83 ++++++++++++++++++++++++++++++++++++--------------- unix/unix.h | 2 +- 3 files changed, 60 insertions(+), 32 deletions(-) diff --git a/unix/gtkdlg.c b/unix/gtkdlg.c index 1b9b8d42..a8143ef5 100644 --- a/unix/gtkdlg.c +++ b/unix/gtkdlg.c @@ -3691,13 +3691,6 @@ void old_keyfile_warning(void) */ } -void fatal_message_box(void *window, const char *msg) -{ - message_box(window, "PuTTY Fatal Error", msg, - string_width("REASONABLY LONG LINE OF TEXT FOR BASIC SANITY"), - FALSE, &buttons_ok); -} - void nonfatal_message_box(void *window, const char *msg) { char *title = dupcat(appname, " Error", NULL); diff --git a/unix/gtkwin.c b/unix/gtkwin.c index e8bc2894..a4c70475 100644 --- a/unix/gtkwin.c +++ b/unix/gtkwin.c @@ -167,6 +167,38 @@ static int send_raw_mouse; static void start_backend(struct gui_data *inst); static void exit_callback(void *vinst); +static void destroy_inst_connection(struct gui_data *inst); +static void delete_inst(struct gui_data *inst); + +static void post_fatal_message_box_toplevel(void *vctx) +{ + struct gui_data *inst = (struct gui_data *)vctx; + gtk_widget_destroy(inst->window); +} + +static void post_fatal_message_box(void *vctx, int result) +{ + struct gui_data *inst = (struct gui_data *)vctx; + unregister_dialog(inst, DIALOG_SLOT_CONNECTION_FATAL); + queue_toplevel_callback(post_fatal_message_box_toplevel, inst); +} + +void fatal_message_box(struct gui_data *inst, const char *msg) +{ + char *title = dupcat(appname, " Fatal Error", NULL); + GtkWidget *dialog = create_message_box( + inst->window, title, msg, + string_width("REASONABLY LONG LINE OF TEXT FOR BASIC SANITY"), + FALSE, &buttons_ok, post_fatal_message_box, inst); + register_dialog(inst, DIALOG_SLOT_CONNECTION_FATAL, dialog); + sfree(title); +} + +static void connection_fatal_callback(void *vinst) +{ + struct gui_data *inst = (struct gui_data *)vinst; + destroy_inst_connection(inst); +} void connection_fatal(void *frontend, const char *p, ...) { @@ -177,10 +209,11 @@ void connection_fatal(void *frontend, const char *p, ...) va_start(ap, p); msg = dupvprintf(p, ap); va_end(ap); - fatal_message_box(inst->window, msg); + fatal_message_box(inst, msg); sfree(msg); - queue_toplevel_callback(exit_callback, inst); + inst->exited = TRUE; /* suppress normal exit handling */ + queue_toplevel_callback(connection_fatal_callback, frontend); } /* @@ -2062,19 +2095,9 @@ static void exit_callback(void *vinst) if (!inst->exited && (exitcode = inst->back->exitcode(inst->backhandle)) >= 0) { - inst->exited = TRUE; - close_on_exit = conf_get_int(inst->conf, CONF_close_on_exit); - if (inst->ldisc) { - ldisc_free(inst->ldisc); - inst->ldisc = NULL; - } - inst->back->free(inst->backhandle); - inst->backhandle = NULL; - inst->back = NULL; - term_provide_resize_fn(inst->term, NULL, NULL); - update_specials_menu(inst); - gtk_widget_set_sensitive(inst->restartitem, TRUE); + destroy_inst_connection(inst); + close_on_exit = conf_get_int(inst->conf, CONF_close_on_exit); if (close_on_exit == FORCE_ON || (close_on_exit == AUTO && exitcode == 0)) { gtk_widget_destroy(inst->window); @@ -2089,6 +2112,26 @@ void notify_remote_exit(void *frontend) queue_toplevel_callback(exit_callback, inst); } +static void destroy_inst_connection(struct gui_data *inst) +{ + inst->exited = TRUE; + if (inst->ldisc) { + ldisc_free(inst->ldisc); + inst->ldisc = NULL; + } + if (inst->backhandle) { + inst->back->free(inst->backhandle); + inst->backhandle = NULL; + inst->back = NULL; + } + if (inst->term) + term_provide_resize_fn(inst->term, NULL, NULL); + if (inst->menu) { + update_specials_menu(inst); + gtk_widget_set_sensitive(inst->restartitem, TRUE); + } +} + static void delete_inst(struct gui_data *inst) { int dialog_slot; @@ -2106,19 +2149,11 @@ static void delete_inst(struct gui_data *inst) gtk_widget_destroy(inst->menu); inst->menu = NULL; } - if (inst->backhandle) { - inst->back->free(inst->backhandle); - inst->backhandle = NULL; - inst->back = NULL; - } + destroy_inst_connection(inst); if (inst->term) { term_free(inst->term); inst->term = NULL; } - if (inst->ldisc) { - ldisc_free(inst->ldisc); - inst->ldisc = NULL; - } if (inst->conf) { conf_free(inst->conf); inst->conf = NULL; @@ -4517,7 +4552,7 @@ static void start_backend(struct gui_data *inst) char *msg = dupprintf("Unable to open connection to %s:\n%s", conf_dest(inst->conf), error); inst->exited = TRUE; - fatal_message_box(inst->window, msg); + fatal_message_box(inst, msg); sfree(msg); exit(0); } diff --git a/unix/unix.h b/unix/unix.h index 893f084e..cc9e71d8 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -155,6 +155,7 @@ enum DialogSlot { DIALOG_SLOT_NETWORK_PROMPT, DIALOG_SLOT_LOGFILE_PROMPT, DIALOG_SLOT_WARN_ON_CLOSE, + DIALOG_SLOT_CONNECTION_FATAL, DIALOG_SLOT_LIMIT /* must remain last */ }; void register_dialog(void *frontend, enum DialogSlot slot, GtkWidget *dialog); @@ -168,7 +169,6 @@ GtkWidget *create_config_box(const char *title, Conf *conf, int midsession, int protcfginfo, post_dialog_fn_t after, void *afterctx); #endif -void fatal_message_box(void *window, const char *msg); void nonfatal_message_box(void *window, const char *msg); void about_box(void *window); void *eventlogstuff_new(void);