Unity 8
UnityApplication.cpp
1 /*
2  * Copyright (C) 2015 Canonical, Ltd.
3  *
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.
7  *
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.
12  *
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/>.
15  */
16 
17 #include "UnityApplication.h"
18 
19 // Qt
20 #include <QLibrary>
21 #include <QProcess>
22 #include <QScreen>
23 #include <QQmlContext>
24 #include <QQmlComponent>
25 
26 #include <QGSettings>
27 
28 #include <libintl.h>
29 
30 // libandroid-properties
31 #include <hybris/properties/properties.h>
32 
33 // qtmir
34 #include <qtmir/displayconfigurationstorage.h>
35 
36 // local
37 #include <paths.h>
38 #include "CachingNetworkManagerFactory.h"
39 #include "UnityCommandLineParser.h"
40 #include "DebuggingController.h"
41 #include "WindowManagementPolicy.h"
42 #include "DisplayConfigurationStorage.h"
43 
44 #include <QDebug>
45 
46 
47 
48 UnityApplication::UnityApplication(int & argc, char ** argv)
49  : qtmir::MirServerApplication(argc, argv, { qtmir::SetWindowManagementPolicy<WindowManagementPolicy>(),
50  qtmir::SetDisplayConfigurationStorage<DisplayConfigurationStorage>() })
51  , m_qmlArgs(this)
52 {
53  setApplicationName(QStringLiteral("unity8"));
54  setOrganizationName(QStringLiteral("Canonical"));
55 
56  setupQmlEngine();
57 
58  if (m_qmlArgs.deviceName().isEmpty()) {
59  char buffer[200];
60  property_get("ro.product.device", buffer /* value */, "desktop" /* default_value*/);
61  m_qmlArgs.setDeviceName(QString(buffer));
62  }
63 
64  // The testability driver is only loaded by QApplication but not by QGuiApplication.
65  // However, QApplication depends on QWidget which would add some unneeded overhead => Let's load the testability driver on our own.
66  if (m_qmlArgs.hasTestability() || getenv("QT_LOAD_TESTABILITY")) {
67  QLibrary testLib(QStringLiteral("qttestability"));
68  if (testLib.load()) {
69  typedef void (*TasInitialize)(void);
70  TasInitialize initFunction = (TasInitialize)testLib.resolve("qt_testability_init");
71  if (initFunction) {
72  initFunction();
73  } else {
74  qCritical("Library qttestability resolve failed!");
75  }
76  } else {
77  qCritical("Library qttestability load failed!");
78  }
79  }
80 
81  bindtextdomain("unity8", translationDirectory().toUtf8().data());
82  textdomain("unity8");
83 
84  QScopedPointer<QGSettings> gSettings(new QGSettings("com.canonical.Unity8"));
85  gSettings->reset(QStringLiteral("alwaysShowOsk"));
86 
87 
88  QByteArray pxpguEnv = qgetenv("GRID_UNIT_PX");
89  bool ok;
90  int pxpgu = pxpguEnv.toInt(&ok);
91  if (!ok) {
92  pxpgu = 8;
93  }
94  m_qmlEngine->rootContext()->setContextProperty("internalGu", pxpgu);
95  m_qmlEngine->rootContext()->setContextProperty(QStringLiteral("applicationArguments"), &m_qmlArgs);
96  m_qmlEngine->rootContext()->setContextProperty("DebuggingController", new DebuggingController(this));
97 
98  auto component(new QQmlComponent(m_qmlEngine, m_qmlArgs.qmlfie()));
99  component->create();
100  if (component->status() == QQmlComponent::Error) {
101  m_qmlEngine->rootContext()->setContextProperty(QStringLiteral("errorString"), component->errorString());
102  auto errorComponent(new QQmlComponent(m_qmlEngine,
103  QUrl::fromLocalFile(::qmlDirectory() + "/ErrorApplication.qml")));
104  errorComponent->create();
105  qDebug() << errorComponent->errorString();
106  return;
107  }
108 
109  #ifdef UNITY8_ENABLE_TOUCH_EMULATION
110  // You will need this if you want to interact with touch-only components using a mouse
111  // Needed only when manually testing on a desktop.
112  if (m_qmlArgs.hasMouseToTouch()) {
113  m_mouseTouchAdaptor = MouseTouchAdaptor::instance();
114  }
115  #endif
116 
117  if (m_qmlArgs.mode().compare("greeter") == 0) {
118  if (!QProcess::startDetached("initctl emit --no-wait unity8-greeter-started")) {
119  qDebug() << "Unable to send unity8-greeter-started event to Upstart";
120  }
121  }
122 }
123 
124 UnityApplication::~UnityApplication()
125 {
126  destroyResources();
127 }
128 
129 void UnityApplication::destroyResources()
130 {
131  #ifdef UNITY8_ENABLE_TOUCH_EMULATION
132  delete m_mouseTouchAdaptor;
133  m_mouseTouchAdaptor = nullptr;
134  #endif
135 
136  delete m_qmlEngine;
137  m_qmlEngine = nullptr;
138 }
139 
140 void UnityApplication::setupQmlEngine()
141 {
142  m_qmlEngine = new QQmlEngine(this);
143 
144  m_qmlEngine->setBaseUrl(QUrl::fromLocalFile(::qmlDirectory()));
145 
146  prependImportPaths(m_qmlEngine, ::overrideImportPaths());
147  appendImportPaths(m_qmlEngine, ::fallbackImportPaths());
148 
149  m_qmlEngine->setNetworkAccessManagerFactory(new CachingNetworkManagerFactory);
150 
151  QObject::connect(m_qmlEngine, &QQmlEngine::quit, this, &QGuiApplication::quit);
152 }
Definition: Screens.h:24