~ubuntu-branches/ubuntu/saucy/kactivities/saucy-proposed

« back to all changes in this revision

Viewing changes to service/ActivityManager_StartStop.cpp

  • Committer: Package Import Robot
  • Author(s): Scott Kitterman, Jonathan Riddell, Scott Kitterman
  • Date: 2012-11-20 13:47:27 UTC
  • mfrom: (1.1.13)
  • Revision ID: package-import@ubuntu.com-20121120134727-vqzk04slqjoay3de
Tags: 4:4.9.80-0ubuntu1
[ Jonathan Riddell ]
* New upstream beta release

[ Scott Kitterman ]
* Add new libkactivities-models1 library package (debian/control, .install,
  and .symbols)
* Add nepomuk-core-dev to build-depends
* Wildcard libkactivities6.install so that soversion changes don't cause
  build failures
* Update libkactivities6.symbols
* Update libkactivities-dev.install for new files for libkactivies-models
* Add new files to libkactivities-bin.install, including Activities kcm

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *   Copyright (C) 2010, 2011, 2012 Ivan Cukic <ivan.cukic(at)kde.org>
3
 
 *
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
7
 
 *   Software Foundation
8
 
 *
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
13
 
 *
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.
18
 
 */
19
 
 
20
 
#include "ActivityManager.h"
21
 
#include "ActivityManager_p.h"
22
 
 
23
 
#include <QDBusInterface>
24
 
#include <KDebug>
25
 
 
26
 
void ActivityManagerPrivate::sessionServiceRegistered()
27
 
{
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 :)
35
 
    } else {
36
 
        delete ksmserverInterface;
37
 
        ksmserverInterface = 0;
38
 
        kDebug() << "couldn't connect to ksmserver! session stuff won't work";
39
 
    }
40
 
}
41
 
 
42
 
void ActivityManagerPrivate::screensaverServiceRegistered()
43
 
{
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)));
49
 
    } else {
50
 
        delete screensaverInterface;
51
 
        screensaverInterface = 0;
52
 
        //kDebug() << "couldn't connect to screensaver!";
53
 
    }
54
 
}
55
 
 
56
 
void ActivityManagerPrivate::setActivityState(const QString & id, ActivityManager::State state)
57
 
{
58
 
    if (activities[id] == state) return;
59
 
 
60
 
    // kDebug() << "Set the state of" << id << "to" << state;
61
 
 
62
 
    /**
63
 
     * Treating 'Starting' as 'Running', and 'Stopping' as 'Stopped'
64
 
     * as far as the config file is concerned
65
 
     */
66
 
    bool configNeedsUpdating = ((activities[id] & 4) != (state & 4));
67
 
 
68
 
    activities[id] = state;
69
 
 
70
 
    switch (state) {
71
 
        case ActivityManager::Running:
72
 
            // kDebug() << "sending ActivityStarted signal";
73
 
            emit q->ActivityStarted(id);
74
 
            break;
75
 
 
76
 
        case ActivityManager::Stopped:
77
 
            // kDebug() << "sending ActivityStopped signal";
78
 
            emit q->ActivityStopped(id);
79
 
            break;
80
 
 
81
 
        default:
82
 
            break;
83
 
    }
84
 
 
85
 
    // kDebug() << "sending ActivityStateChanged signal";
86
 
    emit q->ActivityStateChanged(id, state);
87
 
 
88
 
    if (configNeedsUpdating) {
89
 
        mainConfig().writeEntry("runningActivities",
90
 
                activities.keys(ActivityManager::Running) +
91
 
                activities.keys(ActivityManager::Starting));
92
 
        scheduleConfigSync();
93
 
    }
94
 
}
95
 
 
96
 
void ActivityManagerPrivate::ensureCurrentActivityIsRunning()
97
 
{
98
 
    QStringList runningActivities = q->ListActivities(ActivityManager::Running);
99
 
 
100
 
    if (!runningActivities.contains(currentActivity)) {
101
 
        if (runningActivities.size() > 0) {
102
 
            kDebug() << "Somebody called ensureCurrentActivityIsRunning?";
103
 
            setCurrentActivity(runningActivities.first());
104
 
        } else {
105
 
            // kDebug() << "there are no running activities! eek!";
106
 
        }
107
 
    }
108
 
}
109
 
 
110
 
// Main
111
 
 
112
 
void ActivityManager::StartActivity(const QString & id)
113
 
{
114
 
    // kDebug() << id;
115
 
 
116
 
    if (!d->activities.contains(id) ||
117
 
            d->activities[id] != Stopped) {
118
 
        return;
119
 
    }
120
 
 
121
 
    if (!d->transitioningActivity.isEmpty()) {
122
 
        // kDebug() << "busy!!";
123
 
        //TODO: implement a queue instead
124
 
        return;
125
 
    }
126
 
 
127
 
    d->transitioningActivity = id;
128
 
    d->setActivityState(id, Starting);
129
 
 
130
 
    //ugly hack to avoid dbus deadlocks
131
 
    QMetaObject::invokeMethod(d, "reallyStartActivity", Qt::QueuedConnection, Q_ARG(QString, id));
132
 
}
133
 
 
134
 
void ActivityManagerPrivate::reallyStartActivity(const QString & id)
135
 
{
136
 
    bool called = false;
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();
143
 
 
144
 
        } else {
145
 
            QList<QVariant> ret = reply.arguments();
146
 
            if (ret.length() == 1 && ret.first().toBool()) {
147
 
                called = true;
148
 
            } else {
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
153
 
            }
154
 
        }
155
 
    } else {
156
 
        // kDebug() << "couldn't get kwin interface";
157
 
    }
158
 
 
159
 
    if (!called) {
160
 
        //maybe they use compiz?
161
 
        //go ahead without the session
162
 
        startCompleted();
163
 
    }
164
 
    configSync(); //force immediate sync
165
 
}
166
 
 
167
 
void ActivityManagerPrivate::startCompleted()
168
 
{
169
 
    if (transitioningActivity.isEmpty()) {
170
 
        // kDebug() << "huh?";
171
 
        return;
172
 
    }
173
 
    setActivityState(transitioningActivity, ActivityManager::Running);
174
 
    transitioningActivity.clear();
175
 
}
176
 
 
177
 
void ActivityManager::StopActivity(const QString & id)
178
 
{
179
 
    // kDebug() << id;
180
 
 
181
 
    if (!d->activities.contains(id) ||
182
 
            d->activities[id] == Stopped) {
183
 
        return;
184
 
    }
185
 
 
186
 
    if (!d->transitioningActivity.isEmpty()) {
187
 
        // kDebug() << "busy!!";
188
 
        //TODO: implement a queue instead
189
 
        return;
190
 
    }
191
 
 
192
 
    d->transitioningActivity = id;
193
 
    d->setActivityState(id, Stopping);
194
 
 
195
 
    //ugly hack to avoid dbus deadlocks
196
 
    QMetaObject::invokeMethod(d, "reallyStopActivity", Qt::QueuedConnection, Q_ARG(QString, id));
197
 
}
198
 
 
199
 
void ActivityManagerPrivate::reallyStopActivity(const QString & id)
200
 
{
201
 
    bool called = false;
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();
208
 
 
209
 
        } else {
210
 
            QList<QVariant> ret = reply.arguments();
211
 
            if (ret.length() == 1 && ret.first().toBool()) {
212
 
                called = true;
213
 
 
214
 
            } else {
215
 
                // kDebug() << "call returned false; probably ksmserver is busy";
216
 
                stopCancelled();
217
 
                return; //assume we're mid-logout and just don't touch anything
218
 
            }
219
 
        }
220
 
    } else {
221
 
        // kDebug() << "couldn't get kwin interface";
222
 
    }
223
 
 
224
 
    if (!called) {
225
 
        //maybe they use compiz?
226
 
        //go ahead without the session
227
 
        stopCompleted();
228
 
    }
229
 
}
230
 
 
231
 
void ActivityManagerPrivate::stopCompleted()
232
 
{
233
 
    if (transitioningActivity.isEmpty()) {
234
 
        // kDebug() << "huh?";
235
 
        return;
236
 
    }
237
 
    setActivityState(transitioningActivity, ActivityManager::Stopped);
238
 
    if (currentActivity == transitioningActivity) {
239
 
        ensureCurrentActivityIsRunning();
240
 
    }
241
 
    transitioningActivity.clear();
242
 
    configSync(); //force immediate sync
243
 
}
244
 
 
245
 
void ActivityManagerPrivate::stopCancelled()
246
 
{
247
 
    if (transitioningActivity.isEmpty()) {
248
 
        // kDebug() << "huh?";
249
 
        return;
250
 
    }
251
 
    setActivityState(transitioningActivity, ActivityManager::Running);
252
 
    transitioningActivity.clear();
253
 
}
254
 
 
255
 
int ActivityManager::ActivityState(const QString & id) const
256
 
{
257
 
    //kDebug() << id << "- is it in" << d->activities << "?";
258
 
    if (!d->activities.contains(id)) {
259
 
        return Invalid;
260
 
    } else {
261
 
        // kDebug() << "state of" << id << "is" << d->activities[id];
262
 
        return d->activities[id];
263
 
    }
264
 
}
265
 
 
266
 
void ActivityManagerPrivate::screenLockStateChanged(const bool locked)
267
 
{
268
 
    if (locked) {
269
 
        // already in limbo state.
270
 
        if (currentActivity.isEmpty()) {
271
 
            return;
272
 
        }
273
 
 
274
 
        if (q->IsActivityEncrypted(currentActivity)) {
275
 
            currentActivityBeforeScreenLock = currentActivity;
276
 
            setCurrentActivity(QString());
277
 
        }
278
 
 
279
 
    } else if (!currentActivityBeforeScreenLock.isEmpty()) {
280
 
        setCurrentActivity(currentActivityBeforeScreenLock);
281
 
        currentActivityBeforeScreenLock.clear();
282
 
 
283
 
    }
284
 
}