diff options
author | Damien Miller <djm@mindrot.org> | 2020-09-18 14:50:38 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2020-09-18 14:50:38 +1000 |
commit | 9d3d36bdb10b66abd1af42e8655502487b6ba1fa (patch) | |
tree | 9b933cb3df811b64bdf06863ff37c02e1e1f6ca3 /contrib | |
parent | d6f507f37e6c75a899db0ef8224e72797c5563b6 (diff) |
focus improvement for gnome-ssh-askpass[23]
When serving a SSH_ASKPASS_PROMPT=none information dialog, ensure
then <enter> doesn't immediately close the dialog. Instead, require an
explicit <tab> to reach the close button, or <esc>.
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/gnome-ssh-askpass2.c | 42 |
1 files changed, 37 insertions, 5 deletions
diff --git a/contrib/gnome-ssh-askpass2.c b/contrib/gnome-ssh-askpass2.c index bc83a2d67..7656a776b 100644 --- a/contrib/gnome-ssh-askpass2.c +++ b/contrib/gnome-ssh-askpass2.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #include <X11/Xlib.h> | 59 | #include <X11/Xlib.h> |
60 | #include <gtk/gtk.h> | 60 | #include <gtk/gtk.h> |
61 | #include <gdk/gdkx.h> | 61 | #include <gdk/gdkx.h> |
62 | #include <gdk/gdkkeysyms.h> | ||
62 | 63 | ||
63 | static void | 64 | static void |
64 | report_failed_grab (GtkWidget *parent_window, const char *what) | 65 | report_failed_grab (GtkWidget *parent_window, const char *what) |
@@ -85,6 +86,25 @@ ok_dialog(GtkWidget *entry, gpointer dialog) | |||
85 | gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); | 86 | gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); |
86 | } | 87 | } |
87 | 88 | ||
89 | static gboolean | ||
90 | check_none(GtkWidget *widget, GdkEventKey *event, gpointer dialog) | ||
91 | { | ||
92 | switch (event->keyval) { | ||
93 | case GDK_KEY_Escape: | ||
94 | /* esc -> close dialog */ | ||
95 | gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE); | ||
96 | return TRUE; | ||
97 | case GDK_KEY_Tab: | ||
98 | /* tab -> focus close button */ | ||
99 | gtk_widget_grab_focus(gtk_dialog_get_widget_for_response( | ||
100 | dialog, GTK_RESPONSE_CLOSE)); | ||
101 | return TRUE; | ||
102 | default: | ||
103 | /* eat all other key events */ | ||
104 | return TRUE; | ||
105 | } | ||
106 | } | ||
107 | |||
88 | static int | 108 | static int |
89 | passphrase_dialog(char *message, int prompt_type) | 109 | passphrase_dialog(char *message, int prompt_type) |
90 | { | 110 | { |
@@ -127,17 +147,29 @@ passphrase_dialog(char *message, int prompt_type) | |||
127 | gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_response); | 147 | gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_response); |
128 | gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); | 148 | gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); |
129 | 149 | ||
130 | if (prompt_type == PROMPT_ENTRY) { | 150 | if (prompt_type == PROMPT_ENTRY || prompt_type == PROMPT_NONE) { |
131 | entry = gtk_entry_new(); | 151 | entry = gtk_entry_new(); |
132 | gtk_box_pack_start( | 152 | gtk_box_pack_start( |
133 | GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), | 153 | GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), |
134 | entry, FALSE, FALSE, 0); | 154 | entry, FALSE, FALSE, 0); |
135 | gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); | 155 | gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); |
136 | gtk_widget_grab_focus(entry); | 156 | gtk_widget_grab_focus(entry); |
137 | gtk_widget_show(entry); | 157 | if (prompt_type == PROMPT_ENTRY) { |
138 | /* Make <enter> close dialog */ | 158 | gtk_widget_show(entry); |
139 | g_signal_connect(G_OBJECT(entry), "activate", | 159 | /* Make <enter> close dialog */ |
140 | G_CALLBACK(ok_dialog), dialog); | 160 | g_signal_connect(G_OBJECT(entry), "activate", |
161 | G_CALLBACK(ok_dialog), dialog); | ||
162 | } else { | ||
163 | /* | ||
164 | * Ensure the 'close' button is not focused by default | ||
165 | * but is still reachable via tab. This is a bit of a | ||
166 | * hack - it uses a hidden entry that responds to a | ||
167 | * couple of keypress events (escape and tab only). | ||
168 | */ | ||
169 | gtk_widget_realize(entry); | ||
170 | g_signal_connect(G_OBJECT(entry), "key_press_event", | ||
171 | G_CALLBACK(check_none), dialog); | ||
172 | } | ||
141 | } | 173 | } |
142 | 174 | ||
143 | /* Grab focus */ | 175 | /* Grab focus */ |