http://www.ibiblio.org/pub/historic-linux/ftp-archives/sunsite.unc.edu/Sep-29-1996...
[xscreensaver] / driver / timers.c
index b8c3e91ede3b1153d20e925661ebe4024539668b..bb950d8133ab2e5c7fe1367c2ca44d90ec1a0a0a 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1991-1993 Jamie Zawinski <jwz@lucid.com>
+/* xscreensaver, Copyright (c) 1991-1995 Jamie Zawinski <jwz@netscape.com>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -9,18 +9,32 @@
  * implied warranty.
  */
 
+/* #define DEBUG_TIMERS */
+
 #include <stdio.h>
 #include <X11/Xlib.h>
 #include <X11/Intrinsic.h>
 #include <X11/Xos.h>
 #include <X11/Xmu/Error.h>
 
-#ifdef HAVE_XIDLE
+#ifdef HAVE_XIDLE_EXTENSION
 #include <X11/extensions/xidle.h>
-#endif
+#endif /* HAVE_XIDLE_EXTENSION */
+
+#ifdef HAVE_SAVER_EXTENSION
+#include <X11/extensions/scrnsaver.h>
+extern int saver_ext_event_number;
+extern Window server_saver_window;
+#endif /* HAVE_SAVER_EXTENSION */
 
 #include "xscreensaver.h"
 
+#if __STDC__
+# define P(x)x
+#else
+#define P(x)()
+#endif
+
 extern XtAppContext app;
 
 Time cycle;
@@ -28,14 +42,15 @@ Time timeout;
 Time pointer_timeout;
 Time notice_events_timeout;
 
-extern Bool use_xidle;
+extern Bool use_xidle_extension;
+extern Bool use_saver_extension;
 extern Bool dbox_up_p;
 extern Bool locked_p;
 extern Window screensaver_window;
 
-extern Bool handle_clientmessage P((/*XEvent *, Bool*/));
+extern Bool handle_clientmessage P((XEvent *, Bool));
 
-static time_t last_activity_time; /* for non-XIdle mode */
+static time_t last_activity_time; /* for when we have no server extensions */
 static XtIntervalId timer_id = 0;
 static XtIntervalId check_pointer_timer_id = 0;
 XtIntervalId cycle_id = 0;
@@ -66,9 +81,13 @@ idle_timer (junk1, junk2)
 
 
 static void
+#if __STDC__
+notice_events (Window window, Bool top_p)
+#else
 notice_events (window, top_p)
      Window window;
      Bool top_p;
+#endif
 {
   XWindowAttributes attrs;
   unsigned long events;
@@ -97,7 +116,8 @@ notice_events (window, top_p)
   if (top_p && verbose_p && (events & KeyPressMask))
     {
       /* Only mention one window per tree (hack hack). */
-      printf ("%s: selected KeyPress on 0x%X\n", progname, window);
+      printf ("%s: selected KeyPress on 0x%lX\n", progname,
+             (unsigned long) window);
       top_p = False;
     }
 
@@ -121,6 +141,7 @@ BadWindow_ehandler (dpy, error)
      may have been destroyed <30 seconds after it was created.
    */
   if (error->error_code == BadWindow ||
+      error->error_code == BadMatch ||
       error->error_code == BadDrawable)
     return 0;
   XmuPrintDefaultErrorMessage (dpy, error, stderr);
@@ -130,7 +151,7 @@ BadWindow_ehandler (dpy, error)
 void
 notice_events_timer (closure, timer)
      XtPointer closure;
-     void *timer;
+     XtIntervalId *timer;
 {
   Window window = (Window) closure;
   int (*old_handler) ();
@@ -163,7 +184,13 @@ cycle_timer (junk1, junk2)
       kill_screenhack ();
       spawn_screenhack (False);
     }
-  cycle_id = XtAppAddTimeOut (app, how_long, (XtTimerCallbackProc)cycle_timer, 0);
+  cycle_id = XtAppAddTimeOut (app, how_long, cycle_timer, 0);
+
+#ifdef DEBUG_TIMERS
+  if (verbose_p)
+    printf ("%s: starting cycle_timer (%ld, %ld)\n",
+           progname, how_long, cycle_id);
+#endif
 }
 
 
@@ -181,22 +208,31 @@ activate_lock_timer (junk1, junk2)
 /* Call this when user activity (or "simulated" activity) has been noticed.
  */
 static void
-reset_timers ()
+reset_timers P((void))
 {
+  if (use_saver_extension)
+    return;
+
 #ifdef DEBUG_TIMERS
   if (verbose_p)
-    printf ("%s: restarting idle_timer (%d, %d)\n",
+    printf ("%s: restarting idle_timer (%ld, %ld)\n",
            progname, timeout, timer_id);
 #endif
   XtRemoveTimeOut (timer_id);
-  timer_id = XtAppAddTimeOut (app, timeout, (XtTimerCallbackProc)idle_timer, 0);
+  timer_id = XtAppAddTimeOut (app, timeout, idle_timer, 0);
   if (cycle_id) abort ();
 
+#ifdef DEBUG_TIMERS
+  if (verbose_p)
+    printf ("%s: starting idle_timer (%ld, %ld)\n",
+           progname, timeout, timer_id);
+#endif
+
   last_activity_time = time ((time_t *) 0);
 }
 
-/* When we aren't using XIdle, this timer is used to periodically wake up
-   and poll the mouse position, which is possibly more reliable than
+/* When we aren't using a server extension, this timer is used to periodically
+   wake up and poll the mouse position, which is possibly more reliable than
    selecting motion events on every window.
  */
 static void
@@ -212,12 +248,11 @@ check_pointer_timer (closure, this_timer)
   int root_x, root_y, x, y;
   unsigned int mask;
   XtIntervalId *timerP = (XtIntervalId *) closure;
-#ifdef HAVE_XIDLE
-  if (use_xidle)
+
+  if (use_xidle_extension || use_saver_extension)
     abort ();
-#endif
 
-  *timerP = XtAppAddTimeOut (app, pointer_timeout, (XtTimerCallbackProc)check_pointer_timer,
+  *timerP = XtAppAddTimeOut (app, pointer_timeout, check_pointer_timer,
                             closure);
 
   XQueryPointer (dpy, screensaver_window, &root, &child,
@@ -251,10 +286,18 @@ sleep_until_idle (until_idle_p)
 
   if (until_idle_p)
     {
-      timer_id = XtAppAddTimeOut (app, timeout, (XtTimerCallbackProc)idle_timer, 0);
-#ifdef HAVE_XIDLE
-      if (! use_xidle)
+      if (!use_saver_extension)
+       {
+         /* Wake up periodically to ask the server if we are idle. */
+         timer_id = XtAppAddTimeOut (app, timeout, idle_timer, 0);
+#ifdef DEBUG_TIMERS
+         if (verbose_p)
+           printf ("%s: starting idle_timer (%ld, %ld)\n",
+                   progname, timeout, timer_id);
 #endif
+       }
+
+      if (!use_xidle_extension && !use_saver_extension)
        /* start polling the mouse position */
        check_pointer_timer (&check_pointer_timer_id, 0);
     }
@@ -268,8 +311,8 @@ sleep_until_idle (until_idle_p)
        if (until_idle_p)
          {
            Time idle;
-#ifdef HAVE_XIDLE
-           if (use_xidle)
+#ifdef HAVE_XIDLE_EXTENSION
+           if (use_xidle_extension)
              {
                if (! XGetIdleTime (dpy, &idle))
                  {
@@ -279,14 +322,33 @@ sleep_until_idle (until_idle_p)
                  }
              }
            else
-#endif /* HAVE_XIDLE */
-             idle = 1000 * (last_activity_time - time ((time_t *) 0));
+#endif /* HAVE_XIDLE_EXTENSION */
+#ifdef HAVE_SAVER_EXTENSION
+             if (use_saver_extension)
+               {
+                 /* We don't need to do anything in this case - the synthetic
+                    event isn't necessary, as we get sent specific events
+                    to wake us up. */
+                 idle = 0;
+               }
+           else
+#endif /* HAVE_SAVER_EXTENSION */
+             {
+               idle = 1000 * (last_activity_time - time ((time_t *) 0));
+             }
            
            if (idle >= timeout)
              goto DONE;
-           else
-             timer_id = XtAppAddTimeOut (app, timeout - idle,
-                                         (XtTimerCallbackProc)idle_timer, 0);
+           else if (!use_saver_extension)
+             {
+               timer_id = XtAppAddTimeOut (app, timeout - idle,
+                                           idle_timer, 0);
+#ifdef DEBUG_TIMERS
+               if (verbose_p)
+                 printf ("%s: starting idle_timer (%ld, %ld)\n",
+                         progname, timeout - idle, timer_id);
+#endif /* DEBUG_TIMERS */
+             }
          }
        break;
 
@@ -296,11 +358,18 @@ sleep_until_idle (until_idle_p)
        break;
 
       case CreateNotify:
-#ifdef HAVE_XIDLE
-       if (! use_xidle)
-#endif
-         XtAppAddTimeOut (app, notice_events_timeout, (XtTimerCallbackProc)notice_events_timer,
-                          (XtPointer) event.xcreatewindow.window);
+       if (!use_xidle_extension && !use_saver_extension)
+         {
+           XtAppAddTimeOut (app, notice_events_timeout, notice_events_timer,
+                            (XtPointer) event.xcreatewindow.window);
+#ifdef DEBUG_TIMERS
+           if (verbose_p)
+             printf ("%s: starting notice_events_timer for 0x%X (%lu)\n",
+                     progname,
+                     (unsigned int) event.xcreatewindow.window,
+                     notice_events_timeout);
+#endif /* DEBUG_TIMERS */
+         }
        break;
 
       case KeyPress:
@@ -316,7 +385,7 @@ sleep_until_idle (until_idle_p)
              printf ("%s: MotionNotify at %s\n", progname, timestring ());
            else if (event.xany.type == KeyPress)
              printf ("%s: KeyPress seen on 0x%X at %s\n", progname,
-                     event.xkey.window, timestring ());
+                     (unsigned int) event.xkey.window, timestring ());
          }
 #endif
 
@@ -328,7 +397,59 @@ sleep_until_idle (until_idle_p)
        break;
 
       default:
-       XtDispatchEvent (&event);
+
+#ifdef HAVE_SAVER_EXTENSION
+       if (event.type == saver_ext_event_number)
+         {
+           XScreenSaverNotifyEvent *sevent =
+             (XScreenSaverNotifyEvent *) &event;
+           if (sevent->state == ScreenSaverOn)
+             {
+# ifdef DEBUG_TIMERS
+               if (verbose_p)
+                 printf ("%s: ScreenSaverOn event received at %s\n",
+                         progname, timestring ());
+# endif /* DEBUG_TIMERS */
+
+               /* Get the "real" server window out of the way as soon
+                  as possible. */
+               if (server_saver_window &&
+                   window_exists_p (dpy, server_saver_window))
+                 XUnmapWindow (dpy, server_saver_window);
+
+               if (sevent->kind != ScreenSaverExternal)
+                 {
+# ifdef DEBUG_TIMERS
+                   fprintf (stderr,
+                        "%s: ScreenSaverOn event wasn't of type External!\n",
+                            progname);
+# endif /* DEBUG_TIMERS */
+                 }
+
+               if (until_idle_p)
+                 goto DONE;
+             }
+           else if (sevent->state == ScreenSaverOff)
+             {
+# ifdef DEBUG_TIMERS
+               if (verbose_p)
+                 printf ("%s: ScreenSaverOff event received at %s\n",
+                         progname, timestring ());
+# endif /* DEBUG_TIMERS */
+               if (!until_idle_p)
+                 goto DONE;
+             }
+# ifdef DEBUG_TIMERS
+           else if (verbose_p)
+             printf ("%s: unknown ScreenSaver event received at %s\n",
+                     progname, timestring ());
+# endif /* DEBUG_TIMERS */
+         }
+       else
+
+#endif /* HAVE_SAVER_EXTENSION */
+
+         XtDispatchEvent (&event);
       }
     }
  DONE: