1 /* lock.c --- handling the password dialog for locking-mode.
2 * xscreensaver, Copyright (c) 1993-1998 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 #ifndef NO_LOCKING /* whole file */
22 #include <X11/Intrinsic.h>
23 #include "xscreensaver.h"
24 #include "resources.h"
28 #endif /* HAVE_SYSLOG */
31 # include <X11/extensions/xf86vmode.h>
32 #endif /* HAVE_XF86VMODE */
35 ERROR! You must not include vroot.h in this file.
42 extern char *getenv(const char *name);
43 extern int validate_user(char *name, char *password);
46 vms_passwd_valid_p(char *pw, Bool verbose_p)
48 return (validate_user (getenv("USER"), typed_passwd) == 1);
50 # undef passwd_valid_p
51 # define passwd_valid_p vms_passwd_valid_p
57 #define MAX(a,b) ((a)>(b)?(a):(b))
59 enum passwd_state { pw_read, pw_ok, pw_null, pw_fail, pw_cancel, pw_time };
61 struct passwd_dialog_data {
63 enum passwd_state state;
64 char typed_passwd [80];
72 Dimension border_width;
81 XFontStruct *heading_font;
82 XFontStruct *body_font;
83 XFontStruct *label_font;
84 XFontStruct *passwd_font;
88 Pixel passwd_foreground;
89 Pixel passwd_background;
90 Pixel logo_foreground;
91 Pixel logo_background;
96 Dimension logo_height;
97 Dimension thermo_width;
98 Dimension internal_border;
99 Dimension shadow_width;
101 Dimension passwd_field_x, passwd_field_y;
102 Dimension passwd_field_width, passwd_field_height;
104 Dimension thermo_field_x, thermo_field_y;
105 Dimension thermo_field_height;
110 static void draw_passwd_window (saver_info *si);
111 static void update_passwd_window (saver_info *si, const char *printed_passwd,
113 static void destroy_passwd_window (saver_info *si);
114 static void undo_vp_motion (saver_info *si);
115 static void set_vp_mode_switch_locked (saver_info *si, Bool locked_p);
119 make_passwd_window (saver_info *si)
121 struct passwd *p = getpwuid (getuid ());
122 XSetWindowAttributes attrs;
123 unsigned long attrmask = 0;
124 Screen *screen = si->default_screen->screen;
125 passwd_dialog_data *pw = (passwd_dialog_data *) calloc (1, sizeof(*pw));
126 Colormap cmap = DefaultColormapOfScreen (screen);
131 pw->heading_label = get_string_resource ("passwd.heading.label",
132 "Dialog.Label.Label");
133 pw->body_label = get_string_resource ("passwd.body.label",
134 "Dialog.Label.Label");
135 pw->user_label = get_string_resource ("passwd.user.label",
136 "Dialog.Label.Label");
137 pw->passwd_label = get_string_resource ("passwd.passwd.label",
138 "Dialog.Label.Label");
140 if (!pw->heading_label)
141 pw->heading_label = strdup("ERROR: REESOURCES NOT INSTALLED CORRECTLY");
143 pw->body_label = strdup("ERROR: REESOURCES NOT INSTALLED CORRECTLY");
144 if (!pw->user_label) pw->user_label = strdup("ERROR");
145 if (!pw->passwd_label) pw->passwd_label = strdup("ERROR");
147 /* Put the version number in the label. */
149 char *s = (char *) malloc (strlen(pw->heading_label) + 20);
150 sprintf(s, pw->heading_label, si->version);
151 free (pw->heading_label);
152 pw->heading_label = s;
155 pw->user_string = (p->pw_name ? p->pw_name : "???");
156 pw->passwd_string = strdup("");
158 f = get_string_resource ("passwd.headingFont", "Dialog.Font");
159 pw->heading_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
160 if (!pw->heading_font) pw->heading_font = XLoadQueryFont (si->dpy, "fixed");
163 f = get_string_resource("passwd.bodyFont", "Dialog.Font");
164 pw->body_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
165 if (!pw->body_font) pw->body_font = XLoadQueryFont (si->dpy, "fixed");
168 f = get_string_resource("passwd.labelFont", "Dialog.Font");
169 pw->label_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
170 if (!pw->label_font) pw->label_font = XLoadQueryFont (si->dpy, "fixed");
173 f = get_string_resource("passwd.passwdFont", "Dialog.Font");
174 pw->passwd_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
175 if (!pw->passwd_font) pw->passwd_font = XLoadQueryFont (si->dpy, "fixed");
178 pw->foreground = get_pixel_resource ("passwd.foreground",
181 pw->background = get_pixel_resource ("passwd.background",
185 if (pw->foreground == pw->background)
187 /* Make sure the error messages show up. */
188 pw->foreground = BlackPixelOfScreen (screen);
189 pw->background = WhitePixelOfScreen (screen);
192 pw->passwd_foreground = get_pixel_resource ("passwd.text.foreground",
193 "Dialog.Text.Foreground",
195 pw->passwd_background = get_pixel_resource ("passwd.text.background",
196 "Dialog.Text.Background",
198 pw->logo_foreground = get_pixel_resource ("passwd.logo.foreground",
199 "Dialog.Logo.Foreground",
201 pw->logo_background = get_pixel_resource ("passwd.logo.background",
202 "Dialog.Logo.Background",
204 pw->shadow_top = get_pixel_resource ("passwd.topShadowColor",
207 pw->shadow_bottom = get_pixel_resource ("passwd.bottomShadowColor",
211 pw->logo_width = get_integer_resource ("passwd.logo.width",
212 "Dialog.Logo.Width");
213 pw->logo_height = get_integer_resource ("passwd.logo.height",
214 "Dialog.Logo.Height");
215 pw->thermo_width = get_integer_resource ("passwd.thermometer.width",
216 "Dialog.Thermometer.Width");
217 pw->internal_border = get_integer_resource ("passwd.internalBorderWidth",
218 "Dialog.InternalBorderWidth");
219 pw->shadow_width = get_integer_resource ("passwd.shadowThickness",
220 "Dialog.ShadowThickness");
222 if (pw->logo_width == 0) pw->logo_width = 150;
223 if (pw->logo_height == 0) pw->logo_height = 150;
224 if (pw->internal_border == 0) pw->internal_border = 15;
225 if (pw->shadow_width == 0) pw->shadow_width = 4;
226 if (pw->thermo_width == 0) pw->thermo_width = pw->shadow_width;
229 int direction, ascent, descent;
235 /* Measure the heading_label. */
236 XTextExtents (pw->heading_font,
237 pw->heading_label, strlen(pw->heading_label),
238 &direction, &ascent, &descent, &overall);
239 if (overall.width > pw->width) pw->width = overall.width;
240 pw->height += ascent + descent;
242 /* Measure the body_label. */
243 XTextExtents (pw->body_font,
244 pw->body_label, strlen(pw->body_label),
245 &direction, &ascent, &descent, &overall);
246 if (overall.width > pw->width) pw->width = overall.width;
247 pw->height += ascent + descent;
250 Dimension w2 = 0, w3 = 0;
251 Dimension h2 = 0, h3 = 0;
252 const char *passwd_string = "MMMMMMMMMMMM";
254 /* Measure the user_label. */
255 XTextExtents (pw->label_font,
256 pw->user_label, strlen(pw->user_label),
257 &direction, &ascent, &descent, &overall);
258 if (overall.width > w2) w2 = overall.width;
259 h2 += ascent + descent;
261 /* Measure the passwd_label. */
262 XTextExtents (pw->label_font,
263 pw->passwd_label, strlen(pw->passwd_label),
264 &direction, &ascent, &descent, &overall);
265 if (overall.width > w2) w2 = overall.width;
266 h2 += ascent + descent;
268 /* Measure the user_string. */
269 XTextExtents (pw->passwd_font,
270 pw->user_string, strlen(pw->user_string),
271 &direction, &ascent, &descent, &overall);
272 overall.width += (pw->shadow_width * 4);
273 ascent += (pw->shadow_width * 4);
274 if (overall.width > w3) w3 = overall.width;
275 h3 += ascent + descent;
277 /* Measure the (maximally-sized, dummy) passwd_string. */
278 XTextExtents (pw->passwd_font,
279 passwd_string, strlen(passwd_string),
280 &direction, &ascent, &descent, &overall);
281 overall.width += (pw->shadow_width * 4);
282 ascent += (pw->shadow_width * 4);
283 if (overall.width > w3) w3 = overall.width;
284 h3 += ascent + descent;
286 w2 = w2 + w3 + (pw->shadow_width * 2);
289 if (w2 > pw->width) pw->width = w2;
293 pw->width += (pw->internal_border * 2);
294 pw->height += (pw->internal_border * 4);
296 pw->width += pw->thermo_width + (pw->shadow_width * 3);
298 if (pw->logo_height > pw->height)
299 pw->height = pw->logo_height;
300 else if (pw->height > pw->logo_height)
301 pw->logo_height = pw->height;
303 pw->logo_width = pw->logo_height;
305 pw->width += pw->logo_width;
308 attrmask |= CWOverrideRedirect; attrs.override_redirect = True;
309 attrmask |= CWEventMask; attrs.event_mask = ExposureMask|KeyPressMask;
313 get_screen_viewport (si->default_screen, &x, &y, &w, &h, False);
314 if (si->prefs.debug_p) w /= 2;
315 pw->x = x + ((w + pw->width) / 2) - pw->width;
316 pw->y = y + ((h + pw->height) / 2) - pw->height;
317 if (pw->x < x) pw->x = x;
318 if (pw->y < y) pw->y = y;
321 pw->border_width = get_integer_resource ("passwd.borderWidth",
322 "Dialog.BorderWidth");
325 XCreateWindow (si->dpy,
326 RootWindowOfScreen(screen),
327 pw->x, pw->y, pw->width, pw->height, pw->border_width,
328 DefaultDepthOfScreen (screen), InputOutput,
329 DefaultVisualOfScreen(screen),
331 XSetWindowBackground (si->dpy, si->passwd_dialog, pw->background);
334 /* Before mapping the window, save the bits that are underneath the
335 rectangle the window will occlude. When we lower the window, we
336 restore these bits. This works, because the running screenhack
337 has already been sent SIGSTOP, so we know nothing else is drawing
342 pw->save_under = XCreatePixmap (si->dpy,
343 si->default_screen->screensaver_window,
344 pw->width + (pw->border_width*2) + 1,
345 pw->height + (pw->border_width*2) + 1,
346 si->default_screen->current_depth);
347 gcv.function = GXcopy;
348 gc = XCreateGC (si->dpy, pw->save_under, GCFunction, &gcv);
349 XCopyArea (si->dpy, si->default_screen->screensaver_window,
351 pw->x - pw->border_width, pw->y - pw->border_width,
352 pw->width + (pw->border_width*2) + 1,
353 pw->height + (pw->border_width*2) + 1,
355 XFreeGC (si->dpy, gc);
358 XMapRaised (si->dpy, si->passwd_dialog);
359 XSync (si->dpy, False);
361 move_mouse_grab (si, si->passwd_dialog, si->screens[0].cursor);
363 set_vp_mode_switch_locked (si, True);
367 draw_passwd_window (si);
368 XSync (si->dpy, False);
373 draw_passwd_window (saver_info *si)
375 passwd_dialog_data *pw = si->pw_data;
379 int x1, x2, x3, y1, y2;
383 height = (pw->heading_font->ascent + pw->heading_font->descent +
384 pw->body_font->ascent + pw->body_font->descent +
385 (2 * MAX ((pw->label_font->ascent + pw->label_font->descent),
386 (pw->passwd_font->ascent + pw->passwd_font->descent +
387 (pw->shadow_width * 4)))));
388 spacing = ((pw->height - (2 * pw->shadow_width) -
389 pw->internal_border - height)) / 8;
390 if (spacing < 0) spacing = 0;
392 gcv.foreground = pw->foreground;
393 gc1 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
394 gc2 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
395 x1 = pw->logo_width + pw->thermo_width + (pw->shadow_width * 3);
396 x3 = pw->width - (pw->shadow_width * 2);
397 y1 = (pw->shadow_width * 2) + spacing + spacing;
401 XSetFont (si->dpy, gc1, pw->heading_font->fid);
402 sw = string_width (pw->heading_font, pw->heading_label);
403 x2 = (x1 + ((x3 - x1 - sw) / 2));
404 y1 += spacing + pw->heading_font->ascent + pw->heading_font->descent;
405 XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
406 pw->heading_label, strlen(pw->heading_label));
408 /* text below top heading
410 XSetFont (si->dpy, gc1, pw->body_font->fid);
411 y1 += spacing + pw->body_font->ascent + pw->body_font->descent;
412 sw = string_width (pw->body_font, pw->body_label);
413 x2 = (x1 + ((x3 - x1 - sw) / 2));
414 XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
415 pw->body_label, strlen(pw->body_label));
418 tb_height = (pw->passwd_font->ascent + pw->passwd_font->descent +
419 (pw->shadow_width * 4));
421 /* the "User:" prompt
425 XSetForeground (si->dpy, gc1, pw->foreground);
426 XSetFont (si->dpy, gc1, pw->label_font->fid);
427 y1 += (spacing + tb_height);
428 x2 = (x1 + pw->internal_border +
429 MAX(string_width (pw->label_font, pw->user_label),
430 string_width (pw->label_font, pw->passwd_label)));
431 XDrawString (si->dpy, si->passwd_dialog, gc1,
432 x2 - string_width (pw->label_font, pw->user_label),
434 pw->user_label, strlen(pw->user_label));
436 /* the "Password:" prompt
438 y1 += (spacing + tb_height);
439 XDrawString (si->dpy, si->passwd_dialog, gc1,
440 x2 - string_width (pw->label_font, pw->passwd_label),
442 pw->passwd_label, strlen(pw->passwd_label));
445 XSetForeground (si->dpy, gc2, pw->passwd_background);
447 /* the "user name" text field
450 XSetForeground (si->dpy, gc1, pw->passwd_foreground);
451 XSetFont (si->dpy, gc1, pw->passwd_font->fid);
452 y1 += (spacing + tb_height);
453 x2 += (pw->shadow_width * 4);
455 pw->passwd_field_width = x3 - x2 - pw->internal_border;
456 pw->passwd_field_height = (pw->passwd_font->ascent +
457 pw->passwd_font->descent +
460 XFillRectangle (si->dpy, si->passwd_dialog, gc2,
461 x2 - pw->shadow_width,
462 y1 - (pw->passwd_font->ascent + pw->passwd_font->descent),
463 pw->passwd_field_width, pw->passwd_field_height);
464 XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
465 pw->user_string, strlen(pw->user_string));
467 /* the "password" text field
469 y1 += (spacing + tb_height);
471 pw->passwd_field_x = x2 - pw->shadow_width;
472 pw->passwd_field_y = y1 - (pw->passwd_font->ascent +
473 pw->passwd_font->descent);
475 /* The shadow around the text fields
478 y1 += (spacing + (pw->shadow_width * 3));
479 x1 = x2 - (pw->shadow_width * 2);
480 x2 = pw->passwd_field_width + (pw->shadow_width * 2);
481 y2 = pw->passwd_field_height + (pw->shadow_width * 2);
483 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
486 pw->shadow_bottom, pw->shadow_top);
488 y1 += (spacing + pw->passwd_font->ascent + pw->passwd_font->descent +
489 (pw->shadow_width * 4));
490 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
493 pw->shadow_bottom, pw->shadow_top);
497 XSetForeground (si->dpy, gc1, pw->logo_foreground);
498 XSetForeground (si->dpy, gc2, pw->logo_background);
500 x1 = pw->shadow_width * 3;
501 y1 = pw->shadow_width * 3;
502 x2 = pw->logo_width - (pw->shadow_width * 6);
503 y2 = pw->logo_height - (pw->shadow_width * 6);
505 XFillRectangle (si->dpy, si->passwd_dialog, gc2, x1, y1, x2, y2);
506 skull (si->dpy, si->passwd_dialog, gc1, gc2,
507 x1 + pw->shadow_width, y1 + pw->shadow_width,
508 x2 - (pw->shadow_width * 2), y2 - (pw->shadow_width * 2));
512 pw->thermo_field_x = pw->logo_width + pw->shadow_width;
513 pw->thermo_field_y = pw->shadow_width * 3;
514 pw->thermo_field_height = pw->height - (pw->shadow_width * 6);
516 /* Solid border inside the logo box. */
517 XSetForeground (si->dpy, gc1, pw->foreground);
518 XDrawRectangle (si->dpy, si->passwd_dialog, gc1, x1, y1, x2-1, y2-1);
520 /* The shadow around the logo
522 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
523 pw->shadow_width * 2,
524 pw->shadow_width * 2,
525 pw->logo_width - (pw->shadow_width * 4),
526 pw->logo_height - (pw->shadow_width * 4),
528 pw->shadow_bottom, pw->shadow_top);
530 /* The shadow around the thermometer
532 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
534 pw->shadow_width * 2,
535 pw->thermo_width + (pw->shadow_width * 2),
536 pw->height - (pw->shadow_width * 4),
538 pw->shadow_bottom, pw->shadow_top);
540 /* Solid border inside the thermometer. */
541 XSetForeground (si->dpy, gc1, pw->foreground);
542 XDrawRectangle (si->dpy, si->passwd_dialog, gc1,
543 pw->logo_width + pw->shadow_width,
544 pw->shadow_width * 3,
545 pw->thermo_width - 1,
546 pw->height - (pw->shadow_width * 6) - 1);
548 /* The shadow around the whole window
550 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
551 0, 0, pw->width, pw->height, pw->shadow_width,
552 pw->shadow_top, pw->shadow_bottom);
554 XFreeGC (si->dpy, gc1);
555 XFreeGC (si->dpy, gc2);
557 update_passwd_window (si, pw->passwd_string, pw->ratio);
562 update_passwd_window (saver_info *si, const char *printed_passwd, float ratio)
564 passwd_dialog_data *pw = si->pw_data;
571 gcv.foreground = pw->passwd_foreground;
572 gcv.font = pw->passwd_font->fid;
573 gc1 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground|GCFont, &gcv);
574 gcv.foreground = pw->passwd_background;
575 gc2 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
579 char *s = strdup (printed_passwd);
580 if (pw->passwd_string) free (pw->passwd_string);
581 pw->passwd_string = s;
584 /* the "password" text field
586 rects[0].x = pw->passwd_field_x;
587 rects[0].y = pw->passwd_field_y;
588 rects[0].width = pw->passwd_field_width;
589 rects[0].height = pw->passwd_field_height;
591 XFillRectangle (si->dpy, si->passwd_dialog, gc2,
592 rects[0].x, rects[0].y, rects[0].width, rects[0].height);
594 XSetClipRectangles (si->dpy, gc1, 0, 0, rects, 1, Unsorted);
596 XDrawString (si->dpy, si->passwd_dialog, gc1,
597 rects[0].x + pw->shadow_width,
598 rects[0].y + (pw->passwd_font->ascent +
599 pw->passwd_font->descent),
600 pw->passwd_string, strlen(pw->passwd_string));
602 XSetClipMask (si->dpy, gc1, None);
608 x = (rects[0].x + pw->shadow_width +
609 string_width (pw->passwd_font, pw->passwd_string));
610 y = rects[0].y + pw->shadow_width;
612 if (x > rects[0].x + rects[0].width - 1)
613 x = rects[0].x + rects[0].width - 1;
614 XDrawLine (si->dpy, si->passwd_dialog, gc1,
615 x, y, x, y + pw->passwd_font->ascent);
618 pw->i_beam = (pw->i_beam + 1) % 4;
623 y = pw->thermo_field_height * (1.0 - pw->ratio);
626 XFillRectangle (si->dpy, si->passwd_dialog, gc2,
627 pw->thermo_field_x + 1,
628 pw->thermo_field_y + 1,
631 XSetForeground (si->dpy, gc1, pw->logo_foreground);
632 XFillRectangle (si->dpy, si->passwd_dialog, gc1,
633 pw->thermo_field_x + 1,
634 pw->thermo_field_y + 1 + y,
636 MAX (0, pw->thermo_field_height - y - 2));
639 XFreeGC (si->dpy, gc1);
640 XFreeGC (si->dpy, gc2);
641 XSync (si->dpy, False);
646 destroy_passwd_window (saver_info *si)
648 passwd_dialog_data *pw = si->pw_data;
649 Screen *screen = si->default_screen->screen;
650 Colormap cmap = DefaultColormapOfScreen (screen);
651 Pixel black = BlackPixelOfScreen (screen);
652 Pixel white = WhitePixelOfScreen (screen);
655 XtRemoveTimeOut (pw->timer);
657 move_mouse_grab (si, RootWindowOfScreen(si->screens[0].screen),
658 si->screens[0].cursor);
659 set_vp_mode_switch_locked (si, False);
661 if (si->passwd_dialog)
663 XDestroyWindow (si->dpy, si->passwd_dialog);
664 si->passwd_dialog = 0;
671 gcv.function = GXcopy;
672 gc = XCreateGC (si->dpy, si->default_screen->screensaver_window,
674 XCopyArea (si->dpy, pw->save_under,
675 si->default_screen->screensaver_window, gc,
677 pw->width + (pw->border_width*2) + 1,
678 pw->height + (pw->border_width*2) + 1,
679 pw->x - pw->border_width, pw->y - pw->border_width);
680 XFreePixmap (si->dpy, pw->save_under);
682 XFreeGC (si->dpy, gc);
685 if (pw->heading_label) free (pw->heading_label);
686 if (pw->body_label) free (pw->body_label);
687 if (pw->user_label) free (pw->user_label);
688 if (pw->passwd_label) free (pw->passwd_label);
690 if (pw->heading_font) XFreeFont (si->dpy, pw->heading_font);
691 if (pw->body_font) XFreeFont (si->dpy, pw->body_font);
692 if (pw->label_font) XFreeFont (si->dpy, pw->label_font);
693 if (pw->passwd_font) XFreeFont (si->dpy, pw->passwd_font);
695 if (pw->foreground != black && pw->foreground != white)
696 XFreeColors (si->dpy, cmap, &pw->foreground, 1, 0L);
697 if (pw->background != black && pw->background != white)
698 XFreeColors (si->dpy, cmap, &pw->background, 1, 0L);
699 if (pw->passwd_foreground != black && pw->passwd_foreground != white)
700 XFreeColors (si->dpy, cmap, &pw->passwd_foreground, 1, 0L);
701 if (pw->passwd_background != black && pw->passwd_background != white)
702 XFreeColors (si->dpy, cmap, &pw->passwd_background, 1, 0L);
703 if (pw->logo_foreground != black && pw->logo_foreground != white)
704 XFreeColors (si->dpy, cmap, &pw->logo_foreground, 1, 0L);
705 if (pw->logo_background != black && pw->logo_background != white)
706 XFreeColors (si->dpy, cmap, &pw->logo_background, 1, 0L);
707 if (pw->shadow_top != black && pw->shadow_top != white)
708 XFreeColors (si->dpy, cmap, &pw->shadow_top, 1, 0L);
709 if (pw->shadow_bottom != black && pw->shadow_bottom != white)
710 XFreeColors (si->dpy, cmap, &pw->shadow_bottom, 1, 0L);
712 memset (pw, 0, sizeof(*pw));
719 undo_vp_motion (saver_info *si)
721 #ifdef HAVE_XF86VMODE
722 saver_preferences *p = &si->prefs;
723 int screen = 0; /* always screen 0 */
724 saver_screen_info *ssi = &si->screens[screen];
725 int event, error, x, y;
728 if (ssi->blank_vp_x == -1 && ssi->blank_vp_y == -1)
730 if (!XF86VidModeQueryExtension (si->dpy, &event, &error))
732 if (!XF86VidModeGetViewPort (si->dpy, 0, &x, &y))
734 if (ssi->blank_vp_x == x && ssi->blank_vp_y == y)
737 /* We're going to move the viewport. The mouse has just been grabbed on
738 (and constrained to, thus warped to) the password window, so it is no
739 longer near the edge of the screen. However, wait a bit anyway, just
740 to make sure the server drains its last motion event, so that the
741 screen doesn't continue to scroll after we've reset the viewport.
743 XSync (si->dpy, False);
744 usleep (250); /* 1/4 second */
745 XSync (si->dpy, False);
747 status = XF86VidModeSetViewPort (si->dpy, screen,
748 ssi->blank_vp_x, ssi->blank_vp_y);
751 fprintf (stderr, "%s: unable to move vp from (%d,%d) back to (%d,%d)!\n",
752 blurb(), x, y, ssi->blank_vp_x, ssi->blank_vp_y);
753 else if (p->verbose_p)
754 fprintf (stderr, "%s: vp moved to (%d,%d); moved it back to (%d,%d).\n",
755 blurb(), x, y, ssi->blank_vp_x, ssi->blank_vp_y);
757 #endif /* HAVE_XF86VMODE */
762 set_vp_mode_switch_locked (saver_info *si, Bool locked_p)
764 #ifdef HAVE_XF86VMODE
765 saver_preferences *p = &si->prefs;
766 int screen = 0; /* always screen 0 */
770 if (!XF86VidModeQueryExtension (si->dpy, &event, &error))
772 status = XF86VidModeLockModeSwitch (si->dpy, screen, locked_p);
775 fprintf (stderr, "%s: unable to %s vp switching!\n",
776 blurb(), (locked_p ? "lock" : "unlock"));
777 else if (p->verbose_p)
778 fprintf (stderr, "%s: %s vp switching.\n",
779 blurb(), (locked_p ? "locked" : "unlocked"));
780 #endif /* HAVE_XF86VMODE */
789 passwd_animate_timer (XtPointer closure, XtIntervalId *id)
791 saver_info *si = (saver_info *) closure;
793 passwd_dialog_data *pw = si->pw_data;
797 pw->ratio -= (1.0 / ((double) si->prefs.passwd_timeout / (double) tick));
801 if (pw->state == pw_read)
805 update_passwd_window (si, 0, pw->ratio);
807 if (pw->state == pw_read)
808 pw->timer = XtAppAddTimeOut (si->app, tick, passwd_animate_timer,
813 idle_timer ((XtPointer) si, id);
818 handle_passwd_key (saver_info *si, XKeyEvent *event)
820 saver_preferences *p = &si->prefs;
821 passwd_dialog_data *pw = si->pw_data;
822 int pw_size = sizeof (pw->typed_passwd) - 1;
823 char *typed_passwd = pw->typed_passwd;
827 int size = XLookupString (event, s, 1, 0, 0);
829 if (size != 1) return;
835 case '\010': case '\177': /* Backspace */
839 typed_passwd [strlen(typed_passwd)-1] = 0;
842 case '\025': case '\030': /* Erase line */
843 memset (typed_passwd, 0, pw_size);
846 case '\012': case '\015': /* Enter */
847 if (pw->state != pw_read)
848 ; /* already done? */
849 else if (typed_passwd[0] == 0)
853 update_passwd_window (si, "Checking...", pw->ratio);
854 XSync (si->dpy, False);
855 if (passwd_valid_p (typed_passwd, p->verbose_p))
859 update_passwd_window (si, "", pw->ratio);
864 i = strlen (typed_passwd);
869 typed_passwd [i] = *s;
870 typed_passwd [i+1] = 0;
875 i = strlen(typed_passwd);
876 stars = (char *) malloc(i+1);
877 memset (stars, '*', i);
879 update_passwd_window (si, stars, pw->ratio);
885 passwd_event_loop (saver_info *si)
887 saver_preferences *p = &si->prefs;
890 passwd_animate_timer ((XtPointer) si, 0);
892 while (si->pw_data && si->pw_data->state == pw_read)
894 XtAppNextEvent (si->app, &event);
895 if (event.xany.window == si->passwd_dialog && event.xany.type == Expose)
896 draw_passwd_window (si);
897 else if (event.xany.type == KeyPress)
898 handle_passwd_key (si, &event.xkey);
900 XtDispatchEvent (&event);
903 switch (si->pw_data->state)
905 case pw_ok: msg = 0; break;
906 case pw_null: msg = ""; break;
907 case pw_time: msg = "Timed out!"; break;
908 default: msg = "Sorry!"; break;
911 if (si->pw_data->state == pw_fail)
912 si->unlock_failures++;
915 switch (si->pw_data->state)
918 fprintf (stderr, "%s: password correct.\n", blurb()); break;
920 fprintf (stderr, "%s: password incorrect!\n", blurb()); break;
923 fprintf (stderr, "%s: password entry cancelled.\n", blurb()); break;
925 fprintf (stderr, "%s: password entry timed out.\n", blurb()); break;
930 if (si->pw_data->state == pw_fail)
932 /* If they typed a password (as opposed to just hitting return) and
933 the password was invalid, log it.
935 struct passwd *pw = getpwuid (getuid ());
936 char *d = DisplayString (si->dpy);
937 char *u = (pw->pw_name ? pw->pw_name : "???");
945 # if defined(LOG_AUTHPRIV)
947 # elif defined(LOG_AUTH)
954 openlog (progname, opt, fac);
955 syslog (LOG_NOTICE, "FAILED LOGIN %d ON DISPLAY \"%s\", FOR \"%s\"",
956 si->unlock_failures, d, u);
959 #endif /* HAVE_SYSLOG */
961 if (si->pw_data->state == pw_fail)
962 XBell (si->dpy, False);
964 if (si->pw_data->state == pw_ok && si->unlock_failures != 0)
966 if (si->unlock_failures == 1)
967 fprintf (real_stderr,
968 "%s: WARNING: 1 failed attempt to unlock the screen.\n",
971 fprintf (real_stderr,
972 "%s: WARNING: %d failed attempts to unlock the screen.\n",
973 blurb(), si->unlock_failures);
974 fflush (real_stderr);
976 si->unlock_failures = 0;
981 si->pw_data->i_beam = 0;
982 update_passwd_window (si, msg, 0.0);
983 XSync (si->dpy, False);
986 /* Swallow all pending KeyPress/KeyRelease events. */
989 while (XCheckMaskEvent (si->dpy, KeyPressMask|KeyReleaseMask, &e))
997 unlock_p (saver_info *si)
999 saver_preferences *p = &si->prefs;
1000 Screen *screen = si->default_screen->screen;
1001 Colormap cmap = DefaultColormapOfScreen (screen);
1005 fprintf (stderr, "%s: prompting for password.\n", blurb());
1007 if (si->pw_data || si->passwd_dialog)
1008 destroy_passwd_window (si);
1010 make_passwd_window (si);
1011 if (cmap) XInstallColormap (si->dpy, cmap);
1013 passwd_event_loop (si);
1015 status = (si->pw_data->state == pw_ok);
1016 destroy_passwd_window (si);
1018 cmap = si->default_screen->cmap;
1019 if (cmap) XInstallColormap (si->dpy, cmap);
1024 #endif /* !NO_LOCKING -- whole file */