http://ftp.x.org/contrib/applications/xscreensaver-3.20.tar.gz
[xscreensaver] / driver / xset.c
index c4fb6d6b150ca90ce05cf774d671e2fec05b35cd..6dabdb2d156f9f3942ed070abbce2358f23a64ca 100644 (file)
@@ -1,5 +1,5 @@
 /* xset.c --- interacting with server extensions and the builtin screensaver.
 /* xset.c --- interacting with server extensions and the builtin screensaver.
- * xscreensaver, Copyright (c) 1991-1997 Jamie Zawinski <jwz@netscape.com>
+ * xscreensaver, Copyright (c) 1991-1998 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
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 
 #include "xscreensaver.h"
 
 
 #include "xscreensaver.h"
 
+#ifdef _VROOT_H_
+ERROR!  You must not include vroot.h in this file.
+#endif
+
 \f
 /* MIT SCREEN-SAVER server extension hackery.
  */
 \f
 /* MIT SCREEN-SAVER server extension hackery.
  */
@@ -124,8 +128,8 @@ init_sgi_saver_extension (saver_info *si)
          fprintf (stderr,
        "%s: SGI SCREEN_SAVER extension exists, but can't be initialized;\n\
                perhaps some other screensaver program is already running?\n",
          fprintf (stderr,
        "%s: SGI SCREEN_SAVER extension exists, but can't be initialized;\n\
                perhaps some other screensaver program is already running?\n",
-                  progname);
-         p->use_sgi_saver_extension = False;
+                  blurb());
+         si->using_sgi_saver_extension = False;
          return;
        }
     }
          return;
        }
     }
@@ -134,12 +138,31 @@ init_sgi_saver_extension (saver_info *si)
 #endif /* HAVE_SGI_SAVER_EXTENSION */
 
 \f
 #endif /* HAVE_SGI_SAVER_EXTENSION */
 
 \f
-/* Figuring out what the appropriate XSetScreenSaver() paramters are
+/* XIDLE server extension hackery.
+ */
+
+#ifdef HAVE_XIDLE_EXTENSION
+
+# include <X11/extensions/xidle.h>
+
+Bool
+query_xidle_extension (saver_info *si)
+{
+  int event_number;
+  int error_number;
+  return XidleQueryExtension (si->dpy, &event_number, &error_number);
+}
+
+#endif /* HAVE_XIDLE_EXTENSION */
+
+
+\f
+/* Figuring out what the appropriate XSetScreenSaver() parameters are
    (one wouldn't expect this to be rocket science.)
  */
 
 void
    (one wouldn't expect this to be rocket science.)
  */
 
 void
-disable_builtin_screensaver (saver_info *si, Bool turn_off_p)
+disable_builtin_screensaver (saver_info *si, Bool unblank_screen_p)
 {
   saver_preferences *p = &si->prefs;
   int current_server_timeout, current_server_interval;
 {
   saver_preferences *p = &si->prefs;
   int current_server_timeout, current_server_interval;
@@ -157,52 +180,41 @@ disable_builtin_screensaver (saver_info *si, Bool turn_off_p)
 
   /* On SGIs, if interval is non-zero, it is the number of seconds after
      screen saving starts at which the monitor should be powered down.
 
   /* On SGIs, if interval is non-zero, it is the number of seconds after
      screen saving starts at which the monitor should be powered down.
-     Obviously I don't want that, so make sure it's a large positive number.
+     Obviously I don't want that, so set it to 0 (meaning "never".)
 
      Power saving is disabled if DontPreferBlanking, but in that case,
      we don't get extension events either.  So we can't turn it off that way.
 
 
      Power saving is disabled if DontPreferBlanking, but in that case,
      we don't get extension events either.  So we can't turn it off that way.
 
-     The man page for `XSetScreenSaver' says that setting interval to 0 will
-     disable powering down of the monitor, but this turns out not to be the
-     case on Irix 6.3 (O2); the monitor powers down anyway.  It didn't do
-     this on 6.2, so someone screwed up.
-
-     Extra Sucky Factoid #2: the number can't be more than 15 bits, which
-     is only a bit over nine hours.  So there's just *no fucking way* to make
-     an SGI O2 leave its monitor powered on and idle for more than nine hours.
-     You fucking losers!
-
-     [...Later...]  Ok, it's worse than that.  The above doesn't work either.
-     Setting it to a small number will cause it to power down early; but even
-     if you set it to a large number, it still seems to power down in about
-     an hour.  You fucking fucking fucking losers!
+     Note: if you're running Irix 6.3 (O2), you may find that your monitor is
+     powering down anyway, regardless of the xset settings.  This is fixed by
+     installing SGI patches 2447 and 2537.
    */
    */
-#ifdef HAVE_SGI_SAVER_EXTENSION
-  if (p->use_sgi_saver_extension)
-    desired_server_interval = 32767;
-  else
-#endif
-    desired_server_interval = 0;
+  desired_server_interval = 0;
 
   /* I suspect (but am not sure) that DontAllowExposures might have
 
   /* I suspect (but am not sure) that DontAllowExposures might have
-     something to do with powering off the monitor as well. */
+     something to do with powering off the monitor as well, at least
+     on some systems that don't support XDPMS?  Who know... */
   desired_allow_exp = AllowExposures;
 
   desired_allow_exp = AllowExposures;
 
-#if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION)
-  if (p->use_mit_saver_extension || p->use_sgi_saver_extension)
+  if (si->using_mit_saver_extension || si->using_sgi_saver_extension)
     {
       desired_server_timeout = (p->timeout / 1000);
 
       /* The SGI extension won't give us events unless blanking is on.
         I think (unsure right now) that the MIT extension is the opposite. */
     {
       desired_server_timeout = (p->timeout / 1000);
 
       /* The SGI extension won't give us events unless blanking is on.
         I think (unsure right now) that the MIT extension is the opposite. */
-      if (p->use_sgi_saver_extension)
+      if (si->using_sgi_saver_extension)
        desired_prefer_blank = PreferBlanking;
       else
        desired_prefer_blank = DontPreferBlanking;
     }
   else
        desired_prefer_blank = PreferBlanking;
       else
        desired_prefer_blank = DontPreferBlanking;
     }
   else
-#endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */
     {
     {
+      /* When we're not using an extension, set the server-side timeout to 0,
+        so that the server never gets involved with screen blanking, and we
+        do it all ourselves.  (However, when we *are* using an extension,
+        we tell the server when to notify us, and rather than blanking the
+        screen, the server will send us an X event telling us to blank.)
+       */
       desired_server_timeout = 0;
     }
 
       desired_server_timeout = 0;
     }
 
@@ -211,17 +223,19 @@ disable_builtin_screensaver (saver_info *si, Bool turn_off_p)
       desired_prefer_blank != current_prefer_blank ||
       desired_allow_exp != current_allow_exp)
     {
       desired_prefer_blank != current_prefer_blank ||
       desired_allow_exp != current_allow_exp)
     {
-      if (desired_server_timeout == 0)
-       printf ("%s%sisabling server builtin screensaver.\n\
-       You can re-enable it with \"xset s on\".\n",
-               (p->verbose_p ? "" : progname),
-               (p->verbose_p ? "\n\tD" : ": d"));
+      if (p->verbose_p && unblank_screen_p)
+        /* Used to print this all the time, but really, nobody cares.
+           Now only print it when verbose. */
+       fprintf (stderr,
+                "%s disabling server builtin screensaver.\n"
+                "%s: you can re-enable it with \"xset s on\".\n",
+                blurb(), blurb());
 
       if (p->verbose_p)
 
       if (p->verbose_p)
-       fprintf (stderr, "%s: (xset s %d %d %s %s)\n", progname,
+       fprintf (stderr, "%s: (xset s %d %d; xset s %s; xset s %s)\n", blurb(),
                 desired_server_timeout, desired_server_interval,
                 (desired_prefer_blank ? "blank" : "noblank"),
                 desired_server_timeout, desired_server_interval,
                 (desired_prefer_blank ? "blank" : "noblank"),
-                (desired_allow_exp ? "noexpose" : "expose"));
+                (desired_allow_exp ? "expose" : "noexpose"));
 
       XSetScreenSaver (si->dpy,
                       desired_server_timeout, desired_server_interval,
 
       XSetScreenSaver (si->dpy,
                       desired_server_timeout, desired_server_interval,
@@ -237,16 +251,138 @@ disable_builtin_screensaver (saver_info *si, Bool turn_off_p)
       {
        extension_initted = True;
 # ifdef HAVE_MIT_SAVER_EXTENSION
       {
        extension_initted = True;
 # ifdef HAVE_MIT_SAVER_EXTENSION
-       if (p->use_mit_saver_extension) init_mit_saver_extension(si);
+       if (si->using_mit_saver_extension) init_mit_saver_extension(si);
 # endif
 # ifdef HAVE_SGI_SAVER_EXTENSION
 # endif
 # ifdef HAVE_SGI_SAVER_EXTENSION
-       if (p->use_sgi_saver_extension) init_sgi_saver_extension(si);
+       if (si->using_sgi_saver_extension) init_sgi_saver_extension(si);
 # endif
       }
   }
 #endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */
 
 # endif
       }
   }
 #endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */
 
-  if (turn_off_p)
+  if (unblank_screen_p)
     /* Turn off the server builtin saver if it is now running. */
     XForceScreenSaver (si->dpy, ScreenSaverReset);
 }
     /* Turn off the server builtin saver if it is now running. */
     XForceScreenSaver (si->dpy, ScreenSaverReset);
 }
+
+\f
+/* Display Power Management System (DPMS.)
+
+   On XFree86 systems, "man xset" reports:
+
+       -dpms    The -dpms option disables DPMS (Energy Star) features.
+       +dpms    The +dpms option enables DPMS (Energy Star) features.
+
+       dpms flags...
+                The dpms option allows the DPMS (Energy Star)
+                parameters to be set.  The option can take up to three
+                numerical values, or the `force' flag followed by a
+                DPMS state.  The `force' flags forces the server to
+                immediately switch to the DPMS state specified.  The
+                DPMS state can be one of `standby', `suspend', or
+                `off'.  When numerical values are given, they set the
+                inactivity period before the three modes are activated.
+                The first value given is for the `standby' mode, the
+                second is for the `suspend' mode, and the third is for
+                the `off' mode.  Setting these values implicitly
+                enables the DPMS features.  A value of zero disables a
+                particular mode.
+
+   However, note that the implementation is more than a little bogus,
+   in that there is code in /usr/X11R6/lib/libXdpms.a to implement all
+   the usual server-extension-querying utilities -- but there are no
+   prototypes in any header file!  Thus, the prototypes here.  (The
+   stuff in X11/extensions/dpms.h and X11/extensions/dpmsstr.h define
+   the raw X protcol, they don't define the API to libXdpms.a.)
+
+   Some documentation:
+   Library:  ftp://ftp.x.org/pub/R6.4/xc/doc/specs/Xext/DPMSLib.ms
+   Protocol: ftp://ftp.x.org/pub/R6.4/xc/doc/specs/Xext/DPMS.ms
+ */
+
+#ifdef HAVE_DPMS_EXTENSION
+
+#include <X11/Xproto.h>                        /* for CARD16 */
+#include <X11/extensions/dpms.h>
+#include <X11/extensions/dpmsstr.h>
+
+extern Bool DPMSQueryExtension (Display *dpy, int *event_ret, int *error_ret);
+extern Bool DPMSCapable (Display *dpy);
+extern Status DPMSForceLevel (Display *dpy, CARD16 level);
+extern Status DPMSInfo (Display *dpy, CARD16 *power_level, BOOL *state);
+
+#if 0 /* others we don't use */
+extern Status DPMSGetVersion (Display *dpy, int *major_ret, int *minor_ret);
+extern Status DPMSSetTimeouts (Display *dpy,
+                              CARD16 standby, CARD16 suspend, CARD16 off);
+extern Bool DPMSGetTimeouts (Display *dpy,
+                            CARD16 *standby, CARD16 *suspend, CARD16 *off);
+extern Status DPMSEnable (Display *dpy);
+extern Status DPMSDisable (Display *dpy);
+#endif /* 0 */
+
+
+Bool
+monitor_powered_on_p (saver_info *si)
+{
+  Bool result;
+  int event_number, error_number;
+  BOOL onoff = False;
+  CARD16 state;
+
+  if (!DPMSQueryExtension(si->dpy, &event_number, &error_number))
+    /* Server doesn't know -- assume the monitor is on. */
+    result = True;
+
+  else if (!DPMSCapable(si->dpy))
+    /* Server says the monitor doesn't do power management -- so it's on. */
+    result = True;
+
+  else
+    {
+      DPMSInfo(si->dpy, &state, &onoff);
+      if (!onoff)
+       /* Server says DPMS is disabled -- so the monitor is on. */
+       result = True;
+      else
+       switch (state) {
+       case DPMSModeOn:      result = True;  break;  /* really on */
+       case DPMSModeStandby: result = False; break;  /* kinda off */
+       case DPMSModeSuspend: result = False; break;  /* pretty off */
+       case DPMSModeOff:     result = False; break;  /* really off */
+       default:              result = True;  break;  /* protocol error? */
+       }
+    }
+
+  return result;
+}
+
+void
+monitor_power_on (saver_info *si)
+{
+  if (!monitor_powered_on_p (si))
+    {
+      DPMSForceLevel(si->dpy, DPMSModeOn);
+      XSync(si->dpy, False);
+      if (!monitor_powered_on_p (si))
+       fprintf (stderr,
+       "%s: DPMSForceLevel(dpy, DPMSModeOn) did not power the monitor on?\n",
+                blurb());
+    }
+}
+
+#else  /* !HAVE_DPMS_EXTENSION */
+
+Bool
+monitor_powered_on_p (saver_info *si) 
+{
+  return True; 
+}
+
+void
+monitor_power_on (saver_info *si)
+{
+  return; 
+}
+
+#endif /* !HAVE_DPMS_EXTENSION */