1 //----------------------------------------------------------------------------
3 // This file is part of the KDE project
5 // Copyright (c) 1999 Martin R. Jones <mjones@kde.org>
6 // Copyright (c) 2003 Lubos Lunak <l.lunak@kde.org>
8 // KDE screensaver engine
11 #include <config-workspace.h>
12 #include <config-xautolock.h>
13 #include "xautolock.h"
14 #include "xautolock.moc"
17 #include <X11/Xutil.h>
19 #include "xautolock_c.h"
21 #include <kapplication.h>
23 #include <QTimerEvent>
32 #include <X11/extensions/dpms.h>
34 #ifndef HAVE_DPMSINFO_PROTO
35 Status
DPMSInfo ( Display
*, CARD16
*, BOOL
* );
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
*)
51 //===========================================================================
53 // Detect user inactivity.
54 // Named XAutoLock after the program that it is based on.
56 XAutoLock::XAutoLock()
60 dummy
= dummy
; // shut up
61 xautolock_useXidle
= 0;
64 useXidle
= XidleQueryExtension( QX11Info::display(), &dummy
, &dummy
);
66 #ifdef HAVE_SCREENSAVER
67 if( !xautolock_useXidle
)
68 xautolock_useMit
= XScreenSaverQueryExtension( QX11Info::display(), &dummy
, &dummy
);
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
;
88 mTimerId
= startTimer( CHECK_INTERVAL
);
92 //---------------------------------------------------------------------------
96 XAutoLock::~XAutoLock()
101 //---------------------------------------------------------------------------
103 // The time in seconds of continuous inactivity.
105 void XAutoLock::setTimeout(int t
)
111 void XAutoLock::setDPMS(bool s
)
116 //---------------------------------------------------------------------------
118 // Start watching Activity
120 void XAutoLock::start()
127 //---------------------------------------------------------------------------
129 // Stop watching Activity
131 void XAutoLock::stop()
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
)
165 //---------------------------------------------------------------------------
167 // Process new windows and check the mouse.
169 void XAutoLock::timerEvent(QTimerEvent
*ev
)
171 if (ev
->timerId() != mTimerId
)
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
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;
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
)
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
)
240 if(mActive
&& activate
)
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
))
255 bool XAutoLock::ignoreWindow( WId w
)
257 if( w
!= QX11Info::appRootWindow() && QWidget::find( w
))
262 time_t XAutoLock::idleTime()
264 return time( 0 ) - mLastReset
;
268 void xautolock_resetTriggers()
270 self
->resetTrigger();
274 void xautolock_setTrigger( time_t t
)
276 self
->setTrigger( t
);
280 int xautolock_ignoreWindow( Window w
)
282 return self
->ignoreWindow( w
);