2
* Copyright (C) 2013-2015 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/>.
17
#include "mirsurfacemanager.h"
20
#include <QGuiApplication>
21
#include <QMutexLocker>
24
#include "mirsurface.h"
25
#include "sessionmanager.h"
26
#include "application_manager.h"
27
#include "tracepoints.h" // generated from tracepoints.tp
30
#include <debughelpers.h>
33
#include "nativeinterface.h"
34
#include "mirserver.h"
35
#include "sessionlistener.h"
38
Q_LOGGING_CATEGORY(QTMIR_SURFACES, "qtmir.surfaces")
40
namespace ms = mir::scene;
44
MirSurfaceManager *MirSurfaceManager::instance = nullptr;
47
void connectToSessionListener(MirSurfaceManager *manager, SessionListener *listener)
49
QObject::connect(listener, &SessionListener::sessionCreatedSurface,
50
manager, &MirSurfaceManager::onSessionCreatedSurface);
51
QObject::connect(listener, &SessionListener::sessionDestroyingSurface,
52
manager, &MirSurfaceManager::onSessionDestroyingSurface);
55
MirSurfaceManager* MirSurfaceManager::singleton()
59
NativeInterface *nativeInterface = dynamic_cast<NativeInterface*>(QGuiApplication::platformNativeInterface());
61
if (!nativeInterface) {
62
qCritical("ERROR: Unity.Application QML plugin requires use of the 'mirserver' QPA plugin");
63
QGuiApplication::quit();
67
SessionListener *sessionListener = static_cast<SessionListener*>(nativeInterface->nativeResourceForIntegration("SessionListener"));
68
MirShell *shell = static_cast<MirShell*>(nativeInterface->nativeResourceForIntegration("Shell"));
70
instance = new MirSurfaceManager(nativeInterface->m_mirServer, shell, SessionManager::singleton());
72
connectToSessionListener(instance, sessionListener);
77
MirSurfaceManager::MirSurfaceManager(
78
const QSharedPointer<MirServer>& mirServer,
80
SessionManager* sessionManager,
83
, m_mirServer(mirServer)
85
, m_sessionManager(sessionManager)
87
qCDebug(QTMIR_SURFACES) << "MirSurfaceManager::MirSurfaceManager - this=" << this;
88
setObjectName("qtmir::SurfaceManager");
91
MirSurfaceManager::~MirSurfaceManager()
93
qCDebug(QTMIR_SURFACES) << "MirSurfaceManager::~MirSurfaceManager - this=" << this;
95
m_mirSurfaceToQmlSurfaceHash.clear();
98
void MirSurfaceManager::onSessionCreatedSurface(const mir::scene::Session *mirSession,
99
const std::shared_ptr<mir::scene::Surface> &surface,
100
const std::shared_ptr<SurfaceObserver> &observer)
102
qCDebug(QTMIR_SURFACES) << "MirSurfaceManager::onSessionCreatedSurface - mirSession=" << mirSession
103
<< "surface=" << surface.get() << "surface.name=" << surface->name().c_str();
105
SessionInterface* session = m_sessionManager->findSession(mirSession);
106
auto qmlSurface = new MirSurface(surface, session, m_shell, observer);
108
QMutexLocker lock(&m_mutex);
109
m_mirSurfaceToQmlSurfaceHash.insert(surface.get(), qmlSurface);
113
session->registerSurface(qmlSurface);
115
// Only notify QML of surface creation once it has drawn its first frame.
116
connect(qmlSurface, &MirSurfaceInterface::firstFrameDrawn, this, [=]() {
117
tracepoint(qtmir, firstFrameDrawn);
118
Q_EMIT surfaceCreated(qmlSurface);
121
// clean up after MirSurface is destroyed
122
connect(qmlSurface, &QObject::destroyed, this, [&](QObject *obj) {
123
auto qmlSurface = static_cast<MirSurfaceInterface*>(obj);
125
QMutexLocker lock(&m_mutex);
126
m_mirSurfaceToQmlSurfaceHash.remove(m_mirSurfaceToQmlSurfaceHash.key(qmlSurface));
129
tracepoint(qtmir, surfaceDestroyed);
131
tracepoint(qtmir, surfaceCreated);
134
void MirSurfaceManager::onSessionDestroyingSurface(const mir::scene::Session *session,
135
const std::shared_ptr<mir::scene::Surface> &surface)
137
qCDebug(QTMIR_SURFACES) << "MirSurfaceManager::onSessionDestroyingSurface - session=" << session
138
<< "surface=" << surface.get() << "surface.name=" << surface->name().c_str();
140
MirSurfaceInterface* qmlSurface = nullptr;
142
QMutexLocker lock(&m_mutex);
143
auto it = m_mirSurfaceToQmlSurfaceHash.find(surface.get());
144
if (it != m_mirSurfaceToQmlSurfaceHash.end()) {
146
qmlSurface = it.value();
148
m_mirSurfaceToQmlSurfaceHash.erase(it);
150
qCritical() << "MirSurfaceManager::onSessionDestroyingSurface: unable to find MirSurface corresponding"
151
<< "to surface=" << surface.get() << "surface.name=" << surface->name().c_str();
156
qmlSurface->setLive(false);
157
Q_EMIT surfaceDestroyed(qmlSurface);