summaryrefslogtreecommitdiffstats
path: root/kdesktop/xautolock.cc
diff options
context:
space:
mode:
Diffstat (limited to 'kdesktop/xautolock.cc')
-rw-r--r--kdesktop/xautolock.cc289
1 files changed, 289 insertions, 0 deletions
diff --git a/kdesktop/xautolock.cc b/kdesktop/xautolock.cc
new file mode 100644
index 000000000..d8f4bbfbe
--- /dev/null
+++ b/kdesktop/xautolock.cc
@@ -0,0 +1,289 @@
+//----------------------------------------------------------------------------
+//
+// This file is part of the KDE project
+//
+// Copyright (c) 1999 Martin R. Jones <mjones@kde.org>
+// Copyright (c) 2003 Lubos Lunak <l.lunak@kde.org>
+//
+// KDE screensaver engine
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "xautolock.h"
+#include "xautolock.moc"
+
+#include <kapplication.h>
+#include <kdebug.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <ctime>
+#include "xautolock_c.h"
+
+#ifdef HAVE_DPMS
+extern "C" {
+#include <X11/Xmd.h>
+#ifndef Bool
+#define Bool BOOL
+#endif
+#include <X11/extensions/dpms.h>
+
+#ifndef HAVE_DPMSINFO_PROTO
+Status DPMSInfo ( Display *, CARD16 *, BOOL * );
+#endif
+}
+#endif
+
+int xautolock_useXidle = 0;
+int xautolock_useMit = 0;
+xautolock_corner_t xautolock_corners[ 4 ];
+
+static XAutoLock* self = NULL;
+
+extern "C" {
+static int catchFalseAlarms(Display *, XErrorEvent *)
+{
+ return 0;
+}
+}
+
+//===========================================================================
+//
+// Detect user inactivity.
+// Named XAutoLock after the program that it is based on.
+//
+XAutoLock::XAutoLock()
+{
+ self = this;
+ xautolock_useXidle = 0;
+ xautolock_useMit = 0;
+#ifdef HAVE_XIDLE
+ int dummy1;
+ xautolock_useXidle = XidleQueryExtension( qt_xdisplay(), &dummy1, &dummy1 );
+#endif
+#ifdef HAVE_XSCREENSAVER
+ int dummy2;
+ if( !xautolock_useXidle )
+ xautolock_useMit = XScreenSaverQueryExtension( qt_xdisplay(), &dummy2, &dummy2 );
+#endif
+ if( !xautolock_useXidle && !xautolock_useMit )
+ {
+ kapp->installX11EventFilter( this );
+ int (*oldHandler)(Display *, XErrorEvent *);
+ oldHandler = XSetErrorHandler(catchFalseAlarms);
+ XSync(qt_xdisplay(), False );
+ xautolock_initDiy( qt_xdisplay());
+ XSync(qt_xdisplay(), False );
+ XSetErrorHandler(oldHandler);
+ }
+
+ mTimeout = DEFAULT_TIMEOUT;
+ mDPMS = true;
+ resetTrigger();
+
+ time(&mLastTimeout);
+ mActive = false;
+
+ mTimerId = startTimer( CHECK_INTERVAL );
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Destructor.
+//
+XAutoLock::~XAutoLock()
+{
+ self = NULL;
+}
+
+//---------------------------------------------------------------------------
+//
+// The time in seconds of continuous inactivity.
+//
+void XAutoLock::setTimeout(int t)
+{
+ mTimeout = t;
+ resetTrigger();
+}
+
+void XAutoLock::setDPMS(bool s)
+{
+#ifdef HAVE_DPMS
+ BOOL on;
+ CARD16 state;
+ DPMSInfo( qt_xdisplay(), &state, &on );
+ if (!on)
+ s = false;
+#endif
+ mDPMS = s;
+}
+
+//---------------------------------------------------------------------------
+//
+// Start watching Activity
+//
+void XAutoLock::start()
+{
+ resetTrigger();
+ time(&mLastTimeout);
+ mActive = true;
+}
+
+//---------------------------------------------------------------------------
+//
+// Stop watching Activity
+//
+void XAutoLock::stop()
+{
+ mActive = false;
+}
+
+//---------------------------------------------------------------------------
+//
+// Reset the trigger time.
+//
+void XAutoLock::resetTrigger()
+{
+ mTrigger = time(0) + mTimeout;
+}
+
+//---------------------------------------------------------------------------
+//
+// Move the trigger time in order to postpone (repeat) emitting of timeout().
+//
+void XAutoLock::postpone()
+{
+ mTrigger = time(0) + 60; // delay by 60sec
+}
+
+//---------------------------------------------------------------------------
+//
+// Set the remaining time to 't', if it's shorter than already set.
+//
+void XAutoLock::setTrigger( time_t t )
+{
+ if( t < mTrigger )
+ mTrigger = t;
+}
+
+//---------------------------------------------------------------------------
+//
+// Process new windows and check the mouse.
+//
+void XAutoLock::timerEvent(QTimerEvent *ev)
+{
+ if (ev->timerId() != mTimerId)
+ {
+ return;
+ }
+
+ int (*oldHandler)(Display *, XErrorEvent *) = NULL;
+ if( !xautolock_useXidle && !xautolock_useMit )
+ { // only the diy way needs special X handler
+ XSync( qt_xdisplay(), False );
+ oldHandler = XSetErrorHandler(catchFalseAlarms);
+ }
+
+ xautolock_processQueue();
+
+ time_t now = time(0);
+ if ((now > mLastTimeout && now - mLastTimeout > TIME_CHANGE_LIMIT) ||
+ (mLastTimeout > now && mLastTimeout - now > TIME_CHANGE_LIMIT+1))
+ {
+ /* the time has changed in one large jump. This could be because
+ the date was changed, or the machine was suspended. We'll just
+ reset the triger. */
+ resetTrigger();
+ }
+
+ mLastTimeout = now;
+
+ xautolock_queryIdleTime( qt_xdisplay());
+ xautolock_queryPointer( qt_xdisplay());
+
+ if( !xautolock_useXidle && !xautolock_useMit )
+ XSetErrorHandler(oldHandler);
+
+ bool activate = false;
+
+ //kdDebug() << now << " " << mTrigger << endl;
+ if (now >= mTrigger)
+ {
+ resetTrigger();
+ activate = true;
+ }
+
+#ifdef HAVE_DPMS
+ BOOL on;
+ CARD16 state;
+ DPMSInfo( qt_xdisplay(), &state, &on );
+
+ //kdDebug() << "DPMSInfo " << state << " " << on << endl;
+ // If DPMS is active, it makes XScreenSaverQueryInfo() report idle time
+ // that is always smaller than DPMS timeout (X bug I guess). So if DPMS
+ // saving is active, simply always activate our saving too, otherwise
+ // this could prevent locking from working.
+ if(state == DPMSModeStandby || state == DPMSModeSuspend || state == DPMSModeOff)
+ activate = true;
+ if(!on && mDPMS) {
+ activate = false;
+#ifdef HAVE_XSCREENSAVER
+ XForceScreenSaver(qt_xdisplay(), ScreenSaverReset );
+#endif
+ resetTrigger();
+ }
+#endif
+
+#ifdef HAVE_XSCREENSAVER
+ static XScreenSaverInfo* mitInfo = 0;
+ if (!mitInfo) mitInfo = XScreenSaverAllocInfo ();
+ if (XScreenSaverQueryInfo (qt_xdisplay(), DefaultRootWindow (qt_xdisplay()), mitInfo)) {
+ //kdDebug() << "XScreenSaverQueryInfo " << mitInfo->state << " " << ScreenSaverDisabled << endl;
+ if (mitInfo->state == ScreenSaverDisabled)
+ activate = false;
+ }
+#endif
+
+ if(mActive && activate)
+ emit timeout();
+}
+
+bool XAutoLock::x11Event( XEvent* ev )
+{
+ xautolock_processEvent( ev );
+// don't futher process key events that were received only because XAutoLock wants them
+ if( ev->type == KeyPress && !ev->xkey.send_event
+ && !xautolock_useXidle && !xautolock_useMit
+ && !QWidget::find( ev->xkey.window ))
+ return true;
+ return false;
+}
+
+bool XAutoLock::ignoreWindow( WId w )
+{
+ if( w != qt_xrootwin() && QWidget::find( w ))
+ return true;
+ return false;
+}
+
+extern "C"
+void xautolock_resetTriggers()
+{
+ self->resetTrigger();
+}
+
+extern "C"
+void xautolock_setTrigger( time_t t )
+{
+ self->setTrigger( t );
+}
+
+extern "C"
+int xautolock_ignoreWindow( Window w )
+{
+ return self->ignoreWindow( w );
+}