1 /* lock.c --- handling the password dialog for locking-mode.
2 * xscreensaver, Copyright (c) 1993-2005 Jamie Zawinski <jwz@jwz.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
13 /* Athena locking code contributed by Jon A. Christopher <jac8782@tamu.edu> */
14 /* Copyright 1997, with the same permissions as above. */
20 #include <X11/Intrinsic.h>
21 #include <X11/cursorfont.h>
22 #include <X11/Xos.h> /* for time() */
25 #include "xscreensaver.h"
26 #include "resources.h"
28 #ifndef NO_LOCKING /* (mostly) whole file */
32 #endif /* HAVE_SYSLOG */
34 #ifdef HAVE_XHPDISABLERESET
35 # include <X11/XHPlib.h>
36 static void hp_lock_reset (saver_info *si, Bool lock_p);
37 #endif /* HAVE_XHPDISABLERESET */
39 #ifdef HAVE_VT_LOCKSWITCH
41 # include <sys/ioctl.h>
43 static void linux_lock_vt_switch (saver_info *si, Bool lock_p);
44 #endif /* HAVE_VT_LOCKSWITCH */
47 # include <X11/extensions/xf86vmode.h>
48 static void xfree_lock_mode_switch (saver_info *si, Bool lock_p);
49 #endif /* HAVE_XF86VMODE */
51 #ifdef HAVE_XF86MISCSETGRABKEYSSTATE
52 # include <X11/extensions/xf86misc.h>
53 static void xfree_lock_grab_smasher (saver_info *si, Bool lock_p);
54 #endif /* HAVE_XF86MISCSETGRABKEYSSTATE */
58 ERROR! You must not include vroot.h in this file.
65 extern char *getenv(const char *name);
66 extern int validate_user(char *name, char *password);
69 vms_passwd_valid_p(char *pw, Bool verbose_p)
71 return (validate_user (getenv("USER"), typed_passwd) == 1);
73 # undef passwd_valid_p
74 # define passwd_valid_p vms_passwd_valid_p
80 #define MAX(a,b) ((a)>(b)?(a):(b))
82 enum passwd_state { pw_read, pw_ok, pw_null, pw_fail, pw_cancel, pw_time };
84 struct passwd_dialog_data {
86 saver_screen_info *prompt_screen;
87 int previous_mouse_x, previous_mouse_y;
89 enum passwd_state state;
90 char typed_passwd [80];
98 Dimension border_width;
100 Bool show_stars_p; /* "I regret that I have but one asterisk for my country."
101 -- Nathan Hale, 1776. */
112 XFontStruct *heading_font;
113 XFontStruct *body_font;
114 XFontStruct *label_font;
115 XFontStruct *passwd_font;
116 XFontStruct *date_font;
117 XFontStruct *button_font;
121 Pixel passwd_foreground;
122 Pixel passwd_background;
123 Pixel thermo_foreground;
124 Pixel thermo_background;
127 Pixel button_foreground;
128 Pixel button_background;
130 Dimension logo_width;
131 Dimension logo_height;
132 Dimension thermo_width;
133 Dimension internal_border;
134 Dimension shadow_width;
136 Dimension passwd_field_x, passwd_field_y;
137 Dimension passwd_field_width, passwd_field_height;
139 Dimension login_button_x, login_button_y;
140 Dimension login_button_width, login_button_height;
142 Dimension thermo_field_x, thermo_field_y;
143 Dimension thermo_field_height;
147 unsigned long *logo_pixels;
149 Cursor passwd_cursor;
150 Bool login_button_down_p;
152 Bool login_button_enabled_p;
157 static void draw_passwd_window (saver_info *si);
158 static void update_passwd_window (saver_info *si, const char *printed_passwd,
160 static void destroy_passwd_window (saver_info *si);
161 static void undo_vp_motion (saver_info *si);
162 static void handle_passwd_button (saver_info *si, XEvent *event);
166 make_passwd_window (saver_info *si)
168 struct passwd *p = getpwuid (getuid ());
169 XSetWindowAttributes attrs;
170 unsigned long attrmask = 0;
171 passwd_dialog_data *pw = (passwd_dialog_data *) calloc (1, sizeof(*pw));
175 saver_screen_info *ssi = &si->screens [mouse_screen (si)];
177 /* Display the button only if the "newLoginCommand" pref is non-null.
179 pw->login_button_p = (si->prefs.new_login_command &&
180 *si->prefs.new_login_command);
182 if (pw->login_button_p)
183 pw->passwd_cursor = XCreateFontCursor (si->dpy, XC_top_left_arrow);
185 pw->passwd_cursor = 0;
187 pw->prompt_screen = ssi;
188 if (si->prefs.verbose_p)
189 fprintf (stderr, "%s: %d: creating password dialog.\n",
190 blurb(), pw->prompt_screen->number);
192 screen = pw->prompt_screen->screen;
193 cmap = DefaultColormapOfScreen (screen);
197 pw->show_stars_p = get_boolean_resource("passwd.asterisks", "Boolean");
199 pw->heading_label = get_string_resource ("passwd.heading.label",
200 "Dialog.Label.Label");
201 pw->body_label = get_string_resource ("passwd.body.label",
202 "Dialog.Label.Label");
203 pw->user_label = get_string_resource ("passwd.user.label",
204 "Dialog.Label.Label");
205 pw->passwd_label = get_string_resource ("passwd.passwd.label",
206 "Dialog.Label.Label");
207 pw->login_label = get_string_resource ("passwd.login.label",
208 "Dialog.Button.Label");
210 pw->date_label = get_string_resource ("dateFormat", "DateFormat");
212 if (!pw->heading_label)
213 pw->heading_label = strdup("ERROR: RESOURCES NOT INSTALLED CORRECTLY");
215 pw->body_label = strdup("ERROR: RESOURCES NOT INSTALLED CORRECTLY");
216 if (!pw->user_label) pw->user_label = strdup("ERROR");
217 if (!pw->passwd_label) pw->passwd_label = strdup("ERROR");
218 if (!pw->date_label) pw->date_label = strdup("ERROR");
219 if (!pw->login_label) pw->login_label = strdup ("ERROR (LOGIN)") ;
221 /* Put the version number in the label. */
223 char *s = (char *) malloc (strlen(pw->heading_label) + 20);
224 sprintf(s, pw->heading_label, si->version);
225 free (pw->heading_label);
226 pw->heading_label = s;
229 pw->user_string = strdup (p && p->pw_name ? p->pw_name : "???");
230 pw->passwd_string = strdup("");
232 f = get_string_resource ("passwd.headingFont", "Dialog.Font");
233 pw->heading_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
234 if (!pw->heading_font) pw->heading_font = XLoadQueryFont (si->dpy, "fixed");
237 f = get_string_resource ("passwd.buttonFont", "Dialog.Font");
238 pw->button_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
239 if (!pw->button_font) pw->button_font = XLoadQueryFont (si->dpy, "fixed");
242 f = get_string_resource("passwd.bodyFont", "Dialog.Font");
243 pw->body_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
244 if (!pw->body_font) pw->body_font = XLoadQueryFont (si->dpy, "fixed");
247 f = get_string_resource("passwd.labelFont", "Dialog.Font");
248 pw->label_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
249 if (!pw->label_font) pw->label_font = XLoadQueryFont (si->dpy, "fixed");
252 f = get_string_resource("passwd.passwdFont", "Dialog.Font");
253 pw->passwd_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
254 if (!pw->passwd_font) pw->passwd_font = XLoadQueryFont (si->dpy, "fixed");
257 f = get_string_resource("passwd.dateFont", "Dialog.Font");
258 pw->date_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
259 if (!pw->date_font) pw->date_font = XLoadQueryFont (si->dpy, "fixed");
262 pw->foreground = get_pixel_resource ("passwd.foreground",
265 pw->background = get_pixel_resource ("passwd.background",
269 if (pw->foreground == pw->background)
271 /* Make sure the error messages show up. */
272 pw->foreground = BlackPixelOfScreen (screen);
273 pw->background = WhitePixelOfScreen (screen);
276 pw->passwd_foreground = get_pixel_resource ("passwd.text.foreground",
277 "Dialog.Text.Foreground",
279 pw->passwd_background = get_pixel_resource ("passwd.text.background",
280 "Dialog.Text.Background",
282 pw->button_foreground = get_pixel_resource ("splash.Button.foreground",
283 "Dialog.Button.Foreground",
285 pw->button_background = get_pixel_resource ("splash.Button.background",
286 "Dialog.Button.Background",
288 pw->thermo_foreground = get_pixel_resource ("passwd.thermometer.foreground",
289 "Dialog.Thermometer.Foreground",
291 pw->thermo_background = get_pixel_resource ("passwd.thermometer.background",
292 "Dialog.Thermometer.Background",
294 pw->shadow_top = get_pixel_resource ("passwd.topShadowColor",
297 pw->shadow_bottom = get_pixel_resource ("passwd.bottomShadowColor",
301 pw->logo_width = get_integer_resource ("passwd.logo.width",
302 "Dialog.Logo.Width");
303 pw->logo_height = get_integer_resource ("passwd.logo.height",
304 "Dialog.Logo.Height");
305 pw->thermo_width = get_integer_resource ("passwd.thermometer.width",
306 "Dialog.Thermometer.Width");
307 pw->internal_border = get_integer_resource ("passwd.internalBorderWidth",
308 "Dialog.InternalBorderWidth");
309 pw->shadow_width = get_integer_resource ("passwd.shadowThickness",
310 "Dialog.ShadowThickness");
312 if (pw->logo_width == 0) pw->logo_width = 150;
313 if (pw->logo_height == 0) pw->logo_height = 150;
314 if (pw->internal_border == 0) pw->internal_border = 15;
315 if (pw->shadow_width == 0) pw->shadow_width = 4;
316 if (pw->thermo_width == 0) pw->thermo_width = pw->shadow_width;
319 int direction, ascent, descent;
325 /* Measure the heading_label. */
326 XTextExtents (pw->heading_font,
327 pw->heading_label, strlen(pw->heading_label),
328 &direction, &ascent, &descent, &overall);
329 if (overall.width > pw->width) pw->width = overall.width;
330 pw->height += ascent + descent;
332 /* Measure the body_label. */
333 XTextExtents (pw->body_font,
334 pw->body_label, strlen(pw->body_label),
335 &direction, &ascent, &descent, &overall);
336 if (overall.width > pw->width) pw->width = overall.width;
337 pw->height += ascent + descent;
340 Dimension w2 = 0, w3 = 0, button_w = 0;
341 Dimension h2 = 0, h3 = 0, button_h = 0;
342 const char *passwd_string = "MMMMMMMMMMMM";
344 /* Measure the user_label. */
345 XTextExtents (pw->label_font,
346 pw->user_label, strlen(pw->user_label),
347 &direction, &ascent, &descent, &overall);
348 if (overall.width > w2) w2 = overall.width;
349 h2 += ascent + descent;
351 /* Measure the passwd_label. */
352 XTextExtents (pw->label_font,
353 pw->passwd_label, strlen(pw->passwd_label),
354 &direction, &ascent, &descent, &overall);
355 if (overall.width > w2) w2 = overall.width;
356 h2 += ascent + descent;
358 /* Measure the user_string. */
359 XTextExtents (pw->passwd_font,
360 pw->user_string, strlen(pw->user_string),
361 &direction, &ascent, &descent, &overall);
362 overall.width += (pw->shadow_width * 4);
363 ascent += (pw->shadow_width * 4);
364 if (overall.width > w3) w3 = overall.width;
365 h3 += ascent + descent;
367 /* Measure the (maximally-sized, dummy) passwd_string. */
368 XTextExtents (pw->passwd_font,
369 passwd_string, strlen(passwd_string),
370 &direction, &ascent, &descent, &overall);
371 overall.width += (pw->shadow_width * 4);
372 ascent += (pw->shadow_width * 4);
373 if (overall.width > w3) w3 = overall.width;
374 h3 += ascent + descent;
376 w2 = w2 + w3 + (pw->shadow_width * 2);
379 pw->login_button_width = 0;
380 pw->login_button_height = 0;
382 if (pw->login_button_p)
384 pw->login_button_enabled_p = True;
386 /* Measure the "New Login" button */
387 XTextExtents (pw->button_font, pw->login_label,
388 strlen (pw->login_label),
389 &direction, &ascent, &descent, &overall);
390 button_w = overall.width;
391 button_h = ascent + descent;
393 /* Add some horizontal padding inside the buttons. */
396 button_w += ((ascent + descent) / 2) + (pw->shadow_width * 2);
397 button_h += ((ascent + descent) / 2) + (pw->shadow_width * 2);
399 pw->login_button_width = button_w;
400 pw->login_button_height = button_h;
402 w2 = MAX (w2, button_w);
403 h2 += button_h * 1.5;
406 if (w2 > pw->width) pw->width = w2;
410 pw->width += (pw->internal_border * 2);
411 pw->height += (pw->internal_border * 4);
413 pw->width += pw->thermo_width + (pw->shadow_width * 3);
415 if (pw->logo_height > pw->height)
416 pw->height = pw->logo_height;
417 else if (pw->height > pw->logo_height)
418 pw->logo_height = pw->height;
420 pw->logo_width = pw->logo_height;
422 pw->width += pw->logo_width;
425 attrmask |= CWOverrideRedirect; attrs.override_redirect = True;
427 attrmask |= CWEventMask;
428 attrs.event_mask = (ExposureMask | KeyPressMask |
429 ButtonPressMask | ButtonReleaseMask);
431 /* We need to remember the mouse position and restore it afterward, or
432 sometimes (perhaps only with Xinerama?) the mouse gets warped to
433 inside the bounds of the lock dialog window.
436 Window pointer_root, pointer_child;
437 int root_x, root_y, win_x, win_y;
439 pw->previous_mouse_x = 0;
440 pw->previous_mouse_y = 0;
441 if (XQueryPointer (si->dpy, RootWindowOfScreen (pw->prompt_screen->screen),
442 &pointer_root, &pointer_child,
443 &root_x, &root_y, &win_x, &win_y, &mask))
445 pw->previous_mouse_x = root_x;
446 pw->previous_mouse_y = root_y;
447 if (si->prefs.verbose_p)
448 fprintf (stderr, "%s: %d: mouse is at %d,%d.\n",
449 blurb(), pw->prompt_screen->number,
450 pw->previous_mouse_x, pw->previous_mouse_y);
452 else if (si->prefs.verbose_p)
453 fprintf (stderr, "%s: %d: unable to determine mouse position?\n",
454 blurb(), pw->prompt_screen->number);
457 /* Figure out where on the desktop to place the window so that it will
458 actually be visible; this takes into account virtual viewports as
462 get_screen_viewport (pw->prompt_screen, &x, &y, &w, &h,
463 pw->previous_mouse_x, pw->previous_mouse_y,
464 si->prefs.verbose_p);
465 if (si->prefs.debug_p) w /= 2;
466 pw->x = x + ((w + pw->width) / 2) - pw->width;
467 pw->y = y + ((h + pw->height) / 2) - pw->height;
468 if (pw->x < x) pw->x = x;
469 if (pw->y < y) pw->y = y;
472 pw->border_width = get_integer_resource ("passwd.borderWidth",
473 "Dialog.BorderWidth");
476 XCreateWindow (si->dpy,
477 RootWindowOfScreen(screen),
478 pw->x, pw->y, pw->width, pw->height, pw->border_width,
479 DefaultDepthOfScreen (screen), InputOutput,
480 DefaultVisualOfScreen(screen),
482 XSetWindowBackground (si->dpy, si->passwd_dialog, pw->background);
484 /* We use the default visual, not ssi->visual, so that the logo pixmap's
485 visual matches that of the si->passwd_dialog window. */
486 pw->logo_pixmap = xscreensaver_logo (ssi->screen,
487 /* ssi->current_visual, */
488 DefaultVisualOfScreen(screen),
489 si->passwd_dialog, cmap,
491 &pw->logo_pixels, &pw->logo_npixels,
494 /* Before mapping the window, save the bits that are underneath the
495 rectangle the window will occlude. When we lower the window, we
496 restore these bits. This works, because the running screenhack
497 has already been sent SIGSTOP, so we know nothing else is drawing
502 pw->save_under = XCreatePixmap (si->dpy,
503 pw->prompt_screen->screensaver_window,
504 pw->width + (pw->border_width*2) + 1,
505 pw->height + (pw->border_width*2) + 1,
506 pw->prompt_screen->current_depth);
507 gcv.function = GXcopy;
508 gc = XCreateGC (si->dpy, pw->save_under, GCFunction, &gcv);
509 XCopyArea (si->dpy, pw->prompt_screen->screensaver_window,
511 pw->x - pw->border_width, pw->y - pw->border_width,
512 pw->width + (pw->border_width*2) + 1,
513 pw->height + (pw->border_width*2) + 1,
515 XFreeGC (si->dpy, gc);
518 XMapRaised (si->dpy, si->passwd_dialog);
519 XSync (si->dpy, False);
521 move_mouse_grab (si, si->passwd_dialog,
524 : pw->prompt_screen->cursor),
525 pw->prompt_screen->number);
531 XInstallColormap (si->dpy, cmap);
532 draw_passwd_window (si);
533 XSync (si->dpy, False);
538 draw_passwd_window (saver_info *si)
540 passwd_dialog_data *pw = si->pw_data;
544 int x1, x2, x3, y1, y2;
548 height = (pw->heading_font->ascent + pw->heading_font->descent +
549 pw->body_font->ascent + pw->body_font->descent +
550 (2 * MAX ((pw->label_font->ascent + pw->label_font->descent),
551 (pw->passwd_font->ascent + pw->passwd_font->descent +
552 (pw->shadow_width * 4)))) +
553 pw->date_font->ascent + pw->date_font->descent);
555 if (pw->login_button_p)
556 height += ((pw->button_font->ascent + pw->button_font->descent) * 2 +
557 2 * pw->shadow_width);
559 spacing = (((pw->height
560 - ((pw->login_button_p ? 4 : 2) * pw->shadow_width)
561 - pw->internal_border - height))
564 if (spacing < 0) spacing = 0;
566 gcv.foreground = pw->foreground;
567 gc1 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
568 gc2 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
569 x1 = pw->logo_width + pw->thermo_width + (pw->shadow_width * 3);
570 x3 = pw->width - (pw->shadow_width * 2);
571 y1 = (pw->shadow_width * 2) + spacing + spacing;
575 XSetFont (si->dpy, gc1, pw->heading_font->fid);
576 sw = string_width (pw->heading_font, pw->heading_label);
577 x2 = (x1 + ((x3 - x1 - sw) / 2));
578 y1 += spacing + pw->heading_font->ascent + pw->heading_font->descent;
579 XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
580 pw->heading_label, strlen(pw->heading_label));
582 /* text below top heading
584 XSetFont (si->dpy, gc1, pw->body_font->fid);
585 y1 += spacing + pw->body_font->ascent + pw->body_font->descent;
586 sw = string_width (pw->body_font, pw->body_label);
587 x2 = (x1 + ((x3 - x1 - sw) / 2));
588 XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
589 pw->body_label, strlen(pw->body_label));
592 tb_height = (pw->passwd_font->ascent + pw->passwd_font->descent +
593 (pw->shadow_width * 4));
595 /* the "User:" prompt
599 XSetForeground (si->dpy, gc1, pw->foreground);
600 XSetFont (si->dpy, gc1, pw->label_font->fid);
601 y1 += (spacing + tb_height);
602 x2 = (x1 + pw->internal_border +
603 MAX(string_width (pw->label_font, pw->user_label),
604 string_width (pw->label_font, pw->passwd_label)));
605 XDrawString (si->dpy, si->passwd_dialog, gc1,
606 x2 - string_width (pw->label_font, pw->user_label),
607 y1 - pw->passwd_font->descent,
608 pw->user_label, strlen(pw->user_label));
610 /* the "Password:" prompt
612 y1 += (spacing + tb_height);
613 XDrawString (si->dpy, si->passwd_dialog, gc1,
614 x2 - string_width (pw->label_font, pw->passwd_label),
615 y1 - pw->passwd_font->descent,
616 pw->passwd_label, strlen(pw->passwd_label));
619 XSetForeground (si->dpy, gc2, pw->passwd_background);
621 /* the "user name" text field
624 XSetForeground (si->dpy, gc1, pw->passwd_foreground);
625 XSetFont (si->dpy, gc1, pw->passwd_font->fid);
626 y1 += (spacing + tb_height);
627 x2 += (pw->shadow_width * 4);
629 pw->passwd_field_width = x3 - x2 - pw->internal_border;
630 pw->passwd_field_height = (pw->passwd_font->ascent +
631 pw->passwd_font->descent +
634 XFillRectangle (si->dpy, si->passwd_dialog, gc2,
635 x2 - pw->shadow_width,
636 y1 - (pw->passwd_font->ascent + pw->passwd_font->descent),
637 pw->passwd_field_width, pw->passwd_field_height);
638 XDrawString (si->dpy, si->passwd_dialog, gc1,
640 y1 - pw->passwd_font->descent,
641 pw->user_string, strlen(pw->user_string));
643 /* the "password" text field
645 y1 += (spacing + tb_height);
647 pw->passwd_field_x = x2 - pw->shadow_width;
648 pw->passwd_field_y = y1 - (pw->passwd_font->ascent +
649 pw->passwd_font->descent);
651 /* The shadow around the text fields
654 y1 += (spacing + (pw->shadow_width * 3));
655 x1 = x2 - (pw->shadow_width * 2);
656 x2 = pw->passwd_field_width + (pw->shadow_width * 2);
657 y2 = pw->passwd_field_height + (pw->shadow_width * 2);
659 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
662 pw->shadow_bottom, pw->shadow_top);
664 y1 += (spacing + pw->passwd_font->ascent + pw->passwd_font->descent +
665 (pw->shadow_width * 4));
666 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
669 pw->shadow_bottom, pw->shadow_top);
672 /* The date, below the text fields
676 time_t now = time ((time_t *) 0);
677 struct tm *tm = localtime (&now);
678 memset (buf, 0, sizeof(buf));
679 strftime (buf, sizeof(buf)-1, pw->date_label, tm);
681 XSetFont (si->dpy, gc1, pw->date_font->fid);
682 y1 += pw->shadow_width;
683 y1 += (spacing + tb_height);
685 sw = string_width (pw->date_font, buf);
687 XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1, buf, strlen(buf));
690 /* The "New Login" button
692 if (pw->login_button_p)
694 XSetForeground (si->dpy, gc1, pw->button_foreground);
695 XSetForeground (si->dpy, gc2, pw->button_background);
696 XSetFont (si->dpy, gc1, pw->button_font->fid);
698 sw = string_width (pw->button_font, pw->login_label);
700 x2 = pw->width - pw->internal_border - (pw->shadow_width * 2);
702 /* right aligned button */
703 /* x1 = x2 - pw->login_button_width; */
705 /* centered button */
706 x1 = (pw->logo_width + pw->thermo_width + (pw->shadow_width * 3) +
707 pw->internal_border);
708 x1 = x1 + (x2 - x1 - pw->login_button_width) / 2;
710 y1 = (pw->height - pw->internal_border - pw->login_button_height +
713 ((pw->login_button_height -
714 (pw->button_font->ascent + pw->button_font->descent))
716 pw->button_font->ascent);
718 pw->login_button_x = x1;
719 pw->login_button_y = y1;
724 x1 = pw->shadow_width * 6;
725 y1 = pw->shadow_width * 6;
726 x2 = pw->logo_width - (pw->shadow_width * 12);
727 y2 = pw->logo_height - (pw->shadow_width * 12);
733 unsigned int w, h, bw, d;
734 XGetGeometry (si->dpy, pw->logo_pixmap, &root, &x, &y, &w, &h, &bw, &d);
735 XSetForeground (si->dpy, gc1, pw->foreground);
736 XSetBackground (si->dpy, gc1, pw->background);
738 XCopyPlane (si->dpy, pw->logo_pixmap, si->passwd_dialog, gc1,
740 x1 + ((x2 - (int)w) / 2),
741 y1 + ((y2 - (int)h) / 2),
744 XCopyArea (si->dpy, pw->logo_pixmap, si->passwd_dialog, gc1,
746 x1 + ((x2 - (int)w) / 2),
747 y1 + ((y2 - (int)h) / 2));
752 XSetForeground (si->dpy, gc1, pw->thermo_foreground);
753 XSetForeground (si->dpy, gc2, pw->thermo_background);
755 pw->thermo_field_x = pw->logo_width + pw->shadow_width;
756 pw->thermo_field_y = pw->shadow_width * 5;
757 pw->thermo_field_height = pw->height - (pw->shadow_width * 10);
760 /* Solid border inside the logo box. */
761 XSetForeground (si->dpy, gc1, pw->foreground);
762 XDrawRectangle (si->dpy, si->passwd_dialog, gc1, x1, y1, x2-1, y2-1);
765 /* The shadow around the logo
767 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
768 pw->shadow_width * 4,
769 pw->shadow_width * 4,
770 pw->logo_width - (pw->shadow_width * 8),
771 pw->logo_height - (pw->shadow_width * 8),
773 pw->shadow_bottom, pw->shadow_top);
775 /* The shadow around the thermometer
777 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
779 pw->shadow_width * 4,
780 pw->thermo_width + (pw->shadow_width * 2),
781 pw->height - (pw->shadow_width * 8),
783 pw->shadow_bottom, pw->shadow_top);
786 /* Solid border inside the thermometer. */
787 XSetForeground (si->dpy, gc1, pw->foreground);
788 XDrawRectangle (si->dpy, si->passwd_dialog, gc1,
789 pw->thermo_field_x, pw->thermo_field_y,
790 pw->thermo_width - 1, pw->thermo_field_height - 1);
793 /* The shadow around the whole window
795 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
796 0, 0, pw->width, pw->height, pw->shadow_width,
797 pw->shadow_top, pw->shadow_bottom);
799 XFreeGC (si->dpy, gc1);
800 XFreeGC (si->dpy, gc2);
802 update_passwd_window (si, pw->passwd_string, pw->ratio);
807 update_passwd_window (saver_info *si, const char *printed_passwd, float ratio)
809 passwd_dialog_data *pw = si->pw_data;
816 gcv.foreground = pw->passwd_foreground;
817 gcv.font = pw->passwd_font->fid;
818 gc1 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground|GCFont, &gcv);
819 gcv.foreground = pw->passwd_background;
820 gc2 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
824 char *s = strdup (printed_passwd);
825 if (pw->passwd_string) free (pw->passwd_string);
826 pw->passwd_string = s;
829 /* the "password" text field
831 rects[0].x = pw->passwd_field_x;
832 rects[0].y = pw->passwd_field_y;
833 rects[0].width = pw->passwd_field_width;
834 rects[0].height = pw->passwd_field_height;
836 XFillRectangle (si->dpy, si->passwd_dialog, gc2,
837 rects[0].x, rects[0].y, rects[0].width, rects[0].height);
839 XSetClipRectangles (si->dpy, gc1, 0, 0, rects, 1, Unsorted);
841 XDrawString (si->dpy, si->passwd_dialog, gc1,
842 rects[0].x + pw->shadow_width,
843 rects[0].y + pw->passwd_font->ascent,
844 pw->passwd_string, strlen(pw->passwd_string));
846 XSetClipMask (si->dpy, gc1, None);
852 x = (rects[0].x + pw->shadow_width +
853 string_width (pw->passwd_font, pw->passwd_string));
854 y = rects[0].y + pw->shadow_width;
856 if (x > rects[0].x + rects[0].width - 1)
857 x = rects[0].x + rects[0].width - 1;
858 XDrawLine (si->dpy, si->passwd_dialog, gc1,
860 x, y + pw->passwd_font->ascent + pw->passwd_font->descent-1);
863 pw->i_beam = (pw->i_beam + 1) % 4;
868 y = (pw->thermo_field_height - 2) * (1.0 - pw->ratio);
871 XFillRectangle (si->dpy, si->passwd_dialog, gc2,
872 pw->thermo_field_x + 1,
873 pw->thermo_field_y + 1,
876 XSetForeground (si->dpy, gc1, pw->thermo_foreground);
877 XFillRectangle (si->dpy, si->passwd_dialog, gc1,
878 pw->thermo_field_x + 1,
879 pw->thermo_field_y + 1 + y,
881 MAX (0, pw->thermo_field_height - y - 2));
884 /* The "New Login" button
886 if (pw->login_button_p)
889 XSetFont (si->dpy, gc1, pw->button_font->fid);
890 XSetForeground (si->dpy, gc1,
891 (pw->login_button_enabled_p
892 ? pw->passwd_foreground
893 : pw->shadow_bottom));
894 XSetForeground (si->dpy, gc2, pw->button_background);
896 XFillRectangle (si->dpy, si->passwd_dialog, gc2,
897 pw->login_button_x, pw->login_button_y,
898 pw->login_button_width, pw->login_button_height);
900 sw = string_width (pw->button_font, pw->login_label);
901 x2 = pw->login_button_x + ((pw->login_button_width - sw) / 2);
902 y2 = (pw->login_button_y +
903 ((pw->login_button_height -
904 (pw->button_font->ascent + pw->button_font->descent))
906 pw->button_font->ascent);
908 XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y2,
909 pw->login_label, strlen(pw->login_label));
911 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
912 pw->login_button_x, pw->login_button_y,
913 pw->login_button_width, pw->login_button_height,
915 (pw->login_button_down_p
918 (pw->login_button_down_p
920 : pw->shadow_bottom));
923 XFreeGC (si->dpy, gc1);
924 XFreeGC (si->dpy, gc2);
925 XSync (si->dpy, False);
930 destroy_passwd_window (saver_info *si)
932 saver_preferences *p = &si->prefs;
933 passwd_dialog_data *pw = si->pw_data;
934 saver_screen_info *ssi = pw->prompt_screen;
935 Colormap cmap = DefaultColormapOfScreen (ssi->screen);
936 Pixel black = BlackPixelOfScreen (ssi->screen);
937 Pixel white = WhitePixelOfScreen (ssi->screen);
940 memset (pw->typed_passwd, 0, sizeof(pw->typed_passwd));
941 memset (pw->passwd_string, 0, strlen(pw->passwd_string));
944 XtRemoveTimeOut (pw->timer);
946 move_mouse_grab (si, RootWindowOfScreen (ssi->screen),
947 ssi->cursor, ssi->number);
949 if (pw->passwd_cursor)
950 XFreeCursor (si->dpy, pw->passwd_cursor);
953 fprintf (stderr, "%s: %d: moving mouse back to %d,%d.\n",
954 blurb(), ssi->number,
955 pw->previous_mouse_x, pw->previous_mouse_y);
957 XWarpPointer (si->dpy, None, RootWindowOfScreen (ssi->screen),
959 pw->previous_mouse_x, pw->previous_mouse_y);
961 XSync (si->dpy, False);
962 while (XCheckMaskEvent (si->dpy, PointerMotionMask, &event))
964 fprintf (stderr, "%s: discarding MotionNotify event.\n", blurb());
966 if (si->passwd_dialog)
968 XDestroyWindow (si->dpy, si->passwd_dialog);
969 si->passwd_dialog = 0;
976 gcv.function = GXcopy;
977 gc = XCreateGC (si->dpy, ssi->screensaver_window, GCFunction, &gcv);
978 XCopyArea (si->dpy, pw->save_under,
979 ssi->screensaver_window, gc,
981 pw->width + (pw->border_width*2) + 1,
982 pw->height + (pw->border_width*2) + 1,
983 pw->x - pw->border_width, pw->y - pw->border_width);
984 XFreePixmap (si->dpy, pw->save_under);
986 XFreeGC (si->dpy, gc);
989 if (pw->heading_label) free (pw->heading_label);
990 if (pw->body_label) free (pw->body_label);
991 if (pw->user_label) free (pw->user_label);
992 if (pw->passwd_label) free (pw->passwd_label);
993 if (pw->date_label) free (pw->date_label);
994 if (pw->login_label) free (pw->login_label);
995 if (pw->user_string) free (pw->user_string);
996 if (pw->passwd_string) free (pw->passwd_string);
998 if (pw->heading_font) XFreeFont (si->dpy, pw->heading_font);
999 if (pw->body_font) XFreeFont (si->dpy, pw->body_font);
1000 if (pw->label_font) XFreeFont (si->dpy, pw->label_font);
1001 if (pw->passwd_font) XFreeFont (si->dpy, pw->passwd_font);
1002 if (pw->date_font) XFreeFont (si->dpy, pw->date_font);
1003 if (pw->button_font) XFreeFont (si->dpy, pw->button_font);
1005 if (pw->foreground != black && pw->foreground != white)
1006 XFreeColors (si->dpy, cmap, &pw->foreground, 1, 0L);
1007 if (pw->background != black && pw->background != white)
1008 XFreeColors (si->dpy, cmap, &pw->background, 1, 0L);
1009 if (!(pw->button_foreground == black || pw->button_foreground == white))
1010 XFreeColors (si->dpy, cmap, &pw->button_foreground, 1, 0L);
1011 if (!(pw->button_background == black || pw->button_background == white))
1012 XFreeColors (si->dpy, cmap, &pw->button_background, 1, 0L);
1013 if (pw->passwd_foreground != black && pw->passwd_foreground != white)
1014 XFreeColors (si->dpy, cmap, &pw->passwd_foreground, 1, 0L);
1015 if (pw->passwd_background != black && pw->passwd_background != white)
1016 XFreeColors (si->dpy, cmap, &pw->passwd_background, 1, 0L);
1017 if (pw->thermo_foreground != black && pw->thermo_foreground != white)
1018 XFreeColors (si->dpy, cmap, &pw->thermo_foreground, 1, 0L);
1019 if (pw->thermo_background != black && pw->thermo_background != white)
1020 XFreeColors (si->dpy, cmap, &pw->thermo_background, 1, 0L);
1021 if (pw->shadow_top != black && pw->shadow_top != white)
1022 XFreeColors (si->dpy, cmap, &pw->shadow_top, 1, 0L);
1023 if (pw->shadow_bottom != black && pw->shadow_bottom != white)
1024 XFreeColors (si->dpy, cmap, &pw->shadow_bottom, 1, 0L);
1026 if (pw->logo_pixmap)
1027 XFreePixmap (si->dpy, pw->logo_pixmap);
1028 if (pw->logo_pixels)
1030 if (pw->logo_npixels)
1031 XFreeColors (si->dpy, cmap, pw->logo_pixels, pw->logo_npixels, 0L);
1032 free (pw->logo_pixels);
1033 pw->logo_pixels = 0;
1034 pw->logo_npixels = 0;
1038 XFreePixmap (si->dpy, pw->save_under);
1041 XInstallColormap (si->dpy, cmap);
1043 memset (pw, 0, sizeof(*pw));
1049 static Bool error_handler_hit_p = False;
1052 ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error)
1054 error_handler_hit_p = True;
1059 #ifdef HAVE_XHPDISABLERESET
1060 /* This function enables and disables the C-Sh-Reset hot-key, which
1061 normally resets the X server (logging out the logged-in user.)
1062 We don't want random people to be able to do that while the
1066 hp_lock_reset (saver_info *si, Bool lock_p)
1068 static Bool hp_locked_p = False;
1070 /* Calls to XHPDisableReset and XHPEnableReset must be balanced,
1071 or BadAccess errors occur. (It's ok for this to be global,
1072 since it affects the whole machine, not just the current screen.)
1074 if (hp_locked_p == lock_p)
1078 XHPDisableReset (si->dpy);
1080 XHPEnableReset (si->dpy);
1081 hp_locked_p = lock_p;
1083 #endif /* HAVE_XHPDISABLERESET */
1086 #ifdef HAVE_XF86MISCSETGRABKEYSSTATE
1088 /* This function enables and disables the Ctrl-Alt-KP_star and
1089 Ctrl-Alt-KP_slash hot-keys, which (in XFree86 4.2) break any
1090 grabs and/or kill the grabbing client. That would effectively
1091 unlock the screen, so we don't like that.
1093 The Ctrl-Alt-KP_star and Ctrl-Alt-KP_slash hot-keys only exist
1094 if AllowDeactivateGrabs and/or AllowClosedownGrabs are turned on
1095 in XF86Config. I believe they are disabled by default.
1097 This does not affect any other keys (specifically Ctrl-Alt-BS or
1098 Ctrl-Alt-F1) but I wish it did. Maybe it will someday.
1101 xfree_lock_grab_smasher (saver_info *si, Bool lock_p)
1103 saver_preferences *p = &si->prefs;
1106 XErrorHandler old_handler;
1107 XSync (si->dpy, False);
1108 error_handler_hit_p = False;
1109 old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
1110 XSync (si->dpy, False);
1111 status = XF86MiscSetGrabKeysState (si->dpy, !lock_p);
1112 XSync (si->dpy, False);
1113 if (error_handler_hit_p) status = 666;
1115 if (!lock_p && status == MiscExtGrabStateAlready)
1116 status = MiscExtGrabStateSuccess; /* shut up, consider this success */
1118 if (p->verbose_p && status != MiscExtGrabStateSuccess)
1119 fprintf (stderr, "%s: error: XF86MiscSetGrabKeysState(%d) returned %s\n",
1121 (status == MiscExtGrabStateSuccess ? "MiscExtGrabStateSuccess" :
1122 status == MiscExtGrabStateLocked ? "MiscExtGrabStateLocked" :
1123 status == MiscExtGrabStateAlready ? "MiscExtGrabStateAlready" :
1124 status == 666 ? "an X error" :
1127 XSync (si->dpy, False);
1128 XSetErrorHandler (old_handler);
1129 XSync (si->dpy, False);
1131 #endif /* HAVE_XF86MISCSETGRABKEYSSTATE */
1136 /* This function enables and disables the C-Sh-F1 ... F12 hot-keys,
1137 which, on Linux systems, switches to another virtual console.
1138 We'd like the whole screen/keyboard to be locked, not just one
1139 virtual console, so this function disables that while the X
1142 Unfortunately, this doesn't work -- this ioctl only works when
1143 called by root, and we have disavowed our privileges long ago.
1145 #ifdef HAVE_VT_LOCKSWITCH
1147 linux_lock_vt_switch (saver_info *si, Bool lock_p)
1149 saver_preferences *p = &si->prefs;
1150 static Bool vt_locked_p = False;
1151 const char *dev_console = "/dev/console";
1154 if (lock_p == vt_locked_p)
1157 if (lock_p && !p->lock_vt_p)
1160 fd = open (dev_console, O_RDWR);
1164 sprintf (buf, "%s: couldn't %s VTs: %s", blurb(),
1165 (lock_p ? "lock" : "unlock"),
1167 #if 1 /* #### doesn't work yet, so don't bother complaining */
1173 if (ioctl (fd, (lock_p ? VT_LOCKSWITCH : VT_UNLOCKSWITCH)) == 0)
1175 vt_locked_p = lock_p;
1178 fprintf (stderr, "%s: %s VTs\n", blurb(),
1179 (lock_p ? "locked" : "unlocked"));
1184 sprintf (buf, "%s: couldn't %s VTs: ioctl", blurb(),
1185 (lock_p ? "lock" : "unlock"));
1186 #if 0 /* #### doesn't work yet, so don't bother complaining */
1193 #endif /* HAVE_VT_LOCKSWITCH */
1196 /* This function enables and disables the C-Alt-Plus and C-Alt-Minus
1197 hot-keys, which normally change the resolution of the X server.
1198 We don't want people to be able to switch the server resolution
1199 while the screen is locked, because if they switch to a higher
1200 resolution, it could cause part of the underlying desktop to become
1203 #ifdef HAVE_XF86VMODE
1206 xfree_lock_mode_switch (saver_info *si, Bool lock_p)
1208 static Bool any_mode_locked_p = False;
1209 saver_preferences *p = &si->prefs;
1213 XErrorHandler old_handler;
1215 if (any_mode_locked_p == lock_p)
1217 if (!XF86VidModeQueryExtension (si->dpy, &event, &error))
1220 for (screen = 0; screen < (si->xinerama_p ? 1 : si->nscreens); screen++)
1222 XSync (si->dpy, False);
1223 old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
1224 error_handler_hit_p = False;
1225 status = XF86VidModeLockModeSwitch (si->dpy, screen, lock_p);
1226 XSync (si->dpy, False);
1227 XSetErrorHandler (old_handler);
1228 if (error_handler_hit_p) status = False;
1231 any_mode_locked_p = lock_p;
1233 if (!status && (p->verbose_p || !lock_p))
1234 /* Only print this when verbose, or when we locked but can't unlock.
1235 I tried printing this message whenever it comes up, but
1236 mode-locking always fails if DontZoom is set in XF86Config. */
1237 fprintf (stderr, "%s: %d: unable to %s mode switching!\n",
1238 blurb(), screen, (lock_p ? "lock" : "unlock"));
1239 else if (p->verbose_p)
1240 fprintf (stderr, "%s: %d: %s mode switching.\n",
1241 blurb(), screen, (lock_p ? "locked" : "unlocked"));
1244 #endif /* HAVE_XF86VMODE */
1247 /* If the viewport has been scrolled since the screen was blanked,
1248 then scroll it back to where it belongs. This function only exists
1249 to patch over a very brief race condition.
1252 undo_vp_motion (saver_info *si)
1254 #ifdef HAVE_XF86VMODE
1255 saver_preferences *p = &si->prefs;
1259 if (!XF86VidModeQueryExtension (si->dpy, &event, &error))
1262 for (screen = 0; screen < si->nscreens; screen++)
1264 saver_screen_info *ssi = &si->screens[screen];
1268 if (ssi->blank_vp_x == -1 && ssi->blank_vp_y == -1)
1270 if (!XF86VidModeGetViewPort (si->dpy, screen, &x, &y))
1272 if (ssi->blank_vp_x == x && ssi->blank_vp_y == y)
1275 /* We're going to move the viewport. The mouse has just been grabbed on
1276 (and constrained to, thus warped to) the password window, so it is no
1277 longer near the edge of the screen. However, wait a bit anyway, just
1278 to make sure the server drains its last motion event, so that the
1279 screen doesn't continue to scroll after we've reset the viewport.
1281 XSync (si->dpy, False);
1282 usleep (250000); /* 1/4 second */
1283 XSync (si->dpy, False);
1285 status = XF86VidModeSetViewPort (si->dpy, screen,
1286 ssi->blank_vp_x, ssi->blank_vp_y);
1290 "%s: %d: unable to move vp from (%d,%d) back to (%d,%d)!\n",
1291 blurb(), screen, x, y, ssi->blank_vp_x, ssi->blank_vp_y);
1292 else if (p->verbose_p)
1294 "%s: %d: vp moved to (%d,%d); moved it back to (%d,%d).\n",
1295 blurb(), screen, x, y, ssi->blank_vp_x, ssi->blank_vp_y);
1297 #endif /* HAVE_XF86VMODE */
1306 passwd_animate_timer (XtPointer closure, XtIntervalId *id)
1308 saver_info *si = (saver_info *) closure;
1310 passwd_dialog_data *pw = si->pw_data;
1314 pw->ratio -= (1.0 / ((double) si->prefs.passwd_timeout / (double) tick));
1318 if (pw->state == pw_read)
1319 pw->state = pw_time;
1322 update_passwd_window (si, 0, pw->ratio);
1324 if (pw->state == pw_read)
1325 pw->timer = XtAppAddTimeOut (si->app, tick, passwd_animate_timer,
1330 idle_timer ((XtPointer) si, 0);
1334 static XComposeStatus *compose_status;
1337 handle_passwd_button (saver_info *si, XEvent *event)
1339 saver_preferences *p = &si->prefs;
1340 Bool mouse_in_box = False;
1342 passwd_dialog_data *pw = si->pw_data;
1343 saver_screen_info *ssi = pw->prompt_screen;
1345 if (! pw->login_button_enabled_p)
1349 (event->xbutton.x >= pw->login_button_x &&
1350 event->xbutton.x <= pw->login_button_x + pw->login_button_width &&
1351 event->xbutton.y >= pw->login_button_y &&
1352 event->xbutton.y <= pw->login_button_y + pw->login_button_height);
1354 if (ButtonRelease == event->xany.type &&
1355 pw->login_button_down_p &&
1358 /* Only allow them to press the button once: don't want to
1359 accidentally launch a dozen gdm choosers if the machine
1363 pw->login_button_enabled_p = False;
1366 pw->login_button_down_p = (mouse_in_box &&
1367 ButtonRelease != event->xany.type);
1369 update_passwd_window (si, 0, pw->ratio);
1372 fork_and_exec (ssi, p->new_login_command);
1377 handle_passwd_key (saver_info *si, XKeyEvent *event)
1379 saver_preferences *p = &si->prefs;
1380 passwd_dialog_data *pw = si->pw_data;
1381 int pw_size = sizeof (pw->typed_passwd) - 1;
1382 char *typed_passwd = pw->typed_passwd;
1386 int size = XLookupString (event, s, 1, 0, compose_status);
1388 if (size != 1) return;
1392 /* Add 10% to the time remaining every time a key is pressed. */
1394 if (pw->ratio > 1) pw->ratio = 1;
1398 case '\010': case '\177': /* Backspace */
1402 typed_passwd [strlen(typed_passwd)-1] = 0;
1405 case '\025': case '\030': /* Erase line */
1406 memset (typed_passwd, 0, pw_size);
1409 case '\012': case '\015': /* Enter */
1410 if (pw->state != pw_read)
1411 ; /* already done? */
1412 else if (typed_passwd[0] == 0)
1413 pw->state = pw_null;
1416 update_passwd_window (si, "Checking...", pw->ratio);
1417 XSync (si->dpy, False);
1418 if (passwd_valid_p (typed_passwd, p->verbose_p))
1421 pw->state = pw_fail;
1422 update_passwd_window (si, "", pw->ratio);
1427 i = strlen (typed_passwd);
1432 typed_passwd [i] = *s;
1433 typed_passwd [i+1] = 0;
1438 if (pw->show_stars_p)
1440 i = strlen(typed_passwd);
1441 stars = (char *) malloc(i+1);
1442 memset (stars, '*', i);
1444 update_passwd_window (si, stars, pw->ratio);
1449 update_passwd_window (si, "", pw->ratio);
1455 passwd_event_loop (saver_info *si)
1457 saver_preferences *p = &si->prefs;
1460 unsigned int caps_p = 0;
1462 passwd_animate_timer ((XtPointer) si, 0);
1464 while (si->pw_data && si->pw_data->state == pw_read)
1466 XtAppNextEvent (si->app, &event);
1467 if (event.xany.window == si->passwd_dialog && event.xany.type == Expose)
1468 draw_passwd_window (si);
1469 else if (event.xany.type == KeyPress)
1471 handle_passwd_key (si, &event.xkey);
1472 caps_p = (event.xkey.state & LockMask);
1474 else if ((event.xany.type == ButtonPress ||
1475 event.xany.type == ButtonRelease) &&
1476 si->pw_data->login_button_p)
1477 handle_passwd_button (si, &event);
1479 XtDispatchEvent (&event);
1482 switch (si->pw_data->state)
1484 case pw_ok: msg = 0; break;
1485 case pw_null: msg = ""; break;
1486 case pw_time: msg = "Timed out!"; break;
1487 default: msg = (caps_p ? "CapsLock?" : "Sorry!"); break;
1490 if (si->pw_data->state == pw_fail)
1491 si->unlock_failures++;
1494 switch (si->pw_data->state)
1497 fprintf (stderr, "%s: password correct.\n", blurb()); break;
1499 fprintf (stderr, "%s: password incorrect!%s\n", blurb(),
1500 (caps_p ? " (CapsLock)" : ""));
1504 fprintf (stderr, "%s: password entry cancelled.\n", blurb()); break;
1506 fprintf (stderr, "%s: password entry timed out.\n", blurb()); break;
1511 if (si->pw_data->state == pw_fail)
1513 /* If they typed a password (as opposed to just hitting return) and
1514 the password was invalid, log it.
1516 struct passwd *pw = getpwuid (getuid ());
1517 char *d = DisplayString (si->dpy);
1518 char *u = (pw->pw_name ? pw->pw_name : "???");
1526 # if defined(LOG_AUTHPRIV)
1528 # elif defined(LOG_AUTH)
1535 openlog (progname, opt, fac);
1536 syslog (LOG_NOTICE, "FAILED LOGIN %d ON DISPLAY \"%s\", FOR \"%s\"",
1537 si->unlock_failures, d, u);
1540 #endif /* HAVE_SYSLOG */
1542 if (si->pw_data->state == pw_fail)
1543 XBell (si->dpy, False);
1545 if (si->pw_data->state == pw_ok && si->unlock_failures != 0)
1547 if (si->unlock_failures == 1)
1548 fprintf (real_stderr,
1549 "%s: WARNING: 1 failed attempt to unlock the screen.\n",
1552 fprintf (real_stderr,
1553 "%s: WARNING: %d failed attempts to unlock the screen.\n",
1554 blurb(), si->unlock_failures);
1555 fflush (real_stderr);
1557 si->unlock_failures = 0;
1562 si->pw_data->i_beam = 0;
1563 update_passwd_window (si, msg, 0.0);
1564 XSync (si->dpy, False);
1567 /* Swallow all pending KeyPress/KeyRelease events. */
1570 while (XCheckMaskEvent (si->dpy, KeyPressMask|KeyReleaseMask, &e))
1578 handle_typeahead (saver_info *si)
1580 passwd_dialog_data *pw = si->pw_data;
1582 if (!si->unlock_typeahead)
1585 i = strlen (si->unlock_typeahead);
1586 if (i >= sizeof(pw->typed_passwd) - 1)
1587 i = sizeof(pw->typed_passwd) - 1;
1589 memcpy (pw->typed_passwd, si->unlock_typeahead, i);
1590 pw->typed_passwd [i] = 0;
1592 memset (si->unlock_typeahead, '*', strlen(si->unlock_typeahead));
1593 si->unlock_typeahead[i] = 0;
1594 update_passwd_window (si, si->unlock_typeahead, pw->ratio);
1596 free (si->unlock_typeahead);
1597 si->unlock_typeahead = 0;
1602 unlock_p (saver_info *si)
1604 saver_preferences *p = &si->prefs;
1607 raise_window (si, True, True, True);
1610 fprintf (stderr, "%s: prompting for password.\n", blurb());
1612 if (si->pw_data || si->passwd_dialog)
1613 destroy_passwd_window (si);
1615 make_passwd_window (si);
1617 compose_status = calloc (1, sizeof (*compose_status));
1619 handle_typeahead (si);
1620 passwd_event_loop (si);
1622 status = (si->pw_data->state == pw_ok);
1623 destroy_passwd_window (si);
1625 free (compose_status);
1633 set_locked_p (saver_info *si, Bool locked_p)
1635 si->locked_p = locked_p;
1637 #ifdef HAVE_XHPDISABLERESET
1638 hp_lock_reset (si, locked_p); /* turn off/on C-Sh-Reset */
1640 #ifdef HAVE_VT_LOCKSWITCH
1641 linux_lock_vt_switch (si, locked_p); /* turn off/on C-Alt-F1 */
1643 #ifdef HAVE_XF86VMODE
1644 xfree_lock_mode_switch (si, locked_p); /* turn off/on C-Alt-Plus */
1646 #ifdef HAVE_XF86MISCSETGRABKEYSSTATE
1647 xfree_lock_grab_smasher (si, locked_p); /* turn off/on C-Alt-KP-*,/ */
1650 store_saver_status (si); /* store locked-p */
1654 #else /* NO_LOCKING -- whole file */
1657 set_locked_p (saver_info *si, Bool locked_p)
1659 if (locked_p) abort();
1662 #endif /* !NO_LOCKING */