add more spacing
[personal-kdebase.git] / workspace / krunner / screensaver / saverengine.cpp
blob1a912b188ccd5caad3c7302c49f21d324c69ebf7
1 //===========================================================================
2 //
3 // This file is part of the KDE project
4 //
5 // Copyright 1999 Martin R. Jones <mjones@kde.org>
6 //
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>
17 #include <krandom.h>
18 #include <kdebug.h>
19 #include <klocale.h>
20 #include <QFile>
21 #include <QX11Info>
22 #include <QDBusConnection>
23 #include <assert.h>
24 #include <stdlib.h>
25 #include <time.h>
26 #include <signal.h>
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()
38 : QWidget()
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);
49 // ... and disable it
50 XSetScreenSaver(QX11Info::display(), 0, mXInterval, mXBlanking, mXExposures);
52 mState = Waiting;
53 mXAutoLock = 0;
55 m_nr_throttled = 0;
56 m_nr_inhibited = 0;
57 m_actived_time = -1;
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;
70 configure();
73 //---------------------------------------------------------------------------
75 // Destructor - usual cleanups.
77 SaverEngine::~SaverEngine()
79 delete mXAutoLock;
81 // Restore X screensaver parameters
82 XSetScreenSaver(QX11Info::display(), mXTimeout, mXInterval, mXBlanking,
83 mXExposures);
86 //---------------------------------------------------------------------------
88 void SaverEngine::Lock()
90 bool ok = true;
91 if (mState == Waiting)
93 startLockProcess( ForceLock );
95 else
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()";
118 return;
120 kDebug() << "Saver Lock Ready";
121 processLockTransactions();
122 if (m_nr_throttled)
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 );
141 return false;
144 bool SaverEngine::setupPlasma()
146 if (mState == Waiting)
148 return startLockProcess( PlasmaSetup );
150 return false;
153 //---------------------------------------------------------------------------
154 bool SaverEngine::quit()
156 if (mState == Saving || mState == Preparing)
158 stopLockProcess();
159 return true;
161 return false;
164 //---------------------------------------------------------------------------
165 bool SaverEngine::isEnabled()
167 return mXAutoLock != 0;
170 //---------------------------------------------------------------------------
171 bool SaverEngine::enable( bool e, bool force )
173 if ( !force && e == isEnabled() )
174 return true;
176 // If we aren't in a suitable state, we will not reconfigure.
177 if (mState != Waiting)
178 return false;
180 if (e)
182 if (!mXAutoLock)
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);
193 #else
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());
198 #endif
200 mXAutoLock->start();
201 kDebug() << "Saver Engine started, timeout: " << timeout;
203 else
205 delete mXAutoLock;
206 mXAutoLock = 0;
207 kDebug() << "Saver Engine disabled";
210 return true;
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" );
242 if( path.isEmpty())
244 kDebug() << "Can't find kscreenlocker!";
245 return false;
247 mLockProcess.clearProgram();
248 mLockProcess << path;
249 switch( lock_type )
251 case ForceLock:
252 mLockProcess << QString( "--forcelock" );
253 break;
254 case DontLock:
255 mLockProcess << QString( "--dontlock" );
256 break;
257 case PlasmaSetup:
258 mLockProcess << "--plasmasetup";
259 break;
260 default:
261 break;
264 m_actived_time = time( 0 );
265 mLockProcess.start();
266 if (mLockProcess.waitForStarted() == false )
268 kDebug() << "Failed to start kscreenlocker!";
269 m_actived_time = -1;
270 return false;
273 if (mXAutoLock)
275 mXAutoLock->stop();
278 emit ActiveChanged(true); // DBus signal
279 mState = Preparing;
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);
289 return true;
292 //---------------------------------------------------------------------------
294 // Stop the screen saver.
296 void SaverEngine::stopLockProcess()
298 Q_ASSERT(mState != Waiting);
299 kDebug() << "SaverEngine: stopping lock process";
301 mLockProcess.kill();
304 void SaverEngine::lockProcessExited()
306 Q_ASSERT(mState != Waiting);
307 kDebug() << "SaverEngine: lock process exited";
309 if (mXAutoLock)
311 mXAutoLock->start();
314 processLockTransactions();
315 emit ActiveChanged(false); // DBus signal
316 m_actived_time = -1;
317 mState = Waiting;
320 //---------------------------------------------------------------------------
322 // XAutoLock has detected the required idle time.
324 void SaverEngine::idleTimeout()
326 startLockProcess( DefaultLock );
329 xautolock_corner_t SaverEngine::applyManualSettings(int action)
331 if (action == 0)
333 kDebug() << "no lock";
334 return ca_nothing;
336 else if (action == 1)
338 kDebug() << "lock screen";
339 return ca_forceLock;
341 else if (action == 2)
343 kDebug() << "prevent lock";
344 return ca_dontLock;
346 else
348 kDebug() << "no lock nothing";
349 return ca_nothing;
353 uint SaverEngine::GetSessionIdleTime()
355 return mXAutoLock ? mXAutoLock->idleTime() : 0;
358 uint SaverEngine::GetActiveTime()
360 if ( m_actived_time == -1 )
361 return 0;
362 return time( 0 ) - m_actived_time;
365 bool SaverEngine::GetActive()
367 return ( mState != Waiting );
370 bool SaverEngine::SetActive(bool state)
372 if ( state )
373 return save();
374 else
375 return quit();
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 );
387 m_nr_inhibited++;
388 enable( false );
389 return sr.cookie;
392 void SaverEngine::UnInhibit(uint cookie)
394 QMutableListIterator<ScreenSaverRequest> it( m_requests );
395 while ( it.hasNext() )
397 if ( it.next().cookie == cookie ) {
398 it.remove();
399 if ( !--m_nr_inhibited )
400 enable( true );
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 );
414 m_nr_throttled++;
415 if (mLockProcess.state() == QProcess::Running)
416 ::kill(mLockProcess.pid(), SIGSTOP);
417 return sr.cookie;
420 void SaverEngine::UnThrottle(uint cookie)
422 QMutableListIterator<ScreenSaverRequest> it( m_requests );
423 while ( it.hasNext() )
425 if ( it.next().cookie == cookie ) {
426 it.remove();
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
437 return;
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 );
447 else
448 UnInhibit( r.cookie );
453 #include "saverengine.moc"