1 //===========================================================================
3 // This file is part of the KDE project
5 // Copyright 1999 Martin R. Jones <mjones@kde.org>
9 #include "saverengine.h"
10 #include "kscreensaversettings.h"
11 #include "screensaveradaptor.h"
12 #include "kscreensaveradaptor.h"
14 #include <kstandarddirs.h>
15 #include <kapplication.h>
16 #include <kservicegroup.h>
22 #include <QDBusConnection>
28 #include "xautolock_c.h"
29 extern xautolock_corner_t xautolock_corners
[ 4 ];
31 //===========================================================================
33 // Screen saver engine. Doesn't handle the actual screensaver window,
34 // starting screensaver hacks, or password entry. That's done by
35 // a newly started process.
37 SaverEngine::SaverEngine()
40 (void) new ScreenSaverAdaptor( this );
41 QDBusConnection::sessionBus().registerService( "org.freedesktop.ScreenSaver" ) ;
42 (void) new KScreenSaverAdaptor( this );
43 QDBusConnection::sessionBus().registerService( "org.kde.screensaver" ) ;
44 QDBusConnection::sessionBus().registerObject( "/ScreenSaver", this );
46 // Save X screensaver parameters
47 XGetScreenSaver(QX11Info::display(), &mXTimeout
, &mXInterval
,
48 &mXBlanking
, &mXExposures
);
50 XSetScreenSaver(QX11Info::display(), 0, mXInterval
, mXBlanking
, mXExposures
);
59 connect(&mLockProcess
, SIGNAL(finished(int, QProcess::ExitStatus
)),
60 SLOT(lockProcessExited()));
62 connect(QDBusConnection::sessionBus().interface(),
63 SIGNAL(serviceOwnerChanged(QString
,QString
,QString
)),
64 SLOT(serviceOwnerChanged(QString
,QString
,QString
)));
66 // I make it a really random number to avoid
67 // some assumptions in clients, but just increase
68 // while gnome-ss creates a random number every time
69 m_next_cookie
= KRandom::random() % 20000;
73 //---------------------------------------------------------------------------
75 // Destructor - usual cleanups.
77 SaverEngine::~SaverEngine()
81 // Restore X screensaver parameters
82 XSetScreenSaver(QX11Info::display(), mXTimeout
, mXInterval
, mXBlanking
,
86 //---------------------------------------------------------------------------
88 void SaverEngine::Lock()
91 if (mState
== Waiting
)
93 startLockProcess( ForceLock
);
97 // XXX race condition here
98 ::kill(mLockProcess
.pid(), SIGHUP
);
102 void SaverEngine::processLockTransactions()
104 QList
<QDBusMessage
>::ConstIterator it
= mLockTransactions
.constBegin(),
105 end
= mLockTransactions
.constEnd();
106 for ( ; it
!= end
; ++it
)
108 QDBusConnection::sessionBus().send(*it
);
110 mLockTransactions
.clear();
113 void SaverEngine::saverLockReady()
115 if( mState
!= Preparing
)
117 kDebug() << "Got unexpected saverLockReady()";
120 kDebug() << "Saver Lock Ready";
121 processLockTransactions();
123 ::kill(mLockProcess
.pid(), SIGSTOP
);
126 void SaverEngine::SimulateUserActivity()
128 if ( mXAutoLock
&& mState
== Waiting
)
130 mXAutoLock
->resetTrigger();
134 //---------------------------------------------------------------------------
135 bool SaverEngine::save()
137 if (mState
== Waiting
)
139 return startLockProcess( DefaultLock
);
144 bool SaverEngine::setupPlasma()
146 if (mState
== Waiting
)
148 return startLockProcess( PlasmaSetup
);
153 //---------------------------------------------------------------------------
154 bool SaverEngine::quit()
156 if (mState
== Saving
|| mState
== Preparing
)
164 //---------------------------------------------------------------------------
165 bool SaverEngine::isEnabled()
167 return mXAutoLock
!= 0;
170 //---------------------------------------------------------------------------
171 bool SaverEngine::enable( bool e
, bool force
)
173 if ( !force
&& e
== isEnabled() )
176 // If we aren't in a suitable state, we will not reconfigure.
177 if (mState
!= Waiting
)
184 mXAutoLock
= new XAutoLock();
185 connect(mXAutoLock
, SIGNAL(timeout()), SLOT(idleTimeout()));
188 int timeout
= KScreenSaverSettings::timeout();
189 mXAutoLock
->setTimeout(timeout
);
190 mXAutoLock
->setDPMS(true);
191 #ifdef NOT_FREAKIN_UGLY
192 mXAutoLock
->changeCornerLockStatus( mLockCornerTopLeft
, mLockCornerTopRight
, mLockCornerBottomLeft
, mLockCornerBottomRight
);
194 xautolock_corners
[0] = applyManualSettings(KScreenSaverSettings::actionTopLeft());
195 xautolock_corners
[1] = applyManualSettings(KScreenSaverSettings::actionTopRight());
196 xautolock_corners
[2] = applyManualSettings(KScreenSaverSettings::actionBottomLeft());
197 xautolock_corners
[3] = applyManualSettings(KScreenSaverSettings::actionBottomRight());
201 kDebug() << "Saver Engine started, timeout: " << timeout
;
207 kDebug() << "Saver Engine disabled";
213 //---------------------------------------------------------------------------
214 bool SaverEngine::isBlanked()
216 return (mState
!= Waiting
);
219 //---------------------------------------------------------------------------
221 // Read and apply configuration.
223 void SaverEngine::configure()
225 // create a new config obj to ensure we read the latest options
226 KScreenSaverSettings::self()->readConfig();
228 enable( KScreenSaverSettings::screenSaverEnabled(), true );
231 //---------------------------------------------------------------------------
233 // Start the screen saver.
235 bool SaverEngine::startLockProcess( LockType lock_type
)
237 Q_ASSERT(mState
== Waiting
);
239 kDebug() << "SaverEngine: starting saver";
241 QString path
= KStandardDirs::findExe( "kscreenlocker" );
244 kDebug() << "Can't find kscreenlocker!";
247 mLockProcess
.clearProgram();
248 mLockProcess
<< path
;
252 mLockProcess
<< QString( "--forcelock" );
255 mLockProcess
<< QString( "--dontlock" );
258 mLockProcess
<< "--plasmasetup";
264 m_actived_time
= time( 0 );
265 mLockProcess
.start();
266 if (mLockProcess
.waitForStarted() == false )
268 kDebug() << "Failed to start kscreenlocker!";
278 emit
ActiveChanged(true); // DBus signal
281 // It takes a while for kscreenlocker to start and lock the screen.
282 // Therefore delay the DBus call until it tells krunner that the locking is in effect.
283 // This is done only for --forcelock .
284 if (lock_type
== ForceLock
&& calledFromDBus()) {
285 mLockTransactions
.append(message().createReply());
286 setDelayedReply(true);
292 //---------------------------------------------------------------------------
294 // Stop the screen saver.
296 void SaverEngine::stopLockProcess()
298 Q_ASSERT(mState
!= Waiting
);
299 kDebug() << "SaverEngine: stopping lock process";
304 void SaverEngine::lockProcessExited()
306 Q_ASSERT(mState
!= Waiting
);
307 kDebug() << "SaverEngine: lock process exited";
314 processLockTransactions();
315 emit
ActiveChanged(false); // DBus signal
320 //---------------------------------------------------------------------------
322 // XAutoLock has detected the required idle time.
324 void SaverEngine::idleTimeout()
326 startLockProcess( DefaultLock
);
329 xautolock_corner_t
SaverEngine::applyManualSettings(int action
)
333 kDebug() << "no lock";
336 else if (action
== 1)
338 kDebug() << "lock screen";
341 else if (action
== 2)
343 kDebug() << "prevent lock";
348 kDebug() << "no lock nothing";
353 uint
SaverEngine::GetSessionIdleTime()
355 return mXAutoLock
? mXAutoLock
->idleTime() : 0;
358 uint
SaverEngine::GetActiveTime()
360 if ( m_actived_time
== -1 )
362 return time( 0 ) - m_actived_time
;
365 bool SaverEngine::GetActive()
367 return ( mState
!= Waiting
);
370 bool SaverEngine::SetActive(bool state
)
378 uint
SaverEngine::Inhibit(const QString
&/*application_name*/, const QString
&/*reason*/)
380 ScreenSaverRequest sr
;
381 // sr.appname = application_name;
382 // sr.reasongiven = reason;
383 sr
.cookie
= m_next_cookie
++;
384 sr
.dbusid
= message().service();
385 sr
.type
= ScreenSaverRequest::Inhibit
;
386 m_requests
.append( sr
);
392 void SaverEngine::UnInhibit(uint cookie
)
394 QMutableListIterator
<ScreenSaverRequest
> it( m_requests
);
395 while ( it
.hasNext() )
397 if ( it
.next().cookie
== cookie
) {
399 if ( !--m_nr_inhibited
)
405 uint
SaverEngine::Throttle(const QString
&/*application_name*/, const QString
&/*reason*/)
407 ScreenSaverRequest sr
;
408 // sr.appname = application_name;
409 // sr.reasongiven = reason;
410 sr
.cookie
= m_next_cookie
++;
411 sr
.type
= ScreenSaverRequest::Throttle
;
412 sr
.dbusid
= message().service();
413 m_requests
.append( sr
);
415 if (mLockProcess
.state() == QProcess::Running
)
416 ::kill(mLockProcess
.pid(), SIGSTOP
);
420 void SaverEngine::UnThrottle(uint cookie
)
422 QMutableListIterator
<ScreenSaverRequest
> it( m_requests
);
423 while ( it
.hasNext() )
425 if ( it
.next().cookie
== cookie
) {
427 if ( !--m_nr_throttled
)
428 if (mLockProcess
.state() == QProcess::Running
)
429 ::kill(mLockProcess
.pid(), SIGCONT
);
434 void SaverEngine::serviceOwnerChanged(const QString
& name
, const QString
&, const QString
&newOwner
)
436 if ( !newOwner
.isEmpty() ) // looking for deaths
439 QListIterator
<ScreenSaverRequest
> it( m_requests
);
440 while ( it
.hasNext() )
442 const ScreenSaverRequest
&r
= it
.next();
443 if ( r
.dbusid
== name
)
445 if ( r
.type
== ScreenSaverRequest::Throttle
)
446 UnThrottle( r
.cookie
);
448 UnInhibit( r
.cookie
);
453 #include "saverengine.moc"