http://www.jwz.org/xscreensaver/xscreensaver-5.12.tar.gz
[xscreensaver] / driver / xset.c
index f2afcee755011f33289f5bb6f9b62d7f5ac53af4..46607977ada484781ecd9b82b74bb471bb309fd1 100644 (file)
@@ -1,5 +1,5 @@
 /* xset.c --- interacting with server extensions and the builtin screensaver.
- * xscreensaver, Copyright (c) 1991-2002 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1991-2008 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
@@ -42,14 +42,6 @@ ERROR!  You must not include vroot.h in this file.
 
 # include <X11/extensions/scrnsaver.h>
 
-Bool
-query_mit_saver_extension (saver_info *si)
-{
-  return XScreenSaverQueryExtension (si->dpy,
-                                    &si->mit_saver_ext_event_number,
-                                    &si->mit_saver_ext_error_number);
-}
-
 static int
 ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error)
 {
@@ -93,6 +85,180 @@ init_mit_saver_extension (saver_info *si)
 }
 #endif /* HAVE_MIT_SAVER_EXTENSION */
 
+\f
+#ifdef HAVE_XINPUT
+/* XInputExtension device support */
+#include <X11/extensions/XInput.h>
+
+struct xinput_dev_info {
+  XDevice      *device;
+  XEventClass  press, release, valuator;
+};
+
+Bool
+query_xinput_extension (saver_info *si)
+{
+  XExtCodes codes;
+
+  if (!XQueryExtension (si->dpy, INAME, &codes.major_opcode,
+                       &codes.first_event, &codes.first_error))
+    {
+      if (si->prefs.verbose_p)
+       fprintf (stderr, "\t XInputExtension is not present!\n");
+      return False;
+    }
+  else
+    {
+      if (si->prefs.verbose_p)
+       fprintf (stderr, "\t XInputExtension is present!\n");
+      return True;
+    }
+}
+
+void
+init_xinput_extension (saver_info *si)
+{
+  int i, ndevices;
+  int class;
+  XDeviceInfo *list;
+  XDevice *dev;
+  XAnyClassPtr pClass;
+  XEventClass *event_list;
+  int nevents = 0;
+
+  /* skip if already initialized */
+  if (si->num_xinput_devices && si->xinput_devices)
+    return;
+
+  si->num_xinput_devices = 0;
+
+  list = XListInputDevices (si->dpy, &ndevices);
+  if (list == NULL)
+    {
+      si->xinput_devices = NULL;
+      return;
+    }
+
+  /* We only care about 3 event types per device (DeviceButtonPress,
+     DeviceButtonRelease, and DeviceMotionNotify), hence the "* 3"
+     for the event count. */
+  event_list = calloc(ndevices * 3, sizeof(XEventClass));
+  if (event_list == NULL)
+    return;
+
+  si->xinput_devices = calloc(ndevices, sizeof(struct xinput_dev_info));
+  if (si->xinput_devices == NULL)
+    {
+      free(event_list);
+      return;
+    }
+
+  for (i = 0; i < ndevices; i++)
+    {
+      if ((list[i].use == IsXExtensionDevice)
+#ifdef IsXExtensionPointer
+          || (list[i].use == IsXExtensionPointer)
+#endif
+         )
+        {
+          struct xinput_dev_info *dev_info =
+            &si->xinput_devices[si->num_xinput_devices];
+          Bool device_we_want = False;
+
+          if (si->prefs.debug_p)
+            fprintf(stderr,
+                    "Extension device #%2d: XID=%2d  type=%3d  name=\"%s\"\n",
+                    i, (int) list[i].id, (int) list[i].type, list[i].name);
+
+          dev = XOpenDevice (si->dpy, list[i].id);
+          if (!dev)
+            continue;
+          dev_info->device = dev;
+
+          pClass = list[i].inputclassinfo;
+          for (class = 0; class < list[i].num_classes; class++)
+            {
+              switch (pClass->class)
+                {
+                case ButtonClass:
+                  if (((XButtonInfo *) pClass)->num_buttons > 0)
+                    {
+                      /* Macros set values in the second & third arguments */
+                      DeviceButtonPress (dev, si->xinput_DeviceButtonPress,
+                                         dev_info->press);
+                      event_list[nevents++] = dev_info->press;
+
+                      DeviceButtonRelease (dev, si->xinput_DeviceButtonRelease,
+                                           dev_info->release);
+                      event_list[nevents++] = dev_info->release;
+                      device_we_want = True;
+                    }
+                  break;
+
+                case ValuatorClass:
+                  if (((XValuatorInfo *) pClass)->num_axes > 0)
+                    {
+                      DeviceMotionNotify (dev, si->xinput_DeviceMotionNotify,
+                                          dev_info->valuator);
+                      event_list[nevents++] = dev_info->valuator;
+                      device_we_want = True;
+                    }
+                  break;
+
+                default:
+                  /* ignore other classes of devices/events */
+                  break;
+                }
+
+              pClass = (XAnyClassPtr) & ((char *) pClass)[pClass->length];
+            }
+
+          if (device_we_want)
+            si->num_xinput_devices++;
+          else
+            XCloseDevice (si->dpy, dev);
+        }
+    }
+
+  if (list)
+    XFreeDeviceList (list);
+
+  if ((nevents == 0) || (si->num_xinput_devices == 0))
+    {
+      free(event_list);
+      free(si->xinput_devices);
+      si->xinput_devices = NULL;
+      si->num_xinput_devices = 0;
+      return;
+    }
+
+  for (i = 0; i < si->nscreens; i++)
+    {
+      saver_screen_info *ssi = &si->screens[i];
+      Window root = RootWindowOfScreen (ssi->screen);
+      XSelectExtensionEvent (si->dpy, root, event_list, nevents);
+    }
+
+  free(event_list);
+}
+
+#if 0
+/* not used */
+static void
+close_xinput_extension (saver_info *si)
+{
+  int i;
+
+  for (i = 0; i < si->num_xinput_devices; i++)
+    XCloseDevice (si->dpy, si->xinput_devices[i].device);
+
+  free(si->xinput_devices);
+  si->xinput_devices = NULL;
+  si->num_xinput_devices = 0;
+}
+#endif
+#endif /* HAVE_XINPUT */
+
 \f
 /* SGI SCREEN_SAVER server extension hackery.
  */
@@ -101,14 +267,6 @@ init_mit_saver_extension (saver_info *si)
 
 # include <X11/extensions/XScreenSaver.h>
 
-Bool
-query_sgi_saver_extension (saver_info *si)
-{
-  return XScreenSaverQueryExtension (si->dpy,
-                                    &si->sgi_saver_ext_event_number,
-                                    &si->sgi_saver_ext_error_number);
-}
-
 static void
 init_sgi_saver_extension (saver_info *si)
 {
@@ -137,24 +295,6 @@ init_sgi_saver_extension (saver_info *si)
 
 #endif /* HAVE_SGI_SAVER_EXTENSION */
 
-\f
-/* 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
@@ -193,7 +333,7 @@ disable_builtin_screensaver (saver_info *si, Bool unblank_screen_p)
 
   /* I suspect (but am not sure) that DontAllowExposures might have
      something to do with powering off the monitor as well, at least
-     on some systems that don't support XDPMS?  Who know... */
+     on some systems that don't support XDPMS?  Who knows... */
   desired_allow_exp = AllowExposures;
 
   if (si->using_mit_saver_extension || si->using_sgi_saver_extension)
@@ -218,6 +358,12 @@ disable_builtin_screensaver (saver_info *si, Bool unblank_screen_p)
       desired_server_timeout = 0;
     }
 
+  /* XSetScreenSaver() generates BadValue if either timeout parameter
+     exceeds 15 bits (signed short.)  That is 09:06:07.
+   */
+  if (desired_server_timeout  > 0x7FFF) desired_server_timeout  = 0x7FFF;
+  if (desired_server_interval > 0x7FFF) desired_server_interval = 0x7FFF;
+
   if (desired_server_timeout != current_server_timeout ||
       desired_server_interval != current_server_interval ||
       desired_prefer_blank != current_prefer_blank ||
@@ -259,125 +405,3 @@ disable_builtin_screensaver (saver_info *si, Bool 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 */