/* lock.c --- handling the password dialog for locking-mode.
- * xscreensaver, Copyright (c) 1993-2007 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1993-2008 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
static void xfree_lock_grab_smasher (saver_info *si, Bool lock_p);
#endif /* HAVE_XF86MISCSETGRABKEYSSTATE */
+#ifdef HAVE_RANDR
+# include <X11/extensions/Xrandr.h>
+#endif /* HAVE_RANDR */
#ifdef _VROOT_H_
ERROR! You must not include vroot.h in this file.
extern void xss_authenticate(saver_info *si, Bool verbose_p);
-static void
+static int
new_passwd_window (saver_info *si)
{
passwd_dialog_data *pw;
pw = (passwd_dialog_data *) calloc (1, sizeof(*pw));
if (!pw)
- return;
+ return -1;
/* Display the button only if the "newLoginCommand" pref is non-null.
*/
}
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,
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;
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;
if (cmap)
XInstallColormap (si->dpy, cmap);
draw_passwd_window (si);
+
+ return 0;
}
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)
{
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);
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;
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);
#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;
{
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)
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';
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;
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);
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);
}