diff options
Diffstat (limited to 'core/modules/idleaction/xprintidle.c')
-rw-r--r-- | core/modules/idleaction/xprintidle.c | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/core/modules/idleaction/xprintidle.c b/core/modules/idleaction/xprintidle.c new file mode 100644 index 00000000..7fc62486 --- /dev/null +++ b/core/modules/idleaction/xprintidle.c @@ -0,0 +1,136 @@ +/* + +This program prints the "idle time" of the user to stdout. The "idle +time" is the number of milliseconds since input was received on any +input device. If unsuccessful, the program prints a message to stderr +and exits with a non-zero exit code. + +Copyright (c) 2005, 2008 Magnus Henoch <henoch@dtek.chalmers.se> +Copyright (c) 2006, 2007 by Danny Kukawka + <dkukawka@suse.de>, <danny.kukawka@web.de> +Copyright (c) 2008 Eivind Magnus Hvidevold <hvidevold@gmail.com> + +This program is free software; you can redistribute it and/or modify +it under the terms of version 2 of the GNU General Public License +as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the +Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +The function workaroundCreepyXServer was adapted from kpowersave-0.7.3 by +Eivind Magnus Hvidevold <hvidevold@gmail.com>. kpowersave is licensed under +the GNU GPL, version 2 _only_. + +*/ + +#include <X11/Xlib.h> +#include <X11/extensions/dpms.h> +#include <X11/extensions/scrnsaver.h> +#include <stdio.h> + +void usage(char *name); +unsigned long workaroundCreepyXServer(Display *dpy, unsigned long _idleTime ); + +int main(int argc, char *argv[]) +{ + XScreenSaverInfo ssi; + Display *dpy; + int event_basep, error_basep; + + if (argc != 1) { + usage(argv[0]); + return 1; + } + + dpy = XOpenDisplay(NULL); + if (dpy == NULL) { + fprintf(stderr, "couldn't open display\n"); + return 1; + } + + if (!XScreenSaverQueryExtension(dpy, &event_basep, &error_basep)) { + fprintf(stderr, "screen saver extension not supported\n"); + return 1; + } + + if (!XScreenSaverQueryInfo(dpy, DefaultRootWindow(dpy), &ssi)) { + fprintf(stderr, "couldn't query screen saver info\n"); + return 1; + } + + printf("%lu\n", workaroundCreepyXServer(dpy, ssi.idle)); + + XCloseDisplay(dpy); + return 0; +} + +void usage(char *name) +{ + fprintf(stderr, + "Usage:\n" + "%s\n" + "That is, no command line arguments. The user's idle time\n" + "in milliseconds is printed on stdout.\n", + name); +} + +/*! + * This function works around an XServer idleTime bug in the + * XScreenSaverExtension if dpms is running. In this case the current + * dpms-state time is always subtracted from the current idletime. + * This means: XScreenSaverInfo->idle is not the time since the last + * user activity, as descriped in the header file of the extension. + * This result in SUSE bug # and sf.net bug #. The bug in the XServer itself + * is reported at https://bugs.freedesktop.org/buglist.cgi?quicksearch=6439. + * + * Workaround: Check if if XServer is in a dpms state, check the + * current timeout for this state and add this value to + * the current idle time and return. + * + * \param _idleTime a unsigned long value with the current idletime from + * XScreenSaverInfo->idle + * \return a unsigned long with the corrected idletime + */ +unsigned long workaroundCreepyXServer(Display *dpy, unsigned long _idleTime ){ + int dummy; + CARD16 standby, suspend, off; + CARD16 state; + BOOL onoff; + + if (DPMSQueryExtension(dpy, &dummy, &dummy)) { + if (DPMSCapable(dpy)) { + DPMSGetTimeouts(dpy, &standby, &suspend, &off); + DPMSInfo(dpy, &state, &onoff); + + if (onoff) { + switch (state) { + case DPMSModeStandby: + /* this check is a littlebit paranoid, but be sure */ + if (_idleTime < (unsigned) (standby * 1000)) + _idleTime += (standby * 1000); + break; + case DPMSModeSuspend: + if (_idleTime < (unsigned) ((suspend + standby) * 1000)) + _idleTime += ((suspend + standby) * 1000); + break; + case DPMSModeOff: + if (_idleTime < (unsigned) ((off + suspend + standby) * 1000)) + _idleTime += ((off + suspend + standby) * 1000); + break; + case DPMSModeOn: + default: + break; + } + } + } + } + + return _idleTime; +} |