/* * Copyright (C) 2013-2016 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "ApplicationInfo.h" #include "MirSurface.h" #include "SurfaceManager.h" #include #include #include #include #include #define APPLICATION_DEBUG 0 #if APPLICATION_DEBUG #define DEBUG_MSG(params) qDebug().nospace() << "Application["<createSurface(QString("prompt foo"), Mir::NormalType, Mir::RestoredState, nullptr, /* parentSurface */ screenshotUrl); surfaceManager->notifySurfaceCreated(surface); m_promptSurfaceList->addSurface(surface); surfaceManager->activate(surface); } void ApplicationInfo::createSurface() { if (state() == ApplicationInfo::Stopped) { return; } QString surfaceName = name() + "s window title"; if (m_surfaceList->count() > 0) { surfaceName.append(QString(" %1").arg(m_surfaceList->count()+1)); } auto surfaceManager = SurfaceManager::instance(); if (!surfaceManager) { WARNING_MSG("No SurfaceManager"); return; } bool wasFocused = focused(); auto surface = surfaceManager->createSurface(surfaceName, Mir::NormalType, fullscreen() ? Mir::FullscreenState : Mir::RestoredState, nullptr, /* parentSurface */ m_screenshotFileName, m_qmlFilePath); surface->setShellChrome(m_shellChrome); m_surfaceList->addSurface(surface); ++m_liveSurfaceCount; connect(surface, &MirSurface::liveChanged, this, [this, surface](){ if (!surface->live()) { --m_liveSurfaceCount; if (m_liveSurfaceCount == 0) { if (m_closingSurfaces.contains(surface) || (m_state == Running && m_requestedState == RequestedRunning)) { Q_EMIT closed(); } setState(Stopped); } else { if (m_closingSurfaces.contains(surface) && m_requestedState == RequestedSuspended && m_closingSurfaces.count() == 1) { setState(Suspended); } } m_closingSurfaces.removeAll(surface); } }); connect(surface, &MirSurface::closeRequested, this, [this, surface](){ m_closingSurfaces.append(surface); if (m_state == Suspended) { // resume to allow application to close its surface setState(Running); } }); connect(surface, &MirSurfaceInterface::focusedChanged, this, [&](bool /*value*/) { #if APPLICATION_DEBUG qDebug().nospace() << "Application[" << appId() << "].focusedChanged(" << focused() << ")"; #endif Q_EMIT focusedChanged(focused()); }); connect(surface, &MirSurface::focusRequested, this, &ApplicationInfo::focusRequested); if (wasFocused != focused()) { Q_EMIT focusedChanged(focused()); } if (m_state == Starting) { if (m_requestedState == RequestedRunning) { setState(Running); } else { setState(Suspended); } } surfaceManager->notifySurfaceCreated(surface); surfaceManager->activate(surface); } void ApplicationInfo::setIconId(const QString &iconId) { setIcon(QUrl(testDataDir() + "/graphics/applicationIcons/" + iconId + "@18.png")); } void ApplicationInfo::setScreenshotId(const QString &screenshotId) { QString screenshotFileName; if (screenshotId.endsWith(".svg")) { screenshotFileName = QString("qrc:///Unity/Application/screenshots/%2") .arg(screenshotId); } else { screenshotFileName = QString("qrc:///Unity/Application/screenshots/%2@12.png") .arg(screenshotId); } if (screenshotFileName != m_screenshotFileName) { m_screenshotFileName = screenshotFileName; } } void ApplicationInfo::setQmlFilename(const QString &qmlFilename) { m_qmlFilePath = QString("qrc:///Unity/Application/%1").arg(qmlFilename); } void ApplicationInfo::setName(const QString &value) { if (value != m_name) { m_name = value; Q_EMIT nameChanged(value); } } void ApplicationInfo::setIcon(const QUrl &value) { if (value != m_icon) { m_icon = value; Q_EMIT iconChanged(value); } } void ApplicationInfo::setState(State value) { if (value != m_state) { DEBUG_MSG(qPrintable(stateToStr(value))); if (!m_manualSurfaceCreation && value == ApplicationInfo::Starting) { Q_ASSERT(m_surfaceList->count() == 0); m_surfaceCreationTimer.start(); } else if (value == ApplicationInfo::Stopped) { m_surfaceCreationTimer.stop(); for (int i = 0; i < m_surfaceList->count(); ++i) { MirSurface *surface = static_cast(m_surfaceList->get(i)); surface->setLive(false); } for (int i = 0; i < m_promptSurfaceList->count(); ++i) { auto surface = static_cast(m_promptSurfaceList->get(i)); surface->setLive(false); } } m_state = value; Q_EMIT stateChanged(value); } } void ApplicationInfo::close() { DEBUG_MSG(""); if (m_surfaceList->count() > 0) { for (int i = 0; i < m_surfaceList->count(); ++i) { MirSurface *surface = static_cast(m_surfaceList->get(i)); surface->close(); } } else { setState(Stopped); Q_EMIT closed(); } } void ApplicationInfo::setFullscreen(bool value) { m_fullscreen = value; if (m_surfaceList->rowCount() > 0) { m_surfaceList->get(0)->requestState(Mir::FullscreenState); } } bool ApplicationInfo::fullscreen() const { if (m_surfaceList->rowCount() > 0) { return m_surfaceList->get(0)->state() == Mir::FullscreenState; } else { return m_fullscreen; } } void ApplicationInfo::setManualSurfaceCreation(bool value) { if (value != m_manualSurfaceCreation) { m_manualSurfaceCreation = value; Q_EMIT manualSurfaceCreationChanged(value); if (m_manualSurfaceCreation && m_surfaceCreationTimer.isActive()) { m_surfaceCreationTimer.stop(); } } } Qt::ScreenOrientations ApplicationInfo::supportedOrientations() const { return m_supportedOrientations; } void ApplicationInfo::setSupportedOrientations(Qt::ScreenOrientations orientations) { m_supportedOrientations = orientations; } bool ApplicationInfo::rotatesWindowContents() const { return m_rotatesWindowContents; } void ApplicationInfo::setRotatesWindowContents(bool value) { m_rotatesWindowContents = value; } ApplicationInfo::RequestedState ApplicationInfo::requestedState() const { return m_requestedState; } void ApplicationInfo::setRequestedState(RequestedState value) { if (m_requestedState == value) { return; } DEBUG_MSG((value == RequestedRunning ? "RequestedRunning" : "RequestedSuspended") ); m_requestedState = value; Q_EMIT requestedStateChanged(m_requestedState); if (m_requestedState == RequestedRunning) { if (m_state == Suspended) { Q_ASSERT(m_liveSurfaceCount > 0); setState(Running); } else if (m_state == Stopped) { Q_ASSERT(m_liveSurfaceCount == 0); // it's restarting setState(Starting); } } else if (m_requestedState == RequestedSuspended && m_state == Running && m_closingSurfaces.isEmpty()) { setState(Suspended); } } bool ApplicationInfo::isTouchApp() const { return m_isTouchApp; } void ApplicationInfo::setIsTouchApp(bool isTouchApp) { m_isTouchApp = isTouchApp; } bool ApplicationInfo::exemptFromLifecycle() const { return m_exemptFromLifecycle; } void ApplicationInfo::setExemptFromLifecycle(bool exemptFromLifecycle) { if (m_exemptFromLifecycle != exemptFromLifecycle) { m_exemptFromLifecycle = exemptFromLifecycle; Q_EMIT exemptFromLifecycleChanged(m_exemptFromLifecycle); } } QSize ApplicationInfo::initialSurfaceSize() const { return m_initialSurfaceSize; } void ApplicationInfo::setInitialSurfaceSize(const QSize &size) { if (size != m_initialSurfaceSize) { m_initialSurfaceSize = size; Q_EMIT initialSurfaceSizeChanged(m_initialSurfaceSize); } } void ApplicationInfo::setShellChrome(Mir::ShellChrome shellChrome) { m_shellChrome = shellChrome; if (m_surfaceList->rowCount() > 0) { static_cast(m_surfaceList->get(0))->setShellChrome(shellChrome); } } bool ApplicationInfo::focused() const { bool someSurfaceHasFocus = false; // to be proven wrong for (int i = 0; i < m_surfaceList->count() && !someSurfaceHasFocus; ++i) { someSurfaceHasFocus = m_surfaceList->get(i)->focused(); } return someSurfaceHasFocus; } void ApplicationInfo::onSurfaceCountChanged() { if (m_surfaceList->count() == 0 && m_state == Running) { setState(Stopped); } } void ApplicationInfo::requestFocus() { if (m_surfaceList->count() == 0) { Q_EMIT focusRequested(); } else { auto surface = static_cast(m_surfaceList->get(0)); surface->requestFocus(); } }