/* * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License version 3, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ // Qt #include #include // local #include "mirsurfacemanager.h" #include "sessionmanager.h" #include "application_manager.h" #include "maybe_tracepoints.h" // common #include // QPA mirserver #include "nativeinterface.h" #include "mirserver.h" #include "sessionlistener.h" #include "logging.h" Q_LOGGING_CATEGORY(QTMIR_SURFACES, "qtmir.surfaces") namespace ms = mir::scene; namespace qtmir { MirSurfaceManager *MirSurfaceManager::the_surface_manager = nullptr; void connectToSessionListener(MirSurfaceManager *manager, SessionListener *listener) { QObject::connect(listener, &SessionListener::sessionCreatedSurface, manager, &MirSurfaceManager::onSessionCreatedSurface); QObject::connect(listener, &SessionListener::sessionDestroyingSurface, manager, &MirSurfaceManager::onSessionDestroyingSurface); } MirSurfaceManager* MirSurfaceManager::singleton() { if (!the_surface_manager) { NativeInterface *nativeInterface = dynamic_cast(QGuiApplication::platformNativeInterface()); if (!nativeInterface) { qCritical("ERROR: Unity.Application QML plugin requires use of the 'mirserver' QPA plugin"); QGuiApplication::quit(); return nullptr; } SessionListener *sessionListener = static_cast(nativeInterface->nativeResourceForIntegration("SessionListener")); MirShell *shell = static_cast(nativeInterface->nativeResourceForIntegration("Shell")); the_surface_manager = new MirSurfaceManager(nativeInterface->m_mirServer, shell, SessionManager::singleton()); connectToSessionListener(the_surface_manager, sessionListener); } return the_surface_manager; } MirSurfaceManager::MirSurfaceManager( const QSharedPointer& mirServer, MirShell *shell, SessionManager* sessionManager, QObject *parent) : MirSurfaceItemModel(parent) , m_mirServer(mirServer) , m_shell(shell) , m_sessionManager(sessionManager) { qCDebug(QTMIR_SURFACES) << "MirSurfaceManager::MirSurfaceManager - this=" << this; setObjectName("qtmir::SurfaceManager"); } MirSurfaceManager::~MirSurfaceManager() { qCDebug(QTMIR_SURFACES) << "MirSurfaceManager::~MirSurfaceManager - this=" << this; m_mirSurfaceToItemHash.clear(); } void MirSurfaceManager::onSessionCreatedSurface(const mir::scene::Session *mirSession, const std::shared_ptr &surface, const std::shared_ptr &observer) { qCDebug(QTMIR_SURFACES) << "MirSurfaceManager::onSessionCreatedSurface - mirSession=" << mirSession << "surface=" << surface.get() << "surface.name=" << surface->name().c_str(); SessionInterface* session = m_sessionManager->findSession(mirSession); auto qmlSurface = new MirSurfaceItem(surface, session, m_shell, observer); { QMutexLocker lock(&m_mutex); m_mirSurfaceToItemHash.insert(surface.get(), qmlSurface); } if (session) session->setSurface(qmlSurface); // Only notify QML of surface creation once it has drawn its first frame. connect(qmlSurface, &MirSurfaceItemInterface::firstFrameDrawn, this, [=]() { tracepoint(qtmir, firstFrameDrawn); Q_EMIT surfaceCreated(qmlSurface); insert(0, qmlSurface); }); // clean up after MirSurfaceItem is destroyed connect(qmlSurface, &MirSurfaceItem::destroyed, this, [&](QObject *item) { auto mirSurfaceItem = static_cast(item); { QMutexLocker lock(&m_mutex); m_mirSurfaceToItemHash.remove(m_mirSurfaceToItemHash.key(mirSurfaceItem)); } remove(mirSurfaceItem); tracepoint(qtmir, surfaceDestroyed); }); tracepoint(qtmir, surfaceCreated); } void MirSurfaceManager::onSessionDestroyingSurface(const mir::scene::Session *session, const std::shared_ptr &surface) { qCDebug(QTMIR_SURFACES) << "MirSurfaceManager::onSessionDestroyingSurface - session=" << session << "surface=" << surface.get() << "surface.name=" << surface->name().c_str(); MirSurfaceItemInterface* item = nullptr; { QMutexLocker lock(&m_mutex); auto it = m_mirSurfaceToItemHash.find(surface.get()); if (it != m_mirSurfaceToItemHash.end()) { item = it.value(); m_mirSurfaceToItemHash.remove(m_mirSurfaceToItemHash.key(item)); } else { qCritical() << "MirSurfaceManager::onSessionDestroyingSurface: unable to find MirSurfaceItem corresponding" << "to surface=" << surface.get() << "surface.name=" << surface->name().c_str(); return; } } item->setEnabled(false); //disable input events item->setLive(false); //disable input events Q_EMIT surfaceDestroyed(item); } } // namespace qtmir