not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / krunner / screensaver / xautolock.cpp
blob097cc31a1a36db7f522309b9035861fd055dde2f
1 //----------------------------------------------------------------------------
2 //
3 // This file is part of the KDE project
4 //
5 // Copyright 1999 Martin R. Jones <mjones@kde.org>
6 // Copyright 2003 Lubos Lunak <l.lunak@kde.org>
7 //
8 // KDE screensaver engine
9 //
11 #include <config-workspace.h>
13 #include "xautolock.h"
14 #include "xautolock_c.h"
16 #include <kapplication.h>
17 #include <kdebug.h>
19 #include <QTimerEvent>
20 #include <QX11Info>
22 #include <X11/Xlib.h>
23 #include <X11/Xutil.h>
25 #ifdef HAVE_DPMS
26 extern "C" {
27 #include <X11/Xmd.h>
28 #ifndef Bool
29 #define Bool BOOL
30 #endif
31 #include <X11/extensions/dpms.h>
33 #ifndef HAVE_DPMSINFO_PROTO
34 Status DPMSInfo ( Display *, CARD16 *, BOOL * );
35 #endif
37 #endif
39 #include <ctime>
41 xautolock_corner_t xautolock_corners[ 4 ];
43 static XAutoLock* self = NULL;
45 extern "C" {
46 static int catchFalseAlarms(Display *, XErrorEvent *)
48 return 0;
52 //===========================================================================
54 // Detect user inactivity.
55 // Named XAutoLock after the program that it is based on.
57 XAutoLock::XAutoLock()
59 self = this;
60 #ifdef HAVE_XSCREENSAVER
61 mMitInfo = 0;
62 int dummy;
63 if (XScreenSaverQueryExtension( QX11Info::display(), &dummy, &dummy ))
65 mMitInfo = XScreenSaverAllocInfo();
67 else
68 #endif
70 kapp->installX11EventFilter( this );
71 int (*oldHandler)(Display *, XErrorEvent *);
72 oldHandler = XSetErrorHandler(catchFalseAlarms);
73 XSync(QX11Info::display(), False );
74 xautolock_initDiy( QX11Info::display());
75 XSync(QX11Info::display(), False );
76 XSetErrorHandler(oldHandler);
79 mTimeout = DEFAULT_TIMEOUT;
80 mDPMS = true;
81 resetTrigger();
83 mActive = false;
85 mTimerId = startTimer( CHECK_INTERVAL );
86 mElapsed = 0;
90 //---------------------------------------------------------------------------
92 // Destructor.
94 XAutoLock::~XAutoLock()
96 stop();
97 self = NULL;
100 //---------------------------------------------------------------------------
102 // The time in seconds of continuous inactivity.
104 void XAutoLock::setTimeout(int t)
106 mTimeout = t;
109 void XAutoLock::setDPMS(bool s)
111 #ifdef HAVE_DPMS
112 BOOL on;
113 CARD16 state;
114 DPMSInfo( QX11Info::display(), &state, &on );
115 if (!on)
116 s = false;
117 #endif
118 mDPMS = s;
121 //---------------------------------------------------------------------------
123 // Start watching Activity
125 void XAutoLock::start()
127 mActive = true;
128 resetTrigger();
129 XSetScreenSaver(QX11Info::display(), mTimeout + 10, 100, PreferBlanking, DontAllowExposures); // We'll handle blanking
130 kDebug() << "XSetScreenSaver" << mTimeout + 10;
133 //---------------------------------------------------------------------------
135 // Stop watching Activity
137 void XAutoLock::stop()
139 mActive = false;
140 resetTrigger();
141 XSetScreenSaver(QX11Info::display(), 0, 100, PreferBlanking, DontAllowExposures); // No blanking at all
142 kDebug() << "XSetScreenSaver 0";
145 //---------------------------------------------------------------------------
147 // Reset the trigger time.
149 void XAutoLock::resetTrigger()
151 mLastReset = mElapsed;
152 mTrigger = mElapsed + mTimeout;
153 #ifdef HAVE_XSCREENSAVER
154 mLastIdle = 0;
155 #endif
156 XForceScreenSaver( QX11Info::display(), ScreenSaverReset );
159 //---------------------------------------------------------------------------
161 // Move the trigger time in order to postpone (repeat) emitting of timeout().
163 void XAutoLock::postpone()
165 mTrigger = mElapsed + 60; // delay by 60sec
168 //---------------------------------------------------------------------------
170 // Set the remaining time to 't', if it's shorter than already set.
172 void XAutoLock::setTrigger( int t )
174 time_t newT = mElapsed + qMax(t, 0);
175 if (mTrigger > newT)
176 mTrigger = newT;
179 //---------------------------------------------------------------------------
181 // Process new windows and check the mouse.
183 void XAutoLock::timerEvent(QTimerEvent *ev)
185 if (ev->timerId() != mTimerId)
187 return;
189 mElapsed += CHECK_INTERVAL / 1000;
191 #ifdef HAVE_XSCREENSAVER
192 if (!mMitInfo)
193 #endif
194 { // only the diy way needs special X handler
195 XSync( QX11Info::display(), False );
196 int (*oldHandler)(Display *, XErrorEvent *) =
197 XSetErrorHandler(catchFalseAlarms);
199 xautolock_processQueue();
201 XSetErrorHandler(oldHandler);
204 #ifdef HAVE_XSCREENSAVER
205 if (mMitInfo)
207 Display *d = QX11Info::display();
208 XScreenSaverQueryInfo(d, DefaultRootWindow(d), mMitInfo);
209 if (mLastIdle < mMitInfo->idle)
210 mLastIdle = mMitInfo->idle;
211 else
212 resetTrigger();
214 #endif /* HAVE_XSCREENSAVER */
216 // This needs to be after the above check, so it overrides it.
217 xautolock_queryPointer( QX11Info::display());
219 bool activate = false;
221 // kDebug() << now << mTrigger;
222 if (mElapsed >= mTrigger)
224 resetTrigger();
225 activate = true;
228 #ifdef HAVE_DPMS
229 BOOL on;
230 CARD16 state;
231 DPMSInfo( QX11Info::display(), &state, &on );
233 // kDebug() << "DPMSInfo " << state << on;
234 // If DPMS is active, it makes XScreenSaverQueryInfo() report idle time
235 // that is always smaller than DPMS timeout (X bug I guess). So if DPMS
236 // saving is active, simply always activate our saving too, otherwise
237 // this could prevent locking from working.
238 if(state == DPMSModeStandby || state == DPMSModeSuspend || state == DPMSModeOff)
239 activate = true;
240 if(!on && mDPMS) {
241 activate = false;
242 resetTrigger();
244 #endif
246 #ifdef HAVE_XSCREENSAVER
247 if (mMitInfo && mMitInfo->state == ScreenSaverDisabled)
248 activate = false;
249 #endif
251 if(mActive && activate)
252 emit timeout();
255 bool XAutoLock::x11Event( XEvent* ev )
257 xautolock_processEvent( ev );
258 // don't futher process key events that were received only because XAutoLock wants them
259 if( ev->type == KeyPress && !ev->xkey.send_event
260 #ifdef HAVE_XSCREENSAVER
261 && !mMitInfo
262 #endif
263 && !QWidget::find( ev->xkey.window ))
264 return true;
265 return false;
268 bool XAutoLock::ignoreWindow( WId w )
270 if( w != QX11Info::appRootWindow() && QWidget::find( w ))
271 return true;
272 return false;
275 time_t XAutoLock::idleTime()
277 #ifdef HAVE_XSCREENSAVER
278 if (mMitInfo)
279 return mMitInfo->idle / 1000;
280 #endif
281 return mElapsed - mLastReset;
284 extern "C"
285 void xautolock_resetTriggers()
287 self->resetTrigger();
290 extern "C"
291 void xautolock_setTrigger( int t )
293 self->setTrigger( t );
296 extern "C"
297 int xautolock_ignoreWindow( Window w )
299 return self->ignoreWindow( w );
302 #include "xautolock.moc"