http://ftp.nluug.nl/pub/os/Linux/distr/pardusrepo/sources/xscreensaver-5.02.tar.gz
[xscreensaver] / driver / windows.c
index 7ee76045134b9cf0967b73821c2582aa9ec545fa..23ba01ff3fa75f9ac15e1c6272016c723731bd01 100644 (file)
@@ -1,5 +1,5 @@
 /* windows.c --- turning the screen black; dealing with visuals, virtual roots.
- * xscreensaver, Copyright (c) 1991-2004 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1991-2007 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
@@ -30,7 +30,7 @@
 #endif /* HAVE_UNAME */
 
 #include <stdio.h>
-#include <X11/Xproto.h>                /* for CARD32 */
+/* #include <X11/Xproto.h>     / * for CARD32 */
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>         /* for XSetClassHint() */
 #include <X11/Xatom.h>
 #include <time.h>
 #include <sys/time.h>
 
+/* You might think that to store an array of 32-bit quantities onto a
+   server-side property, you would pass an array of 32-bit data quantities
+   into XChangeProperty().  You would be wrong.  You have to use an array
+   of longs, even if long is 64 bits (using 32 of each 64.)
+ */
+typedef long PROP32;
+
 #ifdef HAVE_MIT_SAVER_EXTENSION
 # include <X11/extensions/scrnsaver.h>
 #endif /* HAVE_MIT_SAVER_EXTENSION */
@@ -269,8 +276,24 @@ grab_keyboard_and_mouse (saver_info *si, Window window, Cursor cursor,
     fprintf (stderr, "%s: couldn't grab pointer!  (%s)\n",
              blurb(), grab_string(mstatus));
 
-  return (kstatus == GrabSuccess ||
-         mstatus == GrabSuccess);
+
+  /* When should we allow blanking to proceed?  The current theory
+     is that a keyboard grab is manditory; a mouse grab is optional.
+
+     - If we don't have a keyboard grab, then we won't be able to
+       read a password to unlock, so the kbd grab is manditory.
+       (We can't conditionalize this on locked_p, because someone
+       might run "xscreensaver-command -lock" at any time.)
+
+     - If we don't have a mouse grab, then we might not see mouse
+       clicks as a signal to unblank -- but we will still see kbd
+       activity, so that's not a disaster.
+   */
+
+  if (kstatus != GrabSuccess)  /* Do not blank without a kbd grab.   */
+    return False;
+
+  return True;                 /* Grab is good, go ahead and blank.  */
 }
 
 static void
@@ -348,25 +371,26 @@ ensure_no_screensaver_running (Display *dpy, Screen *screen)
       Atom type;
       int format;
       unsigned long nitems, bytesafter;
-      char *version;
+      unsigned char *version;
 
       if (XGetWindowProperty (dpy, kids[i], XA_SCREENSAVER_VERSION, 0, 1,
                              False, XA_STRING, &type, &format, &nitems,
-                             &bytesafter, (unsigned char **) &version)
+                             &bytesafter, &version)
          == Success
          && type != None)
        {
-         char *id;
+         unsigned char *id;
          if (!XGetWindowProperty (dpy, kids[i], XA_SCREENSAVER_ID, 0, 512,
                                   False, XA_STRING, &type, &format, &nitems,
-                                  &bytesafter, (unsigned char **) &id)
+                                  &bytesafter, &id)
              == Success
              || type == None)
-           id = "???";
+           id = (unsigned char *) "???";
 
          fprintf (stderr,
       "%s: already running on display %s (window 0x%x)\n from process %s.\n",
-                  blurb(), DisplayString (dpy), (int) kids [i], id);
+                  blurb(), DisplayString (dpy), (int) kids [i],
+                   (char *) id);
          status = True;
        }
     }
@@ -434,7 +458,7 @@ kill_xsetroot_data_1 (Display *dpy, Window window,
   Atom type;
   int format;
   unsigned long nitems, bytesafter;
-  Pixmap *dataP = 0;
+  unsigned char *dataP = 0;
 
   /* If the user has been using xv or xsetroot as a screensaver (to display
      an image on the screensaver window, as a kind of slideshow) then the
@@ -454,17 +478,18 @@ kill_xsetroot_data_1 (Display *dpy, Window window,
    */
   if (XGetWindowProperty (dpy, window, prop, 0, 1,
                          True, AnyPropertyType, &type, &format, &nitems, 
-                         &bytesafter, (unsigned char **) &dataP)
+                         &bytesafter, &dataP)
       == Success
       && type != None)
     {
-      if (dataP && *dataP && type == XA_PIXMAP && format == 32 &&
+      Pixmap *pixP = (Pixmap *) dataP;
+      if (pixP && *pixP && type == XA_PIXMAP && format == 32 &&
          nitems == 1 && bytesafter == 0)
        {
          if (verbose_p)
            fprintf (stderr, "%s: destroying %s data (0x%lX).\n",
-                    blurb(), atom_name, *dataP);
-         safe_XKillClient (dpy, *dataP);
+                    blurb(), atom_name, *pixP);
+         safe_XKillClient (dpy, *pixP);
        }
       else
        fprintf (stderr,
@@ -472,7 +497,7 @@ kill_xsetroot_data_1 (Display *dpy, Window window,
                  "\t%lu, %lu; type: %lu, format: %d, "
                  "nitems: %lu, bytesafter %ld\n",
                 blurb(), atom_name,
-                 (unsigned long) dataP, (dataP ? *dataP : 0), type,
+                 (unsigned long) pixP, (pixP ? *pixP : 0), type,
                 format, nitems, bytesafter);
     }
 }
@@ -522,7 +547,8 @@ save_real_vroot (saver_screen_info *ssi)
       Atom type;
       int format;
       unsigned long nitems, bytesafter;
-      Window *vrootP = 0;
+      unsigned char *dataP = 0;
+      Window *vrootP;
       int j;
 
       /* Skip this window if it is the xscreensaver window of any other
@@ -537,11 +563,13 @@ save_real_vroot (saver_screen_info *ssi)
 
       if (XGetWindowProperty (dpy, kids[i], XA_VROOT, 0, 1, False, XA_WINDOW,
                              &type, &format, &nitems, &bytesafter,
-                             (unsigned char **) &vrootP)
+                             &dataP)
          != Success)
        continue;
-      if (! vrootP)
+      if (! dataP)
        continue;
+
+      vrootP = (Window *) dataP;
       if (ssi->real_vroot)
        {
          if (*vrootP == ssi->screensaver_window) abort ();
@@ -781,9 +809,14 @@ saver_sighup_handler (int sig)
 
   fprintf (stderr, "%s: %s received: restarting...\n",
            blurb(), signal_name(sig));
-  unblank_screen (si);
-  kill_screenhack (si);
-  XSync (si->dpy, False);
+
+  if (si->screen_blanked_p)
+    {
+      unblank_screen (si);
+      kill_screenhack (si);
+      XSync (si->dpy, False);
+    }
+
   restart_process (si);   /* Does not return */
   abort ();
 }
@@ -940,16 +973,16 @@ store_saver_id (saver_screen_info *ssi)
 void
 store_saver_status (saver_info *si)
 {
-  CARD32 *status;
+  PROP32 *status;
   int size = si->nscreens + 2;
   int i;
 
-  status = (CARD32 *) calloc (size, sizeof(CARD32));
+  status = (PROP32 *) calloc (size, sizeof(PROP32));
 
-  status[0] = (CARD32) (si->screen_blanked_p
+  status[0] = (PROP32) (si->screen_blanked_p
                         ? (si->locked_p ? XA_LOCK : XA_BLANK)
                         : 0);
-  status[1] = (CARD32) si->blank_time;
+  status[1] = (PROP32) si->blank_time;
 
   for (i = 0; i < si->nscreens; i++)
     {
@@ -1386,7 +1419,12 @@ initialize_screensaver_window_1 (saver_screen_info *ssi)
   attrs.backing_pixel = ssi->black_pixel;
   attrs.border_pixel = ssi->black_pixel;
 
-  if (p->debug_p && !p->quad_p) width = width / 2;
+  if (p->debug_p
+# ifdef QUAD_MODE
+      && !p->quad_p
+# endif
+      )
+    width = width / 2;
 
   if (!p->verbose_p || printed_visual_info)
     ;
@@ -1564,9 +1602,21 @@ resize_screensaver_window (saver_info *si)
        */
       int nscreens;
       XineramaScreenInfo *xsi = XineramaQueryScreens (si->dpy, &nscreens);
-      if (nscreens != si->nscreens) abort();
+
+      if (nscreens != si->nscreens) {
+        /* Apparently some Xinerama implementations let you use a hot-key
+           to change the number of screens in use!  This is, of course,
+           documented nowhere.  Let's try to do something marginally less
+           bad than crashing.
+         */
+        fprintf (stderr, "%s: bad craziness: xinerama screen count changed "
+                 "from %d to %d!\n", blurb(), si->nscreens, nscreens);
+        if (nscreens > si->nscreens)
+          nscreens = si->nscreens;
+      }
+
       if (!xsi) abort();
-      for (i = 0; i < si->nscreens; i++)
+      for (i = 0; i < nscreens; i++)
         {
           saver_screen_info *ssi = &si->screens[i];
           if (p->verbose_p &&
@@ -1644,7 +1694,12 @@ resize_screensaver_window (saver_info *si)
       changes.height = height;
       changes.border_width = 0;
 
-      if (p->debug_p && !p->quad_p) changes.width = changes.width / 2;
+      if (p->debug_p
+# ifdef QUAD_MODE
+          && !p->quad_p
+# endif
+          ) 
+        changes.width = changes.width / 2;
 
       if (p->verbose_p)
         fprintf (stderr,
@@ -1829,12 +1884,17 @@ blank_screen (saver_info *si)
                                 mscreen);
 
 
+# if 0
   if (si->using_mit_saver_extension || si->using_sgi_saver_extension)
     /* If we're using a server extension, then failure to get a grab is
        not a big deal -- even without the grab, we will still be able
        to un-blank when there is user activity, since the server will
        tell us. */
+    /* #### No, that's not true: if we don't have a keyboard grab,
+            then we can't read passwords to unlock.
+     */
     ok = True;
+# endif /* 0 */
 
   if (!ok)
     return False;
@@ -1947,7 +2007,7 @@ unblank_screen (saver_info *si)
 
   /* If the focus window does has a non-default colormap, then install
      that colormap as well.  (On SGIs, this will cause both the root map
-     and the focus map to be installed simultaniously.  It'd be nice to
+     and the focus map to be installed simultaneously.  It'd be nice to
      pick up the other colormaps that had been installed, too; perhaps
      XListInstalledColormaps could be used for that?)
    */
@@ -2043,6 +2103,13 @@ select_visual (saver_screen_info *ssi, const char *visual_name)
   Visual *new_v = 0;
   Bool got_it;
 
+  /* On some systems (most recently, MacOS X) OpenGL programs get confused
+     when you kill one and re-start another on the same window.  So maybe
+     it's best to just always destroy and recreate the xscreensaver window
+     when changing hacks, instead of trying to reuse the old one?
+   */
+  Bool always_recreate_window_p = True;
+
   if (visual_name && *visual_name)
     {
       if (!strcmp(visual_name, "default-i") ||
@@ -2086,7 +2153,8 @@ select_visual (saver_screen_info *ssi, const char *visual_name)
   ssi->install_cmap_p = install_cmap_p;
 
   if (new_v &&
-      ((ssi->current_visual != new_v) ||
+      (always_recreate_window_p ||
+       (ssi->current_visual != new_v) ||
        (install_cmap_p != was_installed_p)))
     {
       Colormap old_c = ssi->cmap;