ftp://ftp.krokus.ru/pub/OpenBSD/distfiles/xscreensaver-4.06.tar.gz
[xscreensaver] / hacks / screenhack.c
index 9d11b350f665b7bb8bc8d73362ed9abdcaa42a93..1a6cd69f879f8dbcd68accfe65730e4336f8da0c 100644 (file)
@@ -293,10 +293,10 @@ visual_warning (Screen *screen, Window window, Visual *visual, Colormap cmap,
   if (window == RootWindowOfScreen (screen))
     strcpy (win, "root window");
   else
-    sprintf (win, "window 0x%x", (unsigned long) window);
+    sprintf (win, "window 0x%lx", (unsigned long) window);
 
   if (window_p)
-    sprintf (why, "-window-id 0x%x", (unsigned long) window);
+    sprintf (why, "-window-id 0x%lx", (unsigned long) window);
   else
     strcpy (why, "-root");
 
@@ -315,7 +315,7 @@ visual_warning (Screen *screen, Window window, Visual *visual, Colormap cmap,
         {
           fprintf (stderr, "%s: ignoring `-visual %s' because of `%s'.\n",
                    progname, visual_string, why);
-          fprintf (stderr, "%s: using %s's visual 0x%x.\n",
+          fprintf (stderr, "%s: using %s's visual 0x%lx.\n",
                    progname, win, XVisualIDFromVisual (visual));
         }
       free (visual_string);
@@ -327,7 +327,7 @@ visual_warning (Screen *screen, Window window, Visual *visual, Colormap cmap,
     {
       fprintf (stderr, "%s: ignoring `-install' because of `%s'.\n",
                progname, why);
-      fprintf (stderr, "%s: using %s's colormap 0x%x.\n",
+      fprintf (stderr, "%s: using %s's colormap 0x%lx.\n",
                progname, win, (unsigned long) cmap);
     }
 
@@ -338,6 +338,36 @@ visual_warning (Screen *screen, Window window, Visual *visual, Colormap cmap,
 }
 
 
+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);
+}
+
+
 int
 main (int argc, char **argv)
 {
@@ -353,6 +383,8 @@ main (int argc, char **argv)
   Boolean dont_clear /*, dont_map */;
   char version[255];
 
+  fix_fds();
+
 #ifdef XLOCKMORE
   pre_merge_options ();
 #endif
@@ -495,6 +527,7 @@ main (int argc, char **argv)
       XGetWindowAttributes (dpy, window, &xgwa);
       cmap = xgwa.colormap;
       visual = xgwa.visual;
+      screen = xgwa.screen;
       visual_warning (screen, window, visual, cmap, True);
 
       /* Select KeyPress events on the external window.
@@ -502,12 +535,14 @@ main (int argc, char **argv)
       xgwa.your_event_mask |= KeyPressMask;
       XSelectInput (dpy, window, xgwa.your_event_mask);
 
-      /* Select ButtonPress events on the external window, if no other
-         app has already selected it (only one app can select ButtonPress
-         at a time: BadAccess results.)
+      /* Select ButtonPress and ButtonRelease events on the external window,
+         if no other app has already selected them (only one app can select
+         ButtonPress at a time: BadAccess results.)
        */
-      if (! (xgwa.all_event_masks & ButtonPressMask))
-        XSelectInput (dpy, window, xgwa.your_event_mask | ButtonPressMask);
+      if (! (xgwa.all_event_masks & (ButtonPressMask | ButtonReleaseMask)))
+        XSelectInput (dpy, window,
+                      (xgwa.your_event_mask |
+                       ButtonPressMask | ButtonReleaseMask));
     }
   else if (root_p)
     {
@@ -605,7 +640,8 @@ main (int argc, char **argv)
         XWindowAttributes xgwa;
         XGetWindowAttributes (dpy, window, &xgwa);
         XSelectInput (dpy, window,
-                      xgwa.your_event_mask | KeyPressMask | ButtonPressMask);
+                      (xgwa.your_event_mask | KeyPressMask |
+                       ButtonPressMask | ButtonReleaseMask));
         XChangeProperty (dpy, window, XA_WM_PROTOCOLS, XA_ATOM, 32,
                          PropModeReplace,
                          (unsigned char *) &XA_WM_DELETE_WINDOW, 1);