http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.02.tar.gz
[xscreensaver] / driver / xset.c
index c4fb6d6b150ca90ce05cf774d671e2fec05b35cd..f2afcee755011f33289f5bb6f9b62d7f5ac53af4 100644 (file)
@@ -1,5 +1,5 @@
 /* xset.c --- interacting with server extensions and the builtin screensaver.
- * xscreensaver, Copyright (c) 1991-1997 Jamie Zawinski <jwz@netscape.com>
+ * xscreensaver, Copyright (c) 1991-2002 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
 
 #include "xscreensaver.h"
 
+#ifdef _VROOT_H_
+ERROR!  You must not include vroot.h in this file.
+#endif
+
 \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",
-                  progname);
-         p->use_sgi_saver_extension = False;
+                  blurb());
+         si->using_sgi_saver_extension = False;
          return;
        }
     }
@@ -134,12 +138,31 @@ init_sgi_saver_extension (saver_info *si)
 #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
-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;
@@ -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.
-     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.
 
-     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
-     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;
 
-#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. */
-      if (p->use_sgi_saver_extension)
+      if (si->using_sgi_saver_extension)
        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;
     }
 
@@ -211,17 +223,14 @@ disable_builtin_screensaver (saver_info *si, Bool turn_off_p)
       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)
-       fprintf (stderr, "%s: (xset s %d %d %s %s)\n", progname,
+       fprintf (stderr,
+                 "%s: disabling server builtin screensaver:\n"
+                 "%s:  (xset s %d %d; xset s %s; xset s %s)\n",
+                 blurb(), blurb(),
                 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,
@@ -237,16 +246,138 @@ disable_builtin_screensaver (saver_info *si, Bool turn_off_p)
       {
        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
-       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 */
 
-  if (turn_off_p)
+  if (unblank_screen_p)
     /* 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 */