summaryrefslogtreecommitdiff
path: root/contrib/gnome-ssh-askpass2.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gnome-ssh-askpass2.c')
-rw-r--r--contrib/gnome-ssh-askpass2.c99
1 files changed, 94 insertions, 5 deletions
diff --git a/contrib/gnome-ssh-askpass2.c b/contrib/gnome-ssh-askpass2.c
index 88cdfaeff..bf8c92c8f 100644
--- a/contrib/gnome-ssh-askpass2.c
+++ b/contrib/gnome-ssh-askpass2.c
@@ -56,9 +56,11 @@
56#include <stdio.h> 56#include <stdio.h>
57#include <string.h> 57#include <string.h>
58#include <unistd.h> 58#include <unistd.h>
59
59#include <X11/Xlib.h> 60#include <X11/Xlib.h>
60#include <gtk/gtk.h> 61#include <gtk/gtk.h>
61#include <gdk/gdkx.h> 62#include <gdk/gdkx.h>
63#include <gdk/gdkkeysyms.h>
62 64
63static void 65static void
64report_failed_grab (GtkWidget *parent_window, const char *what) 66report_failed_grab (GtkWidget *parent_window, const char *what)
@@ -85,6 +87,67 @@ ok_dialog(GtkWidget *entry, gpointer dialog)
85 gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); 87 gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
86} 88}
87 89
90static gboolean
91check_none(GtkWidget *widget, GdkEventKey *event, gpointer dialog)
92{
93 switch (event->keyval) {
94 case GDK_KEY_Escape:
95 /* esc -> close dialog */
96 gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE);
97 return TRUE;
98 case GDK_KEY_Tab:
99 /* tab -> focus close button */
100 gtk_widget_grab_focus(gtk_dialog_get_widget_for_response(
101 dialog, GTK_RESPONSE_CLOSE));
102 return TRUE;
103 default:
104 /* eat all other key events */
105 return TRUE;
106 }
107}
108
109static int
110parse_env_hex_color(const char *env, GdkColor *c)
111{
112 const char *s;
113 unsigned long ul;
114 char *ep;
115 size_t n;
116
117 if ((s = getenv(env)) == NULL)
118 return 0;
119
120 memset(c, 0, sizeof(*c));
121
122 /* Permit hex rgb or rrggbb optionally prefixed by '#' or '0x' */
123 if (*s == '#')
124 s++;
125 else if (strncmp(s, "0x", 2) == 0)
126 s += 2;
127 n = strlen(s);
128 if (n != 3 && n != 6)
129 goto bad;
130 ul = strtoul(s, &ep, 16);
131 if (*ep != '\0' || ul > 0xffffff) {
132 bad:
133 fprintf(stderr, "Invalid $%s - invalid hex color code\n", env);
134 return 0;
135 }
136 /* Valid hex sequence; expand into a GdkColor */
137 if (n == 3) {
138 /* 4-bit RGB */
139 c->red = ((ul >> 8) & 0xf) << 12;
140 c->green = ((ul >> 4) & 0xf) << 12;
141 c->blue = (ul & 0xf) << 12;
142 } else {
143 /* 8-bit RGB */
144 c->red = ((ul >> 16) & 0xff) << 8;
145 c->green = ((ul >> 8) & 0xff) << 8;
146 c->blue = (ul & 0xff) << 8;
147 }
148 return 1;
149}
150
88static int 151static int
89passphrase_dialog(char *message, int prompt_type) 152passphrase_dialog(char *message, int prompt_type)
90{ 153{
@@ -94,11 +157,16 @@ passphrase_dialog(char *message, int prompt_type)
94 int buttons, default_response; 157 int buttons, default_response;
95 GtkWidget *parent_window, *dialog, *entry; 158 GtkWidget *parent_window, *dialog, *entry;
96 GdkGrabStatus status; 159 GdkGrabStatus status;
160 GdkColor fg, bg;
161 int fg_set = 0, bg_set = 0;
97 162
98 grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL); 163 grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL);
99 grab_pointer = (getenv("GNOME_SSH_ASKPASS_GRAB_POINTER") != NULL); 164 grab_pointer = (getenv("GNOME_SSH_ASKPASS_GRAB_POINTER") != NULL);
100 grab_tries = 0; 165 grab_tries = 0;
101 166
167 fg_set = parse_env_hex_color("GNOME_SSH_ASKPASS_FG_COLOR", &fg);
168 bg_set = parse_env_hex_color("GNOME_SSH_ASKPASS_BG_COLOR", &bg);
169
102 /* Create an invisible parent window so that GtkDialog doesn't 170 /* Create an invisible parent window so that GtkDialog doesn't
103 * complain. */ 171 * complain. */
104 parent_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 172 parent_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
@@ -127,17 +195,38 @@ passphrase_dialog(char *message, int prompt_type)
127 gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_response); 195 gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_response);
128 gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); 196 gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);
129 197
130 if (prompt_type == PROMPT_ENTRY) { 198 if (fg_set)
199 gtk_widget_modify_fg(dialog, GTK_STATE_NORMAL, &fg);
200 if (bg_set)
201 gtk_widget_modify_bg(dialog, GTK_STATE_NORMAL, &bg);
202
203 if (prompt_type == PROMPT_ENTRY || prompt_type == PROMPT_NONE) {
131 entry = gtk_entry_new(); 204 entry = gtk_entry_new();
205 if (fg_set)
206 gtk_widget_modify_fg(entry, GTK_STATE_NORMAL, &fg);
207 if (bg_set)
208 gtk_widget_modify_bg(entry, GTK_STATE_NORMAL, &bg);
132 gtk_box_pack_start( 209 gtk_box_pack_start(
133 GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), 210 GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
134 entry, FALSE, FALSE, 0); 211 entry, FALSE, FALSE, 0);
135 gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); 212 gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
136 gtk_widget_grab_focus(entry); 213 gtk_widget_grab_focus(entry);
137 gtk_widget_show(entry); 214 if (prompt_type == PROMPT_ENTRY) {
138 /* Make <enter> close dialog */ 215 gtk_widget_show(entry);
139 g_signal_connect(G_OBJECT(entry), "activate", 216 /* Make <enter> close dialog */
140 G_CALLBACK(ok_dialog), dialog); 217 g_signal_connect(G_OBJECT(entry), "activate",
218 G_CALLBACK(ok_dialog), dialog);
219 } else {
220 /*
221 * Ensure the 'close' button is not focused by default
222 * but is still reachable via tab. This is a bit of a
223 * hack - it uses a hidden entry that responds to a
224 * couple of keypress events (escape and tab only).
225 */
226 gtk_widget_realize(entry);
227 g_signal_connect(G_OBJECT(entry), "key_press_event",
228 G_CALLBACK(check_none), dialog);
229 }
141 } 230 }
142 231
143 /* Grab focus */ 232 /* Grab focus */