1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

Stop selectable GTK message boxes clobbering PRIMARY.

I noticed today that when GTK PuTTY puts up a message box such as a
host key dialog, which calls our create_message_box function with
selectable=true (so that the host key fingerprint can be conveniently
copy-pasted), a side effect is to take the X11 PRIMARY selection away
from whoever previously had it, even though the message box isn't
actually selecting anything right now.

I don't fully understand what's going on, but it apparently has
something to do with 'select on focus' behaviour, in which tabbing
into a selectable text control automatically selects its entire
contents. That makes sense for edit boxes, but not really for this
kind of thing.

Unfortunately, GTK apparently has no per-widget configuration to turn
that off. (The closest I found is not even per _application_: it lives
in GtkSettings, whose documentation says that it's general across all
GTK apps run by a user!)

So instead I work around it by moving the gtk_label_set_selectable
call to after the focus of the new window has already been sorted out.
Ugly, but it seems to work.
This commit is contained in:
Simon Tatham 2022-11-27 11:14:23 +00:00
parent f4519b6533
commit c14f0e02cc

View File

@ -3446,26 +3446,6 @@ static GtkWidget *create_message_box_general(
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
}
if (parentwin) {
set_transient_window_pos(parentwin, window);
gtk_window_set_transient_for(GTK_WINDOW(window),
@ -3476,6 +3456,34 @@ static GtkWidget *create_message_box_general(
gtk_widget_show(window);
gtk_window_set_focus(GTK_WINDOW(window), NULL);
#if GTK_CHECK_VERSION(2,0,0)
if (selectable) {
/*
* GTK selectable labels have a habit of selecting their
* entire contents when they gain focus. As far as I can see,
* an individual GtkLabel has no way to turn this off - source
* diving suggests that the only configurable option for it is
* "gtk-label-select-on-focus" in the cross-application
* GtkSettings, and there's no per-label or even
* per-application override.
*
* It's ugly to have text in a message box start up all
* selected, and also it interferes with any PRIMARY selection
* you might already have had. So for this purpose we'd prefer
* that the text doesn't _start off_ selected, but it should
* be selectable later.
*
* So we make the label selectable _now_, after the widget is
* shown and the focus has already gone wherever it's going.
*/
struct uctrl *uc = dlg_find_byctrl(dp, textctrl);
gtk_label_select_region(GTK_LABEL(uc->text), 0, 0);
gtk_label_set_selectable(GTK_LABEL(uc->text), true);
}
#else
(void)textctrl; /* placate warning */
#endif
#if !GTK_CHECK_VERSION(2,0,0)
dp->currtreeitem = NULL;
dp->treeitems = NULL;