@@ -0,0 +1,166 @@
2+ * Copyright (C) 2015 Canonical, Ltd.
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
17+#include "ShellApplication.h"
25+// libandroid-properties
26+#include <hybris/properties/properties.h>
30+#include "CachingNetworkManagerFactory.h"
31+#include "MouseTouchAdaptor.h"
32+#include "UnityCommandLineParser.h"
34+ShellApplication::ShellApplication(int & argc, char ** argv, bool isMirServer)
35+ : QGuiApplication(argc, argv)
38+ setApplicationName(QStringLiteral("unity8"));
40+ connect(this, &QGuiApplication::screenAdded, this, &ShellApplication::onScreenAdded);
42+ setupQmlEngine(isMirServer);
44+ UnityCommandLineParser parser(*this);
46+ if (!parser.deviceName().isEmpty()) {
47+ m_qmlArgs.setDeviceName(parser.deviceName());
50+ property_get("ro.product.device", buffer /* value */, "desktop" /* default_value*/);
51+ m_qmlArgs.setDeviceName(QString(buffer));
54+ m_qmlArgs.setMode(parser.mode());
56+ // The testability driver is only loaded by QApplication but not by QGuiApplication.
57+ // However, QApplication depends on QWidget which would add some unneeded overhead => Let's load the testability driver on our own.
58+ if (parser.hasTestability() || getenv("QT_LOAD_TESTABILITY")) {
59+ QLibrary testLib(QStringLiteral("qttestability"));
60+ if (testLib.load()) {
61+ typedef void (*TasInitialize)(void);
62+ TasInitialize initFunction = (TasInitialize)testLib.resolve("qt_testability_init");
66+ qCritical("Library qttestability resolve failed!");
69+ qCritical("Library qttestability load failed!");
73+ bindtextdomain("unity8", translationDirectory().toUtf8().data());
74+ textdomain("unity8");
76+ m_shellView.reset(new ShellView(m_qmlEngine, &m_qmlArgs));
78+ if (parser.windowGeometry().isValid()) {
79+ m_shellView->setWidth(parser.windowGeometry().width());
80+ m_shellView->setHeight(parser.windowGeometry().height());
83+ if (parser.hasFrameless()) {
84+ m_shellView->setFlags(Qt::FramelessWindowHint);
87+ // You will need this if you want to interact with touch-only components using a mouse
88+ // Needed only when manually testing on a desktop.
89+ if (parser.hasMouseToTouch()) {
90+ m_mouseTouchAdaptor.reset(MouseTouchAdaptor::instance());
94+ // Some hard-coded policy for now.
95+ // NB: We don't support more than two screens at the moment
97+ // TODO: Support an arbitrary number of screens and different policies
98+ // (eg cloned desktop, several desktops, etc)
99+ if (isMirServer && screens().count() == 2) {
100+ m_shellView->setScreen(screens().at(1));
102+ m_secondaryWindow.reset(new SecondaryWindow(m_qmlEngine));
103+ m_secondaryWindow->setScreen(screens().at(0));
104+ // QWindow::showFullScreen() also calls QWindow::requestActivate() and we don't want that!
105+ m_secondaryWindow->setWindowState(Qt::WindowFullScreen);
106+ m_secondaryWindow->setVisible(true);
109+ if (isMirServer || parser.hasFullscreen()) {
110+ m_shellView->showFullScreen();
112+ m_shellView->show();
116+void ShellApplication::setupQmlEngine(bool isMirServer)
118+ m_qmlEngine = new QQmlEngine(this);
120+ m_qmlEngine->setBaseUrl(QUrl::fromLocalFile(::qmlDirectory()));
122+ prependImportPaths(m_qmlEngine, ::overrideImportPaths());
124+ prependImportPaths(m_qmlEngine, ::nonMirImportPaths());
126+ appendImportPaths(m_qmlEngine, ::fallbackImportPaths());
128+ m_qmlEngine->setNetworkAccessManagerFactory(new CachingNetworkManagerFactory);
130+ QObject::connect(m_qmlEngine, &QQmlEngine::quit, this, &QGuiApplication::quit);
133+void ShellApplication::onScreenAdded(QScreen * /*screen*/)
135+ // TODO: Support an arbitrary number of screens and different policies
136+ // (eg cloned desktop, several desktops, etc)
137+ if (screens().count() == 2) {
138+ m_shellView->setScreen(screens().at(1));
139+ // Changing the QScreen where a QWindow is drawn makes it also lose focus (besides having
140+ // its backing QPlatformWindow recreated). So lets refocus it.
141+ m_shellView->requestActivate();
143+ m_secondaryWindow.reset(new SecondaryWindow(m_qmlEngine));
144+ m_secondaryWindow->setScreen(screens().at(0));
146+ // QWindow::showFullScreen() also calls QWindow::requestActivate() and we don't want that!
147+ m_secondaryWindow->setWindowState(Qt::WindowFullScreen);
148+ m_secondaryWindow->setVisible(true);
152+void ShellApplication::onScreenAboutToBeRemoved(QScreen *screen)
154+ // TODO: Support an arbitrary number of screens and different policies
155+ // (eg cloned desktop, several desktops, etc)
156+ if (screen == m_shellView->screen()) {
157+ Q_ASSERT(screens().count() > 1);
158+ Q_ASSERT(screens().at(0) != screen);
159+ Q_ASSERT(!m_secondaryWindow.isNull());
160+ m_secondaryWindow.reset();
161+ m_shellView->setScreen(screens().first());
162+ // Changing the QScreen where a QWindow is drawn makes it also lose focus (besides having
163+ // its backing QPlatformWindow recreated). So lets refocus it.
164+ m_shellView->requestActivate();