/* windows.c --- turning the screen black; dealing with visuals, virtual roots.
- * xscreensaver, Copyright (c) 1991-2004 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 */
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;
}
}
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
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 ();
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 ();
}
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++)
{
attrs.backing_pixel = ssi->black_pixel;
attrs.border_pixel = ssi->black_pixel;
- if (p->debug_p && !p->quad_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)
;
*/
int nscreens;
XineramaScreenInfo *xsi = XineramaQueryScreens (si->dpy, &nscreens);
- if (nscreens != si->nscreens) abort();
+
+ 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 < si->nscreens; i++)
+ for (i = 0; i < nscreens; i++)
{
saver_screen_info *ssi = &si->screens[i];
if (p->verbose_p &&
changes.height = height;
changes.border_width = 0;
- if (p->debug_p && !p->quad_p) changes.width = changes.width / 2;
+ if (p->debug_p
+# ifdef QUAD_MODE
+ && !p->quad_p
+# endif
+ )
+ changes.width = changes.width / 2;
if (p->verbose_p)
fprintf (stderr,
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;
/* 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;