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.

(cherry picked from commit c14f0e02cc)
This commit is contained in:
Simon Tatham 2022-11-27 11:14:23 +00:00
parent 1526b56332
commit 2698c2944f

View File

@ -3448,26 +3448,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),
@ -3478,6 +3458,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;