diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-19 20:40:48 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-19 20:40:48 +0000 |
commit | be4fc77c294a41a0db46ba692fbe45b2045b66c3 (patch) | |
tree | 4e930029faf4f131514b080217ad080fd3a5acb8 /src/inactivity.cpp | |
download | tdepowersave-be4fc77c294a41a0db46ba692fbe45b2045b66c3.tar.gz tdepowersave-be4fc77c294a41a0db46ba692fbe45b2045b66c3.zip |
Added KDE3 version of kpowersave
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/kpowersave@1092957 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/inactivity.cpp')
-rw-r--r-- | src/inactivity.cpp | 368 |
1 files changed, 368 insertions, 0 deletions
diff --git a/src/inactivity.cpp b/src/inactivity.cpp new file mode 100644 index 0000000..e432fb7 --- /dev/null +++ b/src/inactivity.cpp @@ -0,0 +1,368 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Danny Kukawka * + * <[email protected]>, <[email protected]> * + * * + * 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. * + ***************************************************************************/ + +/*! \file inactivity.cpp + * \brief In this file can be found the inactivity related code. + * \author Danny Kukawka, <[email protected]>, <[email protected]> + * \date 2006-2007 + */ + +// own header +#include "inactivity.h" + +/* needed for lXext C library linkage */ +extern "C" { + #include <X11/Xproto.h> + #include <X11/extensions/dpms.h> + #include <X11/extensions/scrnsaver.h> +} + +// KDE Headers +#include <klocale.h> + +/*! The default constructor of the class autosuspend */ +inactivity::inactivity() { + kdDebugFuncIn(trace); + + proc = NULL; + + timeToInactivity = 0; + blacklisted_running_last = 0; + + pidof_call_failed = false; + pidof_call_started = false; + pidof_call_returned = false; + blacklisted_running = false; + + int dummy = 0; + has_XSC_Extension = XScreenSaverQueryExtension( qt_xdisplay(), &dummy, &dummy ); + + checkInactivity = new QTimer( this ); + connect( checkInactivity, SIGNAL(timeout()), this, SLOT(check())); + + kdDebugFuncOut(trace); +} + +/*! The default destructor of the class autosuspend */ +inactivity::~inactivity() { + kdDebugFuncIn(trace); + + delete proc; + proc = NULL; + + kdDebugFuncOut(trace); +} + +/*! + * This function start the monitoring of inactivity of user on the X-Server. + * Here wee set the time for the signal \ref inactivityTimeExpired() and start + * the needed QTimer. + * \param timeToExpire Integer value representing the time of inactivity which need + * to elapse befor send signal. The time is in seconds. + * \param blacked QStringList with blacklisted programs which if detected with + * pidof() as running prevent the autosuspend. + */ +void inactivity::start( int timeToExpire, QStringList blacked ) { + kdDebugFuncIn(trace); + + blacklist = blacked; + + if(timeToExpire > 0 && has_XSC_Extension){ + stop(); + timeToInactivity = (unsigned long) (timeToExpire * 1000); + checkInactivity->start(CHECK_for_INACTIVITY, true); + } + + kdDebugFuncOut(trace); +} + +/*! + * \b SLOT to call check as recheck inactivity if befor a running PID + * request was detected. + */ +void inactivity::recheck() { + kdDebugFuncIn(trace); + + check(true); + + kdDebugFuncOut(trace); +} + +/*! + * \b SLOT to call check without a recheck. + */ +void inactivity::check() { + check(false); +} + +/*! + * \b SLOT to check the current idle-time of the X-Server and if there + * are blacklisted programs are running. If the through \ref timeToInactivity + * defined time is expired, this function emit signal \ref inactivityTimeExpired() . + * \param recheck boolean which define if this is a recheck or not. + * \li true, if this is a recheck. In this case we didn't call + * \ref checkBlacklisted() again + * \li false, if this is normal check + */ +void inactivity::check( bool recheck ) { + kdDebugFuncIn(trace); + + if (timeToInactivity > 0) { + checkXInactivity(); + if (!pidof_call_started && !recheck) checkBlacklisted(); + + if( idleTime < blacklisted_running_last ) { + blacklisted_running_last = idleTime; + } + + if((idleTime - blacklisted_running_last ) >= timeToInactivity) { + if (!pidof_call_started) { + if (( pidof_call_returned && !blacklisted_running ) || + ( pidof_call_returned && pidof_call_failed )) { + emit inactivityTimeExpired(); + } + else { + checkInactivity->start(CHECK_for_INACTIVITY, true); + } + } + else { + //called if there is a getPIDs() is running + QTimer::singleShot(500, this, SLOT(recheck())); + } + } + else checkInactivity->start(CHECK_for_INACTIVITY, true); + } else { + kdWarning() << "timeToInactivity <= 0, stoped autosuspend checks!" << endl; + } + + kdDebugFuncOut(trace); +} + +/*! + * This function stop the monitoring and reset all variables and Timer. + */ +void inactivity::stop() { + kdDebugFuncIn(trace); + + if (checkInactivity->isActive()) checkInactivity->stop(); + timeToInactivity = 0; + idleTime = 0; + blacklisted_running_last = 0; + + pidof_call_failed = false; + pidof_call_started = false; + pidof_call_returned = false; + blacklisted_running = false; + + kdDebugFuncOut(trace); +} + +/*! + * This function query the idle-time of user-imput from the X-Server and set + * the return value to \ref idleTime. + */ +void inactivity::checkXInactivity(){ + kdDebugFuncIn(trace); + + idleTime = getXInactivity(); + kdDebug() << "autosuspend::checkXInactivity - idleTime: " << idleTime << endl; + + kdDebugFuncOut(trace); +} + +/*! + * This function query the idle-time of user-imput from the X-Server and + * return the current idle-time. + */ +unsigned long inactivity::getXInactivity(){ + kdDebugFuncIn(trace); + + if(has_XSC_Extension) { + static XScreenSaverInfo* mitInfo = 0; + if (!mitInfo) mitInfo = XScreenSaverAllocInfo (); + XScreenSaverQueryInfo (qt_xdisplay(), DefaultRootWindow (qt_xdisplay()), mitInfo); + kdDebugFuncOut(trace); + return workaroundCreepyXServer(mitInfo->idle); + } + else { + kdDebugFuncOut(trace); + return 0; + } + +} + +/*! + * This function workaround a fucking XServer idleTime bug in the + * XScreenSaverExtension, if dpms is running. In this case always the + * current dpms-state time is extracted from the current idletime. + * This mean: 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 # + * + * 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 ideletime fromm + * XScreenSaverInfo->idle + * \return a unsigned long with the corrected idletime + */ +unsigned long inactivity::workaroundCreepyXServer( unsigned long _idleTime ){ + kdDebugFuncOut(trace); + + int dummy; + CARD16 standby, suspend, off; + CARD16 state; + BOOL onoff; + + Display *dpy = qt_xdisplay(); + + kdDebug() << "Current idleTime: " << _idleTime << endl; + + if (DPMSQueryExtension(dpy, &dummy, &dummy)) { + if (DPMSCapable(dpy)) { + DPMSGetTimeouts(dpy, &standby, &suspend, &off); + DPMSInfo(dpy, &state, &onoff); + + if (onoff) { + switch (state) { + case DPMSModeStandby: + kdDebug() << "DPMS enabled. Monitor in Standby. Standby: " + << standby << " sec" << endl; + // this check is a littlebit paranoid, but be sure + if (_idleTime < (unsigned) (standby * 1000)) + _idleTime += (standby * 1000); + break; + case DPMSModeSuspend: + kdDebug() << "DPMS enabled. Monitor in Suspend. Suspend: " + << suspend << " sec" << endl; + if (_idleTime < (unsigned) ((suspend + standby) * 1000)) + _idleTime += ((suspend + standby) * 1000); + break; + case DPMSModeOff: + kdDebug() << "DPMS enabled. Monitor is Off. Off: " + << off << " sec" << endl; + if (_idleTime < (unsigned) ((off + suspend + standby) * 1000)) + _idleTime += ((off + suspend + standby) * 1000); + break; + case DPMSModeOn: + default: + break; + } + } + } + } + + kdDebug() << "Corrected idleTime: " << _idleTime << endl; + kdDebugFuncOut(trace); + return _idleTime; +} + +/*! + * This funtion starts the monitoring of blacklisted processes. + */ +void inactivity::checkBlacklisted(){ + kdDebugFuncIn(trace); + + if (proc != NULL) { + delete proc; + proc = NULL; + } + + proc = new KProcess; + *proc << "pidof" << blacklist; + + connect( proc, SIGNAL(receivedStdout(KProcess *, char *, int)),this, + SLOT(getPIDs(KProcess *, char *, int))); + connect( proc, SIGNAL(processExited(KProcess *)), + SLOT(getPIDsExited(KProcess *))); + + if (!proc->start(KProcess::NotifyOnExit, KProcess::AllOutput)) + { + emit displayErrorMsg(i18n("Could not start 'pidof'. " + "Could not autosuspend the machine.\n" + "Please check your installation.")); + } + + pidof_call_started = true; + pidof_call_returned = false; + pidof_call_failed = false; + + kdDebugFuncOut(trace); +} + + +/*! + * \b SLOT to get the return of the command pidof and parse this to set + * \ref blacklisted_running . + * \param *proc pointer to the sending KProcess + * \param *buffer the char pointer to the output of the process to stdout + * \param *lenght the length of the buffer + */ +void inactivity::getPIDs(KProcess */*proc*/, char *buffer, int /*lenght*/) { + kdDebugFuncIn(trace); + + QString pids(buffer); + pids.remove(" "); + if(pids.isEmpty() || pids == "\n" ) { + kdDebug() << "NO! BLACKLISTED IS RUNNING" << endl; + blacklisted_running = false; + } + else { + if (pids.contains(QRegExp::QRegExp("[0-9]"))) { + kdDebug() << "BLACKLISTED IS RUNNING" << endl; + blacklisted_running = true; + blacklisted_running_last = idleTime; + } + else { + kdError() << "GET BLACKLISTED FAILED - WRONG RETURN" << endl; + blacklisted_running = false; + pidof_call_failed = true; + } + } + + kdDebugFuncOut(trace); +} + + +/*! + * \b SLOT which called if the call of pidof is exited + * \param proc the KPocess which called this SLOT + */ +void inactivity::getPIDsExited(KProcess *proc){ + kdDebugFuncIn(trace); + + pidof_call_returned = true; + pidof_call_started = false; + + + if (proc->normalExit()){ + // if returned some pids or if pid returned nothing + if (proc->exitStatus() == 1 || proc->exitStatus() == 0){ + pidof_call_failed = false; + kdDebugFuncOut(trace); + return; + } + } + // if something crashed/failed + pidof_call_failed = true; + kdDebugFuncOut(trace); +} + +#include "inactivity.moc" |