X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Flock.c;h=2886115d193e856a9c0ee346f54aaacfedeaa05d;hb=50be9bb40dc60130c99ffa568e6677779904ff70;hp=e1d29dc92a958b31d8cbf3b6489e5997df8d012b;hpb=6b1c86cf395f59389e4ece4ea8f4bea2c332745b;p=xscreensaver diff --git a/driver/lock.c b/driver/lock.c index e1d29dc9..2886115d 100644 --- a/driver/lock.c +++ b/driver/lock.c @@ -1,5 +1,5 @@ /* lock.c --- handling the password dialog for locking-mode. - * xscreensaver, Copyright (c) 1993-2007 Jamie Zawinski + * xscreensaver, Copyright (c) 1993-2008 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -45,6 +45,9 @@ static void xfree_lock_grab_smasher (saver_info *si, Bool lock_p); #endif /* HAVE_XF86MISCSETGRABKEYSSTATE */ +#ifdef HAVE_RANDR +# include +#endif /* HAVE_RANDR */ #ifdef _VROOT_H_ ERROR! You must not include vroot.h in this file. @@ -179,7 +182,7 @@ static void restore_background (saver_info *si); extern void xss_authenticate(saver_info *si, Bool verbose_p); -static void +static int new_passwd_window (saver_info *si) { passwd_dialog_data *pw; @@ -190,7 +193,7 @@ new_passwd_window (saver_info *si) pw = (passwd_dialog_data *) calloc (1, sizeof(*pw)); if (!pw) - return; + return -1; /* Display the button only if the "newLoginCommand" pref is non-null. */ @@ -406,13 +409,14 @@ new_passwd_window (saver_info *si) } si->pw_data = pw; + return 0; } /** * info_msg and prompt may be NULL. */ -static void +static int make_passwd_window (saver_info *si, const char *info_msg, const char *prompt, @@ -428,11 +432,15 @@ make_passwd_window (saver_info *si, cleanup_passwd_window (si); + if (! ssi) /* WTF? Trying to prompt while no screens connected? */ + return -1; + if (!si->pw_data) - new_passwd_window (si); + if (new_passwd_window (si) < 0) + return -1; if (!(pw = si->pw_data)) - return; + return -1; pw->ratio = 1.0; @@ -614,10 +622,11 @@ make_passwd_window (saver_info *si, actually be visible; this takes into account virtual viewports as well as Xinerama. */ { - int x, y, w, h; - get_screen_viewport (pw->prompt_screen, &x, &y, &w, &h, - pw->previous_mouse_x, pw->previous_mouse_y, - si->prefs.verbose_p); + saver_screen_info *ssi = &si->screens [mouse_screen (si)]; + int x = ssi->x; + int y = ssi->y; + int w = ssi->width; + int h = ssi->height; if (si->prefs.debug_p) w /= 2; pw->x = x + ((w + pw->width) / 2) - pw->width; pw->y = y + ((h + pw->height) / 2) - pw->height; @@ -678,6 +687,8 @@ make_passwd_window (saver_info *si, if (cmap) XInstallColormap (si->dpy, cmap); draw_passwd_window (si); + + return 0; } @@ -1277,11 +1288,20 @@ destroy_passwd_window (saver_info *si) XWarpPointer (si->dpy, None, RootWindowOfScreen (ssi->screen), 0, 0, 0, 0, pw->previous_mouse_x, pw->previous_mouse_y); + XSync (si->dpy, False); while (XCheckMaskEvent (si->dpy, PointerMotionMask, &event)) if (p->verbose_p) fprintf (stderr, "%s: discarding MotionNotify event.\n", blurb()); +#ifdef HAVE_XINPUT + if (si->using_xinput_extension && si->xinput_DeviceMotionNotify) + while (XCheckTypedEvent (si->dpy, si->xinput_DeviceMotionNotify, &event)) + if (p->verbose_p) + fprintf (stderr, "%s: discarding DeviceMotionNotify event.\n", + blurb()); +#endif + if (si->passwd_dialog) { if (si->prefs.verbose_p) @@ -1418,8 +1438,12 @@ xfree_lock_grab_smasher (saver_info *si, Bool lock_p) { saver_preferences *p = &si->prefs; int status; - + int event, error; XErrorHandler old_handler; + + if (!XF86MiscQueryExtension(si->dpy, &event, &error)) + return; + XSync (si->dpy, False); error_handler_hit_p = False; old_handler = XSetErrorHandler (ignore_all_errors_ehandler); @@ -1463,6 +1487,7 @@ xfree_lock_mode_switch (saver_info *si, Bool lock_p) static Bool any_mode_locked_p = False; saver_preferences *p = &si->prefs; int screen; + int real_nscreens = ScreenCount (si->dpy); int event, error; Bool status; XErrorHandler old_handler; @@ -1472,7 +1497,7 @@ xfree_lock_mode_switch (saver_info *si, Bool lock_p) if (!XF86VidModeQueryExtension (si->dpy, &event, &error)) return; - for (screen = 0; screen < (si->xinerama_p ? 1 : si->nscreens); screen++) + for (screen = 0; screen < real_nscreens; screen++) { XSync (si->dpy, False); old_handler = XSetErrorHandler (ignore_all_errors_ehandler); @@ -1509,12 +1534,13 @@ undo_vp_motion (saver_info *si) #ifdef HAVE_XF86VMODE saver_preferences *p = &si->prefs; int screen; + int real_nscreens = ScreenCount (si->dpy); int event, error; if (!XF86VidModeQueryExtension (si->dpy, &event, &error)) return; - for (screen = 0; screen < si->nscreens; screen++) + for (screen = 0; screen < real_nscreens; screen++) { saver_screen_info *ssi = &si->screens[screen]; int x, y; @@ -1761,30 +1787,77 @@ passwd_event_loop (saver_info *si) { saver_preferences *p = &si->prefs; char *msg = 0; - XEvent event; + + /* We have to go through this union bullshit because gcc-4.4.0 has + stricter struct-aliasing rules. Without this, the optimizer + can fuck things up. + */ + union { + XEvent x_event; +# ifdef HAVE_RANDR + XRRScreenChangeNotifyEvent xrr_event; +# endif /* HAVE_RANDR */ + } event; passwd_animate_timer ((XtPointer) si, 0); while (si->unlock_state == ul_read) { - XtAppNextEvent (si->app, &event); - if (event.xany.window == si->passwd_dialog && event.xany.type == Expose) + XtAppNextEvent (si->app, &event.x_event); + +#ifdef HAVE_RANDR + if (si->using_randr_extension && + (event.x_event.type == + (si->randr_event_number + RRScreenChangeNotify))) + { + /* The Resize and Rotate extension sends an event when the + size, rotation, or refresh rate of any screen has changed. */ + + if (p->verbose_p) + { + /* XRRRootToScreen is in Xrandr.h 1.4, 2001/06/07 */ + int screen = XRRRootToScreen(si->dpy, event.xrr_event.window); + fprintf (stderr, "%s: %d: screen change event received\n", + blurb(), screen); + } + +#ifdef RRScreenChangeNotifyMask + /* Inform Xlib that it's ok to update its data structures. */ + XRRUpdateConfiguration(&event.x_event); /* Xrandr.h 1.9, 2002/09/29 */ +#endif /* RRScreenChangeNotifyMask */ + + /* Resize the existing xscreensaver windows and cached ssi data. */ + if (update_screen_layout (si)) + { + if (p->verbose_p) + { + fprintf (stderr, "%s: new layout:\n", blurb()); + describe_monitor_layout (si); + } + resize_screensaver_window (si); + } + } + else +#endif /* HAVE_RANDR */ + + if (event.x_event.xany.window == si->passwd_dialog && + event.x_event.xany.type == Expose) draw_passwd_window (si); - else if (event.xany.type == KeyPress) + else if (event.x_event.xany.type == KeyPress) { - handle_passwd_key (si, &event.xkey); - si->pw_data->caps_p = (event.xkey.state & LockMask); + handle_passwd_key (si, &event.x_event.xkey); + si->pw_data->caps_p = (event.x_event.xkey.state & LockMask); } - else if (event.xany.type == ButtonPress || - event.xany.type == ButtonRelease) + else if (event.x_event.xany.type == ButtonPress || + event.x_event.xany.type == ButtonRelease) { si->pw_data->button_state_changed_p = True; - handle_unlock_button (si, &event); + handle_unlock_button (si, &event.x_event); if (si->pw_data->login_button_p) - handle_login_button (si, &event); + handle_login_button (si, &event.x_event); } else - XtDispatchEvent (&event); + XtDispatchEvent (&event.x_event); } switch (si->unlock_state) @@ -1866,11 +1939,10 @@ remove_trailing_whitespace(const char *str) len = strlen(str); newstr = malloc(len + 1); - (void) strcpy(newstr, str); - if (!newstr) return NULL; + (void) strcpy(newstr, str); chr = newstr + len; while (isspace(*--chr) && chr >= newstr) *chr = '\0'; @@ -1898,6 +1970,12 @@ gui_auth_conv(int num_msg, const char *info_msg, *prompt; struct auth_response *responses; + if (si->unlock_state == ul_cancel || + si->unlock_state == ul_time) + /* If we've already cancelled or timed out in this PAM conversation, + don't prompt again even if PAM asks us to! */ + return -1; + if (!(responses = calloc(num_msg, sizeof(struct auth_response)))) goto fail; @@ -1932,9 +2010,11 @@ gui_auth_conv(int num_msg, info_msg_trimmed = remove_trailing_whitespace(info_msg); prompt_trimmed = remove_trailing_whitespace(prompt); - make_passwd_window(si, info_msg_trimmed, prompt_trimmed, - auth_msgs[i].type == AUTH_MSGTYPE_PROMPT_ECHO - ? True : False); + if (make_passwd_window(si, info_msg_trimmed, prompt_trimmed, + auth_msgs[i].type == AUTH_MSGTYPE_PROMPT_ECHO + ? True : False) + < 0) + goto fail; if (info_msg_trimmed) free(info_msg_trimmed); @@ -2033,7 +2113,7 @@ auth_finished_cb (saver_info *si) event.xany.type == Expose) draw_passwd_window (si); else if (event.xany.type == ButtonPress || - event.xany.type == ButtonRelease) + event.xany.type == KeyPress) break; XSync (si->dpy, False); }