-/* xscreensaver, Copyright (c) 1991-1993 Jamie Zawinski <jwz@lucid.com>
+/* xscreensaver, Copyright (c) 1991-1995 Jamie Zawinski <jwz@netscape.com>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
#include "xscreensaver.h"
+#ifdef HAVE_SAVER_EXTENSION
+#include <X11/extensions/scrnsaver.h>
+extern Bool use_saver_extension;
+#endif /* HAVE_SAVER_EXTENSION */
+
#if __STDC__
extern int kill (pid_t, int); /* signal() is in sys/signal.h... */
#endif /* __STDC__ */
+extern Time timeout;
+
extern Bool lock_p, demo_mode_p;
Atom XA_VROOT, XA_XSETROOT_ID;
#if __STDC__
extern void describe_visual (FILE *, Display *, Visual *);
+extern void reset_stderr (void);
#endif
Window screensaver_window = 0;
static unsigned long black_pixel;
static Window real_vroot, real_vroot_value;
+#ifdef HAVE_SAVER_EXTENSION
+Window server_saver_window = 0;
+#endif /* HAVE_SAVER_EXTENSION */
+
#define ALL_POINTER_EVENTS \
(ButtonPressMask | ButtonReleaseMask | EnterWindowMask | \
LeaveWindowMask | PointerMotionMask | PointerMotionHintMask | \
GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime)
void
-grab_keyboard_and_mouse ()
+grab_keyboard_and_mouse P((void))
{
Status status;
XSync (dpy, False);
}
void
-ungrab_keyboard_and_mouse ()
+ungrab_keyboard_and_mouse P((void))
{
XUngrabPointer (dpy, CurrentTime);
XUngrabKeyboard (dpy, CurrentTime);
void
disable_builtin_screensaver ()
{
- int timeout, interval, prefer_blank, allow_exp;
+ int server_timeout, server_interval, prefer_blank, allow_exp;
+ /* Turn off the server builtin saver if it is now running. */
XForceScreenSaver (dpy, ScreenSaverReset);
- XGetScreenSaver (dpy, &timeout, &interval, &prefer_blank, &allow_exp);
- if (timeout != 0)
+ XGetScreenSaver (dpy, &server_timeout, &server_interval,
+ &prefer_blank, &allow_exp);
+
+#ifdef HAVE_SAVER_EXTENSION
+ if (use_saver_extension)
+ {
+ /* Override the values specified with "xset" with our own parameters. */
+ prefer_blank = False;
+ allow_exp = True;
+ server_interval = 0;
+ server_timeout = (timeout / 1000);
+ if (verbose_p)
+ fprintf (stderr,
+ "%s: configuring server for saver timeout of %d seconds.\n",
+ progname, server_timeout);
+ XSetScreenSaver (dpy, server_timeout, server_interval,
+ prefer_blank, allow_exp);
+ }
+ else
+#endif /* HAVE_SAVER_EXTENSION */
+ if (server_timeout != 0)
{
- XSetScreenSaver (dpy, 0, interval, prefer_blank, allow_exp);
+ server_timeout = 0;
+ XSetScreenSaver (dpy, server_timeout, server_interval,
+ prefer_blank, allow_exp);
printf ("%s%sisabling server builtin screensaver.\n\
You can re-enable it with \"xset s on\".\n",
(verbose_p ? "" : progname), (verbose_p ? "\n\tD" : ": d"));
#endif
static void
+#if __STDC__
+store_vroot_property (Window win, Window value)
+#else
store_vroot_property (win, value)
Window win, value;
+#endif
{
#if 0
printf ("%s: storing XA_VROOT = 0x%x (%s) = 0x%x (%s)\n", progname,
}
static void
+#if __STDC__
+remove_vroot_property (Window win)
+#else
remove_vroot_property (win)
Window win;
+#endif
{
#if 0
printf ("%s: removing XA_VROOT from 0x%x (%s)\n", progname, win,
static void
-kill_xsetroot_data ()
+kill_xsetroot_data P((void))
{
Atom type;
int format;
nitems == 1 && bytesafter == 0)
{
if (verbose_p)
- printf ("%s: destroying xsetroot data (0x%X).\n",
+ printf ("%s: destroying xsetroot data (0x%lX).\n",
progname, *dataP);
XKillClient (dpy, *dataP);
}
else
fprintf (stderr, "%s: %sdeleted unrecognised _XSETROOT_ID property: \n\
- %d, %d; type: %d, format: %d, nitems: %d, bytesafter %d\n",
+ %lu, %lu; type: %lu, format: %d, nitems: %lu, bytesafter %ld\n",
progname, (verbose_p ? "## " : ""),
- dataP, (dataP ? *dataP : 0), type,
+ (unsigned long) dataP, (dataP ? *dataP : 0), type,
format, nitems, bytesafter);
}
}
static void handle_signals P((Bool on_p));
static void
-save_real_vroot ()
+save_real_vroot P((void))
{
int i;
Window root = RootWindowOfScreen (screen);
}
static Bool
-restore_real_vroot_1 ()
+restore_real_vroot_1 P((void))
{
if (verbose_p && real_vroot)
- printf ("%s: restoring __SWM_VROOT property on the real vroot (0x%x).\n",
- progname, real_vroot);
+ printf ("%s: restoring __SWM_VROOT property on the real vroot (0x%lx).\n",
+ progname, (unsigned long) real_vroot);
remove_vroot_property (screensaver_window);
if (real_vroot)
{
static void
+#if __STDC__
+catch_signal (int sig, char *signame, Bool on_p)
+#else
catch_signal (sig, signame, on_p)
int sig;
char *signame;
Bool on_p;
+#endif
{
if (! on_p)
signal (sig, SIG_DFL);
catch_signal (SIGFPE, "SIGFPE", on_p);
catch_signal (SIGBUS, "SIGBUS", on_p);
catch_signal (SIGSEGV, "SIGSEGV", on_p);
+#ifdef SIGSYS
catch_signal (SIGSYS, "SIGSYS", on_p);
+#endif
catch_signal (SIGTERM, "SIGTERM", on_p);
#ifdef SIGXCPU
catch_signal (SIGXCPU, "SIGXCPU", on_p);
\f
/* Managing the actual screensaver window */
+Bool
+window_exists_p (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ int (*old_handler) ();
+ XWindowAttributes xgwa;
+ xgwa.screen = 0;
+ old_handler = XSetErrorHandler (BadWindow_ehandler);
+ XGetWindowAttributes (dpy, window, &xgwa);
+ XSync (dpy, False);
+ XSetErrorHandler (old_handler);
+ return (xgwa.screen != 0);
+}
+
void
-initialize_screensaver_window ()
+initialize_screensaver_window P((void))
{
/* This resets the screensaver window as fully as possible, since there's
no way of knowing what some random client may have done to us in the
int height = HeightOfScreen (screen);
char id [2048];
+ reset_stderr ();
+
black.red = black.green = black.blue = 0;
if (cmap == DefaultColormapOfScreen (screen))
cmap = 0;
- if ((install_cmap_p && !demo_mode_p) ||
- (visual != DefaultVisualOfScreen (screen)))
+ if (install_cmap_p || visual != DefaultVisualOfScreen (screen))
{
if (! cmap)
{
attrs.backing_pixel = black_pixel;
attrs.border_pixel = black_pixel;
-/* if (demo_mode_p || lock_p) width = width / 2; #### */
+#if 0
+ if (demo_mode_p || lock_p) width = width / 2; /* #### */
+#endif
+
+ if (screensaver_window || !verbose_p)
+ ;
+ else if (visual == DefaultVisualOfScreen (screen))
+ {
+ fprintf (stderr, "%s: using default visual ", progname);
+ describe_visual (stderr, dpy, visual);
+ }
+ else
+ {
+ fprintf (stderr, "%s: using visual: ", progname);
+ describe_visual (stderr, dpy, visual);
+ fprintf (stderr, "%s: default visual: ", progname);
+ describe_visual (stderr, dpy, DefaultVisualOfScreen (screen));
+ }
+
+#ifdef HAVE_SAVER_EXTENSION
+ if (use_saver_extension)
+ {
+ XScreenSaverInfo *info;
+ Window root = RootWindowOfScreen (screen);
+
+ /* This call sets the server screensaver timeouts to what we think
+ they should be (based on the resources and args xscreensaver was
+ started with.) It's important that we do this to sync back up
+ with the server - if we have turned on prematurely, as by an
+ ACTIVATE ClientMessage, then the server may decide to activate
+ the screensaver while it's already active. That's ok for us,
+ since we would know to ignore that ScreenSaverActivate event,
+ but a side effect of this would be that the server would map its
+ saver window (which we then hide again right away) meaning that
+ the bits currently on the screen get blown away. Ugly. */
+#if 0
+ /* #### Ok, that doesn't work - when we tell the server that the
+ screensaver is "off" it sends us a Deactivate event, which is
+ sensible... but causes the saver to never come on. Hmm. */
+ disable_builtin_screensaver ();
+#endif /* 0 */
+
+#if 0
+ /* #### The MIT-SCREEN-SAVER extension gives us access to the
+ window that the server itself uses for saving the screen.
+ However, using this window in any way, in particular, calling
+ XScreenSaverSetAttributes() as below, tends to make the X server
+ crash. So fuck it, let's try and get along without using it...
+
+ It's also inconvenient to use this window because it doesn't
+ always exist (though the ID is constant.) So to use this
+ window, we'd have to reimplement the ACTIVATE ClientMessage to
+ tell the *server* to tell *us* to turn on, to cause the window
+ to get created at the right time. Gag. */
+ XScreenSaverSetAttributes (dpy, root,
+ 0, 0, width, height, 0,
+ visual_depth, InputOutput, visual,
+ attrmask, &attrs);
+ XSync (dpy, False);
+#endif /* 0 */
+
+ info = XScreenSaverAllocInfo ();
+ XScreenSaverQueryInfo (dpy, root, info);
+ server_saver_window = info->window;
+ if (! server_saver_window) abort ();
+ XFree (info);
+ }
+#endif /* HAVE_SAVER_EXTENSION */
if (screensaver_window)
{
}
else
{
- if (! verbose_p)
- ;
- else if (visual == DefaultVisualOfScreen (screen))
- {
- fprintf (stderr, "%s: using default visual ", progname);
- describe_visual (stderr, dpy, visual);
- }
- else
- {
- fprintf (stderr, "%s: using visual: ", progname);
- describe_visual (stderr, dpy, visual);
- fprintf (stderr, "%s: default visual: ", progname);
- describe_visual (stderr, dpy, DefaultVisualOfScreen (screen));
- }
-
screensaver_window =
XCreateWindow (dpy, RootWindowOfScreen (screen), 0, 0, width, height,
0, visual_depth, InputOutput, visual, attrmask,
&attrs);
}
- class_hints.res_name = progname;
- class_hints.res_class = progclass;
- XSetClassHint (dpy, screensaver_window, &class_hints);
- XStoreName (dpy, screensaver_window, "screensaver");
- XChangeProperty (dpy, screensaver_window, XA_SCREENSAVER_VERSION,
- XA_STRING, 8, PropModeReplace,
- (unsigned char *) screensaver_version,
- strlen (screensaver_version));
-
- sprintf (id, "%d on host ", getpid ());
- if (! XmuGetHostname (id + strlen (id), sizeof (id) - strlen (id) - 1))
- strcat (id, "???");
- XChangeProperty (dpy, screensaver_window, XA_SCREENSAVER_ID, XA_STRING, 8,
- PropModeReplace, (unsigned char *) id, strlen (id));
-
- if (!cursor)
+#ifdef HAVE_SAVER_EXTENSION
+ if (!use_saver_extension ||
+ window_exists_p (dpy, screensaver_window))
+ /* When using the MIT-SCREEN-SAVER extension, the window pointed to
+ by screensaver_window only exists while the saver is active.
+ So we must be careful to only try and manipulate it while it
+ exists...
+ */
+#endif /* HAVE_SAVER_EXTENSION */
{
- Pixmap bit;
- bit = XCreatePixmapFromBitmapData (dpy, screensaver_window, "\000", 1, 1,
- BlackPixelOfScreen (screen),
- BlackPixelOfScreen (screen), 1);
- cursor = XCreatePixmapCursor (dpy, bit, bit, &black, &black, 0, 0);
- XFreePixmap (dpy, bit);
- }
+ class_hints.res_name = progname;
+ class_hints.res_class = progclass;
+ XSetClassHint (dpy, screensaver_window, &class_hints);
+ XStoreName (dpy, screensaver_window, "screensaver");
+ XChangeProperty (dpy, screensaver_window, XA_SCREENSAVER_VERSION,
+ XA_STRING, 8, PropModeReplace,
+ (unsigned char *) screensaver_version,
+ strlen (screensaver_version));
+
+ sprintf (id, "%d on host ", getpid ());
+ if (! XmuGetHostname (id + strlen (id), sizeof (id) - strlen (id) - 1))
+ strcat (id, "???");
+ XChangeProperty (dpy, screensaver_window, XA_SCREENSAVER_ID, XA_STRING,
+ 8, PropModeReplace, (unsigned char *) id, strlen (id));
+
+ if (!cursor)
+ {
+ Pixmap bit;
+ bit = XCreatePixmapFromBitmapData (dpy, screensaver_window, "\000",
+ 1, 1,
+ BlackPixelOfScreen (screen),
+ BlackPixelOfScreen (screen), 1);
+ cursor = XCreatePixmapCursor (dpy, bit, bit, &black, &black, 0, 0);
+ XFreePixmap (dpy, bit);
+ }
- XSetWindowBackground (dpy, screensaver_window, black_pixel);
- if (! demo_mode_p)
- XDefineCursor (dpy, screensaver_window, cursor);
- else
- XUndefineCursor (dpy, screensaver_window);
+ XSetWindowBackground (dpy, screensaver_window, black_pixel);
+ if (! demo_mode_p)
+ XDefineCursor (dpy, screensaver_window, cursor);
+ else
+ XUndefineCursor (dpy, screensaver_window);
+ }
}
fade_colormap (dpy, current_map, cmap2, fade_seconds, fade_ticks, True);
XClearWindow (dpy, screensaver_window);
XMapRaised (dpy, screensaver_window);
+
+#ifdef HAVE_SAVER_EXTENSION
+ if (server_saver_window && window_exists_p (dpy, server_saver_window))
+ XUnmapWindow (dpy, server_saver_window);
+#endif /* HAVE_SAVER_EXTENSION */
+
/* Once the saver window is up, restore the colormap.
(The "black" pixels of the two colormaps are compatible.) */
XInstallColormap (dpy, cmap);
{
XClearWindow (dpy, screensaver_window);
XMapRaised (dpy, screensaver_window);
+#ifdef HAVE_SAVER_EXTENSION
+ if (server_saver_window && window_exists_p (dpy, server_saver_window))
+ XUnmapWindow (dpy, server_saver_window);
+#endif /* HAVE_SAVER_EXTENSION */
}
- if (install_cmap_p && !demo_mode_p)
+ if (install_cmap_p)
XInstallColormap (dpy, cmap);
}
+#ifdef __hpux
+ /* Calls to XHPDisableReset and XHPEnableReset must be balanced,
+ or BadAccess errors occur. */
+static Bool hp_locked_p = False;
+#endif /* __hpux */
+
void
blank_screen ()
{
raise_window (False, False);
grab_keyboard_and_mouse ();
#ifdef __hpux
- if (lock_p)
+ if (lock_p && !hp_locked_p)
XHPDisableReset (dpy); /* turn off C-Sh-Reset */
+ hp_locked_p = True;
#endif
}
}
else
{
- if (install_cmap_p && !demo_mode_p)
+ if (install_cmap_p)
{
XClearWindow (dpy, screensaver_window); /* avoid technicolor */
XInstallColormap (dpy, DefaultColormapOfScreen (screen));
ungrab_keyboard_and_mouse ();
restore_real_vroot ();
#ifdef __hpux
- if (lock_p)
+ if (lock_p && hp_locked_p)
XHPEnableReset (dpy); /* turn C-Sh-Reset back on */
+ hp_locked_p = False;
#endif
}