/* windows.c --- turning the screen black; dealing with visuals, virtual roots.
- * xscreensaver, Copyright (c) 1991-2001 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1991-2007 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
#endif /* HAVE_UNAME */
#include <stdio.h>
-#include <X11/Xproto.h> /* for CARD32 */
+/* #include <X11/Xproto.h> / * for CARD32 */
#include <X11/Xlib.h>
#include <X11/Xutil.h> /* for XSetClassHint() */
#include <X11/Xatom.h>
#include <time.h>
#include <sys/time.h>
+/* You might think that to store an array of 32-bit quantities onto a
+ server-side property, you would pass an array of 32-bit data quantities
+ into XChangeProperty(). You would be wrong. You have to use an array
+ of longs, even if long is 64 bits (using 32 of each 64.)
+ */
+typedef long PROP32;
+
#ifdef HAVE_MIT_SAVER_EXTENSION
# include <X11/extensions/scrnsaver.h>
#endif /* HAVE_MIT_SAVER_EXTENSION */
# include <X11/extensions/Xinerama.h>
#endif /* HAVE_XINERAMA */
-
/* This file doesn't need the Xt headers, so stub these types out... */
#undef XtPointer
#define XtAppContext void*
}
if (p->verbose_p)
- fprintf(stderr, "%s: %d: grabbing keyboard on 0x%x... %s.\n",
+ fprintf(stderr, "%s: %d: grabbing keyboard on 0x%lx... %s.\n",
blurb(), screen_no, (unsigned long) w, grab_string(status));
return status;
}
}
if (p->verbose_p)
- fprintf(stderr, "%s: %d: grabbing mouse on 0x%x... %s.\n",
+ fprintf(stderr, "%s: %d: grabbing mouse on 0x%lx... %s.\n",
blurb(), screen_no, (unsigned long) w, grab_string(status));
return status;
}
saver_preferences *p = &si->prefs;
XUngrabKeyboard(si->dpy, CurrentTime);
if (p->verbose_p)
- fprintf(stderr, "%s: %d: ungrabbing keyboard (was 0x%x).\n",
+ fprintf(stderr, "%s: %d: ungrabbing keyboard (was 0x%lx).\n",
blurb(), si->keyboard_grab_screen,
(unsigned long) si->keyboard_grab_window);
si->keyboard_grab_window = 0;
saver_preferences *p = &si->prefs;
XUngrabPointer(si->dpy, CurrentTime);
if (p->verbose_p)
- fprintf(stderr, "%s: %d: ungrabbing mouse (was 0x%x).\n",
+ fprintf(stderr, "%s: %d: ungrabbing mouse (was 0x%lx).\n",
blurb(), si->mouse_grab_screen,
(unsigned long) si->mouse_grab_window);
si->mouse_grab_window = 0;
}
+/* Apparently there is this program called "rdesktop" which is a windows
+ terminal server client for Unix. It would seem that this program holds
+ the keyboard GRABBED the whole time it has focus! This is, of course,
+ completely idiotic: the whole point of grabbing is to get events when
+ you do *not* have focus, so grabbing *only when* you have focus is
+ completely redundant -- unless your goal is to make xscreensaver not
+ able to ever lock the screen when your program is running.
+
+ If xscreensaver blanks while rdesktop still has a keyboard grab, then
+ when we try to prompt for the password, we won't get the characters:
+ they'll be typed into rdesktop.
+
+ Perhaps rdesktop will release its keyboard grab if it loses focus?
+ What the hell, let's give it a try. If we fail to grab the keyboard
+ four times in a row, we forcibly set focus to "None" and try four
+ more times. (We don't touch focus unless we're already having a hard
+ time getting a grab.)
+ */
+static void
+nuke_focus (saver_info *si, int screen_no)
+{
+ saver_preferences *p = &si->prefs;
+ Window focus = 0;
+ int rev = 0;
+
+ XGetInputFocus (si->dpy, &focus, &rev);
+
+ if (p->verbose_p)
+ {
+ char w[255], r[255];
+
+ if (focus == PointerRoot) strcpy (w, "PointerRoot");
+ else if (focus == None) strcpy (w, "None");
+ else sprintf (w, "0x%lx", (unsigned long) focus);
+
+ if (rev == RevertToParent) strcpy (r, "RevertToParent");
+ else if (rev == RevertToPointerRoot) strcpy (r, "RevertToPointerRoot");
+ else if (rev == RevertToNone) strcpy (r, "RevertToNone");
+ else sprintf (r, "0x%x", rev);
+
+ fprintf (stderr, "%s: %d: removing focus from %s / %s.\n",
+ blurb(), screen_no, w, r);
+ }
+
+ XSetInputFocus (si->dpy, None, RevertToNone, CurrentTime);
+ XSync (si->dpy, False);
+}
+
+
static Bool
grab_keyboard_and_mouse (saver_info *si, Window window, Cursor cursor,
int screen_no)
{
- Status mstatus, kstatus;
+ Status mstatus = 0, kstatus = 0;
int i;
int retries = 4;
+ Bool focus_fuckus = False;
+
+ AGAIN:
for (i = 0; i < retries; i++)
{
}
if (kstatus != GrabSuccess)
- fprintf (stderr, "%s: couldn't grab keyboard! (%s)\n",
- blurb(), grab_string(kstatus));
+ {
+ fprintf (stderr, "%s: couldn't grab keyboard! (%s)\n",
+ blurb(), grab_string(kstatus));
+
+ if (! focus_fuckus)
+ {
+ focus_fuckus = True;
+ nuke_focus (si, screen_no);
+ goto AGAIN;
+ }
+ }
for (i = 0; i < retries; i++)
{
fprintf (stderr, "%s: couldn't grab pointer! (%s)\n",
blurb(), grab_string(mstatus));
- return (kstatus == GrabSuccess ||
- mstatus == GrabSuccess);
+
+ /* When should we allow blanking to proceed? The current theory
+ is that a keyboard grab is manditory; a mouse grab is optional.
+
+ - If we don't have a keyboard grab, then we won't be able to
+ read a password to unlock, so the kbd grab is manditory.
+ (We can't conditionalize this on locked_p, because someone
+ might run "xscreensaver-command -lock" at any time.)
+
+ - If we don't have a mouse grab, then we might not see mouse
+ clicks as a signal to unblank -- but we will still see kbd
+ activity, so that's not a disaster.
+ */
+
+ if (kstatus != GrabSuccess) /* Do not blank without a kbd grab. */
+ return False;
+
+ return True; /* Grab is good, go ahead and blank. */
}
static void
Atom type;
int format;
unsigned long nitems, bytesafter;
- char *version;
+ unsigned char *version;
if (XGetWindowProperty (dpy, kids[i], XA_SCREENSAVER_VERSION, 0, 1,
False, XA_STRING, &type, &format, &nitems,
- &bytesafter, (unsigned char **) &version)
+ &bytesafter, &version)
== Success
&& type != None)
{
- char *id;
+ unsigned char *id;
if (!XGetWindowProperty (dpy, kids[i], XA_SCREENSAVER_ID, 0, 512,
False, XA_STRING, &type, &format, &nitems,
- &bytesafter, (unsigned char **) &id)
+ &bytesafter, &id)
== Success
|| type == None)
- id = "???";
+ id = (unsigned char *) "???";
fprintf (stderr,
"%s: already running on display %s (window 0x%x)\n from process %s.\n",
- blurb(), DisplayString (dpy), (int) kids [i], id);
+ blurb(), DisplayString (dpy), (int) kids [i],
+ (char *) id);
status = True;
}
}
static Bool safe_XKillClient (Display *dpy, XID id);
+#ifdef HAVE_XF86VMODE
+static Bool safe_XF86VidModeGetViewPort (Display *, int, int *, int *);
+#endif /* HAVE_XF86VMODE */
+
+
static void
kill_xsetroot_data_1 (Display *dpy, Window window,
Atom prop, const char *atom_name,
Atom type;
int format;
unsigned long nitems, bytesafter;
- Pixmap *dataP = 0;
+ unsigned char *dataP = 0;
/* If the user has been using xv or xsetroot as a screensaver (to display
an image on the screensaver window, as a kind of slideshow) then the
*/
if (XGetWindowProperty (dpy, window, prop, 0, 1,
True, AnyPropertyType, &type, &format, &nitems,
- &bytesafter, (unsigned char **) &dataP)
+ &bytesafter, &dataP)
== Success
&& type != None)
{
- if (dataP && *dataP && type == XA_PIXMAP && format == 32 &&
+ Pixmap *pixP = (Pixmap *) dataP;
+ if (pixP && *pixP && type == XA_PIXMAP && format == 32 &&
nitems == 1 && bytesafter == 0)
{
if (verbose_p)
fprintf (stderr, "%s: destroying %s data (0x%lX).\n",
- blurb(), atom_name, *dataP);
- safe_XKillClient (dpy, *dataP);
+ blurb(), atom_name, *pixP);
+ safe_XKillClient (dpy, *pixP);
}
else
fprintf (stderr,
"\t%lu, %lu; type: %lu, format: %d, "
"nitems: %lu, bytesafter %ld\n",
blurb(), atom_name,
- (unsigned long) dataP, (dataP ? *dataP : 0), type,
+ (unsigned long) pixP, (pixP ? *pixP : 0), type,
format, nitems, bytesafter);
}
}
Atom type;
int format;
unsigned long nitems, bytesafter;
- Window *vrootP = 0;
+ unsigned char *dataP = 0;
+ Window *vrootP;
+ int j;
+
+ /* Skip this window if it is the xscreensaver window of any other
+ screen (this can happen in the Xinerama case.)
+ */
+ for (j = 0; j < si->nscreens; j++)
+ {
+ saver_screen_info *ssi2 = &si->screens[j];
+ if (kids[i] == ssi2->screensaver_window)
+ goto SKIP;
+ }
if (XGetWindowProperty (dpy, kids[i], XA_VROOT, 0, 1, False, XA_WINDOW,
&type, &format, &nitems, &bytesafter,
- (unsigned char **) &vrootP)
+ &dataP)
!= Success)
continue;
- if (! vrootP)
+ if (! dataP)
continue;
+
+ vrootP = (Window *) dataP;
if (ssi->real_vroot)
{
if (*vrootP == ssi->screensaver_window) abort ();
}
ssi->real_vroot = kids [i];
ssi->real_vroot_value = *vrootP;
+ SKIP:
+ ;
}
XSync (dpy, False);
fprintf (stderr, "%s: %s received: restarting...\n",
blurb(), signal_name(sig));
- unblank_screen (si);
- kill_screenhack (si);
- XSync (si->dpy, False);
+
+ if (si->screen_blanked_p)
+ {
+ unblank_screen (si);
+ kill_screenhack (si);
+ XSync (si->dpy, False);
+ }
+
restart_process (si); /* Does not return */
abort ();
}
if (bugp)
fprintf(real_stderr,
"%s: see http://www.jwz.org/xscreensaver/bugs.html\n"
- "\t\tfor bug reporting information.\n\n",
+ "\t\t\tfor bug reporting information.\n\n",
blurb());
# if defined(HAVE_GETCWD)
void
store_saver_status (saver_info *si)
{
- CARD32 *status;
+ PROP32 *status;
int size = si->nscreens + 2;
int i;
- status = (CARD32 *) calloc (size, sizeof(CARD32));
+ status = (PROP32 *) calloc (size, sizeof(PROP32));
- status[0] = (CARD32) (si->screen_blanked_p
+ status[0] = (PROP32) (si->screen_blanked_p
? (si->locked_p ? XA_LOCK : XA_BLANK)
: 0);
- status[1] = (CARD32) si->blank_time;
+ status[1] = (PROP32) si->blank_time;
for (i = 0; i < si->nscreens; i++)
{
XA_SCREENSAVER_STATUS,
XA_INTEGER, 32, PropModeReplace,
(unsigned char *) status, size);
+ free (status);
}
int w = WidthOfScreen (ssi->screen);
int h = HeightOfScreen (ssi->screen);
-#ifdef HAVE_XF86VMODE
+# ifdef HAVE_XF86VMODE
saver_info *si = ssi->global;
+ saver_preferences *p = &si->prefs;
int event, error;
int dot;
XF86VidModeModeLine ml;
int x, y;
- Bool xinerama_p;
- Bool placement_only_p = (target_x != -1 && target_y != -1);
+ Bool xinerama_p = si->xinerama_p;
-#ifdef HAVE_XINERAMA
- xinerama_p = (XineramaQueryExtension (si->dpy, &event, &error) &&
- XineramaIsActive (si->dpy));
-#else /* !HAVE_XINERAMA */
+# ifndef HAVE_XINERAMA
/* Even if we don't have the client-side Xinerama lib, check to see if
the server supports Xinerama, so that we know to ignore the VidMode
extension -- otherwise a server crash could result. Yay. */
xinerama_p = XQueryExtension (si->dpy, "XINERAMA", &error, &event, &error);
-
-#endif /* !HAVE_XINERAMA */
+# endif /* !HAVE_XINERAMA */
-#ifdef HAVE_XINERAMA
- if (xinerama_p && placement_only_p)
+# ifdef HAVE_XINERAMA
+ if (xinerama_p)
{
- int nscreens = 0;
- XineramaScreenInfo *xsi = XineramaQueryScreens (si->dpy, &nscreens);
- if (xsi)
+ int mouse_p = (target_x != -1 && target_y != -1);
+ int which = -1;
+ int i;
+
+ /* If a mouse position wasn't passed in, assume we're talking about
+ this screen. */
+ if (!mouse_p)
{
- /* Find the screen that contains the mouse. */
- int which = -1;
- int i;
- for (i = 0; i < nscreens; i++)
- {
- if (target_x >= xsi[i].x_org &&
- target_y >= xsi[i].y_org &&
- target_x < xsi[i].x_org + xsi[i].width &&
- target_y < xsi[i].y_org + xsi[i].height)
- which = i;
- if (verbose_p)
- {
- fprintf (stderr, "%s: %d: xinerama vp: %dx%d+%d+%d",
- blurb(), i,
- xsi[which].width, xsi[which].height,
- xsi[i].x_org, xsi[i].y_org);
- if (which == i)
- fprintf (stderr, "; mouse at %d,%d",
- target_x, target_y);
- fprintf (stderr, ".\n");
- }
- }
- if (which == -1) which = 0; /* didn't find it? Use the first. */
- *x_ret = xsi[which].x_org;
- *y_ret = xsi[which].y_org;
- *w_ret = xsi[which].width;
- *h_ret = xsi[which].height;
- XFree (xsi);
- return;
+ target_x = ssi->x;
+ target_y = ssi->y;
}
+
+ /* Find the Xinerama rectangle that contains the mouse position. */
+ for (i = 0; i < si->nscreens; i++)
+ {
+ if (target_x >= si->screens[i].x &&
+ target_y >= si->screens[i].y &&
+ target_x < si->screens[i].x + si->screens[i].width &&
+ target_y < si->screens[i].y + si->screens[i].height)
+ which = i;
+ }
+ if (which == -1) which = 0; /* didn't find it? Use the first. */
+ *x_ret = si->screens[which].x;
+ *y_ret = si->screens[which].y;
+ *w_ret = si->screens[which].width;
+ *h_ret = si->screens[which].height;
+
+ if (verbose_p)
+ {
+ fprintf (stderr, "%s: %d: xinerama vp: %dx%d+%d+%d",
+ blurb(), which,
+ si->screens[which].width, si->screens[which].height,
+ si->screens[which].x, si->screens[which].y);
+ if (mouse_p)
+ fprintf (stderr, "; mouse at %d,%d", target_x, target_y);
+ fprintf (stderr, ".\n");
+ }
+
+ return;
}
-#endif /* HAVE_XINERAMA */
+# endif /* HAVE_XINERAMA */
if (!xinerama_p && /* Xinerama + VidMode = broken. */
XF86VidModeQueryExtension (si->dpy, &event, &error) &&
- XF86VidModeGetModeLine (si->dpy, ssi->number, &dot, &ml) &&
- XF86VidModeGetViewPort (si->dpy, ssi->number, &x, &y))
+ safe_XF86VidModeGetViewPort (si->dpy, ssi->number, &x, &y) &&
+ XF86VidModeGetModeLine (si->dpy, ssi->number, &dot, &ml))
{
char msg[512];
*x_ret = x;
*w_ret, *h_ret, *x_ret, *y_ret);
+ if (p->getviewport_full_of_lies_p)
+ {
+ /* XF86VidModeGetViewPort() tends to be full of lies on laptops
+ that have a docking station or external monitor that runs in
+ a different resolution than the laptop's screen:
+
+ http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=81593
+ http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=208417
+ http://bugs.xfree86.org/show_bug.cgi?id=421
+
+ The XFree86 developers have closed the bug. As far as I can
+ tell, their reason for this was, "this is an X server bug,
+ but it's pretty hard to fix. Therefore, we are closing it."
+
+ So, now there's a preference item for those unfortunate users to
+ tell us not to trust a word that XF86VidModeGetViewPort() says.
+ */
+ static int warned_once = 0;
+ if (!warned_once && verbose_p)
+ {
+ warned_once = 1;
+ fprintf (stderr,
+ "%s: %d: XF86VidModeGetViewPort() says vp is %dx%d+%d+%d;\n"
+ "%s: %d: assuming that is a pack of lies;\n"
+ "%s: %d: using %dx%d+0+0 instead.\n",
+ blurb(), ssi->number,
+ *w_ret, *h_ret, *x_ret, *y_ret,
+ blurb(), ssi->number,
+ blurb(), ssi->number, w, h);
+ }
+
+ *x_ret = 0;
+ *y_ret = 0;
+ *w_ret = w;
+ *h_ret = h;
+ return;
+ }
+
+
/* Apparently, though the server stores the X position in increments of
1 pixel, it will only make changes to the *display* in some other
increment. With XF86_SVGA on a Thinkpad, the display only updates
will still look pretty stupid -- for example, "slidescreen" will cut
off the left and right edges of the grid, etc.
*/
-# define FUDGE 16
+# define FUDGE 16
if (x > 0 && x < w - ml.hdisplay) /* not at left edge or right edge */
{
/* Round X position down to next lower multiple of FUDGE.
*x_ret = ((x - 1) / FUDGE) * FUDGE;
*w_ret += (FUDGE * 2);
}
-# undef FUDGE
+# undef FUDGE
if (*x_ret != x ||
*y_ret != y ||
return;
}
-#endif /* HAVE_XF86VMODE */
+# endif /* HAVE_XF86VMODE */
*x_ret = 0;
*y_ret = 0;
}
+#ifdef HAVE_XF86VMODE
+static Bool
+safe_XF86VidModeGetViewPort (Display *dpy, int screen, int *xP, int *yP)
+{
+ Bool result;
+ XErrorHandler old_handler;
+ XSync (dpy, False);
+ error_handler_hit_p = False;
+ old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
+
+ result = XF86VidModeGetViewPort (dpy, screen, xP, yP);
+
+ XSync (dpy, False);
+ XSetErrorHandler (old_handler);
+ XSync (dpy, False);
+
+ return (error_handler_hit_p
+ ? False
+ : result);
+}
+
+/* There is no "safe_XF86VidModeGetModeLine" because it fails with an
+ untrappable I/O error instead of an X error -- so one must call
+ safe_XF86VidModeGetViewPort first, and assume that both have the
+ same error condition. Thank you XFree, may I have another.
+ */
+
+#endif /* HAVE_XF86VMODE */
+
+
static void
initialize_screensaver_window_1 (saver_screen_info *ssi)
{
attrs.backing_pixel = ssi->black_pixel;
attrs.border_pixel = ssi->black_pixel;
- if (p->debug_p) width = width / 2;
+ if (p->debug_p
+# ifdef QUAD_MODE
+ && !p->quad_p
+# endif
+ )
+ width = width / 2;
if (!p->verbose_p || printed_visual_info)
;
}
+/* Called when the RANDR (Resize and Rotate) extension tells us that the
+ size of the screen has changed while the screen was blanked. If we
+ don't do this, then the screen saver will no longer fully fill the
+ screen, and some of the underlying desktop may be visible.
+ */
+void
+resize_screensaver_window (saver_info *si)
+{
+ saver_preferences *p = &si->prefs;
+ int i;
+
+ /* First update the size info in the saver_screen_info structs.
+ */
+
+# ifdef HAVE_XINERAMA
+ if (si->xinerama_p)
+ {
+ /* As of XFree86 4.3.0, the RANDR and XINERAMA extensions cannot coexist.
+ However, maybe they will someday, so I'm guessing that the right thing
+ to do in that case will be to re-query the Xinerama rectangles after
+ a RANDR size change is received: presumably, if the resolution of one
+ or more of the monitors has changed, then the Xinerama rectangle
+ corresponding to that monitor will also have been updated.
+ */
+ int nscreens;
+ XineramaScreenInfo *xsi = XineramaQueryScreens (si->dpy, &nscreens);
+
+ if (nscreens != si->nscreens) {
+ /* Apparently some Xinerama implementations let you use a hot-key
+ to change the number of screens in use! This is, of course,
+ documented nowhere. Let's try to do something marginally less
+ bad than crashing.
+ */
+ fprintf (stderr, "%s: bad craziness: xinerama screen count changed "
+ "from %d to %d!\n", blurb(), si->nscreens, nscreens);
+ if (nscreens > si->nscreens)
+ nscreens = si->nscreens;
+ }
+
+ if (!xsi) abort();
+ for (i = 0; i < nscreens; i++)
+ {
+ saver_screen_info *ssi = &si->screens[i];
+ if (p->verbose_p &&
+ (ssi->x != xsi[i].x_org ||
+ ssi->y != xsi[i].y_org ||
+ ssi->width != xsi[i].width ||
+ ssi->height != xsi[i].height))
+ fprintf (stderr,
+ "%s: %d: resize xinerama from %dx%d+%d+%d to %dx%d+%d+%d\n",
+ blurb(), i,
+ ssi->width, ssi->height, ssi->x, ssi->y,
+ xsi[i].width, xsi[i].height, xsi[i].x_org, xsi[i].y_org);
+
+ ssi->x = xsi[i].x_org;
+ ssi->y = xsi[i].y_org;
+ ssi->width = xsi[i].width;
+ ssi->height = xsi[i].height;
+ }
+ XFree (xsi);
+ }
+ else
+# endif /* HAVE_XINERAMA */
+ {
+ /* Not Xinerama -- get the real sizes of the root windows. */
+ for (i = 0; i < si->nscreens; i++)
+ {
+ saver_screen_info *ssi = &si->screens[i];
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (si->dpy, RootWindowOfScreen (ssi->screen),
+ &xgwa);
+
+ if (p->verbose_p &&
+ (ssi->x != xgwa.x ||
+ ssi->y != xgwa.y ||
+ ssi->width != xgwa.width ||
+ ssi->height != xgwa.height))
+ fprintf (stderr,
+ "%s: %d: resize screen from %dx%d+%d+%d to %dx%d+%d+%d\n",
+ blurb(), i,
+ ssi->width, ssi->height, ssi->x, ssi->y,
+ xgwa.width, xgwa.height, xgwa.x, xgwa.y);
+
+ ssi->x = xgwa.x;
+ ssi->y = xgwa.y;
+ ssi->width = xgwa.width;
+ ssi->height = xgwa.height;
+ }
+ }
+
+ /* Next, ensure that the screensaver windows are the right size, taking
+ into account both the new size of the screen in question's root window,
+ and any viewport within that.
+ */
+
+ for (i = 0; i < si->nscreens; i++)
+ {
+ saver_screen_info *ssi = &si->screens[i];
+ XWindowAttributes xgwa;
+ XWindowChanges changes;
+ int x, y, width, height;
+ unsigned int changesmask = CWX|CWY|CWWidth|CWHeight|CWBorderWidth;
+
+ XGetWindowAttributes (si->dpy, ssi->screensaver_window, &xgwa);
+ get_screen_viewport (ssi, &x, &y, &width, &height, -1, -1,
+ (p->verbose_p && !si->screen_blanked_p));
+ if (xgwa.x == x &&
+ xgwa.y == y &&
+ xgwa.width == width &&
+ xgwa.height == height)
+ continue; /* no change! */
+
+ changes.x = x;
+ changes.y = y;
+ changes.width = width;
+ changes.height = height;
+ changes.border_width = 0;
+
+ if (p->debug_p
+# ifdef QUAD_MODE
+ && !p->quad_p
+# endif
+ )
+ changes.width = changes.width / 2;
+
+ if (p->verbose_p)
+ fprintf (stderr,
+ "%s: %d: resize 0x%lx from %dx%d+%d+%d to %dx%d+%d+%d\n",
+ blurb(), i, (unsigned long) ssi->screensaver_window,
+ xgwa.width, xgwa.height, xgwa.x, xgwa.y,
+ width, height, x, y);
+ if (! safe_XConfigureWindow (si->dpy, ssi->screensaver_window,
+ changesmask, &changes))
+ {
+ fprintf (stderr,
+ "%s: %d: someone horked our saver window (0x%lx)! Unable to resize it!\n",
+ blurb(), i, (unsigned long) ssi->screensaver_window);
+ }
+ }
+}
+
+
void
raise_window (saver_info *si,
Bool inhibit_fade, Bool between_hacks_p, Bool dont_clear)
/* Note! The server is grabbed, and this will take several seconds
to complete! */
- fade_screens (si->dpy, current_maps, current_windows,
+ fade_screens (si->dpy, current_maps,
+ current_windows, si->nscreens,
p->fade_seconds/1000, p->fade_ticks, True, !dont_clear);
free(current_maps);
mouse_screen (saver_info *si)
{
saver_preferences *p = &si->prefs;
+ Window pointer_root, pointer_child;
+ int root_x, root_y, win_x, win_y;
+ unsigned int mask;
+ int i;
if (si->nscreens == 1)
return 0;
- else
+
+ for (i = 0; i < si->nscreens; i++)
{
- int i;
- for (i = 0; i < si->nscreens; i++)
+ saver_screen_info *ssi = &si->screens[i];
+ if (XQueryPointer (si->dpy, RootWindowOfScreen (ssi->screen),
+ &pointer_root, &pointer_child,
+ &root_x, &root_y, &win_x, &win_y, &mask) &&
+ root_x >= ssi->x &&
+ root_y >= ssi->y &&
+ root_x < ssi->x + ssi->width &&
+ root_y < ssi->y + ssi->height)
{
- saver_screen_info *ssi = &si->screens[i];
- Window pointer_root, pointer_child;
- int root_x, root_y, win_x, win_y;
- unsigned int mask;
- if (XQueryPointer (si->dpy,
- RootWindowOfScreen (ssi->screen),
- &pointer_root, &pointer_child,
- &root_x, &root_y, &win_x, &win_y, &mask))
- {
- if (p->verbose_p)
- fprintf (stderr, "%s: mouse is on screen %d\n",
- blurb(), i, si->nscreens);
- return i;
- }
+ if (p->verbose_p)
+ fprintf (stderr, "%s: mouse is on screen %d of %d\n",
+ blurb(), i, si->nscreens);
+ return i;
}
-
- /* couldn't figure out where the mouse is? Oh well. */
- return 0;
}
+
+ /* couldn't figure out where the mouse is? Oh well. */
+ return 0;
}
mscreen);
+# if 0
if (si->using_mit_saver_extension || si->using_sgi_saver_extension)
/* If we're using a server extension, then failure to get a grab is
not a big deal -- even without the grab, we will still be able
to un-blank when there is user activity, since the server will
tell us. */
+ /* #### No, that's not true: if we don't have a keyboard grab,
+ then we can't read passwords to unlock.
+ */
ok = True;
+# endif /* 0 */
if (!ok)
return False;
for (i = 0; i < si->nscreens; i++)
{
saver_screen_info *ssi = &si->screens[i];
-
- save_real_vroot (ssi);
+ if (ssi->real_screen_p)
+ save_real_vroot (ssi);
store_vroot_property (si->dpy,
ssi->screensaver_window,
ssi->screensaver_window);
{
int ev, er;
if (!XF86VidModeQueryExtension (si->dpy, &ev, &er) ||
- !XF86VidModeGetViewPort (si->dpy, i,
- &ssi->blank_vp_x,
- &ssi->blank_vp_y))
+ !safe_XF86VidModeGetViewPort (si->dpy, i,
+ &ssi->blank_vp_x,
+ &ssi->blank_vp_y))
ssi->blank_vp_x = ssi->blank_vp_y = -1;
}
#endif /* HAVE_XF86VMODE */
XUngrabServer (si->dpy);
XSync (si->dpy, False); /* ###### (danger over) */
-
- fade_screens (si->dpy, 0, current_windows,
+ fade_screens (si->dpy, 0,
+ current_windows, si->nscreens,
p->fade_seconds/1000, p->fade_ticks,
False, False);
/* If the focus window does has a non-default colormap, then install
that colormap as well. (On SGIs, this will cause both the root map
- and the focus map to be installed simultaniously. It'd be nice to
+ and the focus map to be installed simultaneously. It'd be nice to
pick up the other colormaps that had been installed, too; perhaps
XListInstalledColormaps could be used for that?)
*/
Visual *new_v = 0;
Bool got_it;
+ /* On some systems (most recently, MacOS X) OpenGL programs get confused
+ when you kill one and re-start another on the same window. So maybe
+ it's best to just always destroy and recreate the xscreensaver window
+ when changing hacks, instead of trying to reuse the old one?
+ */
+ Bool always_recreate_window_p = True;
+
if (visual_name && *visual_name)
{
if (!strcmp(visual_name, "default-i") ||
ssi->install_cmap_p = install_cmap_p;
if (new_v &&
- ((ssi->current_visual != new_v) ||
+ (always_recreate_window_p ||
+ (ssi->current_visual != new_v) ||
(install_cmap_p != was_installed_p)))
{
Colormap old_c = ssi->cmap;