Merge branch 'central-widget'
[krunner.git] / xautolock.cpp
blob8790bf5f2b335bdc938b63995c1748405e98aa9e
1 //----------------------------------------------------------------------------
2 //
3 // This file is part of the KDE project
4 //
5 // Copyright (c) 1999 Martin R. Jones <mjones@kde.org>
6 // Copyright (c) 2003 Lubos Lunak <l.lunak@kde.org>
7 //
8 // KDE screensaver engine
9 //
11 #include <config-workspace.h>
12 #include <config-xautolock.h>
13 #include "xautolock.h"
14 #include "xautolock.moc"
16 #include <X11/Xlib.h>
17 #include <X11/Xutil.h>
18 #include <ctime>
19 #include "xautolock_c.h"
21 #include <kapplication.h>
23 #include <QTimerEvent>
24 #include <QX11Info>
26 #ifdef HAVE_DPMS
27 extern "C" {
28 #include <X11/Xmd.h>
29 #ifndef Bool
30 #define Bool BOOL
31 #endif
32 #include <X11/extensions/dpms.h>
34 #ifndef HAVE_DPMSINFO_PROTO
35 Status DPMSInfo ( Display *, CARD16 *, BOOL * );
36 #endif
38 #endif
40 int xautolock_useXidle = 0;
41 int xautolock_useMit = 0;
42 xautolock_corner_t xautolock_corners[ 4 ];
44 static XAutoLock* self = NULL;
46 static int catchFalseAlarms(Display *, XErrorEvent *)
48 return 0;
51 //===========================================================================
53 // Detect user inactivity.
54 // Named XAutoLock after the program that it is based on.
56 XAutoLock::XAutoLock()
58 self = this;
59 int dummy = 0;
60 dummy = dummy; // shut up
61 xautolock_useXidle = 0;
62 xautolock_useMit = 0;
63 #ifdef HAVE_XIDLE
64 useXidle = XidleQueryExtension( QX11Info::display(), &dummy, &dummy );
65 #endif
66 #ifdef HAVE_SCREENSAVER
67 if( !xautolock_useXidle )
68 xautolock_useMit = XScreenSaverQueryExtension( QX11Info::display(), &dummy, &dummy );
69 #endif
70 if( !xautolock_useXidle && !xautolock_useMit )
72 kapp->installX11EventFilter( this );
73 int (*oldHandler)(Display *, XErrorEvent *);
74 oldHandler = XSetErrorHandler(catchFalseAlarms);
75 XSync(QX11Info::display(), False );
76 xautolock_initDiy( QX11Info::display());
77 XSync(QX11Info::display(), False );
78 XSetErrorHandler(oldHandler);
81 mTimeout = DEFAULT_TIMEOUT;
82 mDPMS = true;
83 resetTrigger();
85 time(&mLastTimeout);
86 mActive = false;
88 mTimerId = startTimer( CHECK_INTERVAL );
92 //---------------------------------------------------------------------------
94 // Destructor.
96 XAutoLock::~XAutoLock()
98 self = NULL;
101 //---------------------------------------------------------------------------
103 // The time in seconds of continuous inactivity.
105 void XAutoLock::setTimeout(int t)
107 mTimeout = t;
108 resetTrigger();
111 void XAutoLock::setDPMS(bool s)
113 mDPMS = s;
116 //---------------------------------------------------------------------------
118 // Start watching Activity
120 void XAutoLock::start()
122 resetTrigger();
123 time(&mLastTimeout);
124 mActive = true;
127 //---------------------------------------------------------------------------
129 // Stop watching Activity
131 void XAutoLock::stop()
133 mActive = false;
136 //---------------------------------------------------------------------------
138 // Reset the trigger time.
140 void XAutoLock::resetTrigger()
142 mLastReset = time( 0 );
143 mTrigger = mLastReset + mTimeout;
146 //---------------------------------------------------------------------------
148 // Move the trigger time in order to postpone (repeat) emitting of timeout().
150 void XAutoLock::postpone()
152 mTrigger = time(0) + 60; // delay by 60sec
155 //---------------------------------------------------------------------------
157 // Set the remaining time to 't', if it's shorter than already set.
159 void XAutoLock::setTrigger( time_t t )
161 if( t < mTrigger )
162 mTrigger = t;
165 //---------------------------------------------------------------------------
167 // Process new windows and check the mouse.
169 void XAutoLock::timerEvent(QTimerEvent *ev)
171 if (ev->timerId() != mTimerId)
173 return;
176 int (*oldHandler)(Display *, XErrorEvent *) = NULL;
177 if( !xautolock_useXidle && !xautolock_useMit )
178 { // only the diy way needs special X handler
179 XSync( QX11Info::display(), False );
180 oldHandler = XSetErrorHandler(catchFalseAlarms);
183 xautolock_processQueue();
185 time_t now = time(0);
186 if ((now > mLastTimeout && now - mLastTimeout > TIME_CHANGE_LIMIT) ||
187 (mLastTimeout > now && mLastTimeout - now > TIME_CHANGE_LIMIT+1))
189 /* the time has changed in one large jump. This could be because
190 the date was changed, or the machine was suspended. We'll just
191 reset the triger. */
192 resetTrigger();
195 mLastTimeout = now;
197 xautolock_queryIdleTime( QX11Info::display());
198 xautolock_queryPointer( QX11Info::display());
200 if( !xautolock_useXidle && !xautolock_useMit )
201 XSetErrorHandler(oldHandler);
203 bool activate = false;
205 // kDebug() << now << " " << mTrigger << endl;
206 if (now >= mTrigger)
208 resetTrigger();
209 activate = true;
212 #ifdef HAVE_DPMS
213 BOOL on;
214 CARD16 state;
215 DPMSInfo( QX11Info::display(), &state, &on );
217 // kDebug() << "DPMSInfo " << state << " " << on << endl;
218 // If DPMS is active, it makes XScreenSaverQueryInfo() report idle time
219 // that is always smaller than DPMS timeout (X bug I guess). So if DPMS
220 // saving is active, simply always activate our saving too, otherwise
221 // this could prevent locking from working.
222 if(state == DPMSModeStandby || state == DPMSModeSuspend || state == DPMSModeOff)
223 activate = true;
224 if(!on && mDPMS) {
225 activate = false;
226 resetTrigger();
228 #endif
230 #ifdef HAVE_SCREENSAVER
231 static XScreenSaverInfo* mitInfo = 0;
232 if (!mitInfo) mitInfo = XScreenSaverAllocInfo ();
233 if (XScreenSaverQueryInfo (QX11Info::display(), QX11Info::appRootWindow(), mitInfo)) {
234 // kDebug() << "XScreenSaverQueryInfo " << mitInfo->state << " " << ScreenSaverDisabled << endl;
235 if (mitInfo->state == ScreenSaverDisabled)
236 activate = false;
238 #endif
240 if(mActive && activate)
241 emit timeout();
244 bool XAutoLock::x11Event( XEvent* ev )
246 xautolock_processEvent( ev );
247 // don't futher process key events that were received only because XAutoLock wants them
248 if( ev->type == KeyPress && !ev->xkey.send_event
249 && !xautolock_useXidle && !xautolock_useMit
250 && !QWidget::find( ev->xkey.window ))
251 return true;
252 return false;
255 bool XAutoLock::ignoreWindow( WId w )
257 if( w != QX11Info::appRootWindow() && QWidget::find( w ))
258 return true;
259 return false;
262 time_t XAutoLock::idleTime()
264 return time( 0 ) - mLastReset;
267 extern "C"
268 void xautolock_resetTriggers()
270 self->resetTrigger();
273 extern "C"
274 void xautolock_setTrigger( time_t t )
276 self->setTrigger( t );
279 extern "C"
280 int xautolock_ignoreWindow( Window w )
282 return self->ignoreWindow( w );