/*
* 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();
}
}