-/* xscreensaver, Copyright (c) 1991-1999 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1991-2001 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
fflush (stdout);
fflush (stderr);
fprintf (stdout, "\
-xscreensaver %s, copyright (c) 1991-1999 by Jamie Zawinski <jwz@jwz.org>\n\
+xscreensaver %s, copyright (c) 1991-2001 by Jamie Zawinski <jwz@jwz.org>\n\
The standard Xt command-line options are accepted; other options include:\n\
\n\
-timeout <minutes> When the screensaver should activate.\n\
saver_ehandler (Display *dpy, XErrorEvent *error)
{
saver_info *si = global_si_kludge; /* I hate C so much... */
+ int i;
if (!real_stderr) real_stderr = stderr;
fprintf (real_stderr, "\n"
"#######################################"
"#######################################\n\n"
- "%s: X Error! PLEASE REPORT THIS BUG.\n\n"
- "#######################################"
- "#######################################\n\n",
+ "%s: X Error! PLEASE REPORT THIS BUG.\n",
blurb());
+
+ for (i = 0; i < si->nscreens; i++)
+ fprintf (real_stderr, "%s: screen %d: 0x%x, 0x%x, 0x%x\n",
+ blurb(), i,
+ RootWindowOfScreen (si->screens[i].screen),
+ si->screens[i].real_vroot,
+ si->screens[i].screensaver_window);
+
+ fprintf (real_stderr, "\n"
+ "#######################################"
+ "#######################################\n\n");
+
if (XmuPrintDefaultErrorMessage (dpy, error, real_stderr))
{
fprintf (real_stderr, "\n");
"#######################################"
"#######################################\n\n");
fprintf (real_stderr,
- " If at all possible, please re-run xscreensaver with the command\ e\n"
+ " If at all possible, please re-run xscreensaver with the command\n"
" line arguments `-sync -verbose -no-capture', and reproduce this\n"
" bug. That will cause xscreensaver to dump a `core' file to the\n"
" current directory. Please include the stack trace from that core\n"
fprintf (stderr, "\n");
describe_uids (si, stderr);
- fprintf (stderr, "\n"
+
+ if (si->orig_uid && !strncmp (si->orig_uid, "root/", 5))
+ {
+ fprintf (stderr, "\n"
+ "%s: This is probably because you're logging in as root. You\n"
+" shouldn't log in as root: you should log in as a normal user,\n"
+" and then `su' as needed. If you insist on logging in as\n"
+" root, you will have to turn off X's security features before\n"
+" xscreensaver will work.\n"
+ "\n"
+" Please read the manual and FAQ for more information:\n",
+ blurb());
+ }
+ else
+ {
+ fprintf (stderr, "\n"
"%s: Errors at startup are usually authorization problems.\n"
- " Did you read the manual and the FAQ? Specifically,\n"
- " the parts of the manual that talk about XAUTH, XDM,\n"
- " and root logins?\n"
- "\n"
- " http://www.jwz.org/xscreensaver/man.html\n"
- "\n",
+" But you're not logging in as root (good!) so something\n"
+" else must be wrong. Did you read the manual and the FAQ?\n",
blurb());
+ }
+
+ fprintf (stderr, "\n"
+ " http://www.jwz.org/xscreensaver/faq.html\n"
+ " http://www.jwz.org/xscreensaver/man.html\n"
+ "\n");
fflush (stderr);
fflush (stdout);
{
Widget toplevel_shell;
+#ifdef HAVE_PUTENV
+ char *d = getenv ("DISPLAY");
+ if (!d || !*d)
+ {
+ char ndpy[] = "DISPLAY=:0.0";
+ /* if (si->prefs.verbose_p) */ /* sigh, too early to test this... */
+ fprintf (stderr,
+ "%s: warning: $DISPLAY is not set: defaulting to \"%s\".\n",
+ blurb(), ndpy+8);
+ if (putenv (ndpy))
+ abort ();
+ }
+#endif /* HAVE_PUTENV */
+
XSetErrorHandler (saver_ehandler);
XtAppSetErrorMsgHandler (si->app, startup_ehandler);
if (p->verbose_p)
fprintf (stderr,
- "%s %s, copyright (c) 1991-1999 "
+ "%s %s, copyright (c) 1991-2001 "
"by Jamie Zawinski <jwz@jwz.org>.\n",
progname, si->version);
/* Examine all of the display's screens, and populate the `saver_screen_info'
- structures.
+ structures. Make sure this is called after hack_environment() sets $PATH.
*/
static void
initialize_per_screen_info (saver_info *si, Widget toplevel_shell)
ssi->current_visual = ssi->default_visual;
ssi->current_depth = visual_depth (ssi->screen, ssi->current_visual);
+ /* Execute a subprocess to find the GL visual. */
+ ssi->best_gl_visual = get_best_gl_visual (ssi);
+
if (ssi == si->default_screen)
/* Since this is the default screen, use the one already created. */
ssi->toplevel_shell = toplevel_shell;
}
si->fading_possible_p = found_any_writable_cells;
+
+#ifdef HAVE_XF86VMODE_GAMMA
+ si->fading_possible_p = True; /* if we can gamma fade, go for it */
+#endif
}
/* If a server extension is in use, and p->timeout has changed,
we need to inform the server of the new timeout. */
disable_builtin_screensaver (si, False);
+
+ /* If the DPMS settings in the init file have changed,
+ change the settings on the server to match. */
+ sync_server_dpms_settings (si->dpy, p->dpms_enabled_p,
+ p->dpms_standby / 1000,
+ p->dpms_suspend / 1000,
+ p->dpms_off / 1000,
+ False);
}
}
select_events (si);
init_sigchld ();
+
disable_builtin_screensaver (si, True);
+ sync_server_dpms_settings (si->dpy, p->dpms_enabled_p,
+ p->dpms_standby / 1000,
+ p->dpms_suspend / 1000,
+ p->dpms_off / 1000,
+ False);
+
initialize_stderr (si);
make_splash_dialog (si);
/* Processing ClientMessage events.
*/
+
+static Bool error_handler_hit_p = False;
+
+static int
+ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error)
+{
+ error_handler_hit_p = True;
+ return 0;
+}
+
+/* Sometimes some systems send us ClientMessage events with bogus atoms in
+ them. We only look up the atom names for printing warning messages,
+ so don't bomb out when it happens...
+ */
+static char *
+XGetAtomName_safe (Display *dpy, Atom atom)
+{
+ char *result;
+ XErrorHandler old_handler;
+ if (!atom) return 0;
+
+ XSync (dpy, False);
+ error_handler_hit_p = False;
+ old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
+ result = XGetAtomName (dpy, atom);
+ XSync (dpy, False);
+ XSetErrorHandler (old_handler);
+ XSync (dpy, False);
+ if (error_handler_hit_p) result = 0;
+
+ if (result)
+ return result;
+ else
+ {
+ char buf[100];
+ sprintf (buf, "<<undefined atom 0x%04X>>", (unsigned long) atom);
+ return strdup (buf);
+ }
+}
+
+
static void
clientmessage_response (saver_info *si, Window w, Bool error,
const char *stderr_msg,
char *proto;
int L;
saver_preferences *p = &si->prefs;
+ XErrorHandler old_handler;
+
if (error || p->verbose_p)
fprintf (stderr, "%s: %s\n", blurb(), stderr_msg);
strcpy (proto+1, protocol_msg);
L++;
+ /* Ignore all X errors while sending a response to a ClientMessage.
+ Pretty much the only way we could get an error here is if the
+ window we're trying to send the reply on has been deleted, in
+ which case, the sender of the ClientMessage won't see our response
+ anyway.
+ */
+ XSync (si->dpy, False);
+ error_handler_hit_p = False;
+ old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
+
XChangeProperty (si->dpy, w, XA_SCREENSAVER_RESPONSE, XA_STRING, 8,
PropModeReplace, (unsigned char *) proto, L);
+
+ XSync (si->dpy, False);
+ XSetErrorHandler (old_handler);
XSync (si->dpy, False);
+
free (proto);
}
if (event->xclient.message_type != XA_SCREENSAVER)
{
char *str;
- str = XGetAtomName (si->dpy, event->xclient.message_type);
+ str = XGetAtomName_safe (si->dpy, event->xclient.message_type);
fprintf (stderr, "%s: unrecognised ClientMessage type %s received\n",
blurb(), (str ? str : "(null)"));
if (str) XFree (str);
return True;
}
}
- clientmessage_response(si, window, True,
- "ClientMessage DEACTIVATE received while inactive.",
- "not active.");
+ clientmessage_response(si, window, False,
+ "ClientMessage DEACTIVATE received while inactive: resetting idle timer.",
+ "not active: idle timer reset.");
+ reset_timers (si);
}
else if (type == XA_CYCLE)
{
{
char buf [1024];
char *str;
- str = (type ? XGetAtomName(si->dpy, type) : 0);
+ str = XGetAtomName_safe (si->dpy, type);
if (str)
{
analyze_display (saver_info *si)
{
int i, j;
- static const char *exts[][2] = {
- { "SCREEN_SAVER", "SGI Screen-Saver" },
- { "SCREEN-SAVER", "SGI Screen-Saver" },
- { "MIT-SCREEN-SAVER", "MIT Screen-Saver" },
- { "XIDLE", "XIdle" },
- { "SGI-VIDEO-CONTROL", "SGI Video-Control" },
- { "READDISPLAY", "SGI Read-Display" },
- { "MIT-SHM", "Shared Memory" },
- { "DOUBLE-BUFFER", "Double-Buffering" },
- { "DPMS", "Power Management" },
- { "GLX", "GLX" },
- { "XFree86-VidModeExtension", "XF86 Video-Mode" },
- { "XINERAMA", "Xinerama" }
+ static struct {
+ const char *name; const char *desc; Bool useful_p;
+ } exts[] = {
+
+ { "SCREEN_SAVER", "SGI Screen-Saver",
+# ifdef HAVE_SGI_SAVER_EXTENSION
+ True
+# else
+ False
+# endif
+ }, { "SCREEN-SAVER", "SGI Screen-Saver",
+# ifdef HAVE_SGI_SAVER_EXTENSION
+ True
+# else
+ False
+# endif
+ }, { "MIT-SCREEN-SAVER", "MIT Screen-Saver",
+# ifdef HAVE_MIT_SAVER_EXTENSION
+ True
+# else
+ False
+# endif
+ }, { "XIDLE", "XIdle",
+# ifdef HAVE_XIDLE_EXTENSION
+ True
+# else
+ False
+# endif
+ }, { "SGI-VIDEO-CONTROL", "SGI Video-Control",
+# ifdef HAVE_SGI_VC_EXTENSION
+ True
+# else
+ False
+# endif
+ }, { "READDISPLAY", "SGI Read-Display",
+# ifdef HAVE_READ_DISPLAY_EXTENSION
+ True
+# else
+ False
+# endif
+ }, { "MIT-SHM", "Shared Memory",
+# ifdef HAVE_XSHM_EXTENSION
+ True
+# else
+ False
+# endif
+ }, { "DOUBLE-BUFFER", "Double-Buffering",
+# ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+ True
+# else
+ False
+# endif
+ }, { "DPMS", "Power Management",
+# ifdef HAVE_DPMS_EXTENSION
+ True
+# else
+ False
+# endif
+ }, { "GLX", "GLX",
+# ifdef HAVE_GL
+ True
+# else
+ False
+# endif
+ }, { "XFree86-VidModeExtension", "XF86 Video-Mode",
+# ifdef HAVE_XF86VMODE
+ True
+# else
+ False
+# endif
+ }, { "XINERAMA", "Xinerama",
+ True
+ },
};
fprintf (stderr, "%s: running on display \"%s\"\n", blurb(),
for (i = 0; i < countof(exts); i++)
{
int op = 0, event = 0, error = 0;
- if (XQueryExtension (si->dpy, exts[i][0], &op, &event, &error))
- fprintf (stderr, "%s: %s\n", blurb(), exts[i][1]);
+ if (XQueryExtension (si->dpy, exts[i].name, &op, &event, &error))
+ fprintf (stderr, "%s: %s%s\n", blurb(),
+ exts[i].desc,
+ (exts[i].useful_p ? "" :
+ " \t<== unsupported at compile-time!"));
}
for (i = 0; i < si->nscreens; i++)