1 //===========================================================================
3 // This file is part of the KDE project
5 // Copyright (c) 1999 Martin R. Jones <mjones@kde.org>
9 #include "saverengine.h"
10 #include "kscreensaversettings.h"
11 #include "screensaveradaptor.h"
13 #include <kstandarddirs.h>
14 #include <kapplication.h>
15 #include <kservicegroup.h>
25 #include "xautolock_c.h"
26 extern xautolock_corner_t xautolock_corners
[ 4 ];
28 //===========================================================================
30 // Screen saver engine. Doesn't handle the actual screensaver window,
31 // starting screensaver hacks, or password entry. That's done by
32 // a newly started process.
34 SaverEngine::SaverEngine()
36 screensaverService( QDBusConnection::connectToBus( QDBusConnection::SessionBus
,
37 "org.freedesktop.ScreenSaver" ) )
39 (void) new ScreenSaverAdaptor( this );
40 screensaverService
.registerService( "org.freedesktop.ScreenSaver" ) ;
41 screensaverService
.registerObject( "/ScreenSaver", this );
43 // Save X screensaver parameters
44 XGetScreenSaver(QX11Info::display(), &mXTimeout
, &mXInterval
,
45 &mXBlanking
, &mXExposures
);
55 connect(&mLockProcess
, SIGNAL(processExited(K3Process
*)),
56 SLOT(lockProcessExited()));
58 QObject::connect(QDBusConnection::sessionBus().interface(), SIGNAL(serviceOwnerChanged(QString
,QString
,QString
)),
59 SLOT(serviceOwnerChanged(QString
,QString
,QString
)));
61 // I make it a really random number to avoid
62 // some assumptions in clients, but just increase
63 // while gnome-ss creates a random number every time
64 m_next_cookie
= KRandom::random() % 20000;
68 //---------------------------------------------------------------------------
70 // Destructor - usual cleanups.
72 SaverEngine::~SaverEngine()
74 mLockProcess
.detach(); // don't kill it if we crash
77 // Restore X screensaver parameters
78 XSetScreenSaver(QX11Info::display(), mXTimeout
, mXInterval
, mXBlanking
,
82 //---------------------------------------------------------------------------
84 // This should be called only using DBus.
85 void SaverEngine::Lock()
88 if (mState
== Waiting
)
90 ok
= startLockProcess( ForceLock
);
91 // It takes a while for krunner_lock to start and lock the screen.
92 // Therefore delay the DBus call until it tells krunner that the locking is in effect.
93 // This is done only for --forcelock .
94 if( ok
&& mState
!= Saving
)
97 #warning port dcop transactions to dbus
100 DCOPClientTransaction
* trans
= kapp
->dcopClient()->beginTransaction();
101 mLockTransactions
.append( trans
);
107 mLockProcess
.kill( SIGHUP
);
111 void SaverEngine::processLockTransactions()
114 #warning port dcop transactions to dbus
117 for( QVector
< DCOPClientTransaction
* >::ConstIterator it
= mLockTransactions
.begin();
118 it
!= mLockTransactions
.end();
121 DCOPCString replyType
= "void";
123 kapp
->dcopClient()->endTransaction( *it
, replyType
, arr
);
125 mLockTransactions
.clear();
129 void SaverEngine::saverLockReady()
131 if( mState
!= Preparing
)
133 kDebug() << "Got unexpected saverReady()" << endl
;
135 kDebug() << "Saver Lock Ready" << endl
;
136 processLockTransactions();
139 void SaverEngine::SimulateUserActivity()
141 if ( mState
== Waiting
)
144 XSetScreenSaver(QX11Info::display(), 0, mXInterval
, PreferBlanking
, mXExposures
);
145 mXAutoLock
->resetTrigger();
147 XSetScreenSaver(QX11Info::display(), mTimeout
+ 10, mXInterval
, PreferBlanking
, mXExposures
);
151 //---------------------------------------------------------------------------
152 bool SaverEngine::save()
154 if (mState
== Waiting
)
156 return startLockProcess( DefaultLock
);
161 //---------------------------------------------------------------------------
162 bool SaverEngine::quit()
164 if (mState
== Saving
|| mState
== Preparing
)
172 //---------------------------------------------------------------------------
173 bool SaverEngine::isEnabled()
178 //---------------------------------------------------------------------------
179 bool SaverEngine::enable( bool e
)
184 // If we aren't in a suitable state, we will not reconfigure.
185 if (mState
!= Waiting
)
193 mXAutoLock
= new XAutoLock();
194 connect(mXAutoLock
, SIGNAL(timeout()), SLOT(idleTimeout()));
196 mXAutoLock
->setTimeout(mTimeout
);
197 mXAutoLock
->setDPMS(mDPMS
);
198 //mXAutoLock->changeCornerLockStatus( mLockCornerTopLeft, mLockCornerTopRight, mLockCornerBottomLeft, mLockCornerBottomRight);
200 // We'll handle blanking
201 XSetScreenSaver(QX11Info::display(), mTimeout
+ 10, mXInterval
, PreferBlanking
, mXExposures
);
202 kDebug() << "XSetScreenSaver " << mTimeout
+ 10 << endl
;
206 kDebug() << "Saver Engine started, timeout: " << mTimeout
<< endl
;
216 XForceScreenSaver(QX11Info::display(), ScreenSaverReset
);
217 XSetScreenSaver(QX11Info::display(), 0, mXInterval
, PreferBlanking
, DontAllowExposures
);
218 kDebug() << "Saver Engine disabled" << endl
;
224 //---------------------------------------------------------------------------
225 bool SaverEngine::isBlanked()
227 return (mState
!= Waiting
);
230 //---------------------------------------------------------------------------
232 // Read and apply configuration.
234 void SaverEngine::configure()
236 // If we aren't in a suitable state, we will not reconfigure.
237 if (mState
!= Waiting
)
240 // create a new config obj to ensure we read the latest options
241 KScreenSaverSettings::self()->readConfig();
243 bool e
= KScreenSaverSettings::screenSaverEnabled();
244 kDebug() << "enabled " << e
<< endl
;
245 mTimeout
= KScreenSaverSettings::timeout();
246 mDPMS
= KScreenSaverSettings::dpmsDependent();
248 mEnabled
= !e
; // force the enable()
251 action
= KScreenSaverSettings::actionTopLeft();
252 xautolock_corners
[0] = applyManualSettings(action
);
253 action
= KScreenSaverSettings::actionTopRight();
254 xautolock_corners
[1] = applyManualSettings(action
);
255 action
= KScreenSaverSettings::actionBottomLeft();
256 xautolock_corners
[2] = applyManualSettings(action
);
257 action
= KScreenSaverSettings::actionBottomRight();
258 xautolock_corners
[3] = applyManualSettings(action
);
263 //---------------------------------------------------------------------------
265 // Start the screen saver.
267 bool SaverEngine::startLockProcess( LockType lock_type
)
269 if (mState
!= Waiting
)
272 kDebug() << "SaverEngine: starting saver" << endl
;
273 emit
ActiveChanged(true); // DBus signal
275 if (mLockProcess
.isRunning())
279 mLockProcess
.clearArguments();
280 QString path
= KStandardDirs::findExe( "krunner_lock" );
283 kDebug() << "Can't find krunner_lock!" << endl
;
286 mLockProcess
<< path
;
290 mLockProcess
<< QString( "--forcelock" );
293 mLockProcess
<< QString( "--dontlock" );
299 mLockProcess
<< QString( "--blank" );
301 m_actived_time
= time( 0 );
302 if (mLockProcess
.start() == false )
304 kDebug() << "Failed to start krunner_lock!" << endl
;
309 XSetScreenSaver(QX11Info::display(), 0, mXInterval
, PreferBlanking
, mXExposures
);
318 //---------------------------------------------------------------------------
320 // Stop the screen saver.
322 void SaverEngine::stopLockProcess()
325 if (mState
== Waiting
)
327 kWarning() << "SaverEngine::stopSaver() saver not active" << endl
;
330 kDebug() << "SaverEngine: stopping lock" << endl
;
331 emit
ActiveChanged(false); // DBus signal
339 processLockTransactions();
341 XForceScreenSaver(QX11Info::display(), ScreenSaverReset
);
342 XSetScreenSaver(QX11Info::display(), mTimeout
+ 10, mXInterval
, PreferBlanking
, mXExposures
);
345 void SaverEngine::lockProcessExited()
348 kDebug() << "SaverEngine: lock exited" << endl
;
349 if( mState
== Waiting
)
351 emit
ActiveChanged(false); // DBus signal
356 processLockTransactions();
358 XForceScreenSaver(QX11Info::display(), ScreenSaverReset
);
359 XSetScreenSaver(QX11Info::display(), mTimeout
+ 10, mXInterval
, PreferBlanking
, mXExposures
);
362 //---------------------------------------------------------------------------
364 // XAutoLock has detected the required idle time.
366 void SaverEngine::idleTimeout()
368 // disable X screensaver
369 XForceScreenSaver(QX11Info::display(), ScreenSaverReset
);
370 XSetScreenSaver(QX11Info::display(), 0, mXInterval
, PreferBlanking
, DontAllowExposures
);
371 startLockProcess( DefaultLock
);
374 xautolock_corner_t
SaverEngine::applyManualSettings(int action
)
378 kDebug() << "no lock" << endl
;
381 else if (action
== 1)
383 kDebug() << "lock screen" << endl
;
386 else if (action
== 2)
388 kDebug() << "prevent lock" << endl
;
393 kDebug() << "no lock nothing" << endl
;
398 uint
SaverEngine::GetSessionIdleTime()
400 return mXAutoLock
->idleTime();
403 bool SaverEngine::GetSessionIdle()
406 return ( GetSessionIdleTime() > 0 );
409 uint
SaverEngine::GetActiveTime()
411 if ( m_actived_time
== -1 )
413 return time( 0 ) - m_actived_time
;
416 bool SaverEngine::GetActive()
418 return ( mState
!= Waiting
);
421 bool SaverEngine::SetActive(bool state
)
429 uint
SaverEngine::Inhibit(const QString
&application_name
, const QString
&reason_for_inhibit
)
431 ScreenSaverRequest sr
;
432 sr
.appname
= application_name
;
433 sr
.reasongiven
= reason_for_inhibit
;
434 sr
.cookie
= m_next_cookie
++;
435 sr
.dbusid
= "unknown"; // see below for throttle
436 sr
.type
= ScreenSaverRequest::Inhibit
;
437 m_requests
.append( sr
);
443 void SaverEngine::UnInhibit(uint cookie
)
445 QMutableListIterator
<ScreenSaverRequest
> it( m_requests
);
446 while ( it
.hasNext() )
448 if ( it
.next().cookie
== cookie
) {
451 if ( m_nr_inhibited
<= 0 )
457 uint
SaverEngine::Throttle(const QString
&application_name
, const QString
&reason_for_inhibit
)
459 ScreenSaverRequest sr
;
460 sr
.appname
= application_name
;
461 sr
.reasongiven
= reason_for_inhibit
;
462 sr
.cookie
= m_next_cookie
++;
463 sr
.type
= ScreenSaverRequest::Throttle
;
464 #warning thiago says Qt 4.3 can query the dbus connection id in adaptors - waiting
465 sr
.dbusid
= "unknown"; // see above for inhibit
466 m_requests
.append( sr
);
468 mLockProcess
.suspend();
472 void SaverEngine::UnThrottle(uint cookie
)
474 QMutableListIterator
<ScreenSaverRequest
> it( m_requests
);
475 while ( it
.hasNext() )
477 if ( it
.next().cookie
== cookie
) {
480 if ( m_nr_throttled
<= 0 )
481 mLockProcess
.resume();
486 void SaverEngine::serviceOwnerChanged(const QString
& name
,const QString
&oldOwner
,const QString
&newOwner
)
488 Q_UNUSED( oldOwner
);
490 if ( !newOwner
.isEmpty() ) // looking for deaths
493 QListIterator
<ScreenSaverRequest
> it( m_requests
);
494 while ( it
.hasNext() )
496 ScreenSaverRequest r
= it
.next();
497 if ( r
.dbusid
== name
)
499 if ( r
.type
== ScreenSaverRequest::Throttle
)
500 UnThrottle( r
.cookie
);
502 UnInhibit( r
.cookie
);
507 #include "saverengine.moc"