/* xset.c --- interacting with server extensions and the builtin screensaver.
- * xscreensaver, Copyright (c) 1991-2004 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
# 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)
{
}
#endif /* HAVE_MIT_SAVER_EXTENSION */
+\f
+#ifdef HAVE_XINPUT
+/* XInputExtension device support */
+
+Bool
+query_xinput_extension (saver_info *si)
+{
+ XExtCodes codes;
+ return XQueryExtension (si->dpy, INAME, &codes.major_opcode,
+ &codes.first_event, &codes.first_error);
+}
+
+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.
*/
# 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)
{
#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
-/* Resize and Rotate server extension hackery.
- */
-
-#ifdef HAVE_RANDR
-
-# include <X11/extensions/Xrandr.h>
-
-Bool
-query_randr_extension (saver_info *si)
-{
- saver_preferences *p = &si->prefs;
- Bool ok = XRRQueryExtension (si->dpy,
- &si->randr_event_number,
- &si->randr_error_number);
-
- if (ok)
- {
- int nscreens = ScreenCount (si->dpy); /* number of *real* screens */
- int i;
-
- if (p->verbose_p)
- fprintf (stderr, "%s: selecting RANDR events\n", blurb());
- for (i = 0; i < nscreens; i++)
-# ifdef RRScreenChangeNotifyMask /* randr.h 1.5, 2002/09/29 */
- XRRSelectInput (si->dpy, RootWindow (si->dpy, i),
- RRScreenChangeNotifyMask);
-# else /* !RRScreenChangeNotifyMask */ /* Xrandr.h 1.4, 2001/06/07 */
- XRRScreenChangeSelectInput (si->dpy, RootWindow (si->dpy, i), True);
-# endif /* !RRScreenChangeNotifyMask */
- }
-
- return ok;
-}
-
-#endif /* HAVE_RANDR */
-
\f
/* Figuring out what the appropriate XSetScreenSaver() parameters are
/* 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 */