ftp://ftp.linux.ncsu.edu/mirror/ftp.redhat.com/pub/redhat/linux/enterprise/4/en/os...
[xscreensaver] / driver / xscreensaver.c
index de42a100c9980e0ae03fc68f087f24d4c392dc27..ab39b84e62341db668725061a05b382b7e0bc23c 100644 (file)
@@ -255,7 +255,7 @@ do_help (saver_info *si)
   fflush (stdout);
   fflush (stderr);
   fprintf (stdout, "\
-xscreensaver %s, copyright (c) 1991-2003 by Jamie Zawinski <jwz@jwz.org>\n\
+xscreensaver %s, copyright (c) 1991-2004 by Jamie Zawinski <jwz@jwz.org>\n\
 \n\
   All xscreensaver configuration is via the `~/.xscreensaver' file.\n\
   Rather than editing that file by hand, just run `xscreensaver-demo':\n\
@@ -719,7 +719,7 @@ print_banner (saver_info *si)
 
   if (p->verbose_p)
     fprintf (stderr,
-            "%s %s, copyright (c) 1991-2003 "
+            "%s %s, copyright (c) 1991-2004 "
             "by Jamie Zawinski <jwz@jwz.org>.\n",
             progname, si->version);
 
@@ -1034,6 +1034,10 @@ initialize_server_extensions (saver_info *si)
                  blurb());
     }
 
+#ifdef HAVE_RANDR
+  query_randr_extension (si);
+#endif
+
   if (!system_has_proc_interrupts_p)
     {
       si->using_proc_interrupts = False;
@@ -1190,6 +1194,24 @@ main_loop (saver_info *si)
           continue;
         }
 
+      /* Since we're about to blank the screen, kill the de-race timer,
+         if any.  It might still be running if we have unblanked and then
+         re-blanked in a short period (e.g., when using the "next" button
+         in xscreensaver-demo.)
+       */
+      if (si->de_race_id)
+        {
+          if (p->verbose_p)
+            fprintf (stderr, "%s: stopping de-race timer (%d remaining.)\n",
+                     blurb(), si->de_race_ticks);
+          XtRemoveTimeOut (si->de_race_id);
+          si->de_race_id = 0;
+        }
+
+
+      /* Now, try to blank.
+       */
+
       if (! blank_screen (si))
         {
           /* We were unable to grab either the keyboard or mouse.
@@ -1200,13 +1222,29 @@ main_loop (saver_info *si)
              see any events, and the display would be wedged.
 
              So, just go around the loop again and wait for the
-             next bout of idleness.
+             next bout of idleness.  (If the user remains idle, we
+             will next try to blank the screen again in no more than
+             60 seconds.)
           */
+          Time retry = 60 * 1000;
+          if (p->timeout < retry)
+            retry = p->timeout;
 
-          fprintf (stderr,
+          if (p->debug_p)
+            {
+              fprintf (stderr,
+                  "%s: DEBUG MODE: unable to grab -- BLANKING ANYWAY.\n",
+                       blurb());
+            }
+          else
+            {
+              fprintf (stderr,
                   "%s: unable to grab keyboard or mouse!  Blanking aborted.\n",
-                   blurb());
-          continue;
+                       blurb());
+
+              schedule_wakeup_event (si, retry, p->debug_p);
+              continue;
+            }
         }
 
       kill_screenhack (si);
@@ -1348,52 +1386,10 @@ main_loop (saver_info *si)
          si->lock_id = 0;
        }
 
-      /* It's possible that a race condition could have led to the saver
-         window being unexpectedly still mapped.  This can happen like so:
-
-          - screen is blanked
-          - hack is launched
-          - that hack tries to grab a screen image (it does this by
-            first unmapping the saver window, then remapping it.)
-          - hack unmaps window
-          - hack waits
-          - user becomes active
-          - hack re-maps window (*)
-          - driver kills subprocess
-          - driver unmaps window (**)
-
-         The race is that (*) might have been sent to the server before
-         the client process was killed, but, due to scheduling randomness,
-         might not have been received by the server until after (**).
-         In other words, (*) and (**) might happen out of order, meaning
-         the driver will unmap the window, and then after that, the
-         recently-dead client will re-map it.  This leaves the user
-         locked out (it looks like a desktop, but it's not!)
-
-         To avoid this: after un-blanking the screen, sleep for a second,
-         and then really make sure the window is unmapped.
-       */
-      {
-        int i;
-        XSync (si->dpy, False);
-        sleep (1);
-        for (i = 0; i < si->nscreens; i++)
-          {
-            saver_screen_info *ssi = &si->screens[i];
-            Window w = ssi->screensaver_window;
-            XWindowAttributes xgwa;
-            XGetWindowAttributes (si->dpy, w, &xgwa);
-            if (xgwa.map_state != IsUnmapped)
-              {
-                if (p->verbose_p)
-                  fprintf (stderr,
-                           "%s: %d: client race! emergency unmap 0x%lx.\n",
-                           blurb(), i, (unsigned long) w);
-                XUnmapWindow (si->dpy, w);
-              }
-          }
-        XSync (si->dpy, False);
-      }
+      /* Since we're unblanked now, break race conditions and make
+         sure we stay that way (see comment in timers.c.) */
+      if (! si->de_race_id)
+        de_race_timer ((XtPointer) si, 0);
     }
 }
 
@@ -1667,6 +1663,14 @@ handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p)
     {
       if (until_idle_p)
        {
+          if (p->mode == DONT_BLANK)
+            {
+              clientmessage_response(si, window, True,
+                         "ACTIVATE ClientMessage received in DONT_BLANK mode.",
+                                     "screen blanking is currently disabled.");
+              return False;
+            }
+
          clientmessage_response(si, window, False,
                                 "ACTIVATE ClientMessage received.",
                                 "activating.");
@@ -1771,6 +1775,14 @@ handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p)
       char buf2 [255];
       long which = event->xclient.data.l[1];
 
+      if (p->mode == DONT_BLANK)
+        {
+          clientmessage_response(si, window, True,
+                           "SELECT ClientMessage received in DONT_BLANK mode.",
+                                 "screen blanking is currently disabled.");
+          return False;
+        }
+
       sprintf (buf, "SELECT %ld ClientMessage received.", which);
       sprintf (buf2, "activating (%ld).", which);
       clientmessage_response (si, window, False, buf, buf2);
@@ -1890,7 +1902,11 @@ handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p)
                              "not compiled with support for locking.",
                              "locking not enabled.");
 #else /* !NO_LOCKING */
-      if (si->locking_disabled_p)
+      if (p->mode == DONT_BLANK)
+        clientmessage_response(si, window, True,
+                             "LOCK ClientMessage received in DONT_BLANK mode.",
+                               "screen blanking is currently disabled.");
+      else if (si->locking_disabled_p)
        clientmessage_response (si, window, True,
                      "LOCK ClientMessage received, but locking is disabled.",
                              "locking not enabled.");
@@ -2089,7 +2105,17 @@ analyze_display (saver_info *si)
         False
 #     endif
    }, { "XINERAMA",                             "Xinerama",
+#     ifdef HAVE_XINERAMA
+        True
+#     else
+        False
+#     endif
+   }, { "RANDR",                                "Resize-and-Rotate",
+#     ifdef HAVE_RANDR
         True
+#     else
+        False
+#     endif
    }, { "Apple-DRI",                            "Apple-DRI (XDarwin)",
         True
    },