1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-02-09 16:36:34 +00:00

Make the configuration dialog non-modal.

Now every call to do_config_box is replaced with a call to
create_config_box, which returns immediately having constructed the
new GTK window object, and is passed a callback function which it will
arrange to be called when the dialog terminates (whether by OK or by
Cancel). That callback is now what triggers the construction of a
session window after 'Open' is pressed in the initial config box, or
the actual mid-session reconfiguration action after 'Apply' is pressed
in a Change Settings box.

We were already prepared to ignore the re-selection of 'Change
Settings' from the context menu of a window that already had a Change
Settings box open (and not accidentally create a second config box for
the same window); but now we do slightly better, by finding the
existing config box and un-minimising and raising it, in case the user
had forgotten it was there.

That's a useful featurelet, but not the main purpose of this change.
The mani point, of course, is that now the multi-window GtkApplication
based front ends now don't do anything confusing to the nesting of
gtk_main() when config boxes are involved. Whether you're changing the
settings of one (or more than one) of your already-running sessions,
preparing to start up a new PuTTY connection, or both at once, we stay
in the same top-level instance of gtk_main() and all sessions' top-
level callbacks continue to run sensibly.
This commit is contained in:
Simon Tatham 2017-11-26 11:58:02 +00:00
parent 94a2904ab6
commit 817e4ad2dd
7 changed files with 217 additions and 105 deletions

View File

@ -142,6 +142,7 @@ GtkWidget *make_gtk_toplevel_window(void *frontend) { return NULL; }
void launch_duplicate_session(Conf *conf) {} void launch_duplicate_session(Conf *conf) {}
void launch_new_session(void) {} void launch_new_session(void) {}
void launch_saved_session(const char *str) {} void launch_saved_session(const char *str) {}
void session_window_closed(void) {}
#else /* GTK_CHECK_VERSION(3,0,0) */ #else /* GTK_CHECK_VERSION(3,0,0) */
static void startup(GApplication *app, gpointer user_data) static void startup(GApplication *app, gpointer user_data)
@ -190,8 +191,6 @@ GtkWidget *make_gtk_toplevel_window(void *frontend)
return win; return win;
} }
extern int cfgbox(Conf *conf);
void launch_duplicate_session(Conf *conf) void launch_duplicate_session(Conf *conf)
{ {
extern const int dup_check_launchable; extern const int dup_check_launchable;
@ -199,12 +198,20 @@ void launch_duplicate_session(Conf *conf)
new_session_window(conf_copy(conf), NULL); new_session_window(conf_copy(conf), NULL);
} }
void launch_new_session(void) void session_window_closed(void)
{ {
Conf *conf = conf_new(); g_application_release(G_APPLICATION(app));
do_defaults(NULL, conf); }
if (conf_launchable(conf) || cfgbox(conf)) {
static void post_initial_config_box(void *vctx, int result)
{
Conf *conf = (Conf *)vctx;
if (result) {
new_session_window(conf, NULL); new_session_window(conf, NULL);
} else {
conf_free(conf);
g_application_release(G_APPLICATION(app));
} }
} }
@ -212,11 +219,23 @@ void launch_saved_session(const char *str)
{ {
Conf *conf = conf_new(); Conf *conf = conf_new();
do_defaults(str, conf); do_defaults(str, conf);
if (conf_launchable(conf) || cfgbox(conf)) {
g_application_hold(G_APPLICATION(app));
if (!conf_launchable(conf)) {
initial_config_box(conf, post_initial_config_box, conf);
} else {
new_session_window(conf, NULL); new_session_window(conf, NULL);
} }
} }
void launch_new_session(void)
{
/* Same as launch_saved_session except that we pass NULL to
* do_defaults. */
launch_saved_session(NULL);
}
void new_app_win(GtkApplication *app) void new_app_win(GtkApplication *app)
{ {
launch_new_session(); launch_new_session();

View File

@ -92,7 +92,10 @@ struct dlgparam {
int nselparams; int nselparams;
struct selparam *selparams; struct selparam *selparams;
#endif #endif
struct controlbox *ctrlbox;
int retval; int retval;
post_dialog_fn_t after;
void *afterctx;
}; };
#define FLAG_UPDATING_COMBO_LIST 1 #define FLAG_UPDATING_COMBO_LIST 1
#define FLAG_UPDATING_LISTBOX 2 #define FLAG_UPDATING_LISTBOX 2
@ -143,6 +146,7 @@ static void coloursel_ok(GtkButton *button, gpointer data);
static void coloursel_cancel(GtkButton *button, gpointer data); static void coloursel_cancel(GtkButton *button, gpointer data);
#endif #endif
static void window_destroy(GtkWidget *widget, gpointer data); static void window_destroy(GtkWidget *widget, gpointer data);
static void dlgparam_destroy(GtkWidget *widget, gpointer data);
int get_listitemheight(GtkWidget *widget); int get_listitemheight(GtkWidget *widget);
static int uctrl_cmp_byctrl(void *av, void *bv) static int uctrl_cmp_byctrl(void *av, void *bv)
@ -2958,13 +2962,13 @@ void treeview_map_event(GtkWidget *tree, gpointer data)
} }
#endif #endif
int do_config_box(const char *title, Conf *conf, int midsession, GtkWidget *create_config_box(const char *title, Conf *conf,
int protcfginfo) int midsession, int protcfginfo,
post_dialog_fn_t after, void *afterctx)
{ {
GtkWidget *window, *hbox, *vbox, *cols, *label, GtkWidget *window, *hbox, *vbox, *cols, *label,
*tree, *treescroll, *panels, *panelvbox; *tree, *treescroll, *panels, *panelvbox;
int index, level, protocol; int index, level, protocol;
struct controlbox *ctrlbox;
char *path; char *path;
#if GTK_CHECK_VERSION(2,0,0) #if GTK_CHECK_VERSION(2,0,0)
GtkTreeStore *treestore; GtkTreeStore *treestore;
@ -2976,13 +2980,17 @@ int do_config_box(const char *title, Conf *conf, int midsession,
GtkTreeItem *treeitemlevels[8]; GtkTreeItem *treeitemlevels[8];
GtkTree *treelevels[8]; GtkTree *treelevels[8];
#endif #endif
struct dlgparam dp; struct dlgparam *dp;
struct Shortcuts scs; struct Shortcuts scs;
struct selparam *selparams = NULL; struct selparam *selparams = NULL;
int nselparams = 0, selparamsize = 0; int nselparams = 0, selparamsize = 0;
dlg_init(&dp); dp = snew(struct dlgparam);
dp->after = after;
dp->afterctx = afterctx;
dlg_init(dp);
for (index = 0; index < lenof(scs.sc); index++) { for (index = 0; index < lenof(scs.sc); index++) {
scs.sc[index].action = SHORTCUT_EMPTY; scs.sc[index].action = SHORTCUT_EMPTY;
@ -2990,11 +2998,11 @@ int do_config_box(const char *title, Conf *conf, int midsession,
window = our_dialog_new(); window = our_dialog_new();
ctrlbox = ctrl_new_box(); dp->ctrlbox = ctrl_new_box();
protocol = conf_get_int(conf, CONF_protocol); protocol = conf_get_int(conf, CONF_protocol);
setup_config_box(ctrlbox, midsession, protocol, protcfginfo); setup_config_box(dp->ctrlbox, midsession, protocol, protcfginfo);
unix_setup_config_box(ctrlbox, midsession, protocol); unix_setup_config_box(dp->ctrlbox, midsession, protocol);
gtk_setup_config_box(ctrlbox, midsession, window); gtk_setup_config_box(dp->ctrlbox, midsession, window);
gtk_window_set_title(GTK_WINDOW(window), title); gtk_window_set_title(GTK_WINDOW(window), title);
hbox = gtk_hbox_new(FALSE, 4); hbox = gtk_hbox_new(FALSE, 4);
@ -3028,11 +3036,10 @@ int do_config_box(const char *title, Conf *conf, int midsession,
tree = gtk_tree_new(); tree = gtk_tree_new();
gtk_tree_set_view_mode(GTK_TREE(tree), GTK_TREE_VIEW_ITEM); gtk_tree_set_view_mode(GTK_TREE(tree), GTK_TREE_VIEW_ITEM);
gtk_tree_set_selection_mode(GTK_TREE(tree), GTK_SELECTION_BROWSE); gtk_tree_set_selection_mode(GTK_TREE(tree), GTK_SELECTION_BROWSE);
g_signal_connect(G_OBJECT(tree), "focus", g_signal_connect(G_OBJECT(tree), "focus", G_CALLBACK(tree_focus), dp);
G_CALLBACK(tree_focus), &dp);
#endif #endif
g_signal_connect(G_OBJECT(tree), "focus_in_event", g_signal_connect(G_OBJECT(tree), "focus_in_event",
G_CALLBACK(widget_focus), &dp); G_CALLBACK(widget_focus), dp);
shortcut_add(&scs, label, 'g', SHORTCUT_TREE, tree); shortcut_add(&scs, label, 'g', SHORTCUT_TREE, tree);
gtk_widget_show(treescroll); gtk_widget_show(treescroll);
gtk_box_pack_start(GTK_BOX(vbox), treescroll, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), treescroll, TRUE, TRUE, 0);
@ -3045,12 +3052,12 @@ int do_config_box(const char *title, Conf *conf, int midsession,
panelvbox = NULL; panelvbox = NULL;
path = NULL; path = NULL;
level = 0; level = 0;
for (index = 0; index < ctrlbox->nctrlsets; index++) { for (index = 0; index < dp->ctrlbox->nctrlsets; index++) {
struct controlset *s = ctrlbox->ctrlsets[index]; struct controlset *s = dp->ctrlbox->ctrlsets[index];
GtkWidget *w; GtkWidget *w;
if (!*s->pathname) { if (!*s->pathname) {
w = layout_ctrls(&dp, &scs, s, GTK_WINDOW(window)); w = layout_ctrls(dp, &scs, s, GTK_WINDOW(window));
our_dialog_set_action_area(GTK_WINDOW(window), w); our_dialog_set_action_area(GTK_WINDOW(window), w);
} else { } else {
@ -3104,7 +3111,7 @@ int do_config_box(const char *title, Conf *conf, int midsession,
selparams = sresize(selparams, selparamsize, selparams = sresize(selparams, selparamsize,
struct selparam); struct selparam);
} }
selparams[nselparams].dp = &dp; selparams[nselparams].dp = dp;
selparams[nselparams].panels = GTK_NOTEBOOK(panels); selparams[nselparams].panels = GTK_NOTEBOOK(panels);
selparams[nselparams].panel = panelvbox; selparams[nselparams].panel = panelvbox;
selparams[nselparams].shortcuts = scs; /* structure copy */ selparams[nselparams].shortcuts = scs; /* structure copy */
@ -3164,9 +3171,9 @@ int do_config_box(const char *title, Conf *conf, int midsession,
treelevels[j] = NULL; treelevels[j] = NULL;
g_signal_connect(G_OBJECT(treeitem), "key_press_event", g_signal_connect(G_OBJECT(treeitem), "key_press_event",
G_CALLBACK(tree_key_press), &dp); G_CALLBACK(tree_key_press), dp);
g_signal_connect(G_OBJECT(treeitem), "focus_in_event", g_signal_connect(G_OBJECT(treeitem), "focus_in_event",
G_CALLBACK(widget_focus), &dp); G_CALLBACK(widget_focus), dp);
gtk_widget_show(treeitem); gtk_widget_show(treeitem);
@ -3179,7 +3186,7 @@ int do_config_box(const char *title, Conf *conf, int midsession,
nselparams++; nselparams++;
} }
w = layout_ctrls(&dp, &selparams[nselparams-1].shortcuts, s, NULL); w = layout_ctrls(dp, &selparams[nselparams-1].shortcuts, s, NULL);
gtk_box_pack_start(GTK_BOX(panelvbox), w, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(panelvbox), w, FALSE, FALSE, 0);
gtk_widget_show(w); gtk_widget_show(w);
} }
@ -3201,8 +3208,8 @@ int do_config_box(const char *title, Conf *conf, int midsession,
* enough to have all branches expanded without further resizing. * enough to have all branches expanded without further resizing.
*/ */
dp.nselparams = nselparams; dp->nselparams = nselparams;
dp.selparams = selparams; dp->selparams = selparams;
#if !GTK_CHECK_VERSION(3,0,0) #if !GTK_CHECK_VERSION(3,0,0)
{ {
@ -3211,7 +3218,7 @@ int do_config_box(const char *title, Conf *conf, int midsession,
*/ */
GtkRequisition req; GtkRequisition req;
gtk_widget_size_request(tree, &req); gtk_widget_size_request(tree, &req);
initial_treeview_collapse(&dp, tree); initial_treeview_collapse(dp, tree);
gtk_widget_set_size_request(tree, req.width, -1); gtk_widget_set_size_request(tree, req.width, -1);
} }
#else #else
@ -3220,7 +3227,7 @@ int do_config_box(const char *title, Conf *conf, int midsession,
* mapped, because the size computation won't have been done yet. * mapped, because the size computation won't have been done yet.
*/ */
g_signal_connect(G_OBJECT(tree), "map", g_signal_connect(G_OBJECT(tree), "map",
G_CALLBACK(treeview_map_event), &dp); G_CALLBACK(treeview_map_event), dp);
#endif /* GTK 2 vs 3 */ #endif /* GTK 2 vs 3 */
#endif /* GTK 2+ vs 1 */ #endif /* GTK 2+ vs 1 */
@ -3228,26 +3235,26 @@ int do_config_box(const char *title, Conf *conf, int midsession,
g_signal_connect(G_OBJECT(treeselection), "changed", g_signal_connect(G_OBJECT(treeselection), "changed",
G_CALLBACK(treeselection_changed), selparams); G_CALLBACK(treeselection_changed), selparams);
#else #else
dp.ntreeitems = nselparams; dp->ntreeitems = nselparams;
dp.treeitems = snewn(dp.ntreeitems, GtkWidget *); dp->treeitems = snewn(dp->ntreeitems, GtkWidget *);
for (index = 0; index < nselparams; index++) { for (index = 0; index < nselparams; index++) {
g_signal_connect(G_OBJECT(selparams[index].treeitem), "select", g_signal_connect(G_OBJECT(selparams[index].treeitem), "select",
G_CALLBACK(treeitem_sel), G_CALLBACK(treeitem_sel),
&selparams[index]); &selparams[index]);
dp.treeitems[index] = selparams[index].treeitem; dp->treeitems[index] = selparams[index].treeitem;
} }
#endif #endif
dp.data = conf; dp->data = conf;
dlg_refresh(NULL, &dp); dlg_refresh(NULL, dp);
dp.shortcuts = &selparams[0].shortcuts; dp->shortcuts = &selparams[0].shortcuts;
#if !GTK_CHECK_VERSION(2,0,0) #if !GTK_CHECK_VERSION(2,0,0)
dp.currtreeitem = dp.treeitems[0]; dp->currtreeitem = dp->treeitems[0];
#endif #endif
dp.lastfocus = NULL; dp->lastfocus = NULL;
dp.retval = 0; dp->retval = -1;
dp.window = window; dp->window = window;
{ {
/* in gtkwin.c */ /* in gtkwin.c */
@ -3274,8 +3281,8 @@ int do_config_box(const char *title, Conf *conf, int midsession,
/* /*
* Set focus into the first available control. * Set focus into the first available control.
*/ */
for (index = 0; index < ctrlbox->nctrlsets; index++) { for (index = 0; index < dp->ctrlbox->nctrlsets; index++) {
struct controlset *s = ctrlbox->ctrlsets[index]; struct controlset *s = dp->ctrlbox->ctrlsets[index];
int done = 0; int done = 0;
int j; int j;
@ -3284,8 +3291,8 @@ int do_config_box(const char *title, Conf *conf, int midsession,
if (s->ctrls[j]->generic.type != CTRL_TABDELAY && if (s->ctrls[j]->generic.type != CTRL_TABDELAY &&
s->ctrls[j]->generic.type != CTRL_COLUMNS && s->ctrls[j]->generic.type != CTRL_COLUMNS &&
s->ctrls[j]->generic.type != CTRL_TEXT) { s->ctrls[j]->generic.type != CTRL_TEXT) {
dlg_set_focus(s->ctrls[j], &dp); dlg_set_focus(s->ctrls[j], dp);
dp.lastfocus = s->ctrls[j]; dp->lastfocus = s->ctrls[j];
done = 1; done = 1;
break; break;
} }
@ -3295,18 +3302,30 @@ int do_config_box(const char *title, Conf *conf, int midsession,
} }
g_signal_connect(G_OBJECT(window), "destroy", g_signal_connect(G_OBJECT(window), "destroy",
G_CALLBACK(window_destroy), NULL); G_CALLBACK(dlgparam_destroy), dp);
g_signal_connect(G_OBJECT(window), "key_press_event", g_signal_connect(G_OBJECT(window), "key_press_event",
G_CALLBACK(win_key_press), &dp); G_CALLBACK(win_key_press), dp);
gtk_main(); return window;
post_main(); }
dlg_cleanup(&dp); static void dlgparam_destroy(GtkWidget *widget, gpointer data)
sfree(selparams); {
ctrl_free_box(ctrlbox); struct dlgparam *dp = (struct dlgparam *)data;
if (dp->retval >= 0)
return dp.retval; dp->after(dp->afterctx, dp->retval);
dlg_cleanup(dp);
ctrl_free_box(dp->ctrlbox);
#if GTK_CHECK_VERSION(2,0,0)
{
int i;
for (i = 0; i < dp->nselparams; i++)
if (dp->selparams[i].treepath)
gtk_tree_path_free(dp->selparams[i].treepath);
}
sfree(dp->selparams);
#endif
sfree(dp);
} }
static void messagebox_handler(union control *ctrl, void *dlg, static void messagebox_handler(union control *ctrl, void *dlg,

View File

@ -296,8 +296,6 @@ static void version(FILE *fp) {
sfree(buildinfo_text); sfree(buildinfo_text);
} }
static struct gui_data *the_inst;
static const char *geometry_string; static const char *geometry_string;
int do_cmdline(int argc, char **argv, int do_everything, int *allow_launch, int do_cmdline(int argc, char **argv, int do_everything, int *allow_launch,
@ -540,10 +538,35 @@ GtkWidget *make_gtk_toplevel_window(void *frontend)
return gtk_window_new(GTK_WINDOW_TOPLEVEL); return gtk_window_new(GTK_WINDOW_TOPLEVEL);
} }
extern int cfgbox(Conf *conf);
const int buildinfo_gtk_relevant = TRUE; const int buildinfo_gtk_relevant = TRUE;
struct post_initial_config_box_ctx {
Conf *conf;
const char *geometry_string;
};
static void post_initial_config_box(void *vctx, int result)
{
struct post_initial_config_box_ctx ctx =
*(struct post_initial_config_box_ctx *)vctx;
sfree(vctx);
if (result) {
new_session_window(ctx.conf, ctx.geometry_string);
} else {
/* In this main(), which only runs one session in total, a
* negative result from the initial config box means we simply
* terminate. */
conf_free(ctx.conf);
gtk_main_quit();
}
}
void session_window_closed(void)
{
gtk_main_quit();
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
Conf *conf; Conf *conf;
@ -614,21 +637,28 @@ int main(int argc, char **argv)
need_config_box = (!allow_launch || !conf_launchable(conf)); need_config_box = (!allow_launch || !conf_launchable(conf));
} }
/* if (need_config_box) {
* Put up the config box. /*
*/ * Put up the initial config box, which will pass the provided
if (need_config_box && !cfgbox(conf)) * parameters (with conf updated) to new_session_window() when
exit(0); /* config box hit Cancel */ * (if) the user selects Open. Or it might close without
* creating a session window, if the user selects Cancel. Or
/* * it might just create the session window immediately if this
* Create the main session window. We don't really need to keep * is a pterm-style app which doesn't have an initial config
* the return value - the fact that it'll be linked from a zillion * box at all.
* GTK and glib bits and bobs known to the main loop will be */
* sufficient to make everything actually happen - but we stash it struct post_initial_config_box_ctx *ctx =
* in a global variable anyway, so that it'll be easy to find in a snew(struct post_initial_config_box_ctx);
* debugger. ctx->conf = conf;
*/ ctx->geometry_string = geometry_string;
the_inst = new_session_window(conf, geometry_string); initial_config_box(conf, post_initial_config_box, ctx);
} else {
/*
* No initial config needed; just create the session window
* now.
*/
new_session_window(conf, geometry_string);
}
gtk_main(); gtk_main();

View File

@ -130,7 +130,7 @@ struct gui_data {
Conf *conf; Conf *conf;
void *eventlogstuff; void *eventlogstuff;
guint32 input_event_time; /* Timestamp of the most recent input event. */ guint32 input_event_time; /* Timestamp of the most recent input event. */
int reconfiguring; GtkWidget *reconfigure_dialog;
#if GTK_CHECK_VERSION(3,4,0) #if GTK_CHECK_VERSION(3,4,0)
gdouble cumulative_scroll; gdouble cumulative_scroll;
#endif #endif
@ -2007,7 +2007,6 @@ static void exit_callback(void *vinst)
if (close_on_exit == FORCE_ON || if (close_on_exit == FORCE_ON ||
(close_on_exit == AUTO && exitcode == 0)) { (close_on_exit == AUTO && exitcode == 0)) {
gtk_widget_destroy(inst->window); gtk_widget_destroy(inst->window);
gtk_main_quit();
} }
} }
} }
@ -2022,6 +2021,10 @@ void notify_remote_exit(void *frontend)
static void delete_inst(struct gui_data *inst) static void delete_inst(struct gui_data *inst)
{ {
delete_callbacks_for_context(inst); delete_callbacks_for_context(inst);
if (inst->reconfigure_dialog) {
gtk_widget_destroy(inst->reconfigure_dialog);
inst->reconfigure_dialog = NULL;
}
if (inst->window) { if (inst->window) {
gtk_widget_destroy(inst->window); gtk_widget_destroy(inst->window);
inst->window = NULL; inst->window = NULL;
@ -2059,7 +2062,7 @@ void destroy(GtkWidget *widget, gpointer data)
struct gui_data *inst = (struct gui_data *)data; struct gui_data *inst = (struct gui_data *)data;
inst->window = NULL; inst->window = NULL;
delete_inst(inst); delete_inst(inst);
gtk_main_quit(); session_window_closed();
} }
gint focus_event(GtkWidget *widget, GdkEventFocus *event, gpointer data) gint focus_event(GtkWidget *widget, GdkEventFocus *event, gpointer data)
@ -3958,7 +3961,46 @@ void event_log_menuitem(GtkMenuItem *item, gpointer data)
showeventlog(inst->eventlogstuff, inst->window); showeventlog(inst->eventlogstuff, inst->window);
} }
struct after_change_settings_dialog_ctx {
struct gui_data *inst;
Conf *newconf;
};
static void after_change_settings_dialog(void *vctx, int retval);
void change_settings_menuitem(GtkMenuItem *item, gpointer data) void change_settings_menuitem(GtkMenuItem *item, gpointer data)
{
struct gui_data *inst = (struct gui_data *)data;
struct after_change_settings_dialog_ctx *ctx;
char *title;
if (inst->reconfigure_dialog) {
/*
* If this window already had a Change Settings box open, just
* find it and try to make it more prominent.
*/
#if GTK_CHECK_VERSION(2,0,0)
gtk_window_deiconify(GTK_WINDOW(inst->reconfigure_dialog));
#endif
gdk_window_raise(gtk_widget_get_window(inst->reconfigure_dialog));
return;
}
title = dupcat(appname, " Reconfiguration", NULL);
ctx = snew(struct after_change_settings_dialog_ctx);
ctx->inst = inst;
ctx->newconf = conf_copy(inst->conf);
inst->reconfigure_dialog = create_config_box(
title, ctx->newconf, 1,
inst->back ? inst->back->cfg_info(inst->backhandle) : 0,
after_change_settings_dialog, ctx);
sfree(title);
}
static void after_change_settings_dialog(void *vctx, int retval)
{ {
/* This maps colour indices in inst->conf to those used in inst->cols. */ /* This maps colour indices in inst->conf to those used in inst->cols. */
static const int ww[] = { static const int ww[] = {
@ -3966,25 +4008,19 @@ void change_settings_menuitem(GtkMenuItem *item, gpointer data)
0, 8, 1, 9, 2, 10, 3, 11, 0, 8, 1, 9, 2, 10, 3, 11,
4, 12, 5, 13, 6, 14, 7, 15 4, 12, 5, 13, 6, 14, 7, 15
}; };
struct gui_data *inst = (struct gui_data *)data; struct after_change_settings_dialog_ctx ctx =
char *title; *(struct after_change_settings_dialog_ctx *)vctx;
Conf *oldconf, *newconf; struct gui_data *inst = ctx.inst;
Conf *oldconf = inst->conf, *newconf = ctx.newconf;
int i, j, need_size; int i, j, need_size;
sfree(vctx); /* we've copied this already */
assert(lenof(ww) == NCFGCOLOURS); assert(lenof(ww) == NCFGCOLOURS);
if (inst->reconfiguring) inst->reconfigure_dialog = NULL;
return;
else
inst->reconfiguring = TRUE;
title = dupcat(appname, " Reconfiguration", NULL); if (retval) {
oldconf = inst->conf;
newconf = conf_copy(inst->conf);
if (do_config_box(title, newconf, 1,
inst->back?inst->back->cfg_info(inst->backhandle):0)) {
inst->conf = newconf; inst->conf = newconf;
/* Pass new config data to the logging module */ /* Pass new config data to the logging module */
@ -4139,8 +4175,6 @@ void change_settings_menuitem(GtkMenuItem *item, gpointer data)
} else { } else {
conf_free(newconf); conf_free(newconf);
} }
sfree(title);
inst->reconfiguring = FALSE;
} }
static void change_font_size(struct gui_data *inst, int increment) static void change_font_size(struct gui_data *inst, int increment)
@ -4451,7 +4485,7 @@ static void get_monitor_geometry(GtkWidget *widget, GdkRectangle *geometry)
} }
#endif #endif
struct gui_data *new_session_window(Conf *conf, const char *geometry_string) void new_session_window(Conf *conf, const char *geometry_string)
{ {
struct gui_data *inst; struct gui_data *inst;
@ -4781,6 +4815,4 @@ struct gui_data *new_session_window(Conf *conf, const char *geometry_string)
ldisc_echoedit_update(inst->ldisc); /* cause ldisc to notice changes */ ldisc_echoedit_update(inst->ldisc); /* cause ldisc to notice changes */
inst->exited = FALSE; inst->exited = FALSE;
return inst;
} }

View File

@ -121,12 +121,19 @@ unsigned long getticks(void);
/* The per-session frontend structure managed by gtkwin.c */ /* The per-session frontend structure managed by gtkwin.c */
struct gui_data; struct gui_data;
struct gui_data *new_session_window(Conf *conf, const char *geometry_string);
/* Callback when a dialog box finishes */
typedef void (*post_dialog_fn_t)(void *ctx, int result);
/* Start up a session window, with or without a preliminary config box */
void initial_config_box(Conf *conf, post_dialog_fn_t after, void *afterctx);
void new_session_window(Conf *conf, const char *geometry_string);
/* Defined in gtkmain.c */ /* Defined in gtkmain.c */
void launch_duplicate_session(Conf *conf); void launch_duplicate_session(Conf *conf);
void launch_new_session(void); void launch_new_session(void);
void launch_saved_session(const char *str); void launch_saved_session(const char *str);
void session_window_closed(void);
#ifdef MAY_REFER_TO_GTK_IN_HEADERS #ifdef MAY_REFER_TO_GTK_IN_HEADERS
GtkWidget *make_gtk_toplevel_window(void *frontend); GtkWidget *make_gtk_toplevel_window(void *frontend);
#endif #endif
@ -144,8 +151,11 @@ void *get_window(void *frontend); /* void * to avoid depending on gtk.h */
void post_main(void); /* called after any subsidiary gtk_main() */ void post_main(void); /* called after any subsidiary gtk_main() */
/* Things pterm.c needs from gtkdlg.c */ /* Things pterm.c needs from gtkdlg.c */
int do_config_box(const char *title, Conf *conf, #ifdef MAY_REFER_TO_GTK_IN_HEADERS
int midsession, int protcfginfo); 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 fatal_message_box(void *window, const char *msg);
void nonfatal_message_box(void *window, const char *msg); void nonfatal_message_box(void *window, const char *msg);
void about_box(void *window); void about_box(void *window);

View File

@ -18,15 +18,16 @@ Backend *select_backend(Conf *conf)
return &pty_backend; return &pty_backend;
} }
int cfgbox(Conf *conf) void initial_config_box(Conf *conf, post_dialog_fn_t after, void *afterctx)
{ {
/* /*
* This is a no-op in pterm, except that we'll ensure the * This is a no-op in pterm, except that we'll ensure the protocol
* protocol is set to -1 to inhibit the useless Connection * is set to -1 to inhibit the useless Connection panel in the
* panel in the config box. * config box. So we do that and then just immediately call the
* post-dialog function with a positive result.
*/ */
conf_set_int(conf, CONF_protocol, -1); conf_set_int(conf, CONF_protocol, -1);
return 1; after(afterctx, 1);
} }
void cleanup_exit(int code) void cleanup_exit(int code)

View File

@ -10,6 +10,8 @@
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <gdk/gdk.h> #include <gdk/gdk.h>
#define MAY_REFER_TO_GTK_IN_HEADERS
#include "putty.h" #include "putty.h"
#include "storage.h" #include "storage.h"
@ -42,12 +44,11 @@ Backend *select_backend(Conf *conf)
return back; return back;
} }
int cfgbox(Conf *conf) void initial_config_box(Conf *conf, post_dialog_fn_t after, void *afterctx)
{ {
char *title = dupcat(appname, " Configuration", NULL); char *title = dupcat(appname, " Configuration", NULL);
int ret = do_config_box(title, conf, 0, 0); create_config_box(title, conf, FALSE, 0, after, afterctx);
sfree(title); sfree(title);
return ret;
} }
static int got_host = 0; static int got_host = 0;