/* windows.c --- turning the screen black; dealing with visuals, virtual roots.
- * xscreensaver, Copyright (c) 1991-1998 Jamie Zawinski <jwz@netscape.com>
+ * xscreensaver, Copyright (c) 1991-1998 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
#ifdef VMS
# include <unixlib.h> /* for getpid() */
# include "vms-gtod.h" /* for gettimeofday() */
-# if !defined(HAVE_UNAME) && (__VMS_VER >= 70000000)
-# define HAVE_UNAME 1
-# endif /* !HAVE_UNAME */
#endif /* VMS */
-# ifdef HAVE_UNAME
-# include <sys/utsname.h> /* for uname() */
-# endif /* HAVE_UNAME */
+#ifndef VMS
+# include <pwd.h> /* for getpwuid() */
+#else /* VMS */
+# include "vms-pwd.h"
+#endif /* VMS */
+
+#ifdef HAVE_UNAME
+# include <sys/utsname.h> /* for uname() */
+#endif /* HAVE_UNAME */
#include <stdio.h>
#include <X11/Xproto.h> /* for CARD32 */
#include "visual.h"
#include "fade.h"
+
+#ifdef HAVE_VT_LOCKSWITCH
+# include <fcntl.h>
+# include <sys/ioctl.h>
+# include <sys/vt.h>
+ static void lock_vt (saver_info *si, Bool lock_p);
+#endif /* HAVE_VT_LOCKSWITCH */
+
+
extern int kill (pid_t, int); /* signal() is in sys/signal.h... */
Atom XA_VROOT, XA_XSETROOT_ID;
-Atom XA_SCREENSAVER_VERSION, XA_SCREENSAVER_ID;
+Atom XA_SCREENSAVER, XA_SCREENSAVER_VERSION, XA_SCREENSAVER_ID;
Atom XA_SCREENSAVER_TIME;
Button1MotionMask | Button2MotionMask | Button3MotionMask | \
Button4MotionMask | Button5MotionMask | ButtonMotionMask)
-/* I don't really understand Sync vs Async, but these seem to work... */
-#define grab_kbd(dpy,win) \
- XGrabKeyboard ((dpy), (win), True, GrabModeSync, GrabModeAsync, CurrentTime)
-#define grab_mouse(dpy,win,cursor) \
- XGrabPointer ((dpy), (win), True, ALL_POINTER_EVENTS, \
- GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime)
-void
-grab_keyboard_and_mouse (Display *dpy, Window window, Cursor cursor)
+static int
+grab_kbd(saver_info *si, Window w)
{
- Status status;
- XSync (dpy, False);
+ saver_preferences *p = &si->prefs;
+ int status = XGrabKeyboard (si->dpy, w, True,
+ /* I don't really understand Sync vs Async,
+ but these seem to work... */
+ GrabModeSync, GrabModeAsync,
+ CurrentTime);
+ if (status == GrabSuccess)
+ si->keyboard_grab_window = w;
+
+ if (p->verbose_p)
+ fprintf(stderr, "%s: grabbing keyboard on 0x%x... %s.\n",
+ blurb(), (unsigned long) w,
+ (status == GrabSuccess ? "GrabSuccess" :
+ status == AlreadyGrabbed ? "AlreadyGrabbed" :
+ status == GrabInvalidTime ? "GrabInvalidTime" :
+ status == GrabNotViewable ? "GrabNotViewable" :
+ status == GrabFrozen ? "GrabFrozen" :
+ "???"));
+
+ return status;
+}
+
+static const char *
+grab_string(int status)
+{
+ switch (status)
+ {
+ case GrabSuccess: return "GrabSuccess"; break;
+ case AlreadyGrabbed: return "AlreadyGrabbed"; break;
+ case GrabInvalidTime: return "GrabInvalidTime"; break;
+ case GrabNotViewable: return "GrabNotViewable"; break;
+ case GrabFrozen: return "GrabFrozen"; break;
+ default:
+ {
+ static char foo[255];
+ sprintf(foo, "unknown status: %d", status);
+ return foo;
+ }
+ }
+}
+
+
+static int
+grab_mouse (saver_info *si, Window w, Cursor cursor)
+{
+ saver_preferences *p = &si->prefs;
+ int status = XGrabPointer (si->dpy, w, True, ALL_POINTER_EVENTS,
+ GrabModeAsync, GrabModeAsync, None,
+ cursor, CurrentTime);
+ if (status == GrabSuccess)
+ si->mouse_grab_window = w;
+
+ if (p->verbose_p)
+ fprintf(stderr, "%s: grabbing mouse on 0x%x... %s.\n",
+ blurb(), (unsigned long) w, grab_string(status));
+ return status;
+}
+
+
+static void
+ungrab_kbd(saver_info *si)
+{
+ saver_preferences *p = &si->prefs;
+ XUngrabKeyboard(si->dpy, CurrentTime);
+ if (p->verbose_p)
+ fprintf(stderr, "%s: ungrabbing keyboard (was 0x%x).\n", blurb(),
+ (unsigned long) si->keyboard_grab_window);
+ si->keyboard_grab_window = 0;
+}
+
+
+static void
+ungrab_mouse(saver_info *si)
+{
+ saver_preferences *p = &si->prefs;
+ XUngrabPointer(si->dpy, CurrentTime);
+ if (p->verbose_p)
+ fprintf(stderr, "%s: ungrabbing mouse (was 0x%x).\n", blurb(),
+ (unsigned long) si->mouse_grab_window);
+ si->mouse_grab_window = 0;
+}
+
+
+Bool
+grab_keyboard_and_mouse (saver_info *si, Window window, Cursor cursor)
+{
+ Status mstatus, kstatus;
+ XSync (si->dpy, False);
- status = grab_kbd (dpy, window);
- if (status != GrabSuccess)
+ kstatus = grab_kbd (si, window);
+ if (kstatus != GrabSuccess)
{ /* try again in a second */
sleep (1);
- status = grab_kbd (dpy, window);
- if (status != GrabSuccess)
- fprintf (stderr, "%s: couldn't grab keyboard! (%d)\n",
- progname, status);
+ kstatus = grab_kbd (si, window);
+ if (kstatus != GrabSuccess)
+ fprintf (stderr, "%s: couldn't grab keyboard! (%s)\n",
+ blurb(), grab_string(kstatus));
}
- status = grab_mouse (dpy, window, cursor);
- if (status != GrabSuccess)
+
+ mstatus = grab_mouse (si, window, cursor);
+ if (mstatus != GrabSuccess)
{ /* try again in a second */
sleep (1);
- status = grab_mouse (dpy, window, cursor);
- if (status != GrabSuccess)
- fprintf (stderr, "%s: couldn't grab pointer! (%d)\n",
- progname, status);
+ mstatus = grab_mouse (si, window, cursor);
+ if (mstatus != GrabSuccess)
+ fprintf (stderr, "%s: couldn't grab pointer! (%s)\n",
+ blurb(), grab_string(mstatus));
}
+
+ return (kstatus == GrabSuccess ||
+ mstatus == GrabSuccess);
}
void
-ungrab_keyboard_and_mouse (Display *dpy)
+ungrab_keyboard_and_mouse (saver_info *si)
{
- XUngrabPointer (dpy, CurrentTime);
- XUngrabKeyboard (dpy, CurrentTime);
+ ungrab_mouse (si);
+ ungrab_kbd (si);
}
-void
+/* Prints an error message to stderr and returns True if there is another
+ xscreensaver running already. Silently returns False otherwise. */
+Bool
ensure_no_screensaver_running (Display *dpy, Screen *screen)
{
+ Bool status = 0;
int i;
Window root = RootWindowOfScreen (screen);
Window root2, parent, *kids;
fprintf (stderr,
"%s: already running on display %s (window 0x%x)\n from process %s.\n",
- progname, DisplayString (dpy), (int) kids [i], id);
- exit (1);
+ blurb(), DisplayString (dpy), (int) kids [i], id);
+ status = True;
}
}
if (kids) XFree ((char *) kids);
XSync (dpy, False);
XSetErrorHandler (old_handler);
+ return status;
}
#if 0
if (p->verbose_p)
fprintf (stderr,
- "%s: storing XA_VROOT = 0x%x (%s) = 0x%x (%s)\n", progname,
+ "%s: storing XA_VROOT = 0x%x (%s) = 0x%x (%s)\n", blurb(),
win,
(win == screensaver_window ? "ScreenSaver" :
(win == real_vroot ? "VRoot" :
{
#if 0
if (p->verbose_p)
- fprintf (stderr, "%s: removing XA_VROOT from 0x%x (%s)\n", progname, win,
+ fprintf (stderr, "%s: removing XA_VROOT from 0x%x (%s)\n", blurb(), win,
(win == screensaver_window ? "ScreenSaver" :
(win == real_vroot ? "VRoot" :
(win == real_vroot_value ? "Vroot_value" : "???"))));
nitems == 1 && bytesafter == 0)
{
if (verbose_p)
- printf ("%s: destroying xsetroot data (0x%lX).\n",
- progname, *dataP);
+ fprintf (stderr, "%s: destroying xsetroot data (0x%lX).\n",
+ blurb(), *dataP);
XKillClient (dpy, *dataP);
}
else
fprintf (stderr, "%s: deleted unrecognised _XSETROOT_ID property: \n\
%lu, %lu; type: %lu, format: %d, nitems: %lu, bytesafter %ld\n",
- progname, (unsigned long) dataP, (dataP ? *dataP : 0), type,
+ blurb(), (unsigned long) dataP, (dataP ? *dataP : 0), type,
format, nitems, bytesafter);
}
}
Window root = RootWindowOfScreen (screen);
Window root2, parent, *kids;
unsigned int nkids;
+ XErrorHandler old_handler;
+
+ /* It's possible that a window might be deleted between our call to
+ XQueryTree() and our call to XGetWindowProperty(). Don't die if
+ that happens (but just ignore that window, it's not the one we're
+ interested in anyway.)
+ */
+ XSync (dpy, False);
+ old_handler = XSetErrorHandler (BadWindow_ehandler);
+ XSync (dpy, False);
ssi->real_vroot = 0;
ssi->real_vroot_value = 0;
if (*vrootP == ssi->screensaver_window) abort ();
fprintf (stderr,
"%s: more than one virtual root window found (0x%x and 0x%x).\n",
- progname, (int) ssi->real_vroot, (int) kids [i]);
+ blurb(), (int) ssi->real_vroot, (int) kids [i]);
exit (1);
}
ssi->real_vroot = kids [i];
ssi->real_vroot_value = *vrootP;
}
+ XSync (dpy, False);
+ XSetErrorHandler (old_handler);
+ XSync (dpy, False);
+
if (ssi->real_vroot)
{
handle_signals (si, True);
saver_info *si = ssi->global;
saver_preferences *p = &si->prefs;
if (p->verbose_p && ssi->real_vroot)
- printf ("%s: restoring __SWM_VROOT property on the real vroot (0x%lx).\n",
- progname, (unsigned long) ssi->real_vroot);
+ fprintf (stderr,
+ "%s: restoring __SWM_VROOT property on the real vroot (0x%lx).\n",
+ blurb(), (unsigned long) ssi->real_vroot);
remove_vroot_property (si->dpy, ssi->screensaver_window);
if (ssi->real_vroot)
{
signal (sig, SIG_DFL);
if (restore_real_vroot_1 (si))
fprintf (real_stderr, "\n%s: %s intercepted, vroot restored.\n",
- progname, signal_name(sig));
+ blurb(), signal_name(sig));
kill (getpid (), sig);
}
if (((long) signal (sig, restore_real_vroot_handler)) == -1L)
{
char buf [255];
- sprintf (buf, "%s: couldn't catch %s", progname, signal_name(sig));
+ sprintf (buf, "%s: couldn't catch %s", blurb(), signal_name(sig));
perror (buf);
- saver_exit (si, 1);
+ saver_exit (si, 1, 0);
}
}
}
handle_signals (saver_info *si, Bool on_p)
{
#if 0
- if (on_p) printf ("handling signals\n");
- else printf ("unhandling signals\n");
+ if (on_p) fprintf (stderr, "handling signals\n");
+ else fprintf (stderr, "unhandling signals\n");
#endif
catch_signal (si, SIGHUP, on_p);
}
void
-saver_exit (saver_info *si, int status)
+saver_exit (saver_info *si, int status, const char *dump_core_reason)
{
saver_preferences *p = &si->prefs;
static Bool exiting = False;
+ Bool bugp;
Bool vrs;
if (exiting)
emergency_kill_subproc (si);
if (vrs && (p->verbose_p || status != 0))
- fprintf (real_stderr, "%s: vroot restored, exiting.\n", progname);
+ fprintf (real_stderr, "%s: vroot restored, exiting.\n", blurb());
else if (p->verbose_p)
- fprintf (real_stderr, "%s: no vroot to restore; exiting.\n", progname);
+ fprintf (real_stderr, "%s: no vroot to restore; exiting.\n", blurb());
fflush(real_stdout);
else if (status == 1) status = -1;
#endif
-#ifdef DEBUG
- if (si->prefs.debug_p)
- /* Do this to drop a core file, so that we can get a stack trace. */
- abort();
-#endif
+ bugp = !!dump_core_reason;
+
+ if (si->prefs.debug_p && !dump_core_reason)
+ dump_core_reason = "because of -debug";
+
+ if (dump_core_reason)
+ {
+ /* Note that the Linux man page for setuid() says If uid is
+ different from the old effective uid, the process will be
+ forbidden from leaving core dumps.
+ */
+ char cwd[4096]; /* should really be PATH_MAX, but who cares. */
+ cwd[0] = 0;
+ fprintf(real_stderr, "%s: dumping core (%s)\n", blurb(),
+ dump_core_reason);
+
+ if (bugp)
+ fprintf(real_stderr,
+ "%s: see http://www.jwz.org/xscreensaver/bugs.html\n"
+ "\t\tfor bug reporting information.\n\n",
+ blurb());
+
+# if defined(HAVE_GETCWD)
+ if (!getcwd (cwd, sizeof(cwd)))
+# elif defined(HAVE_GETWD)
+ if (!getwd (cwd))
+# endif
+ strcpy(cwd, "unknown.");
+
+ fprintf (real_stderr, "%s: current directory is %s\n", blurb(), cwd);
+ describe_uids (si, real_stderr);
+
+ /* Do this to drop a core file, so that we can get a stack trace. */
+ abort();
+ }
exit (status);
}
return (xgwa.screen != 0);
}
+static void
+store_saver_id (saver_screen_info *ssi)
+{
+ XClassHint class_hints;
+ saver_info *si = ssi->global;
+ unsigned long pid = (unsigned long) getpid ();
+ char buf[20];
+ struct passwd *p = getpwuid (getuid ());
+ const char *name, *host;
+ char *id;
+
+ /* First store the name and class on the window.
+ */
+ class_hints.res_name = progname;
+ class_hints.res_class = progclass;
+ XSetClassHint (si->dpy, ssi->screensaver_window, &class_hints);
+ XStoreName (si->dpy, ssi->screensaver_window, "screensaver");
+
+ /* Then store the xscreensaver version number.
+ */
+ XChangeProperty (si->dpy, ssi->screensaver_window,
+ XA_SCREENSAVER_VERSION,
+ XA_STRING, 8, PropModeReplace,
+ (unsigned char *) si->version,
+ strlen (si->version));
+
+ /* Now store the XSCREENSAVER_ID property, that says what user and host
+ xscreensaver is running as.
+ */
+
+ if (p && p->pw_name && *p->pw_name)
+ name = p->pw_name;
+ else if (p)
+ {
+ sprintf (buf, "%lu", (unsigned long) p->pw_uid);
+ name = buf;
+ }
+ else
+ name = "???";
+
+# if defined(HAVE_UNAME)
+ {
+ struct utsname uts;
+ if (uname (&uts) < 0)
+ host = "???";
+ else
+ host = uts.nodename;
+ }
+# elif defined(VMS)
+ host = getenv("SYS$NODE");
+# else /* !HAVE_UNAME && !VMS */
+ host = "???";
+# endif /* !HAVE_UNAME && !VMS */
+
+ id = (char *) malloc (strlen(name) + strlen(host) + 50);
+ sprintf (id, "%lu (%s@%s)", pid, name, host);
+
+ XChangeProperty (si->dpy, ssi->screensaver_window,
+ XA_SCREENSAVER_ID, XA_STRING,
+ 8, PropModeReplace,
+ (unsigned char *) id, strlen (id));
+ free (id);
+}
+
+
static void
initialize_screensaver_window_1 (saver_screen_info *ssi)
{
saver_info *si = ssi->global;
saver_preferences *p = &si->prefs;
- Bool install_cmap_p = ssi->install_cmap_p;
+ Bool install_cmap_p = ssi->install_cmap_p; /* not p->install_cmap_p */
/* 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
its own set of problems...
*/
XColor black;
- XClassHint class_hints;
XSetWindowAttributes attrs;
unsigned long attrmask;
int width = WidthOfScreen (ssi->screen);
int height = HeightOfScreen (ssi->screen);
- char id [2048];
static Bool printed_visual_info = False; /* only print the message once. */
black.red = black.green = black.blue = 0;
ssi->cmap = 0;
if (ssi->current_visual != DefaultVisualOfScreen (ssi->screen))
+ /* It's not the default visual, so we have no choice but to install. */
install_cmap_p = True;
if (install_cmap_p)
{
if (! ssi->cmap)
{
- ssi->cmap = XCreateColormap (si->dpy, RootWindowOfScreen (ssi->screen),
+ ssi->cmap = XCreateColormap (si->dpy,
+ RootWindowOfScreen (ssi->screen),
ssi->current_visual, AllocNone);
if (! XAllocColor (si->dpy, ssi->cmap, &black)) abort ();
ssi->black_pixel = black.pixel;
attrs.backing_pixel = ssi->black_pixel;
attrs.border_pixel = ssi->black_pixel;
-#ifdef DEBUG
if (p->debug_p) width = width / 2;
-#endif /* DEBUG */
if (!p->verbose_p || printed_visual_info)
;
else if (ssi->current_visual == DefaultVisualOfScreen (ssi->screen))
{
- fprintf (stderr, "%s: using default visual ", progname);
- describe_visual (stderr, ssi->screen, ssi->current_visual);
+ fprintf (stderr, "%s: using default visual ", blurb());
+ describe_visual (stderr, ssi->screen, ssi->current_visual,
+ install_cmap_p);
}
else
{
- fprintf (stderr, "%s: using visual: ", progname);
- describe_visual (stderr, ssi->screen, ssi->current_visual);
- fprintf (stderr, "%s: default visual: ", progname);
+ fprintf (stderr, "%s: using visual: ", blurb());
+ describe_visual (stderr, ssi->screen, ssi->current_visual,
+ install_cmap_p);
+ fprintf (stderr, "%s: default visual: ", blurb());
describe_visual (stderr, ssi->screen,
- DefaultVisualOfScreen (ssi->screen));
+ DefaultVisualOfScreen (ssi->screen),
+ ssi->install_cmap_p);
}
printed_visual_info = True;
#ifdef HAVE_MIT_SAVER_EXTENSION
- if (p->use_mit_saver_extension)
+ if (si->using_mit_saver_extension)
{
XScreenSaverInfo *info;
Window root = RootWindowOfScreen (ssi->screen);
store_activate_time(si, True);
if (p->verbose_p)
fprintf (stderr, "%s: saver window is 0x%lx.\n",
- progname, (unsigned long) ssi->screensaver_window);
+ blurb(), (unsigned long) ssi->screensaver_window);
}
-#ifdef HAVE_MIT_SAVER_EXTENSION
- if (!p->use_mit_saver_extension ||
- window_exists_p (si->dpy, ssi->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...
- (#### The above comment would be true if the MIT extension actually
- worked, but it's not true today -- see `server_mit_saver_window'.)
- */
-#endif /* HAVE_MIT_SAVER_EXTENSION */
- {
- class_hints.res_name = progname;
- class_hints.res_class = progclass;
- XSetClassHint (si->dpy, ssi->screensaver_window, &class_hints);
- XStoreName (si->dpy, ssi->screensaver_window, "screensaver");
- XChangeProperty (si->dpy, ssi->screensaver_window,
- XA_SCREENSAVER_VERSION,
- XA_STRING, 8, PropModeReplace,
- (unsigned char *) si->version,
- strlen (si->version));
-
- sprintf (id, "%lu on host ", (unsigned long) getpid ());
-# if defined(HAVE_UNAME)
- {
- struct utsname uts;
- if (uname (&uts) < 0)
- strcat (id, "???");
- else
- strcat (id, uts.nodename);
- }
-# elif defined(VMS)
- strcat (id, getenv("SYS$NODE"));
-# else /* !HAVE_UNAME && !VMS */
- strcat (id, "???");
-# endif /* !HAVE_UNAME && !VMS */
+ store_saver_id (ssi);
- XChangeProperty (si->dpy, ssi->screensaver_window,
- XA_SCREENSAVER_ID, XA_STRING,
- 8, PropModeReplace, (unsigned char *) id, strlen (id));
+ if (!ssi->cursor)
+ {
+ Pixmap bit;
+ bit = XCreatePixmapFromBitmapData (si->dpy, ssi->screensaver_window,
+ "\000", 1, 1,
+ BlackPixelOfScreen (ssi->screen),
+ BlackPixelOfScreen (ssi->screen),
+ 1);
+ ssi->cursor = XCreatePixmapCursor (si->dpy, bit, bit, &black, &black,
+ 0, 0);
+ XFreePixmap (si->dpy, bit);
+ }
- if (!ssi->cursor)
- {
- Pixmap bit;
- bit = XCreatePixmapFromBitmapData (si->dpy, ssi->screensaver_window,
- "\000", 1, 1,
- BlackPixelOfScreen (ssi->screen),
- BlackPixelOfScreen (ssi->screen),
- 1);
- ssi->cursor = XCreatePixmapCursor (si->dpy, bit, bit, &black, &black,
- 0, 0);
- XFreePixmap (si->dpy, bit);
- }
+ XSetWindowBackground (si->dpy, ssi->screensaver_window, ssi->black_pixel);
- XSetWindowBackground (si->dpy, ssi->screensaver_window,
- ssi->black_pixel);
- if (si->demo_mode_p)
- XUndefineCursor (si->dpy, ssi->screensaver_window);
- else
- XDefineCursor (si->dpy, ssi->screensaver_window, ssi->cursor);
- }
+ if (si->demoing_p)
+ XUndefineCursor (si->dpy, ssi->screensaver_window);
+ else
+ XDefineCursor (si->dpy, ssi->screensaver_window, ssi->cursor);
}
void
saver_preferences *p = &si->prefs;
int i;
+ if (si->demoing_p)
+ inhibit_fade = True;
+
initialize_screensaver_window (si);
reset_watchdog_timer (si, True);
- if (p->fade_p && !inhibit_fade && !si->demo_mode_p)
+ if (p->fade_p && p->fading_possible_p && !inhibit_fade)
{
- int grabbed = -1;
Window *current_windows = (Window *)
calloc(sizeof(Window), si->nscreens);
Colormap *current_maps = (Colormap *)
ssi->black_pixel);
}
- if (p->verbose_p) fprintf (stderr, "%s: fading... ", progname);
+ if (p->verbose_p) fprintf (stderr, "%s: fading...\n", blurb());
- XGrabServer (si->dpy);
+ XGrabServer (si->dpy); /* ############ DANGER! */
- for (i = 0; i < si->nscreens; i++)
- {
- saver_screen_info *ssi = &si->screens[i];
-
- /* grab and blacken mouse on the root window (saver not mapped yet)
- */
- if (grabbed != GrabSuccess)
- grabbed = grab_mouse (si->dpy, ssi->screensaver_window,
- (si->demo_mode_p ? 0 : ssi->cursor));
-
- if (!dont_clear || ssi->stderr_overlay_window)
- /* Do this before the fade, since the stderr cmap won't fade
- even if we uninstall it (beats me...) */
- clear_stderr (ssi);
- }
+ /* Clear the stderr layer on each screen.
+ */
+ if (!dont_clear)
+ for (i = 0; i < si->nscreens; i++)
+ {
+ saver_screen_info *ssi = &si->screens[i];
+ if (ssi->stderr_overlay_window)
+ /* Do this before the fade, since the stderr cmap won't fade
+ even if we uninstall it (beats me...) */
+ clear_stderr (ssi);
+ }
+ /* Note! The server is grabbed, and this will take several seconds
+ to complete! */
fade_screens (si->dpy, current_maps, current_windows,
- p->fade_seconds, p->fade_ticks, True, !dont_clear);
+ p->fade_seconds/1000, p->fade_ticks, True, !dont_clear);
+
free(current_maps);
free(current_windows);
current_maps = 0;
current_windows = 0;
- if (p->verbose_p) fprintf (stderr, "fading done.\n");
+ if (p->verbose_p) fprintf (stderr, "%s: fading done.\n", blurb());
#ifdef HAVE_MIT_SAVER_EXTENSION
for (i = 0; i < si->nscreens; i++)
}
#endif /* HAVE_MIT_SAVER_EXTENSION */
- if (grabbed == GrabSuccess)
- XUngrabPointer (si->dpy, CurrentTime);
XUngrabServer (si->dpy);
+ XSync (si->dpy, False); /* ###### (danger over) */
}
else
{
blank_screen (saver_info *si)
{
int i;
+
+ /* Note: we do our grabs on the root window, not on the screensaver window.
+ If we grabbed on the saver window, then the demo mode and lock dialog
+ boxes wouldn't get any events.
+ */
+ grab_keyboard_and_mouse (si,
+ /*si->screens[0].screensaver_window,*/
+ RootWindowOfScreen(si->screens[0].screen),
+ (si->demoing_p
+ ? 0
+ : si->screens[0].cursor));
+
for (i = 0; i < si->nscreens; i++)
{
saver_screen_info *ssi = &si->screens[i];
}
store_activate_time (si, si->screen_blanked_p);
raise_window (si, False, False, False);
- /* #### */
- grab_keyboard_and_mouse (si->dpy, si->screens[0].screensaver_window,
- (si->demo_mode_p ? 0 : si->screens[0].cursor));
+
#ifdef HAVE_XHPDISABLERESET
if (si->locked_p && !hp_locked_p)
{
}
#endif
+#ifdef HAVE_VT_LOCKSWITCH
+ if (si->locked_p)
+ lock_vt (si, True); /* turn off C-Alt-Fn */
+#endif
+
si->screen_blanked_p = True;
}
unblank_screen (saver_info *si)
{
saver_preferences *p = &si->prefs;
+ Bool unfade_p = (p->fading_possible_p && p->unfade_p);
int i;
+ monitor_power_on (si);
+
store_activate_time (si, True);
reset_watchdog_timer (si, False);
- if (p->unfade_p && !si->demo_mode_p)
+ if (si->demoing_p)
+ unfade_p = False;
+
+ if (unfade_p)
{
- int grabbed = -1;
Window *current_windows = (Window *)
calloc(sizeof(Window), si->nscreens);
ssi->black_pixel);
}
- if (p->verbose_p) fprintf (stderr, "%s: unfading... ", progname);
+ if (p->verbose_p) fprintf (stderr, "%s: unfading...\n", blurb());
+
XSync (si->dpy, False);
- XGrabServer (si->dpy);
+ XGrabServer (si->dpy); /* ############ DANGER! */
XSync (si->dpy, False);
+
+ /* Clear the stderr layer on each screen.
+ */
for (i = 0; i < si->nscreens; i++)
{
saver_screen_info *ssi = &si->screens[i];
- if (grabbed != GrabSuccess)
- grabbed = grab_mouse (si->dpy, RootWindowOfScreen (ssi->screen),
- 0);
clear_stderr (ssi);
}
+
XUngrabServer (si->dpy);
- XSync (si->dpy, False);
+ XSync (si->dpy, False); /* ###### (danger over) */
+
fade_screens (si->dpy, 0, current_windows,
- p->fade_seconds, p->fade_ticks,
+ p->fade_seconds/1000, p->fade_ticks,
False, False);
free(current_windows);
current_windows = 0;
- if (p->verbose_p) fprintf (stderr, "unfading done.\n");
- if (grabbed == GrabSuccess)
- XUngrabPointer (si->dpy, CurrentTime);
+ if (p->verbose_p) fprintf (stderr, "%s: unfading done.\n", blurb());
}
else
{
store_activate_time(si, False); /* store unblank time */
- ungrab_keyboard_and_mouse (si->dpy);
+ ungrab_keyboard_and_mouse (si);
restore_real_vroot (si);
#ifdef HAVE_XHPDISABLERESET
}
#endif
+#ifdef HAVE_VT_LOCKSWITCH
+ lock_vt (si, False); /* turn C-Alt-Fn back on */
+#endif
+
/* Unmap the windows a second time, dammit -- just to avoid a race
with the screen-grabbing hacks. (I'm not sure if this is really
necessary; I'm stabbing in the dark now.)
got_it = !!new_v;
if (new_v && new_v != DefaultVisualOfScreen(ssi->screen))
+ /* It's not the default visual, so we have no choice but to install. */
install_cmap_p = True;
ssi->install_cmap_p = install_cmap_p;
if (p->verbose_p)
{
+ fprintf (stderr, "%s: switching to visual ", blurb());
+ describe_visual (stderr, ssi->screen, new_v, install_cmap_p);
#if 0
- fprintf (stderr, "%s: switching visuals\tfrom: ", progname);
- describe_visual (stderr, ssi->screen, ssi->current_visual);
- fprintf (stderr, "\t\t\t\tto: ");
- describe_visual (stderr, ssi->screen, new_v);
- fprintf (stderr, "\t\t\t\t install cmap: %s\n",
- (install_cmap_p ? "yes" : "no"));
-#else
- fprintf (stderr, "%s: switching to visual ", progname);
- describe_visual (stderr, ssi->screen, new_v);
+ fprintf (stderr, "%s: from ", blurb());
+ describe_visual (stderr, ssi->screen, ssi->current_visual,
+ was_installed_p);
#endif
}
ssi->screensaver_window = 0;
initialize_screensaver_window_1 (ssi);
+
+ /* stderr_overlay_window is a child of screensaver_window, so we need
+ to destroy that as well (actually, we just need to invalidate and
+ drop our pointers to it, but this will destroy it, which is ok so
+ long as it happens before old_w itself is destroyed.) */
+ reset_stderr (ssi);
+
raise_window (si, True, True, False);
store_vroot_property (si->dpy,
ssi->screensaver_window, ssi->screensaver_window);
store_activate_time (si, True);
+
+
+ /* Transfer the grabs from the old window to the new.
+ Actually I think none of this is necessary, since we always
+ hold our grabs on the root window, but I wrote this before
+ re-discovering that...
+ */
+
+
+ /* If we're destroying the window that holds our mouse grab,
+ transfer the grab to the new window. (Grab the server while
+ so doing, to avoid a race condition.)
+ */
+ if (old_w == si->mouse_grab_window)
+ {
+ XGrabServer (si->dpy); /* ############ DANGER! */
+ ungrab_mouse (si);
+ grab_mouse (si, ssi->screensaver_window,
+ (si->demoing_p
+ ? 0
+ : ssi->cursor));
+ XUngrabServer (si->dpy);
+ XSync (si->dpy, False); /* ###### (danger over) */
+ }
+
+ /* If we're destroying the window that holds our keyboard grab,
+ transfer the grab to the new window. (Grab the server while
+ so doing, to avoid a race condition.)
+ */
+ if (old_w == si->keyboard_grab_window)
+ {
+ XGrabServer (si->dpy); /* ############ DANGER! */
+ ungrab_kbd(si);
+ grab_kbd(si, ssi->screensaver_window);
+ XUngrabServer (si->dpy);
+ XSync (si->dpy, False); /* ###### (danger over) */
+ }
+
+ /* Now we can destroy this window without horking our grabs. */
+
XDestroyWindow (si->dpy, old_w);
+
+ if (p->verbose_p)
+ fprintf (stderr, "%s: destroyed old saver window 0x%lx.\n",
+ blurb(), (unsigned long) old_w);
+
if (old_c &&
old_c != DefaultColormapOfScreen (ssi->screen) &&
old_c != ssi->demo_cmap)
return got_it;
}
+
+\f
+/* VT locking */
+
+#ifdef HAVE_VT_LOCKSWITCH
+static void
+lock_vt (saver_info *si, Bool lock_p)
+{
+ saver_preferences *p = &si->prefs;
+ static Bool locked_p = False;
+ const char *dev_console = "/dev/console";
+ int fd;
+
+ if (lock_p == locked_p)
+ return;
+
+ if (lock_p && !p->lock_vt_p)
+ return;
+
+ fd = open (dev_console, O_RDWR);
+ if (fd < 0)
+ {
+ char buf [255];
+ sprintf (buf, "%s: couldn't %s VTs: %s", blurb(),
+ (lock_p ? "lock" : "unlock"),
+ dev_console);
+#if 0 /* #### doesn't work yet, so don't bother complaining */
+ perror (buf);
+#endif
+ return;
+ }
+
+ if (ioctl (fd, (lock_p ? VT_LOCKSWITCH : VT_UNLOCKSWITCH)) == 0)
+ {
+ locked_p = lock_p;
+
+ if (p->verbose_p)
+ fprintf (stderr, "%s: %s VTs\n", blurb(),
+ (lock_p ? "locked" : "unlocked"));
+ }
+ else
+ {
+ char buf [255];
+ sprintf (buf, "%s: couldn't %s VTs: ioctl", blurb(),
+ (lock_p ? "lock" : "unlock"));
+#if 0 /* #### doesn't work yet, so don't bother complaining */
+ perror (buf);
+#endif
+ }
+
+ close (fd);
+}
+#endif /* HAVE_VT_LOCKSWITCH */