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 #ifdef HAVE_XSCREENSAVER
44 xautolock_corner_t xautolock_corners
[ 4 ];
46 static XAutoLock
* self
= NULL
;
49 static int catchFalseAlarms(Display
*, XErrorEvent
*)
55 //===========================================================================
57 // Detect user inactivity.
58 // Named XAutoLock after the program that it is based on.
60 XAutoLock::XAutoLock()
63 #ifdef HAVE_XSCREENSAVER
65 xautolock_useMit
= XScreenSaverQueryExtension( QX11Info::display(), &dummy
, &dummy
);
67 if( !xautolock_useMit
)
69 kapp
->installX11EventFilter( this );
70 int (*oldHandler
)(Display
*, XErrorEvent
*);
71 oldHandler
= XSetErrorHandler(catchFalseAlarms
);
72 XSync(QX11Info::display(), False
);
73 xautolock_initDiy( QX11Info::display());
74 XSync(QX11Info::display(), False
);
75 XSetErrorHandler(oldHandler
);
78 mTimeout
= DEFAULT_TIMEOUT
;
85 mTimerId
= startTimer( CHECK_INTERVAL
);
89 //---------------------------------------------------------------------------
93 XAutoLock::~XAutoLock()
99 //---------------------------------------------------------------------------
101 // The time in seconds of continuous inactivity.
103 void XAutoLock::setTimeout(int t
)
108 void XAutoLock::setDPMS(bool s
)
113 DPMSInfo( QX11Info::display(), &state
, &on
);
120 //---------------------------------------------------------------------------
122 // Start watching Activity
124 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
= time( 0 );
152 mTrigger
= mLastReset
+ mTimeout
;
153 XForceScreenSaver( QX11Info::display(), ScreenSaverReset
);
156 //---------------------------------------------------------------------------
158 // Move the trigger time in order to postpone (repeat) emitting of timeout().
160 void XAutoLock::postpone()
162 mTrigger
= time(0) + 60; // delay by 60sec
165 //---------------------------------------------------------------------------
167 // Set the remaining time to 't', if it's shorter than already set.
169 void XAutoLock::setTrigger( time_t t
)
175 //---------------------------------------------------------------------------
177 // Process new windows and check the mouse.
179 void XAutoLock::timerEvent(QTimerEvent
*ev
)
181 if (ev
->timerId() != mTimerId
)
186 int (*oldHandler
)(Display
*, XErrorEvent
*) = NULL
;
187 if( !xautolock_useMit
)
188 { // only the diy way needs special X handler
189 XSync( QX11Info::display(), False
);
190 oldHandler
= XSetErrorHandler(catchFalseAlarms
);
193 xautolock_processQueue();
195 time_t now
= time(0);
196 if ((now
> mLastTimeout
&& now
- mLastTimeout
> TIME_CHANGE_LIMIT
) ||
197 (mLastTimeout
> now
&& mLastTimeout
- now
> TIME_CHANGE_LIMIT
+1))
199 /* the time has changed in one large jump. This could be because
200 the date was changed, or the machine was suspended. We'll just
207 xautolock_queryIdleTime( QX11Info::display());
208 xautolock_queryPointer( QX11Info::display());
210 if( !xautolock_useMit
)
211 XSetErrorHandler(oldHandler
);
213 bool activate
= false;
215 // kDebug() << now << mTrigger;
225 DPMSInfo( QX11Info::display(), &state
, &on
);
227 // kDebug() << "DPMSInfo " << state << on;
228 // If DPMS is active, it makes XScreenSaverQueryInfo() report idle time
229 // that is always smaller than DPMS timeout (X bug I guess). So if DPMS
230 // saving is active, simply always activate our saving too, otherwise
231 // this could prevent locking from working.
232 if(state
== DPMSModeStandby
|| state
== DPMSModeSuspend
|| state
== DPMSModeOff
)
240 #ifdef HAVE_XSCREENSAVER
241 static XScreenSaverInfo
* mitInfo
= 0;
242 if (!mitInfo
) mitInfo
= XScreenSaverAllocInfo ();
243 if (XScreenSaverQueryInfo (QX11Info::display(), QX11Info::appRootWindow(), mitInfo
)) {
244 // kDebug() << "XScreenSaverQueryInfo " << mitInfo->state << ScreenSaverDisabled;
245 if (mitInfo
->state
== ScreenSaverDisabled
)
250 if(mActive
&& activate
)
254 bool XAutoLock::x11Event( XEvent
* ev
)
256 xautolock_processEvent( ev
);
257 // don't futher process key events that were received only because XAutoLock wants them
258 if( ev
->type
== KeyPress
&& !ev
->xkey
.send_event
260 && !QWidget::find( ev
->xkey
.window
))
265 bool XAutoLock::ignoreWindow( WId w
)
267 if( w
!= QX11Info::appRootWindow() && QWidget::find( w
))
272 time_t XAutoLock::idleTime()
274 return time( 0 ) - mLastReset
;
278 void xautolock_resetTriggers()
280 self
->resetTrigger();
284 void xautolock_setTrigger( time_t t
)
286 self
->setTrigger( t
);
290 int xautolock_ignoreWindow( Window w
)
292 return self
->ignoreWindow( w
);
295 #include "xautolock.moc"