diff --git a/unix/gtkdlg.c b/unix/gtkdlg.c index 86a71cd6..9139f6fc 100644 --- a/unix/gtkdlg.c +++ b/unix/gtkdlg.c @@ -3138,12 +3138,13 @@ static void messagebox_handler(union control *ctrl, void *dlg, if (event == EVENT_ACTION) dlg_end(dlg, ctrl->generic.context.i); } -int messagebox(GtkWidget *parentwin, char *title, char *msg, int minwid, ...) +int messagebox(GtkWidget *parentwin, char *title, char *msg, + int minwid, int selectable, ...) { GtkWidget *window, *w0, *w1; struct controlbox *ctrlbox; struct controlset *s0, *s1; - union control *c; + union control *c, *textctrl; struct dlgparam dp; struct Shortcuts scs; int index, ncols; @@ -3158,7 +3159,7 @@ int messagebox(GtkWidget *parentwin, char *title, char *msg, int minwid, ...) ctrlbox = ctrl_new_box(); ncols = 0; - va_start(ap, minwid); + va_start(ap, selectable); while (va_arg(ap, char *) != NULL) { ncols++; (void) va_arg(ap, int); /* shortcut */ @@ -3173,7 +3174,7 @@ int messagebox(GtkWidget *parentwin, char *title, char *msg, int minwid, ...) c->columns.percentages = sresize(c->columns.percentages, ncols, int); for (index = 0; index < ncols; index++) c->columns.percentages[index] = (index+1)*100/ncols - index*100/ncols; - va_start(ap, minwid); + va_start(ap, selectable); index = 0; while (1) { char *title = va_arg(ap, char *); @@ -3194,7 +3195,7 @@ int messagebox(GtkWidget *parentwin, char *title, char *msg, int minwid, ...) va_end(ap); s1 = ctrl_getset(ctrlbox, "x", "", ""); - ctrl_text(s1, msg, HELPCTX(no_help)); + textctrl = ctrl_text(s1, msg, HELPCTX(no_help)); window = gtk_dialog_new(); gtk_window_set_title(GTK_WINDOW(window), title); @@ -3213,6 +3214,26 @@ int messagebox(GtkWidget *parentwin, char *title, char *msg, int minwid, ...) dp.retval = 0; dp.window = window; + if (selectable) { +#if GTK_CHECK_VERSION(2,0,0) + struct uctrl *uc = dlg_find_byctrl(&dp, textctrl); + gtk_label_set_selectable(GTK_LABEL(uc->text), TRUE); + + /* + * GTK selectable labels have a habit of selecting their + * entire contents when they gain focus. It's ugly to have + * text in a message box start up all selected, so we suppress + * this by manually selecting none of it - but we must do this + * when the widget _already has_ focus, otherwise our work + * will be undone when it gains it shortly. + */ + gtk_widget_grab_focus(uc->text); + gtk_label_select_region(GTK_LABEL(uc->text), 0, 0); +#else + (void)textctrl; /* placate warning */ +#endif + } + gtk_window_set_modal(GTK_WINDOW(window), TRUE); if (parentwin) { set_transient_window_pos(parentwin, window); @@ -3220,7 +3241,9 @@ int messagebox(GtkWidget *parentwin, char *title, char *msg, int minwid, ...) GTK_WINDOW(parentwin)); } else gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); + gtk_container_set_focus_child(GTK_CONTAINER(window), NULL); gtk_widget_show(window); + gtk_window_set_focus(GTK_WINDOW(window), NULL); gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(window_destroy), NULL); @@ -3250,6 +3273,7 @@ int reallyclose(void *frontend) int ret = messagebox(GTK_WIDGET(get_window(frontend)), title, "Are you sure you want to close this session?", string_width("Most of the width of the above text"), + FALSE, "Yes", 'y', +1, 1, "No", 'n', -1, 0, NULL); @@ -3303,6 +3327,7 @@ int verify_ssh_host_key(void *frontend, char *host, int port, char *keytype, ret = messagebox(GTK_WIDGET(get_window(frontend)), "PuTTY Security Alert", text, string_width(fingerprint), + TRUE, "Accept", 'a', 0, 2, "Connect Once", 'o', 0, 1, "Cancel", 'c', -1, 0, @@ -3336,6 +3361,7 @@ int askalg(void *frontend, const char *algtype, const char *algname, ret = messagebox(GTK_WIDGET(get_window(frontend)), "PuTTY Security Alert", text, string_width("Continue with connection?"), + FALSE, "Yes", 'y', 0, 1, "No", 'n', 0, 0, NULL); @@ -3359,14 +3385,14 @@ void fatal_message_box(void *window, char *msg) { messagebox(window, "PuTTY Fatal Error", msg, string_width("REASONABLY LONG LINE OF TEXT FOR BASIC SANITY"), - "OK", 'o', 1, 1, NULL); + FALSE, "OK", 'o', 1, 1, NULL); } void nonfatal_message_box(void *window, char *msg) { messagebox(window, "PuTTY Error", msg, string_width("REASONABLY LONG LINE OF TEXT FOR BASIC SANITY"), - "OK", 'o', 1, 1, NULL); + FALSE, "OK", 'o', 1, 1, NULL); } void fatalbox(char *p, ...) @@ -3439,7 +3465,7 @@ static void licence_clicked(GtkButton *button, gpointer data) messagebox(aboutbox, title, licence, string_width("LONGISH LINE OF TEXT SO THE LICENCE" " BOX ISN'T EXCESSIVELY TALL AND THIN"), - "OK", 'o', 1, 1, NULL); + TRUE, "OK", 'o', 1, 1, NULL); sfree(title); } @@ -3476,25 +3502,35 @@ void about_box(void *window) GTK_SIGNAL_FUNC(licence_clicked), NULL); gtk_widget_show(w); - w = gtk_label_new(appname); + { + char *label_text = dupprintf + ("%s\n\n%s\n\n%s", + appname, ver, + "Copyright 1997-2015 Simon Tatham. All rights reserved"); + w = gtk_label_new(label_text); + gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_CENTER); +#if GTK_CHECK_VERSION(2,0,0) + gtk_label_set_selectable(GTK_LABEL(w), TRUE); +#endif + sfree(label_text); + } gtk_box_pack_start(GTK_BOX(GTK_DIALOG(aboutbox)->vbox), w, FALSE, FALSE, 0); - gtk_widget_show(w); - - w = gtk_label_new(ver); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(aboutbox)->vbox), - w, FALSE, FALSE, 5); - gtk_widget_show(w); - - w = gtk_label_new("Copyright 1997-2015 Simon Tatham. All rights reserved"); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(aboutbox)->vbox), - w, FALSE, FALSE, 5); +#if GTK_CHECK_VERSION(2,0,0) + /* + * Same precautions against initial select-all as in messagebox(). + */ + gtk_widget_grab_focus(w); + gtk_label_select_region(GTK_LABEL(w), 0, 0); +#endif gtk_widget_show(w); set_transient_window_pos(GTK_WIDGET(window), aboutbox); gtk_window_set_transient_for(GTK_WINDOW(aboutbox), GTK_WINDOW(window)); + gtk_container_set_focus_child(GTK_CONTAINER(aboutbox), NULL); gtk_widget_show(aboutbox); + gtk_window_set_focus(GTK_WINDOW(aboutbox), NULL); } struct eventlog_stuff { @@ -3757,6 +3793,7 @@ int askappend(void *frontend, Filename *filename, mbret = messagebox(get_window(frontend), mbtitle, message, string_width("LINE OF TEXT SUITABLE FOR THE" " ASKAPPEND WIDTH"), + FALSE, "Overwrite", 'o', 1, 2, "Append", 'a', 0, 1, "Disable", 'd', -1, 0, diff --git a/unix/gtkwin.c b/unix/gtkwin.c index 12501e69..3d3789f8 100644 --- a/unix/gtkwin.c +++ b/unix/gtkwin.c @@ -3191,7 +3191,7 @@ void change_settings_menuitem(GtkMenuItem *item, gpointer data) errmsg); messagebox(inst->window, "Font setup error", msgboxtext, string_width("Could not change fonts in terminal window:"), - "OK", 'o', +1, 1, + FALSE, "OK", 'o', +1, 1, NULL); sfree(msgboxtext); sfree(errmsg); diff --git a/unix/unix.h b/unix/unix.h index e78800b5..1968a423 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -93,7 +93,8 @@ void showeventlog(void *estuff, void *parentwin); void logevent_dlg(void *estuff, const char *string); int reallyclose(void *frontend); #ifdef MAY_REFER_TO_GTK_IN_HEADERS -int messagebox(GtkWidget *parentwin, char *title, char *msg, int minwid, ...); +int messagebox(GtkWidget *parentwin, char *title, + char *msg, int minwid, int selectable, ...); int string_width(char *text); #endif