2
* Copyright (C) 2014-2016 Canonical, Ltd.
4
* This program is free software: you can redistribute it and/or modify it under
5
* the terms of the GNU Lesser General Public License version 3, as published by
6
* the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful, but WITHOUT
9
* ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10
* SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
* Lesser General Public License for more details.
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18
#include <QGuiApplication>
21
#include "application_manager.h"
22
#include "debughelpers.h"
23
#include "sessionmanager.h"
26
#include "nativeinterface.h"
27
#include "sessionlistener.h"
29
#include "promptsessionlistener.h"
32
#include <mir/scene/prompt_session.h>
33
#include <mir/scene/prompt_session_manager.h>
34
#include <mir/report_exception.h>
36
namespace ms = mir::scene;
40
SessionManager *SessionManager::the_session_manager = nullptr;
43
void connectToSessionListener(SessionManager *manager, SessionListener *listener)
45
QObject::connect(listener, &SessionListener::sessionStarting,
46
manager, &SessionManager::onSessionStarting);
47
QObject::connect(listener, &SessionListener::sessionStopping,
48
manager, &SessionManager::onSessionStopping);
51
void connectToPromptSessionListener(SessionManager * manager, PromptSessionListener * listener)
53
QObject::connect(listener, &PromptSessionListener::promptSessionStarting,
54
manager, &SessionManager::onPromptSessionStarting);
55
QObject::connect(listener, &PromptSessionListener::promptSessionStopping,
56
manager, &SessionManager::onPromptSessionStopping);
57
QObject::connect(listener, &PromptSessionListener::promptProviderAdded,
58
manager, &SessionManager::onPromptProviderAdded);
59
QObject::connect(listener, &PromptSessionListener::promptProviderRemoved,
60
manager, &SessionManager::onPromptProviderRemoved);
63
SessionManager* SessionManager::singleton()
66
if (!the_session_manager) {
68
NativeInterface *nativeInterface = dynamic_cast<NativeInterface*>(QGuiApplication::platformNativeInterface());
70
if (!nativeInterface) {
71
qCritical("ERROR: Unity.Application QML plugin requires use of the 'mirserver' QPA plugin");
72
QGuiApplication::quit();
76
SessionListener *sessionListener = static_cast<SessionListener*>(nativeInterface->nativeResourceForIntegration("SessionListener"));
77
PromptSessionListener *promptSessionListener = static_cast<PromptSessionListener*>(nativeInterface->nativeResourceForIntegration("PromptSessionListener"));
79
the_session_manager = new SessionManager(nativeInterface->thePromptSessionManager(), ApplicationManager::singleton());
81
connectToSessionListener(the_session_manager, sessionListener);
82
connectToPromptSessionListener(the_session_manager, promptSessionListener);
84
return the_session_manager;
88
// We only call mir::report_exception() here to force linkage against libmirserver.
89
// Unless we force this module to have a link dependency on libmirserver we get
90
// several tests hanging during link loading. I wish I understood why. alan_g
91
mir::report_exception();
95
SessionManager::SessionManager(
96
const std::shared_ptr<mir::scene::PromptSessionManager>& promptSessionManager,
97
ApplicationManager* applicationManager,
99
: SessionModel(parent)
100
, m_promptSessionManager(promptSessionManager)
101
, m_applicationManager(applicationManager)
103
qCDebug(QTMIR_SESSIONS) << "SessionManager::SessionManager - this=" << this;
104
setObjectName(QStringLiteral("qtmir::SessionManager"));
107
SessionManager::~SessionManager()
109
qCDebug(QTMIR_SESSIONS) << "SessionManager::~SessionManager - this=" << this;
112
SessionInterface *SessionManager::findSession(const mir::scene::Session* session) const
114
if (!session) return nullptr;
116
for (SessionInterface* child : list()) {
117
if (child->session().get() == session)
123
void SessionManager::onSessionStarting(std::shared_ptr<mir::scene::Session> const& session)
125
qCDebug(QTMIR_SESSIONS) << "SessionManager::onSessionStarting - sessionName=" << session->name().c_str();
127
Session* qmlSession = new Session(session, m_promptSessionManager);
128
insert(0, qmlSession);
130
Application* application = m_applicationManager->findApplicationWithSession(session);
131
if (application && application->state() != Application::Running) {
132
application->setSession(qmlSession);
134
// need to remove if we've destroyed outside
135
connect(qmlSession, &Session::destroyed, this, [&](QObject *item) {
136
auto sessionToRemove = static_cast<Session*>(item);
137
remove(sessionToRemove);
140
Q_EMIT sessionStarting(qmlSession);
143
void SessionManager::onSessionStopping(std::shared_ptr<mir::scene::Session> const& session)
145
qCDebug(QTMIR_SESSIONS) << "SessionManager::onSessionStopping - sessionName=" << session->name().c_str();
147
SessionInterface* qmlSession = findSession(session.get());
148
if (!qmlSession) return;
152
qmlSession->setLive(false);
153
Q_EMIT sessionStopping(qmlSession);
156
void SessionManager::onPromptSessionStarting(const std::shared_ptr<ms::PromptSession>& promptSession)
158
qCDebug(QTMIR_SESSIONS) << "SessionManager::onPromptSessionStarting - promptSession=" << promptSession.get();
160
std::shared_ptr<mir::scene::Session> appSession = m_promptSessionManager->application_for(promptSession);
161
SessionInterface *qmlAppSession = findSession(appSession.get());
163
m_mirPromptToSessionHash[promptSession.get()] = qmlAppSession;
164
qmlAppSession->appendPromptSession(promptSession);
166
qCDebug(QTMIR_SESSIONS) << "SessionManager::onPromptSessionStarting - could not find app session for prompt session";
170
void SessionManager::onPromptSessionStopping(const std::shared_ptr<ms::PromptSession>& promptSession)
172
qCDebug(QTMIR_SESSIONS) << "SessionManager::onPromptSessionStopping - promptSession=" << promptSession.get();
174
for (SessionInterface *qmlSession : this->list()) {
175
qmlSession->removePromptSession(promptSession);
177
m_mirPromptToSessionHash.remove(promptSession.get());
180
void SessionManager::onPromptProviderAdded(const mir::scene::PromptSession *promptSession,
181
const std::shared_ptr<mir::scene::Session> &promptProvider)
183
qCDebug(QTMIR_SESSIONS) << "SessionManager::onPromptProviderAdded - promptSession=" << promptSession << " promptProvider=" << promptProvider.get();
185
SessionInterface* qmlAppSession = m_mirPromptToSessionHash.value(promptSession, nullptr);
186
if (!qmlAppSession) {
187
qCDebug(QTMIR_SESSIONS) << "SessionManager::onPromptProviderAdded - could not find session item for app session";
191
SessionInterface* qmlPromptProvider = findSession(promptProvider.get());
192
if (!qmlPromptProvider) {
193
qCDebug(QTMIR_SESSIONS) << "SessionManager::onPromptProviderAdded - could not find session item for provider session";
197
qmlAppSession->addChildSession(qmlPromptProvider);
200
void SessionManager::onPromptProviderRemoved(const mir::scene::PromptSession *promptSession,
201
const std::shared_ptr<mir::scene::Session> &promptProvider)
203
qCDebug(QTMIR_SESSIONS) << "SessionManager::onPromptProviderRemoved - promptSession=" << promptSession << " promptProvider=" << promptProvider.get();
205
SessionInterface* qmlPromptProvider = findSession(promptProvider.get());
206
if (!qmlPromptProvider) {
207
qCDebug(QTMIR_SESSIONS) << "SessionManager::onPromptProviderAdded - could not find session item for provider session";
210
qmlPromptProvider->setLive(false);