Unity 8
main.cpp
1 /*
2  * Copyright (C) 2012-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 // Qt
18 #include <QCommandLineParser>
19 #include <QtQuick/QQuickView>
20 #include <QtGui/QGuiApplication>
21 #include <QtQml/QQmlEngine>
22 #include <QtQml/QQmlContext>
23 #include <QLibrary>
24 #include <QDebug>
25 #include <csignal>
26 #include <libintl.h>
27 
28 // local
29 #include <paths.h>
30 #include "MouseTouchAdaptor.h"
31 #include "ApplicationArguments.h"
32 #include "CachingNetworkManagerFactory.h"
33 
34 // Ubuntu Gestures
35 #include <TouchRegistry.h>
36 
37 int main(int argc, const char *argv[])
38 {
39  bool isMirServer = false;
40  if (qgetenv("QT_QPA_PLATFORM") == "ubuntumirclient") {
41  setenv("QT_QPA_PLATFORM", "mirserver", 1 /* overwrite */);
42  isMirServer = true;
43  }
44 
45  QGuiApplication::setApplicationName("unity8");
46  QGuiApplication *application;
47 
48  QCommandLineParser parser;
49  parser.setApplicationDescription("Description: Unity 8 Shell");
50  parser.addHelpOption();
51 
52  QCommandLineOption fullscreenOption("fullscreen",
53  "Run in fullscreen");
54  parser.addOption(fullscreenOption);
55 
56  QCommandLineOption framelessOption("frameless",
57  "Run without window borders");
58  parser.addOption(framelessOption);
59 
60  QCommandLineOption mousetouchOption("mousetouch",
61  "Allow the mouse to provide touch input");
62  parser.addOption(mousetouchOption);
63 
64  QCommandLineOption windowGeometryOption(QStringList() << "windowgeometry",
65  "Specify the window geometry as [<width>x<height>]", "windowgeometry", "1");
66  parser.addOption(windowGeometryOption);
67 
68  QCommandLineOption testabilityOption("testability",
69  "DISCOURAGED: Please set QT_LOAD_TESTABILITY instead. \n \
70 Load the testability driver");
71  parser.addOption(testabilityOption);
72 
73  QCommandLineOption modeOption("mode",
74  "Whether to run greeter and/or shell [full-greeter, full-shell, greeter, shell]",
75  "mode", "full-greeter");
76  parser.addOption(modeOption);
77 
78  application = new QGuiApplication(argc, (char**)argv);
79 
80  // Treat args with single dashes the same as arguments with two dashes
81  // Ex: -fullscreen == --fullscreen
82  parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
83  parser.process(*application);
84 
85  QString indicatorProfile = qgetenv("UNITY_INDICATOR_PROFILE");
86  if (indicatorProfile.isEmpty()) {
87  indicatorProfile = "phone";
88  }
89 
90  ApplicationArguments qmlArgs;
91  if (parser.isSet(windowGeometryOption) &&
92  parser.value(windowGeometryOption).split('x').size() == 2)
93  {
94  QStringList geom = parser.value(windowGeometryOption).split('x');
95  qmlArgs.setSize(geom.at(0).toInt(), geom.at(1).toInt());
96  }
97 
98  // If an invalid option was specified, set it to the default
99  // If no default was provided in the QCommandLineOption constructor, abort.
100  QString shellMode;
101  if(!parser.isSet(modeOption) ||
102  (parser.value(modeOption) != "full-greeter" &&
103  parser.value(modeOption) != "full-shell" &&
104  parser.value(modeOption) != "greeter" &&
105  parser.value(modeOption) != "shell"))
106  {
107  if (modeOption.defaultValues().first() != nullptr) {
108  shellMode = modeOption.defaultValues().first();
109  qWarning() << "Mode argument was not provided or was set to an illegal value. Using default value of --mode=" << shellMode;
110  } else {
111  qFatal("Shell mode argument was not provided and there is no default mode,");
112  }
113 
114  } else {
115  shellMode = parser.value(modeOption);
116  }
117 
118  // The testability driver is only loaded by QApplication but not by QGuiApplication.
119  // However, QApplication depends on QWidget which would add some unneeded overhead => Let's load the testability driver on our own.
120  if (parser.isSet(testabilityOption) || getenv("QT_LOAD_TESTABILITY")) {
121  QLibrary testLib(QLatin1String("qttestability"));
122  if (testLib.load()) {
123  typedef void (*TasInitialize)(void);
124  TasInitialize initFunction = (TasInitialize)testLib.resolve("qt_testability_init");
125  if (initFunction) {
126  initFunction();
127  } else {
128  qCritical("Library qttestability resolve failed!");
129  }
130  } else {
131  qCritical("Library qttestability load failed!");
132  }
133  }
134 
135  bindtextdomain("unity8", translationDirectory().toUtf8().data());
136  textdomain("unity8");
137 
138  QQuickView* view = new QQuickView();
139  view->setResizeMode(QQuickView::SizeRootObjectToView);
140  view->setColor("black");
141  view->setTitle("Unity8 Shell");
142  view->engine()->setBaseUrl(QUrl::fromLocalFile(::qmlDirectory()));
143  view->rootContext()->setContextProperty("applicationArguments", &qmlArgs);
144  view->rootContext()->setContextProperty("indicatorProfile", indicatorProfile);
145  view->rootContext()->setContextProperty("shellMode", shellMode);
146  if (parser.isSet(framelessOption)) {
147  view->setFlags(Qt::FramelessWindowHint);
148  }
149  TouchRegistry touchRegistry;
150  view->installEventFilter(&touchRegistry);
151 
152  // You will need this if you want to interact with touch-only components using a mouse
153  // Needed only when manually testing on a desktop.
154  MouseTouchAdaptor *mouseTouchAdaptor = 0;
155  if (parser.isSet(mousetouchOption)) {
156  mouseTouchAdaptor = MouseTouchAdaptor::instance();
157  }
158 
159  QUrl source(::qmlDirectory()+"Shell.qml");
160  prependImportPaths(view->engine(), ::overrideImportPaths());
161  if (!isMirServer) {
162  prependImportPaths(view->engine(), ::nonMirImportPaths());
163  }
164  appendImportPaths(view->engine(), ::fallbackImportPaths());
165 
166  CachingNetworkManagerFactory *managerFactory = new CachingNetworkManagerFactory();
167  view->engine()->setNetworkAccessManagerFactory(managerFactory);
168 
169  view->setSource(source);
170  QObject::connect(view->engine(), SIGNAL(quit()), application, SLOT(quit()));
171 
172  if (isMirServer || parser.isSet(fullscreenOption)) {
173  view->showFullScreen();
174  } else {
175  view->show();
176  }
177 
178  int result = application->exec();
179 
180  delete view;
181  delete mouseTouchAdaptor;
182  delete application;
183 
184  return result;
185 }