+ struct xscreensaver_function_table *ft = xscreensaver_function_table;
+
+ char *visual_string = get_string_resource (DisplayOfScreen (screen),
+ "visualID", "VisualID");
+ Visual *desired_visual = pick_visual (screen);
+ char win[100];
+ char why[100];
+
+ if (window == RootWindowOfScreen (screen))
+ strcpy (win, "root window");
+ else
+ sprintf (win, "window 0x%lx", (unsigned long) window);
+
+ if (window_p)
+ sprintf (why, "-window-id 0x%lx", (unsigned long) window);
+ else
+ strcpy (why, "-root");
+
+ if (visual_string && *visual_string)
+ {
+ char *s;
+ for (s = visual_string; *s; s++)
+ if (isupper (*s)) *s = _tolower (*s);
+
+ if (!strcmp (visual_string, "default") ||
+ !strcmp (visual_string, "default") ||
+ !strcmp (visual_string, "best"))
+ /* don't warn about these, just silently DWIM. */
+ ;
+ else if (visual != desired_visual)
+ {
+ fprintf (stderr, "%s: ignoring `-visual %s' because of `%s'.\n",
+ progname, visual_string, why);
+ fprintf (stderr, "%s: using %s's visual 0x%lx.\n",
+ progname, win, XVisualIDFromVisual (visual));
+ }
+ free (visual_string);
+ }
+
+ if (visual == DefaultVisualOfScreen (screen) &&
+ has_writable_cells (screen, visual) &&
+ get_boolean_resource (DisplayOfScreen (screen),
+ "installColormap", "InstallColormap"))
+ {
+ fprintf (stderr, "%s: ignoring `-install' because of `%s'.\n",
+ progname, why);
+ fprintf (stderr, "%s: using %s's colormap 0x%lx.\n",
+ progname, win, (unsigned long) cmap);
+ }
+
+ if (ft->validate_visual_hook)
+ {
+ if (! ft->validate_visual_hook (screen, win, visual))
+ exit (1);
+ }
+}
+
+
+static void
+fix_fds (void)
+{
+ /* Bad Things Happen if stdin, stdout, and stderr have been closed
+ (as by the `sh incantation "attraction >&- 2>&-"). When you do
+ that, the X connection gets allocated to one of these fds, and
+ then some random library writes to stderr, and random bits get
+ stuffed down the X pipe, causing "Xlib: sequence lost" errors.
+ So, we cause the first three file descriptors to be open to
+ /dev/null if they aren't open to something else already. This
+ must be done before any other files are opened (or the closing
+ of that other file will again free up one of the "magic" first
+ three FDs.)
+
+ We do this by opening /dev/null three times, and then closing
+ those fds, *unless* any of them got allocated as #0, #1, or #2,
+ in which case we leave them open. Gag.
+
+ Really, this crap is technically required of *every* X program,
+ if you want it to be robust in the face of "2>&-".
+ */
+ int fd0 = open ("/dev/null", O_RDWR);
+ int fd1 = open ("/dev/null", O_RDWR);
+ int fd2 = open ("/dev/null", O_RDWR);
+ if (fd0 > 2) close (fd0);
+ if (fd1 > 2) close (fd1);
+ if (fd2 > 2) close (fd2);
+}
+
+
+#ifdef DEBUG_TIMING
+
+static void
+check_timing (unsigned long delay)
+{
+ static unsigned long frame_count = 0;
+ static unsigned long delay_sum = 0;
+ static struct timeval prev1 = { 0, };
+ static struct timeval prev2 = { 0, };
+ struct timeval now;
+ double uprev1, uprev2, unow;
+
+# ifdef GETTIMEOFDAY_TWO_ARGS
+ gettimeofday (&now, 0);
+# else
+ gettimeofday (&now);
+# endif
+
+ if (prev1.tv_sec == 0)
+ prev1 = prev2 = now;
+
+ frame_count++;
+
+ uprev1 = prev1.tv_sec + ((double) prev1.tv_usec * 0.000001);
+ uprev2 = prev2.tv_sec + ((double) prev2.tv_usec * 0.000001);
+ unow = now.tv_sec + ((double) now.tv_usec * 0.000001);
+
+ if (unow >= uprev1 + 1.5)
+ fprintf (stderr,
+ "%s: warning: blocked event processing for %.1f secs!\n",
+ progname, unow - uprev1);
+ prev1 = now;
+
+ if (unow >= uprev2 + 10.0)
+ {
+ double fps = frame_count / (unow - uprev2);
+ double elapsed = unow - uprev2;
+ double slept = (delay_sum * 0.000001);
+ double sleep_ratio = slept / elapsed;
+
+ if (sleep_ratio < 0.10) {
+ fprintf (stderr,
+ "%s: warning: only %.0f%% idle over the"
+ " last %2.0f secs (at %.1f FPS)\n",
+ progname, 100 * sleep_ratio, elapsed, fps);
+ }
+
+ prev2 = now;
+ frame_count = 0;
+ delay_sum = 0;
+ }
+
+ delay_sum += delay;
+}
+
+#else /* !DEBUG_TIMING */
+# define check_timing(delay) /**/
+#endif /* !DEBUG_TIMING */
+
+static Boolean
+screenhack_table_handle_events (Display *dpy,
+ const struct xscreensaver_function_table *ft,
+ Window window, void *closure
+#ifdef DEBUG_PAIR
+ , Window window2, void *closure2
+#endif
+ )
+{
+ XtAppContext app = XtDisplayToApplicationContext (dpy);
+
+ if (XtAppPending (app) & (XtIMTimer|XtIMAlternateInput))
+ XtAppProcessEvent (app, XtIMTimer|XtIMAlternateInput);
+