From 671267f44bdb0940ce0cd3f92a15c0da7daaf5f6 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 26 Nov 2017 14:55:15 +0000 Subject: [PATCH] GTK: system for not leaving stale network prompt dialogs. When I switch verify_ssh_host_key() and friends over to creating non-modal message boxes and returning to the main loop, there will be a risk that their parent window will need to close for some other reason while the user hasn't answered the pending question yet. (E.g. if the user presses the main session window's close button, which will no longer be a prohibited UI action once the transient dialog is not modal.) At that point we need to get rid of the pending dialog box, both for UI purposes (it would look silly and be confusing to leave it lying around) and for memory management (if the user subsequently clicks OK in such a dialog it would probably try to leave its result somewhere stale). So now there's a mechanism for gtkwin.c remembering what the current 'network prompt dialog' is, if any (in which category I intend to include everything triggered from ssh.c's various reasons for asking crypto-related questions), and cleaning it up when the struct gui_data it belongs to goes away. --- unix/gtkwin.c | 25 ++++++++++++++++++++++++- unix/unix.h | 6 +++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/unix/gtkwin.c b/unix/gtkwin.c index 88b438a5..00e07485 100644 --- a/unix/gtkwin.c +++ b/unix/gtkwin.c @@ -131,6 +131,7 @@ struct gui_data { void *eventlogstuff; guint32 input_event_time; /* Timestamp of the most recent input event. */ GtkWidget *reconfigure_dialog; + GtkWidget *network_prompt_dialog; #if GTK_CHECK_VERSION(3,4,0) gdouble cumulative_scroll; #endif @@ -301,12 +302,30 @@ static Mouse_Button translate_button(Mouse_Button button) * Return the top-level GtkWindow associated with a particular * front end instance. */ -void *get_window(void *frontend) +GtkWidget *get_window(void *frontend) { struct gui_data *inst = (struct gui_data *)frontend; return inst->window; } +/* + * Set and clear a pointer to a dialog box created as a result of the + * network code wanting to ask an asynchronous user question (e.g. + * 'what about this dodgy host key, then?'). + */ +void register_network_prompt_dialog(void *frontend, GtkWidget *dialog) +{ + struct gui_data *inst = (struct gui_data *)frontend; + assert(!inst->network_prompt_dialog); + inst->network_prompt_dialog = dialog; +} +void unregister_network_prompt_dialog(void *frontend) +{ + struct gui_data *inst = (struct gui_data *)frontend; + assert(inst->network_prompt_dialog); + inst->network_prompt_dialog = NULL; +} + /* * Minimise or restore the window in response to a server-side * request. @@ -2025,6 +2044,10 @@ static void delete_inst(struct gui_data *inst) gtk_widget_destroy(inst->reconfigure_dialog); inst->reconfigure_dialog = NULL; } + if (inst->network_prompt_dialog) { + gtk_widget_destroy(inst->network_prompt_dialog); + inst->network_prompt_dialog = NULL; + } if (inst->window) { gtk_widget_destroy(inst->window); inst->window = NULL; diff --git a/unix/unix.h b/unix/unix.h index a9bd71f4..979fe448 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -147,7 +147,11 @@ int font_dimension(void *frontend, int which);/* 0 for width, 1 for height */ long get_windowid(void *frontend); /* Things gtkdlg.c needs from pterm.c */ -void *get_window(void *frontend); /* void * to avoid depending on gtk.h */ +#ifdef MAY_REFER_TO_GTK_IN_HEADERS +GtkWidget *get_window(void *frontend); +void register_network_prompt_dialog(void *frontend, GtkWidget *dialog); +void unregister_network_prompt_dialog(void *frontend); +#endif void post_main(void); /* called after any subsidiary gtk_main() */ /* Things pterm.c needs from gtkdlg.c */