2
* Copyright (C) 2010, 2011, 2012 Ivan Cukic <ivan.cukic(at)kde.org>
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License version 2,
6
* or (at your option) any later version, as published by the Free
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details
14
* You should have received a copy of the GNU General Public
15
* License along with this program; if not, write to the
16
* Free Software Foundation, Inc.,
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
#include "ActivityManager.h"
21
#include "ActivityManager_p.h"
23
#include <QDBusInterface>
26
void ActivityManagerPrivate::sessionServiceRegistered()
28
delete ksmserverInterface;
29
ksmserverInterface = new QDBusInterface("org.kde.ksmserver", "/KSMServer", "org.kde.KSMServerInterface");
30
if (ksmserverInterface->isValid()) {
31
ksmserverInterface->setParent(this);
32
connect(ksmserverInterface, SIGNAL(subSessionOpened()), this, SLOT(startCompleted()));
33
connect(ksmserverInterface, SIGNAL(subSessionClosed()), this, SLOT(stopCompleted()));
34
connect(ksmserverInterface, SIGNAL(subSessionCloseCanceled()), this, SLOT(stopCancelled())); //spelling fail :)
36
delete ksmserverInterface;
37
ksmserverInterface = 0;
38
kDebug() << "couldn't connect to ksmserver! session stuff won't work";
42
void ActivityManagerPrivate::screensaverServiceRegistered()
44
delete screensaverInterface;
45
screensaverInterface = new QDBusInterface("org.freedesktop.ScreenSaver", "/ScreenSaver", "org.freedesktop.ScreenSaver");
46
if (screensaverInterface->isValid()) {
47
screensaverInterface->setParent(this);
48
connect(screensaverInterface, SIGNAL(ActiveChanged(bool)), this, SLOT(screenLockStateChanged(bool)));
50
delete screensaverInterface;
51
screensaverInterface = 0;
52
//kDebug() << "couldn't connect to screensaver!";
56
void ActivityManagerPrivate::setActivityState(const QString & id, ActivityManager::State state)
58
if (activities[id] == state) return;
60
// kDebug() << "Set the state of" << id << "to" << state;
63
* Treating 'Starting' as 'Running', and 'Stopping' as 'Stopped'
64
* as far as the config file is concerned
66
bool configNeedsUpdating = ((activities[id] & 4) != (state & 4));
68
activities[id] = state;
71
case ActivityManager::Running:
72
// kDebug() << "sending ActivityStarted signal";
73
emit q->ActivityStarted(id);
76
case ActivityManager::Stopped:
77
// kDebug() << "sending ActivityStopped signal";
78
emit q->ActivityStopped(id);
85
// kDebug() << "sending ActivityStateChanged signal";
86
emit q->ActivityStateChanged(id, state);
88
if (configNeedsUpdating) {
89
mainConfig().writeEntry("runningActivities",
90
activities.keys(ActivityManager::Running) +
91
activities.keys(ActivityManager::Starting));
96
void ActivityManagerPrivate::ensureCurrentActivityIsRunning()
98
QStringList runningActivities = q->ListActivities(ActivityManager::Running);
100
if (!runningActivities.contains(currentActivity)) {
101
if (runningActivities.size() > 0) {
102
kDebug() << "Somebody called ensureCurrentActivityIsRunning?";
103
setCurrentActivity(runningActivities.first());
105
// kDebug() << "there are no running activities! eek!";
112
void ActivityManager::StartActivity(const QString & id)
116
if (!d->activities.contains(id) ||
117
d->activities[id] != Stopped) {
121
if (!d->transitioningActivity.isEmpty()) {
122
// kDebug() << "busy!!";
123
//TODO: implement a queue instead
127
d->transitioningActivity = id;
128
d->setActivityState(id, Starting);
130
//ugly hack to avoid dbus deadlocks
131
QMetaObject::invokeMethod(d, "reallyStartActivity", Qt::QueuedConnection, Q_ARG(QString, id));
134
void ActivityManagerPrivate::reallyStartActivity(const QString & id)
137
// start the starting :)
138
QDBusInterface kwin("org.kde.kwin", "/KWin", "org.kde.KWin");
139
if (kwin.isValid()) {
140
QDBusMessage reply = kwin.call("startActivity", id);
141
if (reply.type() == QDBusMessage::ErrorMessage) {
142
// kDebug() << "dbus error:" << reply.errorMessage();
145
QList<QVariant> ret = reply.arguments();
146
if (ret.length() == 1 && ret.first().toBool()) {
149
// kDebug() << "call returned false; probably ksmserver is busy";
150
setActivityState(transitioningActivity, ActivityManager::Stopped);
151
transitioningActivity.clear();
152
return; //assume we're mid-logout and just don't touch anything
156
// kDebug() << "couldn't get kwin interface";
160
//maybe they use compiz?
161
//go ahead without the session
164
configSync(); //force immediate sync
167
void ActivityManagerPrivate::startCompleted()
169
if (transitioningActivity.isEmpty()) {
170
// kDebug() << "huh?";
173
setActivityState(transitioningActivity, ActivityManager::Running);
174
transitioningActivity.clear();
177
void ActivityManager::StopActivity(const QString & id)
181
if (!d->activities.contains(id) ||
182
d->activities[id] == Stopped) {
186
if (!d->transitioningActivity.isEmpty()) {
187
// kDebug() << "busy!!";
188
//TODO: implement a queue instead
192
d->transitioningActivity = id;
193
d->setActivityState(id, Stopping);
195
//ugly hack to avoid dbus deadlocks
196
QMetaObject::invokeMethod(d, "reallyStopActivity", Qt::QueuedConnection, Q_ARG(QString, id));
199
void ActivityManagerPrivate::reallyStopActivity(const QString & id)
202
// start the stopping :)
203
QDBusInterface kwin("org.kde.kwin", "/KWin", "org.kde.KWin");
204
if (kwin.isValid()) {
205
QDBusMessage reply = kwin.call("stopActivity", id);
206
if (reply.type() == QDBusMessage::ErrorMessage) {
207
// kDebug() << "dbus error:" << reply.errorMessage();
210
QList<QVariant> ret = reply.arguments();
211
if (ret.length() == 1 && ret.first().toBool()) {
215
// kDebug() << "call returned false; probably ksmserver is busy";
217
return; //assume we're mid-logout and just don't touch anything
221
// kDebug() << "couldn't get kwin interface";
225
//maybe they use compiz?
226
//go ahead without the session
231
void ActivityManagerPrivate::stopCompleted()
233
if (transitioningActivity.isEmpty()) {
234
// kDebug() << "huh?";
237
setActivityState(transitioningActivity, ActivityManager::Stopped);
238
if (currentActivity == transitioningActivity) {
239
ensureCurrentActivityIsRunning();
241
transitioningActivity.clear();
242
configSync(); //force immediate sync
245
void ActivityManagerPrivate::stopCancelled()
247
if (transitioningActivity.isEmpty()) {
248
// kDebug() << "huh?";
251
setActivityState(transitioningActivity, ActivityManager::Running);
252
transitioningActivity.clear();
255
int ActivityManager::ActivityState(const QString & id) const
257
//kDebug() << id << "- is it in" << d->activities << "?";
258
if (!d->activities.contains(id)) {
261
// kDebug() << "state of" << id << "is" << d->activities[id];
262
return d->activities[id];
266
void ActivityManagerPrivate::screenLockStateChanged(const bool locked)
269
// already in limbo state.
270
if (currentActivity.isEmpty()) {
274
if (q->IsActivityEncrypted(currentActivity)) {
275
currentActivityBeforeScreenLock = currentActivity;
276
setCurrentActivity(QString());
279
} else if (!currentActivityBeforeScreenLock.isEmpty()) {
280
setCurrentActivity(currentActivityBeforeScreenLock);
281
currentActivityBeforeScreenLock.clear();