1 //----------------------------------------------------------------------------
3 // This file is part of the KDE project
5 // Copyright 1999 Martin R. Jones <mjones@kde.org>
6 // Copyright 2003 Lubos Lunak <l.lunak@kde.org>
8 // KDE screensaver engine
11 #include <config-workspace.h>
13 #include "xautolock.h"
14 #include "xautolock_c.h"
16 #include <kapplication.h>
19 #include <QTimerEvent>
23 #include <X11/Xutil.h>
31 #include <X11/extensions/dpms.h>
33 #ifndef HAVE_DPMSINFO_PROTO
34 Status
DPMSInfo ( Display
*, CARD16
*, BOOL
* );
41 xautolock_corner_t xautolock_corners
[ 4 ];
43 static XAutoLock
* self
= NULL
;
46 static int catchFalseAlarms(Display
*, XErrorEvent
*)
52 //===========================================================================
54 // Detect user inactivity.
55 // Named XAutoLock after the program that it is based on.
57 XAutoLock::XAutoLock()
60 #ifdef HAVE_XSCREENSAVER
63 if (XScreenSaverQueryExtension( QX11Info::display(), &dummy
, &dummy
))
65 mMitInfo
= XScreenSaverAllocInfo();
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
;
85 mTimerId
= startTimer( CHECK_INTERVAL
);
90 //---------------------------------------------------------------------------
94 XAutoLock::~XAutoLock()
100 //---------------------------------------------------------------------------
102 // The time in seconds of continuous inactivity.
104 void XAutoLock::setTimeout(int t
)
109 void XAutoLock::setDPMS(bool s
)
114 DPMSInfo( QX11Info::display(), &state
, &on
);
121 //---------------------------------------------------------------------------
123 // Start watching Activity
125 void XAutoLock::start()
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()
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
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);
179 //---------------------------------------------------------------------------
181 // Process new windows and check the mouse.
183 void XAutoLock::timerEvent(QTimerEvent
*ev
)
185 if (ev
->timerId() != mTimerId
)
189 mElapsed
+= CHECK_INTERVAL
/ 1000;
191 #ifdef HAVE_XSCREENSAVER
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
207 Display
*d
= QX11Info::display();
208 XScreenSaverQueryInfo(d
, DefaultRootWindow(d
), mMitInfo
);
209 if (mLastIdle
< mMitInfo
->idle
)
210 mLastIdle
= mMitInfo
->idle
;
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
)
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
)
246 #ifdef HAVE_XSCREENSAVER
247 if (mMitInfo
&& mMitInfo
->state
== ScreenSaverDisabled
)
251 if(mActive
&& activate
)
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
263 && !QWidget::find( ev
->xkey
.window
))
268 bool XAutoLock::ignoreWindow( WId w
)
270 if( w
!= QX11Info::appRootWindow() && QWidget::find( w
))
275 time_t XAutoLock::idleTime()
277 #ifdef HAVE_XSCREENSAVER
279 return mMitInfo
->idle
/ 1000;
281 return mElapsed
- mLastReset
;
285 void xautolock_resetTriggers()
287 self
->resetTrigger();
291 void xautolock_setTrigger( int t
)
293 self
->setTrigger( t
);
297 int xautolock_ignoreWindow( Window w
)
299 return self
->ignoreWindow( w
);
302 #include "xautolock.moc"