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;
109 XFontStruct *heading_font;
110 XFontStruct *body_font;
111 XFontStruct *label_font;
112 XFontStruct *passwd_font;
113 XFontStruct *date_font;
114 XFontStruct *button_font;
118 Pixel passwd_foreground;
119 Pixel passwd_background;
120 Pixel thermo_foreground;
121 Pixel thermo_background;
124 Pixel button_foreground;
125 Pixel button_background;
127 Dimension logo_width;
128 Dimension logo_height;
129 Dimension thermo_width;
130 Dimension internal_border;
131 Dimension shadow_width;
133 Dimension passwd_field_x, passwd_field_y;
134 Dimension passwd_field_width, passwd_field_height;
136 Dimension login_button_x, login_button_y;
137 Dimension login_button_width, login_button_height;
139 Dimension thermo_field_x, thermo_field_y;
140 Dimension thermo_field_height;
144 unsigned long *logo_pixels;
146 Cursor passwd_cursor;
147 Bool login_button_down_p;
149 Bool login_button_enabled_p;
154 static void draw_passwd_window (saver_info *si);
155 static void update_passwd_window (saver_info *si, const char *printed_passwd,
157 static void destroy_passwd_window (saver_info *si);
158 static void undo_vp_motion (saver_info *si);
159 static void handle_passwd_button (saver_info *si, XEvent *event);
163 make_passwd_window (saver_info *si)
165 struct passwd *p = getpwuid (getuid ());
166 XSetWindowAttributes attrs;
167 unsigned long attrmask = 0;
168 passwd_dialog_data *pw = (passwd_dialog_data *) calloc (1, sizeof(*pw));
172 saver_screen_info *ssi = &si->screens [mouse_screen (si)];
174 /* Display the button only if the "newLoginCommand" pref is non-null.
176 pw->login_button_p = (si->prefs.new_login_command &&
177 *si->prefs.new_login_command);
179 if (pw->login_button_p)
180 pw->passwd_cursor = XCreateFontCursor (si->dpy, XC_top_left_arrow);
182 pw->passwd_cursor = 0;
184 pw->prompt_screen = ssi;
185 if (si->prefs.verbose_p)
186 fprintf (stderr, "%s: %d: creating password dialog.\n",
187 blurb(), pw->prompt_screen->number);
189 screen = pw->prompt_screen->screen;
190 cmap = DefaultColormapOfScreen (screen);
194 pw->heading_label = get_string_resource ("passwd.heading.label",
195 "Dialog.Label.Label");
196 pw->body_label = get_string_resource ("passwd.body.label",
197 "Dialog.Label.Label");
198 pw->user_label = get_string_resource ("passwd.user.label",
199 "Dialog.Label.Label");
200 pw->passwd_label = get_string_resource ("passwd.passwd.label",
201 "Dialog.Label.Label");
202 pw->login_label = get_string_resource ("passwd.login.label",
203 "Dialog.Button.Label");
205 pw->date_label = get_string_resource ("dateFormat", "DateFormat");
207 if (!pw->heading_label)
208 pw->heading_label = strdup("ERROR: RESOURCES NOT INSTALLED CORRECTLY");
210 pw->body_label = strdup("ERROR: RESOURCES NOT INSTALLED CORRECTLY");
211 if (!pw->user_label) pw->user_label = strdup("ERROR");
212 if (!pw->passwd_label) pw->passwd_label = strdup("ERROR");
213 if (!pw->date_label) pw->date_label = strdup("ERROR");
214 if (!pw->login_label) pw->login_label = strdup ("ERROR (LOGIN)") ;
216 /* Put the version number in the label. */
218 char *s = (char *) malloc (strlen(pw->heading_label) + 20);
219 sprintf(s, pw->heading_label, si->version);
220 free (pw->heading_label);
221 pw->heading_label = s;
224 pw->user_string = strdup (p && p->pw_name ? p->pw_name : "???");
225 pw->passwd_string = strdup("");
227 f = get_string_resource ("passwd.headingFont", "Dialog.Font");
228 pw->heading_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
229 if (!pw->heading_font) pw->heading_font = XLoadQueryFont (si->dpy, "fixed");
232 f = get_string_resource ("passwd.buttonFont", "Dialog.Font");
233 pw->button_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
234 if (!pw->button_font) pw->button_font = XLoadQueryFont (si->dpy, "fixed");
237 f = get_string_resource("passwd.bodyFont", "Dialog.Font");
238 pw->body_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
239 if (!pw->body_font) pw->body_font = XLoadQueryFont (si->dpy, "fixed");
242 f = get_string_resource("passwd.labelFont", "Dialog.Font");
243 pw->label_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
244 if (!pw->label_font) pw->label_font = XLoadQueryFont (si->dpy, "fixed");
247 f = get_string_resource("passwd.passwdFont", "Dialog.Font");
248 pw->passwd_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
249 if (!pw->passwd_font) pw->passwd_font = XLoadQueryFont (si->dpy, "fixed");
252 f = get_string_resource("passwd.dateFont", "Dialog.Font");
253 pw->date_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
254 if (!pw->date_font) pw->date_font = XLoadQueryFont (si->dpy, "fixed");
257 pw->foreground = get_pixel_resource ("passwd.foreground",
260 pw->background = get_pixel_resource ("passwd.background",
264 if (pw->foreground == pw->background)
266 /* Make sure the error messages show up. */
267 pw->foreground = BlackPixelOfScreen (screen);
268 pw->background = WhitePixelOfScreen (screen);
271 pw->passwd_foreground = get_pixel_resource ("passwd.text.foreground",
272 "Dialog.Text.Foreground",
274 pw->passwd_background = get_pixel_resource ("passwd.text.background",
275 "Dialog.Text.Background",
277 pw->button_foreground = get_pixel_resource ("splash.Button.foreground",
278 "Dialog.Button.Foreground",
280 pw->button_background = get_pixel_resource ("splash.Button.background",
281 "Dialog.Button.Background",
283 pw->thermo_foreground = get_pixel_resource ("passwd.thermometer.foreground",
284 "Dialog.Thermometer.Foreground",
286 pw->thermo_background = get_pixel_resource ("passwd.thermometer.background",
287 "Dialog.Thermometer.Background",
289 pw->shadow_top = get_pixel_resource ("passwd.topShadowColor",
292 pw->shadow_bottom = get_pixel_resource ("passwd.bottomShadowColor",
296 pw->logo_width = get_integer_resource ("passwd.logo.width",
297 "Dialog.Logo.Width");
298 pw->logo_height = get_integer_resource ("passwd.logo.height",
299 "Dialog.Logo.Height");
300 pw->thermo_width = get_integer_resource ("passwd.thermometer.width",
301 "Dialog.Thermometer.Width");
302 pw->internal_border = get_integer_resource ("passwd.internalBorderWidth",
303 "Dialog.InternalBorderWidth");
304 pw->shadow_width = get_integer_resource ("passwd.shadowThickness",
305 "Dialog.ShadowThickness");
307 if (pw->logo_width == 0) pw->logo_width = 150;
308 if (pw->logo_height == 0) pw->logo_height = 150;
309 if (pw->internal_border == 0) pw->internal_border = 15;
310 if (pw->shadow_width == 0) pw->shadow_width = 4;
311 if (pw->thermo_width == 0) pw->thermo_width = pw->shadow_width;
314 int direction, ascent, descent;
320 /* Measure the heading_label. */
321 XTextExtents (pw->heading_font,
322 pw->heading_label, strlen(pw->heading_label),
323 &direction, &ascent, &descent, &overall);
324 if (overall.width > pw->width) pw->width = overall.width;
325 pw->height += ascent + descent;
327 /* Measure the body_label. */
328 XTextExtents (pw->body_font,
329 pw->body_label, strlen(pw->body_label),
330 &direction, &ascent, &descent, &overall);
331 if (overall.width > pw->width) pw->width = overall.width;
332 pw->height += ascent + descent;
335 Dimension w2 = 0, w3 = 0, button_w = 0;
336 Dimension h2 = 0, h3 = 0, button_h = 0;
337 const char *passwd_string = "MMMMMMMMMMMM";
339 /* Measure the user_label. */
340 XTextExtents (pw->label_font,
341 pw->user_label, strlen(pw->user_label),
342 &direction, &ascent, &descent, &overall);
343 if (overall.width > w2) w2 = overall.width;
344 h2 += ascent + descent;
346 /* Measure the passwd_label. */
347 XTextExtents (pw->label_font,
348 pw->passwd_label, strlen(pw->passwd_label),
349 &direction, &ascent, &descent, &overall);
350 if (overall.width > w2) w2 = overall.width;
351 h2 += ascent + descent;
353 /* Measure the user_string. */
354 XTextExtents (pw->passwd_font,
355 pw->user_string, strlen(pw->user_string),
356 &direction, &ascent, &descent, &overall);
357 overall.width += (pw->shadow_width * 4);
358 ascent += (pw->shadow_width * 4);
359 if (overall.width > w3) w3 = overall.width;
360 h3 += ascent + descent;
362 /* Measure the (maximally-sized, dummy) passwd_string. */
363 XTextExtents (pw->passwd_font,
364 passwd_string, strlen(passwd_string),
365 &direction, &ascent, &descent, &overall);
366 overall.width += (pw->shadow_width * 4);
367 ascent += (pw->shadow_width * 4);
368 if (overall.width > w3) w3 = overall.width;
369 h3 += ascent + descent;
371 w2 = w2 + w3 + (pw->shadow_width * 2);
374 pw->login_button_width = 0;
375 pw->login_button_height = 0;
377 if (pw->login_button_p)
379 pw->login_button_enabled_p = True;
381 /* Measure the "New Login" button */
382 XTextExtents (pw->button_font, pw->login_label,
383 strlen (pw->login_label),
384 &direction, &ascent, &descent, &overall);
385 button_w = overall.width;
386 button_h = ascent + descent;
388 /* Add some horizontal padding inside the buttons. */
391 button_w += ((ascent + descent) / 2) + (pw->shadow_width * 2);
392 button_h += ((ascent + descent) / 2) + (pw->shadow_width * 2);
394 pw->login_button_width = button_w;
395 pw->login_button_height = button_h;
397 w2 = MAX (w2, button_w);
398 h2 += button_h * 1.5;
401 if (w2 > pw->width) pw->width = w2;
405 pw->width += (pw->internal_border * 2);
406 pw->height += (pw->internal_border * 4);
408 pw->width += pw->thermo_width + (pw->shadow_width * 3);
410 if (pw->logo_height > pw->height)
411 pw->height = pw->logo_height;
412 else if (pw->height > pw->logo_height)
413 pw->logo_height = pw->height;
415 pw->logo_width = pw->logo_height;
417 pw->width += pw->logo_width;
420 attrmask |= CWOverrideRedirect; attrs.override_redirect = True;
422 attrmask |= CWEventMask;
423 attrs.event_mask = (ExposureMask | KeyPressMask |
424 ButtonPressMask | ButtonReleaseMask);
426 /* We need to remember the mouse position and restore it afterward, or
427 sometimes (perhaps only with Xinerama?) the mouse gets warped to
428 inside the bounds of the lock dialog window.
431 Window pointer_root, pointer_child;
432 int root_x, root_y, win_x, win_y;
434 pw->previous_mouse_x = 0;
435 pw->previous_mouse_y = 0;
436 if (XQueryPointer (si->dpy, RootWindowOfScreen (pw->prompt_screen->screen),
437 &pointer_root, &pointer_child,
438 &root_x, &root_y, &win_x, &win_y, &mask))
440 pw->previous_mouse_x = root_x;
441 pw->previous_mouse_y = root_y;
442 if (si->prefs.verbose_p)
443 fprintf (stderr, "%s: %d: mouse is at %d,%d.\n",
444 blurb(), pw->prompt_screen->number,
445 pw->previous_mouse_x, pw->previous_mouse_y);
447 else if (si->prefs.verbose_p)
448 fprintf (stderr, "%s: %d: unable to determine mouse position?\n",
449 blurb(), pw->prompt_screen->number);
452 /* Figure out where on the desktop to place the window so that it will
453 actually be visible; this takes into account virtual viewports as
457 get_screen_viewport (pw->prompt_screen, &x, &y, &w, &h,
458 pw->previous_mouse_x, pw->previous_mouse_y,
459 si->prefs.verbose_p);
460 if (si->prefs.debug_p) w /= 2;
461 pw->x = x + ((w + pw->width) / 2) - pw->width;
462 pw->y = y + ((h + pw->height) / 2) - pw->height;
463 if (pw->x < x) pw->x = x;
464 if (pw->y < y) pw->y = y;
467 pw->border_width = get_integer_resource ("passwd.borderWidth",
468 "Dialog.BorderWidth");
471 XCreateWindow (si->dpy,
472 RootWindowOfScreen(screen),
473 pw->x, pw->y, pw->width, pw->height, pw->border_width,
474 DefaultDepthOfScreen (screen), InputOutput,
475 DefaultVisualOfScreen(screen),
477 XSetWindowBackground (si->dpy, si->passwd_dialog, pw->background);
479 /* We use the default visual, not ssi->visual, so that the logo pixmap's
480 visual matches that of the si->passwd_dialog window. */
481 pw->logo_pixmap = xscreensaver_logo (ssi->screen,
482 /* ssi->current_visual, */
483 DefaultVisualOfScreen(screen),
484 si->passwd_dialog, cmap,
486 &pw->logo_pixels, &pw->logo_npixels,
489 /* Before mapping the window, save the bits that are underneath the
490 rectangle the window will occlude. When we lower the window, we
491 restore these bits. This works, because the running screenhack
492 has already been sent SIGSTOP, so we know nothing else is drawing
497 pw->save_under = XCreatePixmap (si->dpy,
498 pw->prompt_screen->screensaver_window,
499 pw->width + (pw->border_width*2) + 1,
500 pw->height + (pw->border_width*2) + 1,
501 pw->prompt_screen->current_depth);
502 gcv.function = GXcopy;
503 gc = XCreateGC (si->dpy, pw->save_under, GCFunction, &gcv);
504 XCopyArea (si->dpy, pw->prompt_screen->screensaver_window,
506 pw->x - pw->border_width, pw->y - pw->border_width,
507 pw->width + (pw->border_width*2) + 1,
508 pw->height + (pw->border_width*2) + 1,
510 XFreeGC (si->dpy, gc);
513 XMapRaised (si->dpy, si->passwd_dialog);
514 XSync (si->dpy, False);
516 move_mouse_grab (si, si->passwd_dialog,
519 : pw->prompt_screen->cursor),
520 pw->prompt_screen->number);
526 XInstallColormap (si->dpy, cmap);
527 draw_passwd_window (si);
528 XSync (si->dpy, False);
533 draw_passwd_window (saver_info *si)
535 passwd_dialog_data *pw = si->pw_data;
539 int x1, x2, x3, y1, y2;
543 height = (pw->heading_font->ascent + pw->heading_font->descent +
544 pw->body_font->ascent + pw->body_font->descent +
545 (2 * MAX ((pw->label_font->ascent + pw->label_font->descent),
546 (pw->passwd_font->ascent + pw->passwd_font->descent +
547 (pw->shadow_width * 4)))) +
548 pw->date_font->ascent + pw->date_font->descent);
550 if (pw->login_button_p)
551 height += ((pw->button_font->ascent + pw->button_font->descent) * 2 +
552 2 * pw->shadow_width);
554 spacing = (((pw->height
555 - ((pw->login_button_p ? 4 : 2) * pw->shadow_width)
556 - pw->internal_border - height))
559 if (spacing < 0) spacing = 0;
561 gcv.foreground = pw->foreground;
562 gc1 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
563 gc2 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
564 x1 = pw->logo_width + pw->thermo_width + (pw->shadow_width * 3);
565 x3 = pw->width - (pw->shadow_width * 2);
566 y1 = (pw->shadow_width * 2) + spacing + spacing;
570 XSetFont (si->dpy, gc1, pw->heading_font->fid);
571 sw = string_width (pw->heading_font, pw->heading_label);
572 x2 = (x1 + ((x3 - x1 - sw) / 2));
573 y1 += spacing + pw->heading_font->ascent + pw->heading_font->descent;
574 XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
575 pw->heading_label, strlen(pw->heading_label));
577 /* text below top heading
579 XSetFont (si->dpy, gc1, pw->body_font->fid);
580 y1 += spacing + pw->body_font->ascent + pw->body_font->descent;
581 sw = string_width (pw->body_font, pw->body_label);
582 x2 = (x1 + ((x3 - x1 - sw) / 2));
583 XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
584 pw->body_label, strlen(pw->body_label));
587 tb_height = (pw->passwd_font->ascent + pw->passwd_font->descent +
588 (pw->shadow_width * 4));
590 /* the "User:" prompt
594 XSetForeground (si->dpy, gc1, pw->foreground);
595 XSetFont (si->dpy, gc1, pw->label_font->fid);
596 y1 += (spacing + tb_height);
597 x2 = (x1 + pw->internal_border +
598 MAX(string_width (pw->label_font, pw->user_label),
599 string_width (pw->label_font, pw->passwd_label)));
600 XDrawString (si->dpy, si->passwd_dialog, gc1,
601 x2 - string_width (pw->label_font, pw->user_label),
602 y1 - pw->passwd_font->descent,
603 pw->user_label, strlen(pw->user_label));
605 /* the "Password:" prompt
607 y1 += (spacing + tb_height);
608 XDrawString (si->dpy, si->passwd_dialog, gc1,
609 x2 - string_width (pw->label_font, pw->passwd_label),
610 y1 - pw->passwd_font->descent,
611 pw->passwd_label, strlen(pw->passwd_label));
614 XSetForeground (si->dpy, gc2, pw->passwd_background);
616 /* the "user name" text field
619 XSetForeground (si->dpy, gc1, pw->passwd_foreground);
620 XSetFont (si->dpy, gc1, pw->passwd_font->fid);
621 y1 += (spacing + tb_height);
622 x2 += (pw->shadow_width * 4);
624 pw->passwd_field_width = x3 - x2 - pw->internal_border;
625 pw->passwd_field_height = (pw->passwd_font->ascent +
626 pw->passwd_font->descent +
629 XFillRectangle (si->dpy, si->passwd_dialog, gc2,
630 x2 - pw->shadow_width,
631 y1 - (pw->passwd_font->ascent + pw->passwd_font->descent),
632 pw->passwd_field_width, pw->passwd_field_height);
633 XDrawString (si->dpy, si->passwd_dialog, gc1,
635 y1 - pw->passwd_font->descent,
636 pw->user_string, strlen(pw->user_string));
638 /* the "password" text field
640 y1 += (spacing + tb_height);
642 pw->passwd_field_x = x2 - pw->shadow_width;
643 pw->passwd_field_y = y1 - (pw->passwd_font->ascent +
644 pw->passwd_font->descent);
646 /* The shadow around the text fields
649 y1 += (spacing + (pw->shadow_width * 3));
650 x1 = x2 - (pw->shadow_width * 2);
651 x2 = pw->passwd_field_width + (pw->shadow_width * 2);
652 y2 = pw->passwd_field_height + (pw->shadow_width * 2);
654 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
657 pw->shadow_bottom, pw->shadow_top);
659 y1 += (spacing + pw->passwd_font->ascent + pw->passwd_font->descent +
660 (pw->shadow_width * 4));
661 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
664 pw->shadow_bottom, pw->shadow_top);
667 /* The date, below the text fields
671 time_t now = time ((time_t *) 0);
672 struct tm *tm = localtime (&now);
673 memset (buf, 0, sizeof(buf));
674 strftime (buf, sizeof(buf)-1, pw->date_label, tm);
676 XSetFont (si->dpy, gc1, pw->date_font->fid);
677 y1 += pw->shadow_width;
678 y1 += (spacing + tb_height);
680 sw = string_width (pw->date_font, buf);
682 XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1, buf, strlen(buf));
685 /* The "New Login" button
687 if (pw->login_button_p)
689 XSetForeground (si->dpy, gc1, pw->button_foreground);
690 XSetForeground (si->dpy, gc2, pw->button_background);
691 XSetFont (si->dpy, gc1, pw->button_font->fid);
693 sw = string_width (pw->button_font, pw->login_label);
695 x2 = pw->width - pw->internal_border - (pw->shadow_width * 2);
697 /* right aligned button */
698 /* x1 = x2 - pw->login_button_width; */
700 /* centered button */
701 x1 = (pw->logo_width + pw->thermo_width + (pw->shadow_width * 3) +
702 pw->internal_border);
703 x1 = x1 + (x2 - x1 - pw->login_button_width) / 2;
705 y1 = (pw->height - pw->internal_border - pw->login_button_height +
708 ((pw->login_button_height -
709 (pw->button_font->ascent + pw->button_font->descent))
711 pw->button_font->ascent);
713 pw->login_button_x = x1;
714 pw->login_button_y = y1;
719 x1 = pw->shadow_width * 6;
720 y1 = pw->shadow_width * 6;
721 x2 = pw->logo_width - (pw->shadow_width * 12);
722 y2 = pw->logo_height - (pw->shadow_width * 12);
728 unsigned int w, h, bw, d;
729 XGetGeometry (si->dpy, pw->logo_pixmap, &root, &x, &y, &w, &h, &bw, &d);
730 XSetForeground (si->dpy, gc1, pw->foreground);
731 XSetBackground (si->dpy, gc1, pw->background);
733 XCopyPlane (si->dpy, pw->logo_pixmap, si->passwd_dialog, gc1,
735 x1 + ((x2 - (int)w) / 2),
736 y1 + ((y2 - (int)h) / 2),
739 XCopyArea (si->dpy, pw->logo_pixmap, si->passwd_dialog, gc1,
741 x1 + ((x2 - (int)w) / 2),
742 y1 + ((y2 - (int)h) / 2));
747 XSetForeground (si->dpy, gc1, pw->thermo_foreground);
748 XSetForeground (si->dpy, gc2, pw->thermo_background);
750 pw->thermo_field_x = pw->logo_width + pw->shadow_width;
751 pw->thermo_field_y = pw->shadow_width * 5;
752 pw->thermo_field_height = pw->height - (pw->shadow_width * 10);
755 /* Solid border inside the logo box. */
756 XSetForeground (si->dpy, gc1, pw->foreground);
757 XDrawRectangle (si->dpy, si->passwd_dialog, gc1, x1, y1, x2-1, y2-1);
760 /* The shadow around the logo
762 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
763 pw->shadow_width * 4,
764 pw->shadow_width * 4,
765 pw->logo_width - (pw->shadow_width * 8),
766 pw->logo_height - (pw->shadow_width * 8),
768 pw->shadow_bottom, pw->shadow_top);
770 /* The shadow around the thermometer
772 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
774 pw->shadow_width * 4,
775 pw->thermo_width + (pw->shadow_width * 2),
776 pw->height - (pw->shadow_width * 8),
778 pw->shadow_bottom, pw->shadow_top);
781 /* Solid border inside the thermometer. */
782 XSetForeground (si->dpy, gc1, pw->foreground);
783 XDrawRectangle (si->dpy, si->passwd_dialog, gc1,
784 pw->thermo_field_x, pw->thermo_field_y,
785 pw->thermo_width - 1, pw->thermo_field_height - 1);
788 /* The shadow around the whole window
790 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
791 0, 0, pw->width, pw->height, pw->shadow_width,
792 pw->shadow_top, pw->shadow_bottom);
794 XFreeGC (si->dpy, gc1);
795 XFreeGC (si->dpy, gc2);
797 update_passwd_window (si, pw->passwd_string, pw->ratio);
802 update_passwd_window (saver_info *si, const char *printed_passwd, float ratio)
804 passwd_dialog_data *pw = si->pw_data;
811 gcv.foreground = pw->passwd_foreground;
812 gcv.font = pw->passwd_font->fid;
813 gc1 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground|GCFont, &gcv);
814 gcv.foreground = pw->passwd_background;
815 gc2 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
819 char *s = strdup (printed_passwd);
820 if (pw->passwd_string) free (pw->passwd_string);
821 pw->passwd_string = s;
824 /* the "password" text field
826 rects[0].x = pw->passwd_field_x;
827 rects[0].y = pw->passwd_field_y;
828 rects[0].width = pw->passwd_field_width;
829 rects[0].height = pw->passwd_field_height;
831 XFillRectangle (si->dpy, si->passwd_dialog, gc2,
832 rects[0].x, rects[0].y, rects[0].width, rects[0].height);
834 XSetClipRectangles (si->dpy, gc1, 0, 0, rects, 1, Unsorted);
836 XDrawString (si->dpy, si->passwd_dialog, gc1,
837 rects[0].x + pw->shadow_width,
838 rects[0].y + pw->passwd_font->ascent,
839 pw->passwd_string, strlen(pw->passwd_string));
841 XSetClipMask (si->dpy, gc1, None);
847 x = (rects[0].x + pw->shadow_width +
848 string_width (pw->passwd_font, pw->passwd_string));
849 y = rects[0].y + pw->shadow_width;
851 if (x > rects[0].x + rects[0].width - 1)
852 x = rects[0].x + rects[0].width - 1;
853 XDrawLine (si->dpy, si->passwd_dialog, gc1,
855 x, y + pw->passwd_font->ascent + pw->passwd_font->descent-1);
858 pw->i_beam = (pw->i_beam + 1) % 4;
863 y = (pw->thermo_field_height - 2) * (1.0 - pw->ratio);
866 XFillRectangle (si->dpy, si->passwd_dialog, gc2,
867 pw->thermo_field_x + 1,
868 pw->thermo_field_y + 1,
871 XSetForeground (si->dpy, gc1, pw->thermo_foreground);
872 XFillRectangle (si->dpy, si->passwd_dialog, gc1,
873 pw->thermo_field_x + 1,
874 pw->thermo_field_y + 1 + y,
876 MAX (0, pw->thermo_field_height - y - 2));
879 /* The "New Login" button
881 if (pw->login_button_p)
884 XSetFont (si->dpy, gc1, pw->button_font->fid);
885 XSetForeground (si->dpy, gc1,
886 (pw->login_button_enabled_p
887 ? pw->passwd_foreground
888 : pw->shadow_bottom));
889 XSetForeground (si->dpy, gc2, pw->button_background);
891 XFillRectangle (si->dpy, si->passwd_dialog, gc2,
892 pw->login_button_x, pw->login_button_y,
893 pw->login_button_width, pw->login_button_height);
895 sw = string_width (pw->button_font, pw->login_label);
896 x2 = pw->login_button_x + ((pw->login_button_width - sw) / 2);
897 y2 = (pw->login_button_y +
898 ((pw->login_button_height -
899 (pw->button_font->ascent + pw->button_font->descent))
901 pw->button_font->ascent);
903 XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y2,
904 pw->login_label, strlen(pw->login_label));
906 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
907 pw->login_button_x, pw->login_button_y,
908 pw->login_button_width, pw->login_button_height,
910 (pw->login_button_down_p
913 (pw->login_button_down_p
915 : pw->shadow_bottom));
918 XFreeGC (si->dpy, gc1);
919 XFreeGC (si->dpy, gc2);
920 XSync (si->dpy, False);
925 destroy_passwd_window (saver_info *si)
927 saver_preferences *p = &si->prefs;
928 passwd_dialog_data *pw = si->pw_data;
929 saver_screen_info *ssi = pw->prompt_screen;
930 Colormap cmap = DefaultColormapOfScreen (ssi->screen);
931 Pixel black = BlackPixelOfScreen (ssi->screen);
932 Pixel white = WhitePixelOfScreen (ssi->screen);
935 memset (pw->typed_passwd, 0, sizeof(pw->typed_passwd));
936 memset (pw->passwd_string, 0, strlen(pw->passwd_string));
939 XtRemoveTimeOut (pw->timer);
941 move_mouse_grab (si, RootWindowOfScreen (ssi->screen),
942 ssi->cursor, ssi->number);
944 if (pw->passwd_cursor)
945 XFreeCursor (si->dpy, pw->passwd_cursor);
948 fprintf (stderr, "%s: %d: moving mouse back to %d,%d.\n",
949 blurb(), ssi->number,
950 pw->previous_mouse_x, pw->previous_mouse_y);
952 XWarpPointer (si->dpy, None, RootWindowOfScreen (ssi->screen),
954 pw->previous_mouse_x, pw->previous_mouse_y);
956 XSync (si->dpy, False);
957 while (XCheckMaskEvent (si->dpy, PointerMotionMask, &event))
959 fprintf (stderr, "%s: discarding MotionNotify event.\n", blurb());
961 if (si->passwd_dialog)
963 XDestroyWindow (si->dpy, si->passwd_dialog);
964 si->passwd_dialog = 0;
971 gcv.function = GXcopy;
972 gc = XCreateGC (si->dpy, ssi->screensaver_window, GCFunction, &gcv);
973 XCopyArea (si->dpy, pw->save_under,
974 ssi->screensaver_window, gc,
976 pw->width + (pw->border_width*2) + 1,
977 pw->height + (pw->border_width*2) + 1,
978 pw->x - pw->border_width, pw->y - pw->border_width);
979 XFreePixmap (si->dpy, pw->save_under);
981 XFreeGC (si->dpy, gc);
984 if (pw->heading_label) free (pw->heading_label);
985 if (pw->body_label) free (pw->body_label);
986 if (pw->user_label) free (pw->user_label);
987 if (pw->passwd_label) free (pw->passwd_label);
988 if (pw->date_label) free (pw->date_label);
989 if (pw->login_label) free (pw->login_label);
990 if (pw->user_string) free (pw->user_string);
991 if (pw->passwd_string) free (pw->passwd_string);
993 if (pw->heading_font) XFreeFont (si->dpy, pw->heading_font);
994 if (pw->body_font) XFreeFont (si->dpy, pw->body_font);
995 if (pw->label_font) XFreeFont (si->dpy, pw->label_font);
996 if (pw->passwd_font) XFreeFont (si->dpy, pw->passwd_font);
997 if (pw->date_font) XFreeFont (si->dpy, pw->date_font);
998 if (pw->button_font) XFreeFont (si->dpy, pw->button_font);
1000 if (pw->foreground != black && pw->foreground != white)
1001 XFreeColors (si->dpy, cmap, &pw->foreground, 1, 0L);
1002 if (pw->background != black && pw->background != white)
1003 XFreeColors (si->dpy, cmap, &pw->background, 1, 0L);
1004 if (!(pw->button_foreground == black || pw->button_foreground == white))
1005 XFreeColors (si->dpy, cmap, &pw->button_foreground, 1, 0L);
1006 if (!(pw->button_background == black || pw->button_background == white))
1007 XFreeColors (si->dpy, cmap, &pw->button_background, 1, 0L);
1008 if (pw->passwd_foreground != black && pw->passwd_foreground != white)
1009 XFreeColors (si->dpy, cmap, &pw->passwd_foreground, 1, 0L);
1010 if (pw->passwd_background != black && pw->passwd_background != white)
1011 XFreeColors (si->dpy, cmap, &pw->passwd_background, 1, 0L);
1012 if (pw->thermo_foreground != black && pw->thermo_foreground != white)
1013 XFreeColors (si->dpy, cmap, &pw->thermo_foreground, 1, 0L);
1014 if (pw->thermo_background != black && pw->thermo_background != white)
1015 XFreeColors (si->dpy, cmap, &pw->thermo_background, 1, 0L);
1016 if (pw->shadow_top != black && pw->shadow_top != white)
1017 XFreeColors (si->dpy, cmap, &pw->shadow_top, 1, 0L);
1018 if (pw->shadow_bottom != black && pw->shadow_bottom != white)
1019 XFreeColors (si->dpy, cmap, &pw->shadow_bottom, 1, 0L);
1021 if (pw->logo_pixmap)
1022 XFreePixmap (si->dpy, pw->logo_pixmap);
1023 if (pw->logo_pixels)
1025 if (pw->logo_npixels)
1026 XFreeColors (si->dpy, cmap, pw->logo_pixels, pw->logo_npixels, 0L);
1027 free (pw->logo_pixels);
1028 pw->logo_pixels = 0;
1029 pw->logo_npixels = 0;
1033 XFreePixmap (si->dpy, pw->save_under);
1036 XInstallColormap (si->dpy, cmap);
1038 memset (pw, 0, sizeof(*pw));
1044 static Bool error_handler_hit_p = False;
1047 ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error)
1049 error_handler_hit_p = True;
1054 #ifdef HAVE_XHPDISABLERESET
1055 /* This function enables and disables the C-Sh-Reset hot-key, which
1056 normally resets the X server (logging out the logged-in user.)
1057 We don't want random people to be able to do that while the
1061 hp_lock_reset (saver_info *si, Bool lock_p)
1063 static Bool hp_locked_p = False;
1065 /* Calls to XHPDisableReset and XHPEnableReset must be balanced,
1066 or BadAccess errors occur. (It's ok for this to be global,
1067 since it affects the whole machine, not just the current screen.)
1069 if (hp_locked_p == lock_p)
1073 XHPDisableReset (si->dpy);
1075 XHPEnableReset (si->dpy);
1076 hp_locked_p = lock_p;
1078 #endif /* HAVE_XHPDISABLERESET */
1081 #ifdef HAVE_XF86MISCSETGRABKEYSSTATE
1083 /* This function enables and disables the Ctrl-Alt-KP_star and
1084 Ctrl-Alt-KP_slash hot-keys, which (in XFree86 4.2) break any
1085 grabs and/or kill the grabbing client. That would effectively
1086 unlock the screen, so we don't like that.
1088 The Ctrl-Alt-KP_star and Ctrl-Alt-KP_slash hot-keys only exist
1089 if AllowDeactivateGrabs and/or AllowClosedownGrabs are turned on
1090 in XF86Config. I believe they are disabled by default.
1092 This does not affect any other keys (specifically Ctrl-Alt-BS or
1093 Ctrl-Alt-F1) but I wish it did. Maybe it will someday.
1096 xfree_lock_grab_smasher (saver_info *si, Bool lock_p)
1098 saver_preferences *p = &si->prefs;
1101 XErrorHandler old_handler;
1102 XSync (si->dpy, False);
1103 error_handler_hit_p = False;
1104 old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
1105 XSync (si->dpy, False);
1106 status = XF86MiscSetGrabKeysState (si->dpy, !lock_p);
1107 XSync (si->dpy, False);
1108 if (error_handler_hit_p) status = 666;
1110 if (!lock_p && status == MiscExtGrabStateAlready)
1111 status = MiscExtGrabStateSuccess; /* shut up, consider this success */
1113 if (p->verbose_p && status != MiscExtGrabStateSuccess)
1114 fprintf (stderr, "%s: error: XF86MiscSetGrabKeysState(%d) returned %s\n",
1116 (status == MiscExtGrabStateSuccess ? "MiscExtGrabStateSuccess" :
1117 status == MiscExtGrabStateLocked ? "MiscExtGrabStateLocked" :
1118 status == MiscExtGrabStateAlready ? "MiscExtGrabStateAlready" :
1119 status == 666 ? "an X error" :
1122 XSync (si->dpy, False);
1123 XSetErrorHandler (old_handler);
1124 XSync (si->dpy, False);
1126 #endif /* HAVE_XF86MISCSETGRABKEYSSTATE */
1131 /* This function enables and disables the C-Sh-F1 ... F12 hot-keys,
1132 which, on Linux systems, switches to another virtual console.
1133 We'd like the whole screen/keyboard to be locked, not just one
1134 virtual console, so this function disables that while the X
1137 Unfortunately, this doesn't work -- this ioctl only works when
1138 called by root, and we have disavowed our privileges long ago.
1140 #ifdef HAVE_VT_LOCKSWITCH
1142 linux_lock_vt_switch (saver_info *si, Bool lock_p)
1144 saver_preferences *p = &si->prefs;
1145 static Bool vt_locked_p = False;
1146 const char *dev_console = "/dev/console";
1149 if (lock_p == vt_locked_p)
1152 if (lock_p && !p->lock_vt_p)
1155 fd = open (dev_console, O_RDWR);
1159 sprintf (buf, "%s: couldn't %s VTs: %s", blurb(),
1160 (lock_p ? "lock" : "unlock"),
1162 #if 1 /* #### doesn't work yet, so don't bother complaining */
1168 if (ioctl (fd, (lock_p ? VT_LOCKSWITCH : VT_UNLOCKSWITCH)) == 0)
1170 vt_locked_p = lock_p;
1173 fprintf (stderr, "%s: %s VTs\n", blurb(),
1174 (lock_p ? "locked" : "unlocked"));
1179 sprintf (buf, "%s: couldn't %s VTs: ioctl", blurb(),
1180 (lock_p ? "lock" : "unlock"));
1181 #if 0 /* #### doesn't work yet, so don't bother complaining */
1188 #endif /* HAVE_VT_LOCKSWITCH */
1191 /* This function enables and disables the C-Alt-Plus and C-Alt-Minus
1192 hot-keys, which normally change the resolution of the X server.
1193 We don't want people to be able to switch the server resolution
1194 while the screen is locked, because if they switch to a higher
1195 resolution, it could cause part of the underlying desktop to become
1198 #ifdef HAVE_XF86VMODE
1201 xfree_lock_mode_switch (saver_info *si, Bool lock_p)
1203 static Bool any_mode_locked_p = False;
1204 saver_preferences *p = &si->prefs;
1208 XErrorHandler old_handler;
1210 if (any_mode_locked_p == lock_p)
1212 if (!XF86VidModeQueryExtension (si->dpy, &event, &error))
1215 for (screen = 0; screen < (si->xinerama_p ? 1 : si->nscreens); screen++)
1217 XSync (si->dpy, False);
1218 old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
1219 error_handler_hit_p = False;
1220 status = XF86VidModeLockModeSwitch (si->dpy, screen, lock_p);
1221 XSync (si->dpy, False);
1222 XSetErrorHandler (old_handler);
1223 if (error_handler_hit_p) status = False;
1226 any_mode_locked_p = lock_p;
1228 if (!status && (p->verbose_p || !lock_p))
1229 /* Only print this when verbose, or when we locked but can't unlock.
1230 I tried printing this message whenever it comes up, but
1231 mode-locking always fails if DontZoom is set in XF86Config. */
1232 fprintf (stderr, "%s: %d: unable to %s mode switching!\n",
1233 blurb(), screen, (lock_p ? "lock" : "unlock"));
1234 else if (p->verbose_p)
1235 fprintf (stderr, "%s: %d: %s mode switching.\n",
1236 blurb(), screen, (lock_p ? "locked" : "unlocked"));
1239 #endif /* HAVE_XF86VMODE */
1242 /* If the viewport has been scrolled since the screen was blanked,
1243 then scroll it back to where it belongs. This function only exists
1244 to patch over a very brief race condition.
1247 undo_vp_motion (saver_info *si)
1249 #ifdef HAVE_XF86VMODE
1250 saver_preferences *p = &si->prefs;
1254 if (!XF86VidModeQueryExtension (si->dpy, &event, &error))
1257 for (screen = 0; screen < si->nscreens; screen++)
1259 saver_screen_info *ssi = &si->screens[screen];
1263 if (ssi->blank_vp_x == -1 && ssi->blank_vp_y == -1)
1265 if (!XF86VidModeGetViewPort (si->dpy, screen, &x, &y))
1267 if (ssi->blank_vp_x == x && ssi->blank_vp_y == y)
1270 /* We're going to move the viewport. The mouse has just been grabbed on
1271 (and constrained to, thus warped to) the password window, so it is no
1272 longer near the edge of the screen. However, wait a bit anyway, just
1273 to make sure the server drains its last motion event, so that the
1274 screen doesn't continue to scroll after we've reset the viewport.
1276 XSync (si->dpy, False);
1277 usleep (250000); /* 1/4 second */
1278 XSync (si->dpy, False);
1280 status = XF86VidModeSetViewPort (si->dpy, screen,
1281 ssi->blank_vp_x, ssi->blank_vp_y);
1285 "%s: %d: unable to move vp from (%d,%d) back to (%d,%d)!\n",
1286 blurb(), screen, x, y, ssi->blank_vp_x, ssi->blank_vp_y);
1287 else if (p->verbose_p)
1289 "%s: %d: vp moved to (%d,%d); moved it back to (%d,%d).\n",
1290 blurb(), screen, x, y, ssi->blank_vp_x, ssi->blank_vp_y);
1292 #endif /* HAVE_XF86VMODE */
1301 passwd_animate_timer (XtPointer closure, XtIntervalId *id)
1303 saver_info *si = (saver_info *) closure;
1305 passwd_dialog_data *pw = si->pw_data;
1309 pw->ratio -= (1.0 / ((double) si->prefs.passwd_timeout / (double) tick));
1313 if (pw->state == pw_read)
1314 pw->state = pw_time;
1317 update_passwd_window (si, 0, pw->ratio);
1319 if (pw->state == pw_read)
1320 pw->timer = XtAppAddTimeOut (si->app, tick, passwd_animate_timer,
1325 idle_timer ((XtPointer) si, 0);
1329 static XComposeStatus *compose_status;
1332 handle_passwd_button (saver_info *si, XEvent *event)
1334 saver_preferences *p = &si->prefs;
1335 Bool mouse_in_box = False;
1337 passwd_dialog_data *pw = si->pw_data;
1338 saver_screen_info *ssi = pw->prompt_screen;
1340 if (! pw->login_button_enabled_p)
1344 (event->xbutton.x >= pw->login_button_x &&
1345 event->xbutton.x <= pw->login_button_x + pw->login_button_width &&
1346 event->xbutton.y >= pw->login_button_y &&
1347 event->xbutton.y <= pw->login_button_y + pw->login_button_height);
1349 if (ButtonRelease == event->xany.type &&
1350 pw->login_button_down_p &&
1353 /* Only allow them to press the button once: don't want to
1354 accidentally launch a dozen gdm choosers if the machine
1358 pw->login_button_enabled_p = False;
1361 pw->login_button_down_p = (mouse_in_box &&
1362 ButtonRelease != event->xany.type);
1364 update_passwd_window (si, 0, pw->ratio);
1367 fork_and_exec (ssi, p->new_login_command);
1372 handle_passwd_key (saver_info *si, XKeyEvent *event)
1374 saver_preferences *p = &si->prefs;
1375 passwd_dialog_data *pw = si->pw_data;
1376 int pw_size = sizeof (pw->typed_passwd) - 1;
1377 char *typed_passwd = pw->typed_passwd;
1381 int size = XLookupString (event, s, 1, 0, compose_status);
1383 if (size != 1) return;
1389 case '\010': case '\177': /* Backspace */
1393 typed_passwd [strlen(typed_passwd)-1] = 0;
1396 case '\025': case '\030': /* Erase line */
1397 memset (typed_passwd, 0, pw_size);
1400 case '\012': case '\015': /* Enter */
1401 if (pw->state != pw_read)
1402 ; /* already done? */
1403 else if (typed_passwd[0] == 0)
1404 pw->state = pw_null;
1407 update_passwd_window (si, "Checking...", pw->ratio);
1408 XSync (si->dpy, False);
1409 if (passwd_valid_p (typed_passwd, p->verbose_p))
1412 pw->state = pw_fail;
1413 update_passwd_window (si, "", pw->ratio);
1418 i = strlen (typed_passwd);
1423 typed_passwd [i] = *s;
1424 typed_passwd [i+1] = 0;
1429 i = strlen(typed_passwd);
1430 stars = (char *) malloc(i+1);
1431 memset (stars, '*', i);
1433 update_passwd_window (si, stars, pw->ratio);
1439 passwd_event_loop (saver_info *si)
1441 saver_preferences *p = &si->prefs;
1444 unsigned int caps_p = 0;
1446 passwd_animate_timer ((XtPointer) si, 0);
1448 while (si->pw_data && si->pw_data->state == pw_read)
1450 XtAppNextEvent (si->app, &event);
1451 if (event.xany.window == si->passwd_dialog && event.xany.type == Expose)
1452 draw_passwd_window (si);
1453 else if (event.xany.type == KeyPress)
1455 handle_passwd_key (si, &event.xkey);
1456 caps_p = (event.xkey.state & LockMask);
1458 else if ((event.xany.type == ButtonPress ||
1459 event.xany.type == ButtonRelease) &&
1460 si->pw_data->login_button_p)
1461 handle_passwd_button (si, &event);
1463 XtDispatchEvent (&event);
1466 switch (si->pw_data->state)
1468 case pw_ok: msg = 0; break;
1469 case pw_null: msg = ""; break;
1470 case pw_time: msg = "Timed out!"; break;
1471 default: msg = (caps_p ? "CapsLock?" : "Sorry!"); break;
1474 if (si->pw_data->state == pw_fail)
1475 si->unlock_failures++;
1478 switch (si->pw_data->state)
1481 fprintf (stderr, "%s: password correct.\n", blurb()); break;
1483 fprintf (stderr, "%s: password incorrect!%s\n", blurb(),
1484 (caps_p ? " (CapsLock)" : ""));
1488 fprintf (stderr, "%s: password entry cancelled.\n", blurb()); break;
1490 fprintf (stderr, "%s: password entry timed out.\n", blurb()); break;
1495 if (si->pw_data->state == pw_fail)
1497 /* If they typed a password (as opposed to just hitting return) and
1498 the password was invalid, log it.
1500 struct passwd *pw = getpwuid (getuid ());
1501 char *d = DisplayString (si->dpy);
1502 char *u = (pw->pw_name ? pw->pw_name : "???");
1510 # if defined(LOG_AUTHPRIV)
1512 # elif defined(LOG_AUTH)
1519 openlog (progname, opt, fac);
1520 syslog (LOG_NOTICE, "FAILED LOGIN %d ON DISPLAY \"%s\", FOR \"%s\"",
1521 si->unlock_failures, d, u);
1524 #endif /* HAVE_SYSLOG */
1526 if (si->pw_data->state == pw_fail)
1527 XBell (si->dpy, False);
1529 if (si->pw_data->state == pw_ok && si->unlock_failures != 0)
1531 if (si->unlock_failures == 1)
1532 fprintf (real_stderr,
1533 "%s: WARNING: 1 failed attempt to unlock the screen.\n",
1536 fprintf (real_stderr,
1537 "%s: WARNING: %d failed attempts to unlock the screen.\n",
1538 blurb(), si->unlock_failures);
1539 fflush (real_stderr);
1541 si->unlock_failures = 0;
1546 si->pw_data->i_beam = 0;
1547 update_passwd_window (si, msg, 0.0);
1548 XSync (si->dpy, False);
1551 /* Swallow all pending KeyPress/KeyRelease events. */
1554 while (XCheckMaskEvent (si->dpy, KeyPressMask|KeyReleaseMask, &e))
1562 handle_typeahead (saver_info *si)
1564 passwd_dialog_data *pw = si->pw_data;
1566 if (!si->unlock_typeahead)
1569 i = strlen (si->unlock_typeahead);
1570 if (i >= sizeof(pw->typed_passwd) - 1)
1571 i = sizeof(pw->typed_passwd) - 1;
1573 memcpy (pw->typed_passwd, si->unlock_typeahead, i);
1574 pw->typed_passwd [i] = 0;
1576 memset (si->unlock_typeahead, '*', strlen(si->unlock_typeahead));
1577 si->unlock_typeahead[i] = 0;
1578 update_passwd_window (si, si->unlock_typeahead, pw->ratio);
1580 free (si->unlock_typeahead);
1581 si->unlock_typeahead = 0;
1586 unlock_p (saver_info *si)
1588 saver_preferences *p = &si->prefs;
1591 raise_window (si, True, True, True);
1594 fprintf (stderr, "%s: prompting for password.\n", blurb());
1596 if (si->pw_data || si->passwd_dialog)
1597 destroy_passwd_window (si);
1599 make_passwd_window (si);
1601 compose_status = calloc (1, sizeof (*compose_status));
1603 handle_typeahead (si);
1604 passwd_event_loop (si);
1606 status = (si->pw_data->state == pw_ok);
1607 destroy_passwd_window (si);
1609 free (compose_status);
1617 set_locked_p (saver_info *si, Bool locked_p)
1619 si->locked_p = locked_p;
1621 #ifdef HAVE_XHPDISABLERESET
1622 hp_lock_reset (si, locked_p); /* turn off/on C-Sh-Reset */
1624 #ifdef HAVE_VT_LOCKSWITCH
1625 linux_lock_vt_switch (si, locked_p); /* turn off/on C-Alt-F1 */
1627 #ifdef HAVE_XF86VMODE
1628 xfree_lock_mode_switch (si, locked_p); /* turn off/on C-Alt-Plus */
1630 #ifdef HAVE_XF86MISCSETGRABKEYSSTATE
1631 xfree_lock_grab_smasher (si, locked_p); /* turn off/on C-Alt-KP-*,/ */
1634 store_saver_status (si); /* store locked-p */
1638 #else /* NO_LOCKING -- whole file */
1641 set_locked_p (saver_info *si, Bool locked_p)
1643 if (locked_p) abort();
1646 #endif /* !NO_LOCKING */