~lukas-kde/unity8/activateWindows

« back to all changes in this revision

Viewing changes to src/ShellApplication.cpp

  • Committer: Lukáš Tinkl
  • Date: 2015-10-26 13:50:42 UTC
  • mfrom: (2004.1.15 trunk)
  • Revision ID: lukas.tinkl@canonical.com-20151026135042-njfom5vn3nb8fxhy
merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "ShellApplication.h"
 
18
 
 
19
// Qt
 
20
#include <QLibrary>
 
21
#include <QScreen>
 
22
 
 
23
#include <libintl.h>
 
24
 
 
25
// libandroid-properties
 
26
#include <hybris/properties/properties.h>
 
27
 
 
28
// local
 
29
#include <paths.h>
 
30
#include "CachingNetworkManagerFactory.h"
 
31
#include "MouseTouchAdaptor.h"
 
32
#include "UnityCommandLineParser.h"
 
33
 
 
34
ShellApplication::ShellApplication(int & argc, char ** argv, bool isMirServer)
 
35
    : QGuiApplication(argc, argv)
 
36
    , m_shellView(nullptr)
 
37
    , m_secondaryWindow(nullptr)
 
38
    , m_mouseTouchAdaptor(nullptr)
 
39
    , m_qmlEngine(nullptr)
 
40
{
 
41
 
 
42
    setApplicationName(QStringLiteral("unity8"));
 
43
 
 
44
    connect(this, &QGuiApplication::screenAdded, this, &ShellApplication::onScreenAdded);
 
45
 
 
46
    setupQmlEngine(isMirServer);
 
47
 
 
48
    UnityCommandLineParser parser(*this);
 
49
 
 
50
    if (!parser.deviceName().isEmpty()) {
 
51
        m_deviceName = parser.deviceName();
 
52
    } else {
 
53
        char buffer[200];
 
54
        property_get("ro.product.device", buffer /* value */, "desktop" /* default_value*/);
 
55
        m_deviceName = QString(buffer);
 
56
    }
 
57
    m_qmlArgs.setDeviceName(m_deviceName);
 
58
 
 
59
    m_qmlArgs.setMode(parser.mode());
 
60
 
 
61
    // The testability driver is only loaded by QApplication but not by QGuiApplication.
 
62
    // However, QApplication depends on QWidget which would add some unneeded overhead => Let's load the testability driver on our own.
 
63
    if (parser.hasTestability() || getenv("QT_LOAD_TESTABILITY")) {
 
64
        QLibrary testLib(QStringLiteral("qttestability"));
 
65
        if (testLib.load()) {
 
66
            typedef void (*TasInitialize)(void);
 
67
            TasInitialize initFunction = (TasInitialize)testLib.resolve("qt_testability_init");
 
68
            if (initFunction) {
 
69
                initFunction();
 
70
            } else {
 
71
                qCritical("Library qttestability resolve failed!");
 
72
            }
 
73
        } else {
 
74
            qCritical("Library qttestability load failed!");
 
75
        }
 
76
    }
 
77
 
 
78
    bindtextdomain("unity8", translationDirectory().toUtf8().data());
 
79
    textdomain("unity8");
 
80
 
 
81
    m_shellView = new ShellView(m_qmlEngine, &m_qmlArgs);
 
82
 
 
83
    if (parser.windowGeometry().isValid()) {
 
84
        m_shellView->setWidth(parser.windowGeometry().width());
 
85
        m_shellView->setHeight(parser.windowGeometry().height());
 
86
    }
 
87
 
 
88
    if (parser.hasFrameless()) {
 
89
        m_shellView->setFlags(Qt::FramelessWindowHint);
 
90
    }
 
91
 
 
92
    // You will need this if you want to interact with touch-only components using a mouse
 
93
    // Needed only when manually testing on a desktop.
 
94
    if (parser.hasMouseToTouch()) {
 
95
        m_mouseTouchAdaptor = MouseTouchAdaptor::instance();
 
96
    }
 
97
 
 
98
 
 
99
    // Some hard-coded policy for now.
 
100
    // NB: We don't support more than two screens at the moment
 
101
    //
 
102
    // TODO: Support an arbitrary number of screens and different policies
 
103
    //       (eg cloned desktop, several desktops, etc)
 
104
    if (isMirServer && screens().count() == 2) {
 
105
        m_shellView->setScreen(screens().at(1));
 
106
        m_qmlArgs.setDeviceName("desktop");
 
107
 
 
108
        m_secondaryWindow = new SecondaryWindow(m_qmlEngine);
 
109
        m_secondaryWindow->setScreen(screens().at(0));
 
110
        // QWindow::showFullScreen() also calls QWindow::requestActivate() and we don't want that!
 
111
        m_secondaryWindow->setWindowState(Qt::WindowFullScreen);
 
112
        m_secondaryWindow->setVisible(true);
 
113
    }
 
114
 
 
115
    if (isMirServer || parser.hasFullscreen()) {
 
116
        m_shellView->showFullScreen();
 
117
    } else {
 
118
        m_shellView->show();
 
119
    }
 
120
}
 
121
 
 
122
ShellApplication::~ShellApplication()
 
123
{
 
124
    destroyResources();
 
125
}
 
126
 
 
127
void ShellApplication::destroyResources()
 
128
{
 
129
    // Deletion order is important. Don't use QScopedPointers and the like
 
130
    // Otherwise the process will hang on shutdown (bug somewhere I guess).
 
131
    delete m_shellView;
 
132
    m_shellView = nullptr;
 
133
 
 
134
    delete m_secondaryWindow;
 
135
    m_secondaryWindow = nullptr;
 
136
 
 
137
    delete m_mouseTouchAdaptor;
 
138
    m_mouseTouchAdaptor = nullptr;
 
139
 
 
140
    delete m_qmlEngine;
 
141
    m_qmlEngine = nullptr;
 
142
}
 
143
 
 
144
void ShellApplication::setupQmlEngine(bool isMirServer)
 
145
{
 
146
    m_qmlEngine = new QQmlEngine(this);
 
147
 
 
148
    m_qmlEngine->setBaseUrl(QUrl::fromLocalFile(::qmlDirectory()));
 
149
 
 
150
    prependImportPaths(m_qmlEngine, ::overrideImportPaths());
 
151
    if (!isMirServer) {
 
152
        prependImportPaths(m_qmlEngine, ::nonMirImportPaths());
 
153
    }
 
154
    appendImportPaths(m_qmlEngine, ::fallbackImportPaths());
 
155
 
 
156
    m_qmlEngine->setNetworkAccessManagerFactory(new CachingNetworkManagerFactory);
 
157
 
 
158
    QObject::connect(m_qmlEngine, &QQmlEngine::quit, this, &QGuiApplication::quit);
 
159
}
 
160
 
 
161
void ShellApplication::onScreenAdded(QScreen * /*screen*/)
 
162
{
 
163
    // TODO: Support an arbitrary number of screens and different policies
 
164
    //       (eg cloned desktop, several desktops, etc)
 
165
    if (screens().count() == 2) {
 
166
        m_shellView->setScreen(screens().at(1));
 
167
        m_qmlArgs.setDeviceName("desktop");
 
168
        // Changing the QScreen where a QWindow is drawn makes it also lose focus (besides having
 
169
        // its backing QPlatformWindow recreated). So lets refocus it.
 
170
        m_shellView->requestActivate();
 
171
 
 
172
        m_secondaryWindow = new SecondaryWindow(m_qmlEngine);
 
173
        m_secondaryWindow->setScreen(screens().at(0));
 
174
 
 
175
        // QWindow::showFullScreen() also calls QWindow::requestActivate() and we don't want that!
 
176
        m_secondaryWindow->setWindowState(Qt::WindowFullScreen);
 
177
        m_secondaryWindow->setVisible(true);
 
178
    }
 
179
}
 
180
 
 
181
void ShellApplication::onScreenAboutToBeRemoved(QScreen *screen)
 
182
{
 
183
    // TODO: Support an arbitrary number of screens and different policies
 
184
    //       (eg cloned desktop, several desktops, etc)
 
185
    if (screen == m_shellView->screen()) {
 
186
        Q_ASSERT(screens().count() > 1);
 
187
        Q_ASSERT(screens().at(0) != screen);
 
188
        Q_ASSERT(m_secondaryWindow);
 
189
        delete m_secondaryWindow;
 
190
        m_secondaryWindow = nullptr;
 
191
        m_shellView->setScreen(screens().first());
 
192
        m_qmlArgs.setDeviceName(m_deviceName);
 
193
        // Changing the QScreen where a QWindow is drawn makes it also lose focus (besides having
 
194
        // its backing QPlatformWindow recreated). So lets refocus it.
 
195
        m_shellView->requestActivate();
 
196
    }
 
197
}