Merge lp:~mzanetti/unity8/move-screenshots-to-tests into lp:unity8
- move-screenshots-to-tests
- Merge into trunk
Proposed by
Michael Zanetti
Status: | Superseded |
---|---|
Proposed branch: | lp:~mzanetti/unity8/move-screenshots-to-tests |
Merge into: | lp:unity8 |
Diff against target: |
2445 lines (+1138/-270) 47 files modified
CMakeLists.txt (+1/-1) debian/control (+2/-2) plugins/Utils/CMakeLists.txt (+2/-0) plugins/Utils/applicationsfiltermodel.cpp (+101/-0) plugins/Utils/applicationsfiltermodel.h (+69/-0) plugins/Utils/plugin.cpp (+2/-0) plugins/Utils/windowstatestorage.cpp (+62/-23) plugins/Utils/windowstatestorage.h (+13/-1) qml/Components/Dialogs.qml (+29/-2) qml/Components/ModeSwitchWarningDialog.qml (+95/-0) qml/Components/Orientations.qml (+29/-0) qml/Components/ShellDialog.qml (+1/-1) qml/Components/WindowControlButtons.qml (+3/-0) qml/DeviceConfiguration.qml (+91/-71) qml/OrientedShell.qml (+32/-22) qml/Panel/Panel.qml (+5/-3) qml/Shell.qml (+8/-12) qml/Stages/AbstractStage.qml (+63/-0) qml/Stages/DesktopStage.qml (+14/-24) qml/Stages/PhoneStage.qml (+21/-34) qml/Stages/ShimStage.qml (+1/-1) qml/Stages/SpreadDelegate.qml (+8/-9) qml/Stages/TabletStage.qml (+24/-36) qml/Stages/WindowResizeArea.qml (+38/-7) tests/mocks/GSettings.1.0/fake_gsettings.cpp (+31/-0) tests/mocks/GSettings.1.0/fake_gsettings.h (+10/-0) tests/mocks/Unity/Application/ApplicationInfo.cpp (+16/-6) tests/mocks/Unity/Application/ApplicationInfo.h (+4/-0) tests/mocks/Unity/Application/ApplicationManager.cpp (+10/-0) tests/mocks/Unity/Application/ApplicationManager.h (+1/-1) tests/mocks/Unity/Application/ApplicationTestInterface.cpp (+2/-2) tests/mocks/Unity/Application/resources/surfaces.qrc (+13/-0) tests/mocks/Unity/Launcher/MockLauncherModel.cpp (+3/-0) tests/mocks/Utils/CMakeLists.txt (+2/-0) tests/mocks/Utils/plugin.cpp (+2/-0) tests/mocks/Utils/windowstatestorage.cpp (+17/-0) tests/mocks/Utils/windowstatestorage.h (+12/-0) tests/plugins/Unity/Launcher/launchermodeltest.cpp (+1/-0) tests/qmltests/CMakeLists.txt (+1/-0) tests/qmltests/Components/tst_ModeSwitchWarningDialog.qml (+75/-0) tests/qmltests/Components/tst_ZoomableImage.qml (+1/-1) tests/qmltests/Stages/tst_PhoneStage.qml (+0/-2) tests/qmltests/Stages/tst_SpreadDelegate.qml (+6/-2) tests/qmltests/Stages/tst_TabletStage.qml (+2/-2) tests/qmltests/Stages/tst_WindowResizeArea.qml (+35/-2) tests/qmltests/tst_OrientedShell.qml (+1/-1) tests/qmltests/tst_Shell.qml (+179/-2) |
To merge this branch: | bzr merge lp:~mzanetti/unity8/move-screenshots-to-tests |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Unity Team | Pending | ||
Review via email: mp+276797@code.launchpad.net |
This proposal has been superseded by a proposal from 2015-11-05.
Commit message
move screenshots out of the Dash dir
This was consuming 2.5 megs of installed size while they really are
only used for testing.
Description of the change
* Are there any related MPs required for this MP to build/function as expected? Please list.
see prereq
* Did you perform an exploratory manual test run of your code change and any related functionality?
yes
* Did you make sure that your branch does not contain spurious tags?
yes
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
n/a
* If you changed the UI, has there been a design review?
n/a
To post a comment you must log in.
- 2024. By Michael Zanetti
-
fix createSession
- 2025. By Michael Zanetti
-
merge prereq
- 2026. By Michael Zanetti
-
mege trunk
- 2027. By Michael Zanetti
-
merge prereq
- 2028. By Michael Zanetti
-
strip qrc to make QImage understand it
Unmerged revisions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2015-10-21 11:51:38 +0000 |
3 | +++ CMakeLists.txt 2015-11-05 18:02:15 +0000 |
4 | @@ -57,7 +57,7 @@ |
5 | find_package(Qt5Concurrent 5.2 REQUIRED) |
6 | find_package(Qt5Sql 5.2 REQUIRED) |
7 | |
8 | -pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=9) |
9 | +pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=10) |
10 | |
11 | # Standard install paths |
12 | include(GNUInstallDirs) |
13 | |
14 | === modified file 'debian/control' |
15 | --- debian/control 2015-10-21 11:51:11 +0000 |
16 | +++ debian/control 2015-11-05 18:02:15 +0000 |
17 | @@ -127,7 +127,7 @@ |
18 | qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1627) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1627), |
19 | qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl, |
20 | ubuntu-thumbnailer-impl-0, |
21 | - unity-application-impl-9, |
22 | + unity-application-impl-10, |
23 | unity-notifications-impl-3, |
24 | unity-plugin-scopes | unity-scopes-impl, |
25 | unity-scopes-impl-7, |
26 | @@ -173,7 +173,7 @@ |
27 | Depends: ${misc:Depends}, |
28 | ${shlibs:Depends}, |
29 | Provides: unity-application-impl, |
30 | - unity-application-impl-9, |
31 | + unity-application-impl-10, |
32 | Replaces: unity8-autopilot (<< 8.02+15.04.20150422-0ubuntu1) |
33 | Description: Fake environment for running Unity 8 shell |
34 | Provides fake implementations of some QML modules used by Unity 8 shell |
35 | |
36 | === modified file 'plugins/Utils/CMakeLists.txt' |
37 | --- plugins/Utils/CMakeLists.txt 2015-09-29 14:46:24 +0000 |
38 | +++ plugins/Utils/CMakeLists.txt 2015-11-05 18:02:15 +0000 |
39 | @@ -10,6 +10,8 @@ |
40 | |
41 | set(QMLPLUGIN_SRC |
42 | activefocuslogger.cpp |
43 | + ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h |
44 | + applicationsfiltermodel.cpp |
45 | constants.cpp |
46 | HomeKeyWatcher.cpp |
47 | inputwatcher.cpp |
48 | |
49 | === added file 'plugins/Utils/applicationsfiltermodel.cpp' |
50 | --- plugins/Utils/applicationsfiltermodel.cpp 1970-01-01 00:00:00 +0000 |
51 | +++ plugins/Utils/applicationsfiltermodel.cpp 2015-11-05 18:02:15 +0000 |
52 | @@ -0,0 +1,101 @@ |
53 | +/* |
54 | + * Copyright (C) 2015 Canonical, Ltd. |
55 | + * |
56 | + * This program is free software; you can redistribute it and/or modify |
57 | + * it under the terms of the GNU General Public License as published by |
58 | + * the Free Software Foundation; version 3. |
59 | + * |
60 | + * This program is distributed in the hope that it will be useful, |
61 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
62 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
63 | + * GNU General Public License for more details. |
64 | + * |
65 | + * You should have received a copy of the GNU General Public License |
66 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
67 | + */ |
68 | + |
69 | +// unity-api |
70 | +#include <unity/shell/application/ApplicationManagerInterface.h> |
71 | +#include <unity/shell/application/ApplicationInfoInterface.h> |
72 | + |
73 | +#include "applicationsfiltermodel.h" |
74 | + |
75 | +using namespace unity::shell::application; |
76 | + |
77 | +ApplicationsFilterModel::ApplicationsFilterModel(QObject *parent): |
78 | + QSortFilterProxyModel(parent), |
79 | + m_appModel(nullptr), |
80 | + m_filterTouchApps(false), |
81 | + m_filterLegacyApps(false) |
82 | +{ |
83 | +} |
84 | + |
85 | +ApplicationManagerInterface *ApplicationsFilterModel::applicationsModel() const |
86 | +{ |
87 | + return m_appModel; |
88 | +} |
89 | + |
90 | +void ApplicationsFilterModel::setApplicationsModel(ApplicationManagerInterface *applicationsModel) |
91 | +{ |
92 | + if (m_appModel != applicationsModel) { |
93 | + if (m_appModel) { |
94 | + disconnect(m_appModel, &ApplicationManagerInterface::countChanged, this, &ApplicationsFilterModel::countChanged); |
95 | + } |
96 | + m_appModel = applicationsModel; |
97 | + setSourceModel(m_appModel); |
98 | + Q_EMIT applicationsModelChanged(); |
99 | + connect(m_appModel, &ApplicationManagerInterface::countChanged, this, &ApplicationsFilterModel::countChanged); |
100 | + } |
101 | +} |
102 | + |
103 | +bool ApplicationsFilterModel::filterTouchApps() const |
104 | +{ |
105 | + return m_filterTouchApps; |
106 | +} |
107 | + |
108 | +void ApplicationsFilterModel::setFilterTouchApps(bool filterTouchApps) |
109 | +{ |
110 | + if (m_filterTouchApps != filterTouchApps) { |
111 | + m_filterTouchApps = filterTouchApps; |
112 | + Q_EMIT filterTouchAppsChanged(); |
113 | + |
114 | + invalidateFilter(); |
115 | + Q_EMIT countChanged(); |
116 | + } |
117 | +} |
118 | + |
119 | +bool ApplicationsFilterModel::filterLegacyApps() const |
120 | +{ |
121 | + return m_filterLegacyApps; |
122 | +} |
123 | + |
124 | +void ApplicationsFilterModel::setFilterLegacyApps(bool filterLegacyApps) |
125 | +{ |
126 | + if (m_filterLegacyApps != filterLegacyApps) { |
127 | + m_filterLegacyApps = filterLegacyApps; |
128 | + Q_EMIT filterLegacyAppsChanged(); |
129 | + |
130 | + invalidateFilter(); |
131 | + Q_EMIT countChanged(); |
132 | + } |
133 | +} |
134 | + |
135 | +bool ApplicationsFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const |
136 | +{ |
137 | + Q_UNUSED(source_parent); |
138 | + |
139 | + ApplicationInfoInterface *app = m_appModel->get(source_row); |
140 | + Q_ASSERT(app); |
141 | + if (m_filterLegacyApps && !app->isTouchApp()) { |
142 | + return false; |
143 | + } |
144 | + if (m_filterTouchApps && app->isTouchApp()) { |
145 | + return false; |
146 | + } |
147 | + return true; |
148 | +} |
149 | + |
150 | +ApplicationInfoInterface *ApplicationsFilterModel::get(int index) const |
151 | +{ |
152 | + return m_appModel->get(mapToSource(this->index(index, 0)).row()); |
153 | +} |
154 | |
155 | === added file 'plugins/Utils/applicationsfiltermodel.h' |
156 | --- plugins/Utils/applicationsfiltermodel.h 1970-01-01 00:00:00 +0000 |
157 | +++ plugins/Utils/applicationsfiltermodel.h 2015-11-05 18:02:15 +0000 |
158 | @@ -0,0 +1,69 @@ |
159 | +/* |
160 | + * Copyright (C) 2015 Canonical, Ltd. |
161 | + * |
162 | + * This program is free software; you can redistribute it and/or modify |
163 | + * it under the terms of the GNU General Public License as published by |
164 | + * the Free Software Foundation; version 3. |
165 | + * |
166 | + * This program is distributed in the hope that it will be useful, |
167 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
168 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
169 | + * GNU General Public License for more details. |
170 | + * |
171 | + * You should have received a copy of the GNU General Public License |
172 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
173 | + */ |
174 | + |
175 | +#ifndef APPLICATIONSFILTERMODEL_H |
176 | +#define APPLICATIONSFILTERMODEL_H |
177 | + |
178 | +#include <QSortFilterProxyModel> |
179 | + |
180 | +namespace unity { |
181 | +namespace shell { |
182 | +namespace application { |
183 | +class ApplicationManagerInterface; |
184 | +class ApplicationInfoInterface; |
185 | +} |
186 | +} |
187 | +} |
188 | +using namespace unity::shell::application; |
189 | + |
190 | +class ApplicationsFilterModel: public QSortFilterProxyModel |
191 | +{ |
192 | + Q_OBJECT |
193 | + |
194 | + Q_PROPERTY(unity::shell::application::ApplicationManagerInterface* applicationsModel READ applicationsModel WRITE setApplicationsModel NOTIFY applicationsModelChanged) |
195 | + Q_PROPERTY(bool filterTouchApps READ filterTouchApps WRITE setFilterTouchApps NOTIFY filterTouchAppsChanged) |
196 | + Q_PROPERTY(bool filterLegacyApps READ filterLegacyApps WRITE setFilterLegacyApps NOTIFY filterLegacyAppsChanged) |
197 | + |
198 | + Q_PROPERTY(int count READ rowCount NOTIFY countChanged) |
199 | +public: |
200 | + ApplicationsFilterModel(QObject *parent = 0); |
201 | + |
202 | + ApplicationManagerInterface* applicationsModel() const; |
203 | + void setApplicationsModel(ApplicationManagerInterface* applicationsModel); |
204 | + |
205 | + bool filterTouchApps() const; |
206 | + void setFilterTouchApps(bool filterTouchApps); |
207 | + |
208 | + bool filterLegacyApps() const; |
209 | + void setFilterLegacyApps(bool filterLegacyApps); |
210 | + |
211 | + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; |
212 | + |
213 | + Q_INVOKABLE unity::shell::application::ApplicationInfoInterface* get(int index) const; |
214 | + |
215 | +Q_SIGNALS: |
216 | + void applicationsModelChanged(); |
217 | + void filterTouchAppsChanged(); |
218 | + void filterLegacyAppsChanged(); |
219 | + void countChanged(); |
220 | + |
221 | +private: |
222 | + ApplicationManagerInterface* m_appModel; |
223 | + bool m_filterTouchApps; |
224 | + bool m_filterLegacyApps; |
225 | +}; |
226 | + |
227 | +#endif |
228 | |
229 | === modified file 'plugins/Utils/plugin.cpp' |
230 | --- plugins/Utils/plugin.cpp 2015-09-29 14:46:24 +0000 |
231 | +++ plugins/Utils/plugin.cpp 2015-11-05 18:02:15 +0000 |
232 | @@ -35,6 +35,7 @@ |
233 | #include "windowstatestorage.h" |
234 | #include "constants.h" |
235 | #include "timezoneFormatter.h" |
236 | +#include "applicationsfiltermodel.h" |
237 | |
238 | static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine) |
239 | { |
240 | @@ -66,6 +67,7 @@ |
241 | qmlRegisterSingletonType<TimezoneFormatter>(uri, 0, 1, "TimezoneFormatter", |
242 | [](QQmlEngine*, QJSEngine*) -> QObject* { return new TimezoneFormatter; }); |
243 | qmlRegisterType<ActiveFocusLogger>(uri, 0, 1, "ActiveFocusLogger"); |
244 | + qmlRegisterType<ApplicationsFilterModel>(uri, 0, 1, "ApplicationsFilterModel"); |
245 | } |
246 | |
247 | void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri) |
248 | |
249 | === modified file 'plugins/Utils/windowstatestorage.cpp' |
250 | --- plugins/Utils/windowstatestorage.cpp 2015-09-14 09:11:08 +0000 |
251 | +++ plugins/Utils/windowstatestorage.cpp 2015-11-05 18:02:15 +0000 |
252 | @@ -47,26 +47,38 @@ |
253 | m_db.close(); |
254 | } |
255 | |
256 | +void WindowStateStorage::saveState(const QString &windowId, WindowStateStorage::WindowState state) |
257 | +{ |
258 | + const QString queryString = QStringLiteral("INSERT OR REPLACE INTO state (windowId, state) values ('%1', '%2');") |
259 | + .arg(windowId) |
260 | + .arg((int)state); |
261 | + |
262 | + saveValue(queryString); |
263 | +} |
264 | + |
265 | +WindowStateStorage::WindowState WindowStateStorage::getState(const QString &windowId, WindowStateStorage::WindowState defaultValue) const |
266 | +{ |
267 | + const QString queryString = QStringLiteral("SELECT * FROM state WHERE windowId = '%1';") |
268 | + .arg(windowId); |
269 | + |
270 | + QSqlQuery query = getValue(queryString); |
271 | + |
272 | + if (!query.first()) { |
273 | + return defaultValue; |
274 | + } |
275 | + return (WindowState)query.value("state").toInt(); |
276 | +} |
277 | + |
278 | void WindowStateStorage::saveGeometry(const QString &windowId, const QRect &rect) |
279 | { |
280 | - QMutexLocker mutexLocker(&s_mutex); |
281 | - |
282 | - QString queryString = QStringLiteral("INSERT OR REPLACE INTO geometry (windowId, x, y, width, height) values ('%1', '%2', '%3', '%4', '%5');") |
283 | + const QString queryString = QStringLiteral("INSERT OR REPLACE INTO geometry (windowId, x, y, width, height) values ('%1', '%2', '%3', '%4', '%5');") |
284 | .arg(windowId) |
285 | .arg(rect.x()) |
286 | .arg(rect.y()) |
287 | .arg(rect.width()) |
288 | .arg(rect.height()); |
289 | |
290 | - QFuture<void> future = QtConcurrent::run(executeAsyncQuery, queryString); |
291 | - m_asyncQueries.append(future); |
292 | - |
293 | - QFutureWatcher<void> *futureWatcher = new QFutureWatcher<void>(); |
294 | - futureWatcher->setFuture(future); |
295 | - connect(futureWatcher, &QFutureWatcher<void>::finished, |
296 | - this, |
297 | - [=](){ m_asyncQueries.removeAll(futureWatcher->future()); |
298 | - futureWatcher->deleteLater(); }); |
299 | + saveValue(queryString); |
300 | } |
301 | |
302 | void WindowStateStorage::executeAsyncQuery(const QString &queryString) |
303 | @@ -82,20 +94,13 @@ |
304 | } |
305 | } |
306 | |
307 | -QRect WindowStateStorage::getGeometry(const QString &windowId, const QRect &defaultValue) |
308 | +QRect WindowStateStorage::getGeometry(const QString &windowId, const QRect &defaultValue) const |
309 | { |
310 | - QMutexLocker l(&s_mutex); |
311 | QString queryString = QStringLiteral("SELECT * FROM geometry WHERE windowId = '%1';") |
312 | .arg(windowId); |
313 | - QSqlQuery query; |
314 | - |
315 | - bool ok = query.exec(queryString); |
316 | - if (!ok) { |
317 | - qWarning() << "Error retrieving window state for" << windowId |
318 | - << "Driver error:" << query.lastError().driverText() |
319 | - << "Database error:" << query.lastError().databaseText(); |
320 | - return defaultValue; |
321 | - } |
322 | + |
323 | + QSqlQuery query = getValue(queryString); |
324 | + |
325 | if (!query.first()) { |
326 | return defaultValue; |
327 | } |
328 | @@ -114,4 +119,38 @@ |
329 | QSqlQuery query; |
330 | query.exec(QStringLiteral("CREATE TABLE geometry(windowId TEXT UNIQUE, x INTEGER, y INTEGER, width INTEGER, height INTEGER);")); |
331 | } |
332 | + |
333 | + if (!m_db.tables().contains("state")) { |
334 | + QSqlQuery query; |
335 | + query.exec("CREATE TABLE state(windowId TEXT UNIQUE, state INTEGER);"); |
336 | + } |
337 | +} |
338 | + |
339 | +void WindowStateStorage::saveValue(const QString &queryString) |
340 | +{ |
341 | + QMutexLocker mutexLocker(&s_mutex); |
342 | + |
343 | + QFuture<void> future = QtConcurrent::run(executeAsyncQuery, queryString); |
344 | + m_asyncQueries.append(future); |
345 | + |
346 | + QFutureWatcher<void> *futureWatcher = new QFutureWatcher<void>(); |
347 | + futureWatcher->setFuture(future); |
348 | + connect(futureWatcher, &QFutureWatcher<void>::finished, |
349 | + this, |
350 | + [=](){ m_asyncQueries.removeAll(futureWatcher->future()); |
351 | + futureWatcher->deleteLater(); }); |
352 | +} |
353 | + |
354 | +QSqlQuery WindowStateStorage::getValue(const QString &queryString) const |
355 | +{ |
356 | + QMutexLocker l(&s_mutex); |
357 | + QSqlQuery query; |
358 | + |
359 | + bool ok = query.exec(queryString); |
360 | + if (!ok) { |
361 | + qWarning() << "Error retrieving database query:" << queryString |
362 | + << "Driver error:" << query.lastError().driverText() |
363 | + << "Database error:" << query.lastError().databaseText(); |
364 | + } |
365 | + return query; |
366 | } |
367 | |
368 | === modified file 'plugins/Utils/windowstatestorage.h' |
369 | --- plugins/Utils/windowstatestorage.h 2015-03-13 19:01:32 +0000 |
370 | +++ plugins/Utils/windowstatestorage.h 2015-11-05 18:02:15 +0000 |
371 | @@ -22,16 +22,28 @@ |
372 | class WindowStateStorage: public QObject |
373 | { |
374 | Q_OBJECT |
375 | + Q_ENUMS(WindowState) |
376 | public: |
377 | + enum WindowState { |
378 | + WindowStateNormal, |
379 | + WindowStateMaximized |
380 | + }; |
381 | + |
382 | WindowStateStorage(QObject *parent = 0); |
383 | virtual ~WindowStateStorage(); |
384 | |
385 | + Q_INVOKABLE void saveState(const QString &windowId, WindowState state); |
386 | + Q_INVOKABLE WindowState getState(const QString &windowId, WindowState defaultValue) const; |
387 | + |
388 | Q_INVOKABLE void saveGeometry(const QString &windowId, const QRect &rect); |
389 | - Q_INVOKABLE QRect getGeometry(const QString &windowId, const QRect &defaultValue); |
390 | + Q_INVOKABLE QRect getGeometry(const QString &windowId, const QRect &defaultValue) const; |
391 | |
392 | private: |
393 | void initdb(); |
394 | |
395 | + void saveValue(const QString &queryString); |
396 | + QSqlQuery getValue(const QString &queryString) const; |
397 | + |
398 | static void executeAsyncQuery(const QString &queryString); |
399 | static QMutex s_mutex; |
400 | |
401 | |
402 | === modified file 'qml/Components/Dialogs.qml' |
403 | --- qml/Components/Dialogs.qml 2015-10-09 12:36:14 +0000 |
404 | +++ qml/Components/Dialogs.qml 2015-11-05 18:02:15 +0000 |
405 | @@ -1,5 +1,5 @@ |
406 | /* |
407 | - * Copyright (C) 2014 Canonical, Ltd. |
408 | + * Copyright (C) 2014-2015 Canonical, Ltd. |
409 | * |
410 | * This program is free software; you can redistribute it and/or modify |
411 | * it under the terms of the GNU General Public License as published by |
412 | @@ -21,6 +21,7 @@ |
413 | import Ubuntu.Components 1.1 |
414 | import GlobalShortcut 1.0 |
415 | import Unity.Platform 1.0 |
416 | +import Utils 0.1 |
417 | import "../Greeter" |
418 | |
419 | Item { |
420 | @@ -45,6 +46,31 @@ |
421 | d.showPowerDialog(); |
422 | } |
423 | |
424 | + onUsageScenarioChanged: { |
425 | + if (usageScenario != "desktop" && legacyAppsModel.count > 0 && !d.modeSwitchWarningPopup) { |
426 | + var comp = Qt.createComponent(Qt.resolvedUrl("ModeSwitchWarningDialog.qml")) |
427 | + d.modeSwitchWarningPopup = comp.createObject(root, {model: legacyAppsModel}); |
428 | + d.modeSwitchWarningPopup.forceClose.connect(function() { |
429 | + while (legacyAppsModel.count > 0) { |
430 | + ApplicationManager.stopApplication(legacyAppsModel.get(0).appId); |
431 | + } |
432 | + d.modeSwitchWarningPopup.hide(); |
433 | + d.modeSwitchWarningPopup.destroy(); |
434 | + d.modeSwitchWarningPopup = null; |
435 | + }) |
436 | + } else if (usageScenario == "desktop" && d.modeSwitchWarningPopup) { |
437 | + d.modeSwitchWarningPopup.hide(); |
438 | + d.modeSwitchWarningPopup.destroy(); |
439 | + d.modeSwitchWarningPopup = null; |
440 | + } |
441 | + } |
442 | + |
443 | + ApplicationsFilterModel { |
444 | + id: legacyAppsModel |
445 | + applicationsModel: ApplicationManager |
446 | + filterTouchApps: true |
447 | + } |
448 | + |
449 | GlobalShortcut { // reboot/shutdown dialog |
450 | shortcut: Qt.Key_PowerDown |
451 | active: Platform.isPC |
452 | @@ -91,6 +117,8 @@ |
453 | id: d // private stuff |
454 | objectName: "dialogsPrivate" |
455 | |
456 | + property var modeSwitchWarningPopup: null |
457 | + |
458 | function showPowerDialog() { |
459 | if (!dialogLoader.active) { |
460 | dialogLoader.sourceComponent = powerDialogComponent; |
461 | @@ -270,5 +298,4 @@ |
462 | unitySessionService.endSession(); |
463 | } |
464 | } |
465 | - |
466 | } |
467 | |
468 | === added file 'qml/Components/ModeSwitchWarningDialog.qml' |
469 | --- qml/Components/ModeSwitchWarningDialog.qml 1970-01-01 00:00:00 +0000 |
470 | +++ qml/Components/ModeSwitchWarningDialog.qml 2015-11-05 18:02:15 +0000 |
471 | @@ -0,0 +1,95 @@ |
472 | +/* |
473 | + * Copyright (C) 2015 Canonical, Ltd. |
474 | + * |
475 | + * This program is free software; you can redistribute it and/or modify |
476 | + * it under the terms of the GNU General Public License as published by |
477 | + * the Free Software Foundation; version 3. |
478 | + * |
479 | + * This program is distributed in the hope that it will be useful, |
480 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
481 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
482 | + * GNU General Public License for more details. |
483 | + * |
484 | + * You should have received a copy of the GNU General Public License |
485 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
486 | + */ |
487 | + |
488 | +import QtQuick 2.4 |
489 | +import QtQuick.Layouts 1.1 |
490 | +import Ubuntu.Components 1.2 |
491 | +import Ubuntu.Components.ListItems 1.2 |
492 | +import Ubuntu.Components.Popups 1.2 |
493 | + |
494 | +ShellDialog { |
495 | + id: root |
496 | + objectName: "modeSwitchWarningDialog" |
497 | + |
498 | + property alias model: appRepeater.model |
499 | + |
500 | + signal forceClose(); |
501 | + |
502 | + Label { |
503 | + text: i18n.tr("Apps may have unsaved data:") |
504 | + fontSize: "large" |
505 | + color: "#5D5D5D" |
506 | + } |
507 | + |
508 | + Repeater { |
509 | + id: appRepeater |
510 | + RowLayout { |
511 | + spacing: units.gu(2) |
512 | + Image { |
513 | + Layout.preferredHeight: units.gu(2) |
514 | + Layout.preferredWidth: units.gu(2) |
515 | + source: model.icon |
516 | + sourceSize.width: width |
517 | + sourceSize.height: height |
518 | + } |
519 | + Label { |
520 | + Layout.fillWidth: true |
521 | + text: model.name |
522 | + color: "#888888" |
523 | + } |
524 | + } |
525 | + } |
526 | + |
527 | + Label { |
528 | + text: i18n.tr("Re-dock, save your work and close these apps to continue.") |
529 | + wrapMode: Text.WordWrap |
530 | + color: "#888888" |
531 | + } |
532 | + |
533 | + Label { |
534 | + text: i18n.tr("Or force close now (unsaved data will be lost).") |
535 | + wrapMode: Text.WordWrap |
536 | + color: "#888888" |
537 | + } |
538 | + |
539 | + ThinDivider {} |
540 | + |
541 | + RowLayout { |
542 | + Label { |
543 | + objectName: "reconnectLabel" |
544 | + Layout.fillWidth: true |
545 | + property bool clicked: false |
546 | + property string notClickedText: i18n.tr("OK, I will reconnect") |
547 | + property string clickedText: i18n.tr("Reconnect now!") |
548 | + text: clicked ? clickedText : notClickedText |
549 | + color: "#333333" |
550 | + |
551 | + MouseArea { |
552 | + anchors.fill: parent |
553 | + onClicked: parent.clicked = true; |
554 | + } |
555 | + } |
556 | + |
557 | + Button { |
558 | + objectName: "forceCloseButton" |
559 | + text: i18n.tr("Close all") |
560 | + color: UbuntuColors.red |
561 | + onClicked: { |
562 | + root.forceClose(); |
563 | + } |
564 | + } |
565 | + } |
566 | +} |
567 | |
568 | === added file 'qml/Components/Orientations.qml' |
569 | --- qml/Components/Orientations.qml 1970-01-01 00:00:00 +0000 |
570 | +++ qml/Components/Orientations.qml 2015-11-05 18:02:15 +0000 |
571 | @@ -0,0 +1,29 @@ |
572 | +/* |
573 | + * Copyright 2015 Canonical Ltd. |
574 | + * |
575 | + * This program is free software; you can redistribute it and/or modify |
576 | + * it under the terms of the GNU General Public License as published by |
577 | + * the Free Software Foundation; version 3. |
578 | + * |
579 | + * This program is distributed in the hope that it will be useful, |
580 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
581 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
582 | + * GNU General Public License for more details. |
583 | + * |
584 | + * You should have received a copy of the GNU General Public License |
585 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
586 | + */ |
587 | + |
588 | +import QtQuick 2.4 |
589 | + |
590 | +QtObject { |
591 | + // Just because "native" is a reserved keyword :( |
592 | + property int native_: Qt.PortraitOrientation |
593 | + |
594 | + property int primary: Qt.PortraitOrientation |
595 | + |
596 | + property int landscape: Qt.LandscapeOrientation |
597 | + property int invertedLandscape: Qt.InvertedLandscapeOrientation |
598 | + property int portrait: Qt.PortraitOrientation |
599 | + property int invertedPortrait: Qt.InvertedPortraitOrientation |
600 | +} |
601 | |
602 | === modified file 'qml/Components/ShellDialog.qml' |
603 | --- qml/Components/ShellDialog.qml 2015-08-24 15:39:53 +0000 |
604 | +++ qml/Components/ShellDialog.qml 2015-11-05 18:02:15 +0000 |
605 | @@ -31,7 +31,7 @@ |
606 | // NB: PopupBase, Dialog's superclass, will check for the existence of this property |
607 | property bool reparentToRootItem: false |
608 | |
609 | - onVisibleChanged: { if (!visible) { dialogLoader.active = false; } } |
610 | + onVisibleChanged: { if (!visible && dialogLoader) { dialogLoader.active = false; } } |
611 | |
612 | Keys.onEscapePressed: hide() |
613 | |
614 | |
615 | === modified file 'qml/Components/WindowControlButtons.qml' |
616 | --- qml/Components/WindowControlButtons.qml 2014-11-24 11:21:38 +0000 |
617 | +++ qml/Components/WindowControlButtons.qml 2015-11-05 18:02:15 +0000 |
618 | @@ -28,6 +28,7 @@ |
619 | signal maximize() |
620 | |
621 | Rectangle { |
622 | + objectName: "closeWindowButton" |
623 | height: parent.height; width: height; radius: height / 2 |
624 | gradient: Gradient { |
625 | GradientStop { color: "#F49073"; position: 0 } |
626 | @@ -38,6 +39,7 @@ |
627 | MouseArea { anchors.fill: parent; onClicked: root.close() } |
628 | } |
629 | Rectangle { |
630 | + objectName: "minimizeWindowButton" |
631 | height: parent.height; width: height; radius: height / 2 |
632 | gradient: Gradient { |
633 | GradientStop { color: "#92918C"; position: 0 } |
634 | @@ -48,6 +50,7 @@ |
635 | MouseArea { anchors.fill: parent; onClicked: root.minimize() } |
636 | } |
637 | Rectangle { |
638 | + objectName: "maximizeWindowButton" |
639 | height: parent.height; width: height; radius: height / 2 |
640 | gradient: Gradient { |
641 | GradientStop { color: "#92918C"; position: 0 } |
642 | |
643 | === modified file 'qml/DeviceConfiguration.qml' |
644 | --- qml/DeviceConfiguration.qml 2015-10-05 16:43:41 +0000 |
645 | +++ qml/DeviceConfiguration.qml 2015-11-05 18:02:15 +0000 |
646 | @@ -16,79 +16,99 @@ |
647 | |
648 | import QtQuick 2.0 |
649 | |
650 | -StateGroup { |
651 | +QtObject { |
652 | id: root |
653 | |
654 | readonly property int useNativeOrientation: -1 |
655 | |
656 | - property int primaryOrientation: useNativeOrientation |
657 | - |
658 | - property int supportedOrientations: Qt.PortraitOrientation |
659 | - | Qt.InvertedPortraitOrientation |
660 | - | Qt.LandscapeOrientation |
661 | - | Qt.InvertedLandscapeOrientation |
662 | - |
663 | - // Supported values so far: |
664 | - // "phone", "tablet" or "desktop" |
665 | - property string category: "phone" |
666 | - |
667 | - property int ignoredMice: 0 |
668 | - |
669 | - |
670 | - property alias name: root.state |
671 | - |
672 | - states: [ |
673 | - State { |
674 | - name: "mako" |
675 | - PropertyChanges { |
676 | - target: root |
677 | - supportedOrientations: Qt.PortraitOrientation |
678 | - | Qt.LandscapeOrientation |
679 | - | Qt.InvertedLandscapeOrientation |
680 | - } |
681 | - }, |
682 | - State { |
683 | - name: "krillin" |
684 | - PropertyChanges { |
685 | - target: root |
686 | - supportedOrientations: Qt.PortraitOrientation |
687 | - | Qt.LandscapeOrientation |
688 | - | Qt.InvertedLandscapeOrientation |
689 | - } |
690 | - }, |
691 | - State { |
692 | - name: "arale" |
693 | - PropertyChanges { |
694 | - target: root |
695 | - supportedOrientations: Qt.PortraitOrientation |
696 | - | Qt.LandscapeOrientation |
697 | - | Qt.InvertedLandscapeOrientation |
698 | - ignoredMice: 1 |
699 | - } |
700 | - }, |
701 | - State { |
702 | - name: "manta" |
703 | - PropertyChanges { |
704 | - target: root |
705 | - category: "tablet" |
706 | - } |
707 | - }, |
708 | - State { |
709 | - name: "flo" |
710 | - PropertyChanges { |
711 | - target: root |
712 | - primaryOrientation: Qt.InvertedLandscapeOrientation |
713 | - category: "tablet" |
714 | - } |
715 | - }, |
716 | - State { |
717 | - name: "desktop" |
718 | - PropertyChanges { |
719 | - target: root |
720 | - category: "desktop" |
721 | - supportedOrientations: root.useNativeOrientation |
722 | - } |
723 | - } |
724 | - ] |
725 | - |
726 | + // The only writable property in the API |
727 | + // all other properties are set according to the device name |
728 | + property alias name: priv.state |
729 | + |
730 | + readonly property alias primaryOrientation: priv.primaryOrientation |
731 | + readonly property alias supportedOrientations: priv.supportedOrientations |
732 | + readonly property alias landscapeOrientation: priv.landscapeOrientation |
733 | + readonly property alias invertedLandscapeOrientation: priv.invertedLandscapeOrientation |
734 | + readonly property alias portraitOrientation: priv.portraitOrientation |
735 | + readonly property alias invertedPortraitOrientation: priv.invertedPortraitOrientation |
736 | + |
737 | + readonly property alias category: priv.category |
738 | + |
739 | + readonly property alias ignoredMice: priv.ignoredMice |
740 | + |
741 | + readonly property var priv: StateGroup { |
742 | + id: priv |
743 | + |
744 | + property int primaryOrientation: root.useNativeOrientation |
745 | + |
746 | + property int supportedOrientations: Qt.PortraitOrientation |
747 | + | Qt.InvertedPortraitOrientation |
748 | + | Qt.LandscapeOrientation |
749 | + | Qt.InvertedLandscapeOrientation |
750 | + |
751 | + property int landscapeOrientation: Qt.LandscapeOrientation |
752 | + property int invertedLandscapeOrientation: Qt.InvertedLandscapeOrientation |
753 | + property int portraitOrientation: Qt.PortraitOrientation |
754 | + property int invertedPortraitOrientation: Qt.InvertedPortraitOrientation |
755 | + |
756 | + // Supported values so far: |
757 | + // "phone", "tablet" or "desktop" |
758 | + property string category: "phone" |
759 | + |
760 | + property int ignoredMice: 0 |
761 | + |
762 | + states: [ |
763 | + State { |
764 | + name: "mako" |
765 | + PropertyChanges { |
766 | + target: priv |
767 | + supportedOrientations: Qt.PortraitOrientation |
768 | + | Qt.LandscapeOrientation |
769 | + | Qt.InvertedLandscapeOrientation |
770 | + } |
771 | + }, |
772 | + State { |
773 | + name: "krillin" |
774 | + PropertyChanges { |
775 | + target: priv |
776 | + supportedOrientations: Qt.PortraitOrientation |
777 | + | Qt.LandscapeOrientation |
778 | + | Qt.InvertedLandscapeOrientation |
779 | + } |
780 | + }, |
781 | + State { |
782 | + name: "arale" |
783 | + PropertyChanges { |
784 | + target: priv |
785 | + supportedOrientations: Qt.PortraitOrientation |
786 | + | Qt.LandscapeOrientation |
787 | + | Qt.InvertedLandscapeOrientation |
788 | + ignoredMice: 1 |
789 | + } |
790 | + }, |
791 | + State { |
792 | + name: "manta" |
793 | + PropertyChanges { |
794 | + target: priv |
795 | + category: "tablet" |
796 | + } |
797 | + }, |
798 | + State { |
799 | + name: "flo" |
800 | + PropertyChanges { |
801 | + target: priv |
802 | + landscapeOrientation: Qt.InvertedLandscapeOrientation |
803 | + primaryOrientation: Qt.InvertedLandscapeOrientation |
804 | + category: "tablet" |
805 | + } |
806 | + }, |
807 | + State { |
808 | + name: "desktop" |
809 | + PropertyChanges { |
810 | + target: priv |
811 | + category: "desktop" |
812 | + } |
813 | + } |
814 | + ] |
815 | + } |
816 | } |
817 | |
818 | === modified file 'qml/OrientedShell.qml' |
819 | --- qml/OrientedShell.qml 2015-10-05 19:15:03 +0000 |
820 | +++ qml/OrientedShell.qml 2015-11-05 18:02:15 +0000 |
821 | @@ -32,20 +32,31 @@ |
822 | implicitWidth: units.gu(40) |
823 | implicitHeight: units.gu(71) |
824 | |
825 | - // NB: native and primary orientations here don't map exactly to their QScreen counterparts |
826 | - readonly property int nativeOrientation: width > height ? Qt.LandscapeOrientation : Qt.PortraitOrientation |
827 | - |
828 | - readonly property int primaryOrientation: |
829 | - deviceConfiguration.primaryOrientation == deviceConfiguration.useNativeOrientation |
830 | - ? nativeOrientation : deviceConfiguration.primaryOrientation |
831 | - |
832 | DeviceConfiguration { |
833 | id: deviceConfiguration |
834 | name: applicationArguments.deviceName |
835 | } |
836 | |
837 | - |
838 | - // to be overwritten by tests |
839 | + property alias orientations: d.orientations |
840 | + |
841 | + Item { |
842 | + id: d |
843 | + |
844 | + property Orientations orientations: Orientations { |
845 | + id: orientations |
846 | + // NB: native and primary orientations here don't map exactly to their QScreen counterparts |
847 | + native_: root.width > root.height ? Qt.LandscapeOrientation : Qt.PortraitOrientation |
848 | + |
849 | + primary: deviceConfiguration.primaryOrientation == deviceConfiguration.useNativeOrientation |
850 | + ? native_ : deviceConfiguration.primaryOrientation |
851 | + |
852 | + landscape: deviceConfiguration.landscapeOrientation |
853 | + invertedLandscape: deviceConfiguration.invertedLandscapeOrientation |
854 | + portrait: deviceConfiguration.portraitOrientation |
855 | + invertedPortrait: deviceConfiguration.invertedPortraitOrientation |
856 | + } |
857 | + } |
858 | + // to be overwritten by tests |
859 | property var unity8Settings: Unity8Settings {} |
860 | property var oskSettings: GSettings { schema.id: "com.canonical.keyboard.maliit" } |
861 | |
862 | @@ -101,7 +112,7 @@ |
863 | |
864 | property int acceptedOrientationAngle: { |
865 | if (orientation & supportedOrientations) { |
866 | - return Screen.angleBetween(nativeOrientation, orientation); |
867 | + return Screen.angleBetween(orientations.native_, orientation); |
868 | } else if (shell.orientation & supportedOrientations) { |
869 | // stay where we are |
870 | return shell.orientationAngle; |
871 | @@ -111,16 +122,16 @@ |
872 | // rotate to some supported orientation as we can't stay where we currently are |
873 | // TODO: Choose the closest to the current one |
874 | if (supportedOrientations & Qt.PortraitOrientation) { |
875 | - return Screen.angleBetween(nativeOrientation, Qt.PortraitOrientation); |
876 | + return Screen.angleBetween(orientations.native_, Qt.PortraitOrientation); |
877 | } else if (supportedOrientations & Qt.LandscapeOrientation) { |
878 | - return Screen.angleBetween(nativeOrientation, Qt.LandscapeOrientation); |
879 | + return Screen.angleBetween(orientations.native_, Qt.LandscapeOrientation); |
880 | } else if (supportedOrientations & Qt.InvertedPortraitOrientation) { |
881 | - return Screen.angleBetween(nativeOrientation, Qt.InvertedPortraitOrientation); |
882 | + return Screen.angleBetween(orientations.native_, Qt.InvertedPortraitOrientation); |
883 | } else if (supportedOrientations & Qt.InvertedLandscapeOrientation) { |
884 | - return Screen.angleBetween(nativeOrientation, Qt.InvertedLandscapeOrientation); |
885 | + return Screen.angleBetween(orientations.native_, Qt.InvertedLandscapeOrientation); |
886 | } else { |
887 | // if all fails, fallback to primary orientation |
888 | - return Screen.angleBetween(nativeOrientation, primaryOrientation); |
889 | + return Screen.angleBetween(orientations.native_, orientations.primary); |
890 | } |
891 | } |
892 | } |
893 | @@ -128,19 +139,19 @@ |
894 | function angleToOrientation(angle) { |
895 | switch (angle) { |
896 | case 0: |
897 | - return nativeOrientation; |
898 | + return orientations.native_; |
899 | case 90: |
900 | - return nativeOrientation === Qt.PortraitOrientation ? Qt.InvertedLandscapeOrientation |
901 | + return orientations.native_ === Qt.PortraitOrientation ? Qt.InvertedLandscapeOrientation |
902 | : Qt.PortraitOrientation; |
903 | case 180: |
904 | - return nativeOrientation === Qt.PortraitOrientation ? Qt.InvertedPortraitOrientation |
905 | + return orientations.native_ === Qt.PortraitOrientation ? Qt.InvertedPortraitOrientation |
906 | : Qt.InvertedLandscapeOrientation; |
907 | case 270: |
908 | - return nativeOrientation === Qt.PortraitOrientation ? Qt.LandscapeOrientation |
909 | + return orientations.native_ === Qt.PortraitOrientation ? Qt.LandscapeOrientation |
910 | : Qt.InvertedPortraitOrientation; |
911 | default: |
912 | console.warn("angleToOrientation: Invalid orientation angle: " + angle); |
913 | - return primaryOrientation; |
914 | + return orientations.primary; |
915 | } |
916 | } |
917 | |
918 | @@ -159,8 +170,7 @@ |
919 | width: root.width |
920 | height: root.height |
921 | orientation: root.angleToOrientation(orientationAngle) |
922 | - primaryOrientation: root.primaryOrientation |
923 | - nativeOrientation: root.nativeOrientation |
924 | + orientations: root.orientations |
925 | nativeWidth: root.width |
926 | nativeHeight: root.height |
927 | mode: applicationArguments.mode |
928 | |
929 | === modified file 'qml/Panel/Panel.qml' |
930 | --- qml/Panel/Panel.qml 2015-09-29 12:48:46 +0000 |
931 | +++ qml/Panel/Panel.qml 2015-11-05 18:02:15 +0000 |
932 | @@ -28,6 +28,7 @@ |
933 | property alias callHint: __callHint |
934 | property bool fullscreenMode: false |
935 | property real indicatorAreaShowProgress: 1.0 |
936 | + property bool locked: false |
937 | |
938 | opacity: fullscreenMode && indicators.fullyClosed ? 0.0 : 1.0 |
939 | |
940 | @@ -136,7 +137,7 @@ |
941 | } |
942 | |
943 | shown: false |
944 | - width: root.width - (PanelState.buttonsVisible ? windowControlButtons.width : 0) |
945 | + width: root.width - (windowControlButtons.visible ? windowControlButtons.width : 0) |
946 | minimizedPanelHeight: units.gu(3) |
947 | expandedPanelHeight: units.gu(7) |
948 | openedHeight: root.height - indicatorOrangeLine.height |
949 | @@ -164,13 +165,14 @@ |
950 | |
951 | WindowControlButtons { |
952 | id: windowControlButtons |
953 | + objectName: "panelWindowControlButtons" |
954 | anchors { |
955 | left: parent.left |
956 | top: parent.top |
957 | margins: units.gu(0.7) |
958 | } |
959 | height: indicators.minimizedPanelHeight - anchors.margins * 2 |
960 | - visible: PanelState.buttonsVisible |
961 | + visible: PanelState.buttonsVisible && !root.locked |
962 | onClose: PanelState.close() |
963 | onMinimize: PanelState.minimize() |
964 | onMaximize: PanelState.maximize() |
965 | @@ -189,7 +191,7 @@ |
966 | id: __callHint |
967 | anchors { |
968 | top: parent.top |
969 | - left: PanelState.buttonsVisible ? windowControlButtons.right : parent.left |
970 | + left: windowControlButtons.visible ? windowControlButtons.right : parent.left |
971 | } |
972 | height: indicators.minimizedPanelHeight |
973 | visible: active && indicators.state == "initial" |
974 | |
975 | === modified file 'qml/Shell.qml' |
976 | --- qml/Shell.qml 2015-10-16 17:11:54 +0000 |
977 | +++ qml/Shell.qml 2015-11-05 18:02:15 +0000 |
978 | @@ -49,14 +49,14 @@ |
979 | // to be set from outside |
980 | property int orientationAngle: 0 |
981 | property int orientation |
982 | - property int primaryOrientation |
983 | - property int nativeOrientation |
984 | + property Orientations orientations |
985 | property real nativeWidth |
986 | property real nativeHeight |
987 | property alias indicatorAreaShowProgress: panel.indicatorAreaShowProgress |
988 | property bool beingResized |
989 | property string usageScenario: "phone" // supported values: "phone", "tablet" or "desktop" |
990 | property string mode: "full-greeter" |
991 | + property bool cursorVisible: false |
992 | function updateFocusedAppOrientation() { |
993 | applicationsDisplayLoader.item.updateFocusedAppOrientation(); |
994 | } |
995 | @@ -298,21 +298,16 @@ |
996 | } |
997 | Binding { |
998 | target: applicationsDisplayLoader.item |
999 | + property: "orientations" |
1000 | + value: shell.orientations |
1001 | + } |
1002 | + Binding { |
1003 | + target: applicationsDisplayLoader.item |
1004 | property: "background" |
1005 | value: wallpaperResolver.background |
1006 | } |
1007 | Binding { |
1008 | target: applicationsDisplayLoader.item |
1009 | - property: "shellPrimaryOrientation" |
1010 | - value: shell.primaryOrientation |
1011 | - } |
1012 | - Binding { |
1013 | - target: applicationsDisplayLoader.item |
1014 | - property: "nativeOrientation" |
1015 | - value: shell.nativeOrientation |
1016 | - } |
1017 | - Binding { |
1018 | - target: applicationsDisplayLoader.item |
1019 | property: "nativeWidth" |
1020 | value: shell.nativeWidth |
1021 | } |
1022 | @@ -536,6 +531,7 @@ |
1023 | |
1024 | fullscreenMode: (topmostApplicationIsFullscreen && !lightDM.greeter.active && launcher.progress == 0) |
1025 | || greeter.hasLockedApp |
1026 | + locked: greeter && greeter.active |
1027 | } |
1028 | |
1029 | Launcher { |
1030 | |
1031 | === added file 'qml/Stages/AbstractStage.qml' |
1032 | --- qml/Stages/AbstractStage.qml 1970-01-01 00:00:00 +0000 |
1033 | +++ qml/Stages/AbstractStage.qml 2015-11-05 18:02:15 +0000 |
1034 | @@ -0,0 +1,63 @@ |
1035 | +/* |
1036 | + * Copyright (C) 2015 Canonical, Ltd. |
1037 | + * |
1038 | + * This program is free software; you can redistribute it and/or modify |
1039 | + * it under the terms of the GNU General Public License as published by |
1040 | + * the Free Software Foundation; version 3. |
1041 | + * |
1042 | + * This program is distributed in the hope that it will be useful, |
1043 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1044 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1045 | + * GNU General Public License for more details. |
1046 | + * |
1047 | + * You should have received a copy of the GNU General Public License |
1048 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1049 | + */ |
1050 | + |
1051 | +import QtQuick 2.4 |
1052 | +import Ubuntu.Components 1.3 |
1053 | +import GSettings 1.0 |
1054 | + |
1055 | +Rectangle { |
1056 | + id: root |
1057 | + |
1058 | + color: "#111111" |
1059 | + |
1060 | + // Controls to be set from outside |
1061 | + property bool altTabPressed |
1062 | + property url background |
1063 | + property bool beingResized |
1064 | + property int dragAreaWidth |
1065 | + property bool interactive |
1066 | + property real inverseProgress // This is the progress for left edge drags, in pixels. |
1067 | + property bool keepDashRunning: true |
1068 | + property real maximizedAppTopMargin |
1069 | + property real nativeHeight |
1070 | + property real nativeWidth |
1071 | + property QtObject orientations |
1072 | + property int shellOrientation |
1073 | + property int shellOrientationAngle |
1074 | + property bool spreadEnabled: true // If false, animations and right edge will be disabled |
1075 | + property bool suspended |
1076 | + |
1077 | + // To be read from outside |
1078 | + property var mainApp: null |
1079 | + property int mainAppWindowOrientationAngle |
1080 | + property bool orientationChangesEnabled |
1081 | + |
1082 | + // Shared code for use in stage implementations |
1083 | + GSettings { |
1084 | + id: lifecycleExceptions |
1085 | + schema.id: "com.canonical.qtmir" |
1086 | + } |
1087 | + |
1088 | + function isExemptFromLifecycle(appId) { |
1089 | + var shortAppId = appId.split('_')[0]; |
1090 | + for (var i = 0; i < lifecycleExceptions.lifecycleExemptAppids.length; i++) { |
1091 | + if (shortAppId === lifecycleExceptions.lifecycleExemptAppids[i]) { |
1092 | + return true; |
1093 | + } |
1094 | + } |
1095 | + return false; |
1096 | + } |
1097 | +} |
1098 | |
1099 | === modified file 'qml/Stages/DesktopStage.qml' |
1100 | --- qml/Stages/DesktopStage.qml 2015-10-19 14:27:57 +0000 |
1101 | +++ qml/Stages/DesktopStage.qml 2015-11-05 18:02:15 +0000 |
1102 | @@ -22,39 +22,21 @@ |
1103 | import Unity.Application 0.1 |
1104 | import "../Components" |
1105 | import "../Components/PanelState" |
1106 | +import "../Components" |
1107 | import Utils 0.1 |
1108 | import Ubuntu.Gestures 0.1 |
1109 | |
1110 | -Rectangle { |
1111 | +AbstractStage { |
1112 | id: root |
1113 | anchors.fill: parent |
1114 | |
1115 | - // Controls to be set from outside |
1116 | - property int dragAreaWidth // just to comply with the interface shared between stages |
1117 | - property real maximizedAppTopMargin |
1118 | - property bool interactive |
1119 | - property bool spreadEnabled // just to comply with the interface shared between stages |
1120 | - property real inverseProgress: 0 // just to comply with the interface shared between stages |
1121 | - property int shellOrientationAngle: 0 |
1122 | - property int shellOrientation |
1123 | - property int shellPrimaryOrientation |
1124 | - property int nativeOrientation |
1125 | - property bool beingResized: false |
1126 | - property bool keepDashRunning: true |
1127 | - property bool suspended: false |
1128 | - property alias background: wallpaper.source |
1129 | - property alias altTabPressed: spread.altTabPressed |
1130 | - |
1131 | // functions to be called from outside |
1132 | function updateFocusedAppOrientation() { /* TODO */ } |
1133 | function updateFocusedAppOrientationAnimated() { /* TODO */} |
1134 | |
1135 | - // To be read from outside |
1136 | - readonly property var mainApp: ApplicationManager.focusedApplicationId |
1137 | + mainApp: ApplicationManager.focusedApplicationId |
1138 | ? ApplicationManager.findApplication(ApplicationManager.focusedApplicationId) |
1139 | : null |
1140 | - property int mainAppWindowOrientationAngle: 0 |
1141 | - readonly property bool orientationChangesEnabled: false |
1142 | |
1143 | Connections { |
1144 | target: ApplicationManager |
1145 | @@ -111,6 +93,7 @@ |
1146 | property: "buttonsVisible" |
1147 | value: priv.focusedAppDelegate !== null && priv.focusedAppDelegate.state === "maximized" |
1148 | } |
1149 | + Component.onDestruction: PanelState.buttonsVisible = false; |
1150 | |
1151 | FocusScope { |
1152 | id: appContainer |
1153 | @@ -121,6 +104,7 @@ |
1154 | CrossFadeImage { |
1155 | id: wallpaper |
1156 | anchors.fill: parent |
1157 | + source: root.background |
1158 | sourceSize { height: root.height; width: root.width } |
1159 | fillMode: Image.PreserveAspectCrop |
1160 | } |
1161 | @@ -140,6 +124,7 @@ |
1162 | |
1163 | property bool maximized: false |
1164 | property bool minimized: false |
1165 | + property bool animationsEnabled: true |
1166 | |
1167 | onFocusChanged: { |
1168 | if (focus && ApplicationManager.focusedApplicationId !== model.appId) { |
1169 | @@ -158,15 +143,18 @@ |
1170 | value: ApplicationInfoInterface.RequestedRunning // Always running for now |
1171 | } |
1172 | |
1173 | - function maximize() { |
1174 | + function maximize(animated) { |
1175 | + animationsEnabled = (animated === undefined) || animated; |
1176 | minimized = false; |
1177 | maximized = true; |
1178 | } |
1179 | - function minimize() { |
1180 | + function minimize(animated) { |
1181 | + animationsEnabled = (animated === undefined) || animated; |
1182 | maximized = false; |
1183 | minimized = true; |
1184 | } |
1185 | - function unmaximize() { |
1186 | + function unmaximize(animated) { |
1187 | + animationsEnabled = (animated === undefined) || animated; |
1188 | minimized = false; |
1189 | maximized = false; |
1190 | } |
1191 | @@ -188,6 +176,7 @@ |
1192 | Transition { |
1193 | from: "maximized,minimized,normal," |
1194 | to: "maximized,minimized,normal," |
1195 | + enabled: appDelegate.animationsEnabled |
1196 | PropertyAnimation { target: appDelegate; properties: "x,y,opacity,width,height,scale" } |
1197 | }, |
1198 | Transition { |
1199 | @@ -269,5 +258,6 @@ |
1200 | anchors.fill: parent |
1201 | workspace: appContainer |
1202 | focus: state == "altTab" |
1203 | + altTabPressed: root.altTabPressed |
1204 | } |
1205 | } |
1206 | |
1207 | === modified file 'qml/Stages/PhoneStage.qml' |
1208 | --- qml/Stages/PhoneStage.qml 2015-09-21 13:37:47 +0000 |
1209 | +++ qml/Stages/PhoneStage.qml 2015-11-05 18:02:15 +0000 |
1210 | @@ -22,29 +22,15 @@ |
1211 | import Utils 0.1 |
1212 | import "../Components" |
1213 | |
1214 | -Rectangle { |
1215 | +AbstractStage { |
1216 | id: root |
1217 | |
1218 | - // Controls to be set from outside |
1219 | - property int dragAreaWidth |
1220 | - property real maximizedAppTopMargin |
1221 | - property bool interactive |
1222 | - property bool spreadEnabled: true // If false, animations and right edge will be disabled |
1223 | - property real inverseProgress: 0 // This is the progress for left edge drags, in pixels. |
1224 | property QtObject applicationManager: ApplicationManager |
1225 | property bool focusFirstApp: true // If false, focused app will appear on right edge like other apps |
1226 | property bool altTabEnabled: true |
1227 | property real startScale: 1.1 |
1228 | property real endScale: 0.7 |
1229 | - property bool keepDashRunning: true |
1230 | - property bool suspended: false |
1231 | - property int shellOrientationAngle: 0 |
1232 | - property int shellOrientation |
1233 | - property int shellPrimaryOrientation |
1234 | - property int nativeOrientation |
1235 | - property real nativeWidth |
1236 | - property real nativeHeight |
1237 | - property bool beingResized: false |
1238 | + |
1239 | onBeingResizedChanged: { |
1240 | if (beingResized) { |
1241 | // Brace yourselves for impact! |
1242 | @@ -56,6 +42,8 @@ |
1243 | priv.reset(); |
1244 | } |
1245 | } |
1246 | + |
1247 | + // Functions to be called from outside |
1248 | function updateFocusedAppOrientation() { |
1249 | if (spreadRepeater.count > 0) { |
1250 | spreadRepeater.itemAt(0).matchShellOrientation(); |
1251 | @@ -71,7 +59,7 @@ |
1252 | |
1253 | var supportedOrientations = spreadDelegate.application.supportedOrientations; |
1254 | if (supportedOrientations === Qt.PrimaryOrientation) { |
1255 | - supportedOrientations = spreadDelegate.shellPrimaryOrientation; |
1256 | + supportedOrientations = root.orientations.primary; |
1257 | } |
1258 | |
1259 | if (delta === 180 && (supportedOrientations & spreadDelegate.shellOrientation)) { |
1260 | @@ -85,16 +73,14 @@ |
1261 | } |
1262 | } |
1263 | |
1264 | - // To be read from outside |
1265 | - readonly property var mainApp: applicationManager.focusedApplicationId |
1266 | + mainApp: applicationManager.focusedApplicationId |
1267 | ? applicationManager.findApplication(applicationManager.focusedApplicationId) |
1268 | : null |
1269 | |
1270 | - property int mainAppWindowOrientationAngle: 0 |
1271 | - readonly property bool orientationChangesEnabled: priv.focusedAppOrientationChangesEnabled |
1272 | - && !priv.focusedAppDelegateIsDislocated |
1273 | - && !(priv.focusedAppDelegate && priv.focusedAppDelegate.xBehavior.running) |
1274 | - && spreadView.phase === 0 |
1275 | + orientationChangesEnabled: priv.focusedAppOrientationChangesEnabled |
1276 | + && !priv.focusedAppDelegateIsDislocated |
1277 | + && !(priv.focusedAppDelegate && priv.focusedAppDelegate.xBehavior.running) |
1278 | + && spreadView.phase === 0 |
1279 | |
1280 | // How far left the stage has been dragged |
1281 | readonly property real dragProgress: spreadRepeater.count > 0 ? -spreadRepeater.itemAt(0).xTranslate : 0 |
1282 | @@ -106,8 +92,6 @@ |
1283 | |
1284 | signal opened() |
1285 | |
1286 | - color: "#111111" |
1287 | - |
1288 | function select(appId) { |
1289 | spreadView.snapTo(priv.indexOf(appId)); |
1290 | } |
1291 | @@ -438,16 +422,21 @@ |
1292 | dropShadow: spreadView.active || priv.focusedAppDelegateIsDislocated |
1293 | focusFirstApp: root.focusFirstApp |
1294 | |
1295 | + readonly property bool isDash: model.appId == "unity8-dash" |
1296 | + |
1297 | + readonly property bool canSuspend: model.isTouchApp |
1298 | + && !isExemptFromLifecycle(model.appId) |
1299 | + |
1300 | Binding { |
1301 | target: appDelegate.application |
1302 | property: "requestedState" |
1303 | - value: (isDash && root.keepDashRunning) || (!root.suspended && appDelegate.focus) |
1304 | - ? ApplicationInfoInterface.RequestedRunning |
1305 | - : ApplicationInfoInterface.RequestedSuspended |
1306 | + value: !canSuspend |
1307 | + || (isDash && root.keepDashRunning) |
1308 | + || (!root.suspended && appDelegate.focus) |
1309 | + ? ApplicationInfoInterface.RequestedRunning |
1310 | + : ApplicationInfoInterface.RequestedSuspended |
1311 | } |
1312 | |
1313 | - readonly property bool isDash: model.appId == "unity8-dash" |
1314 | - |
1315 | z: isDash && !spreadView.active ? -1 : behavioredIndex |
1316 | |
1317 | x: { |
1318 | @@ -535,11 +524,9 @@ |
1319 | visible: (progress >= 0 && progress < 1.7) |
1320 | || (isDash && priv.focusedAppDelegateIsDislocated) |
1321 | |
1322 | - |
1323 | shellOrientationAngle: root.shellOrientationAngle |
1324 | shellOrientation: root.shellOrientation |
1325 | - shellPrimaryOrientation: root.shellPrimaryOrientation |
1326 | - nativeOrientation: root.nativeOrientation |
1327 | + orientations: root.orientations |
1328 | |
1329 | onClicked: { |
1330 | if (root.altTabEnabled && spreadView.phase == 2) { |
1331 | |
1332 | === modified file 'qml/Stages/ShimStage.qml' |
1333 | --- qml/Stages/ShimStage.qml 2015-04-21 19:43:25 +0000 |
1334 | +++ qml/Stages/ShimStage.qml 2015-11-05 18:02:15 +0000 |
1335 | @@ -17,7 +17,7 @@ |
1336 | import QtQuick 2.3 |
1337 | import Ubuntu.Components 0.1 |
1338 | |
1339 | -Rectangle { |
1340 | +AbstractStage { |
1341 | id: shimStage |
1342 | |
1343 | anchors.fill: parent |
1344 | |
1345 | === modified file 'qml/Stages/SpreadDelegate.qml' |
1346 | --- qml/Stages/SpreadDelegate.qml 2015-09-21 13:10:02 +0000 |
1347 | +++ qml/Stages/SpreadDelegate.qml 2015-11-05 18:02:15 +0000 |
1348 | @@ -42,8 +42,7 @@ |
1349 | property alias application: appWindow.application |
1350 | property int shellOrientationAngle |
1351 | property int shellOrientation |
1352 | - property int shellPrimaryOrientation |
1353 | - property int nativeOrientation |
1354 | + property QtObject orientations |
1355 | |
1356 | function matchShellOrientation() { |
1357 | if (!root.application) |
1358 | @@ -157,7 +156,7 @@ |
1359 | var supportedOrientations = root.application.supportedOrientations; |
1360 | |
1361 | if (supportedOrientations === Qt.PrimaryOrientation) { |
1362 | - supportedOrientations = root.shellPrimaryOrientation; |
1363 | + supportedOrientations = root.orientations.primary; |
1364 | } |
1365 | |
1366 | // If it doesn't support shell's current orientation |
1367 | @@ -166,18 +165,18 @@ |
1368 | if (supportedOrientations & root.shellOrientation) { |
1369 | chosenOrientation = root.shellOrientation; |
1370 | } else if (supportedOrientations & Qt.PortraitOrientation) { |
1371 | - chosenOrientation = Qt.PortraitOrientation; |
1372 | + chosenOrientation = root.orientations.portrait; |
1373 | } else if (supportedOrientations & Qt.LandscapeOrientation) { |
1374 | - chosenOrientation = Qt.LandscapeOrientation; |
1375 | + chosenOrientation = root.orientations.landscape; |
1376 | } else if (supportedOrientations & Qt.InvertedPortraitOrientation) { |
1377 | - chosenOrientation = Qt.InvertedPortraitOrientation; |
1378 | + chosenOrientation = root.orientations.invertedPortrait; |
1379 | } else if (supportedOrientations & Qt.InvertedLandscapeOrientation) { |
1380 | - chosenOrientation = Qt.InvertedLandscapeOrientation; |
1381 | + chosenOrientation = root.orientations.invertedLandscape; |
1382 | } else { |
1383 | - chosenOrientation = root.shellPrimaryOrientation; |
1384 | + chosenOrientation = root.orientations.primary; |
1385 | } |
1386 | |
1387 | - return Screen.angleBetween(root.nativeOrientation, chosenOrientation); |
1388 | + return Screen.angleBetween(root.orientations.native_, chosenOrientation); |
1389 | } |
1390 | |
1391 | rotation: normalizeAngle(appWindowWithShadow.orientationAngle - root.shellOrientationAngle) |
1392 | |
1393 | === modified file 'qml/Stages/TabletStage.qml' |
1394 | --- qml/Stages/TabletStage.qml 2015-08-03 13:47:44 +0000 |
1395 | +++ qml/Stages/TabletStage.qml 2015-11-05 18:02:15 +0000 |
1396 | @@ -21,29 +21,12 @@ |
1397 | import Utils 0.1 |
1398 | import "../Components" |
1399 | |
1400 | -Rectangle { |
1401 | +AbstractStage { |
1402 | id: root |
1403 | objectName: "stages" |
1404 | anchors.fill: parent |
1405 | - color: "#111111" |
1406 | - |
1407 | - // Controls to be set from outside |
1408 | - property int dragAreaWidth |
1409 | - property real maximizedAppTopMargin |
1410 | - property bool interactive |
1411 | - property alias beingResized: spreadView.beingResized |
1412 | - |
1413 | - property bool spreadEnabled: true // If false, animations and right edge will be disabled |
1414 | - |
1415 | - property real inverseProgress: 0 // This is the progress for left edge drags, in pixels. |
1416 | - property bool keepDashRunning: true |
1417 | - property bool suspended: false |
1418 | - property int shellOrientationAngle: 0 |
1419 | - property int shellOrientation |
1420 | - property int shellPrimaryOrientation |
1421 | - property int nativeOrientation |
1422 | - property real nativeWidth |
1423 | - property real nativeHeight |
1424 | + |
1425 | + // Functions to be called from outside |
1426 | function updateFocusedAppOrientation() { |
1427 | var mainStageAppIndex = priv.indexOf(priv.mainStageAppId); |
1428 | if (mainStageAppIndex >= 0 && mainStageAppIndex < spreadRepeater.count) { |
1429 | @@ -64,7 +47,7 @@ |
1430 | |
1431 | var supportedOrientations = spreadDelegate.application.supportedOrientations; |
1432 | if (supportedOrientations === Qt.PrimaryOrientation) { |
1433 | - supportedOrientations = spreadDelegate.shellPrimaryOrientation; |
1434 | + supportedOrientations = spreadDelegate.orientations.primary; |
1435 | } |
1436 | |
1437 | if (delta === 180 && (supportedOrientations & spreadDelegate.shellOrientation)) { |
1438 | @@ -86,10 +69,7 @@ |
1439 | } |
1440 | } |
1441 | |
1442 | - // To be read from outside |
1443 | - property var mainApp: null |
1444 | - property int mainAppWindowOrientationAngle: 0 |
1445 | - readonly property bool orientationChangesEnabled: priv.mainAppOrientationChangesEnabled |
1446 | + orientationChangesEnabled: priv.mainAppOrientationChangesEnabled |
1447 | |
1448 | onWidthChanged: { |
1449 | spreadView.selectedIndex = -1; |
1450 | @@ -130,7 +110,7 @@ |
1451 | property string oldFocusedAppId: "" |
1452 | property bool mainAppOrientationChangesEnabled: false |
1453 | |
1454 | - property real landscapeHeight: root.nativeOrientation == Qt.LandscapeOrientation ? |
1455 | + property real landscapeHeight: root.orientations.native_ == Qt.LandscapeOrientation ? |
1456 | root.nativeHeight : root.nativeWidth |
1457 | |
1458 | property bool shellIsLandscape: root.shellOrientation === Qt.LandscapeOrientation |
1459 | @@ -302,7 +282,7 @@ |
1460 | } |
1461 | |
1462 | property bool animateX: true |
1463 | - property bool beingResized: false |
1464 | + property bool beingResized: root.beingResized |
1465 | onBeingResizedChanged: { |
1466 | if (beingResized) { |
1467 | // Brace yourselves for impact! |
1468 | @@ -629,15 +609,18 @@ |
1469 | |
1470 | readonly property bool isDash: model.appId == "unity8-dash" |
1471 | |
1472 | + readonly property bool canSuspend: model.isTouchApp |
1473 | + && !isExemptFromLifecycle(model.appId) |
1474 | + |
1475 | Binding { |
1476 | target: spreadTile.application |
1477 | property: "requestedState" |
1478 | - value: (spreadTile.isDash && root.keepDashRunning) |
1479 | - || |
1480 | - (!root.suspended && (model.appId == priv.mainStageAppId |
1481 | - || model.appId == priv.sideStageAppId)) |
1482 | - ? ApplicationInfoInterface.RequestedRunning |
1483 | - : ApplicationInfoInterface.RequestedSuspended |
1484 | + value: !canSuspend |
1485 | + || (isDash && root.keepDashRunning) |
1486 | + || (!root.suspended && (model.appId == priv.mainStageAppId |
1487 | + || model.appId == priv.sideStageAppId)) |
1488 | + ? ApplicationInfoInterface.RequestedRunning |
1489 | + : ApplicationInfoInterface.RequestedSuspended |
1490 | } |
1491 | |
1492 | // FIXME: A regular binding doesn't update any more after closing an app. |
1493 | @@ -691,9 +674,14 @@ |
1494 | |
1495 | shellOrientationAngle: wantsMainStage ? root.shellOrientationAngle : 0 |
1496 | shellOrientation: wantsMainStage ? root.shellOrientation : Qt.PortraitOrientation |
1497 | - shellPrimaryOrientation: wantsMainStage ? root.shellPrimaryOrientation : Qt.PortraitOrientation |
1498 | - nativeOrientation: wantsMainStage ? root.nativeOrientation : Qt.PortraitOrientation |
1499 | - |
1500 | + orientations: Orientations { |
1501 | + primary: spreadTile.wantsMainStage ? root.orientations.primary : Qt.PortraitOrientation |
1502 | + native_: spreadTile.wantsMainStage ? root.orientations.native_ : Qt.PortraitOrientation |
1503 | + portrait: root.orientations.portrait |
1504 | + invertedPortrait: root.orientations.invertedPortrait |
1505 | + landscape: root.orientations.landscape |
1506 | + invertedLandscape: root.orientations.invertedLandscape |
1507 | + } |
1508 | |
1509 | onClicked: { |
1510 | if (spreadView.phase == 2) { |
1511 | |
1512 | === modified file 'qml/Stages/WindowResizeArea.qml' |
1513 | --- qml/Stages/WindowResizeArea.qml 2015-09-29 12:48:46 +0000 |
1514 | +++ qml/Stages/WindowResizeArea.qml 2015-11-05 18:02:15 +0000 |
1515 | @@ -36,18 +36,49 @@ |
1516 | property int minWidth: 0 |
1517 | property int minHeight: 0 |
1518 | |
1519 | + QtObject { |
1520 | + id: priv |
1521 | + |
1522 | + property int normalX: 0 |
1523 | + property int normalY: 0 |
1524 | + property int normalWidth: 0 |
1525 | + property int normalHeight: 0 |
1526 | + |
1527 | + function updateNormalGeometry() { |
1528 | + if (root.target.state == "normal") { |
1529 | + normalX = root.target.x |
1530 | + normalY = root.target.y |
1531 | + normalWidth = root.target.width |
1532 | + normalHeight = root.target.height |
1533 | + } |
1534 | + } |
1535 | + } |
1536 | + |
1537 | + Connections { |
1538 | + target: root.target |
1539 | + onXChanged: priv.updateNormalGeometry(); |
1540 | + onYChanged: priv.updateNormalGeometry(); |
1541 | + onWidthChanged: priv.updateNormalGeometry(); |
1542 | + onHeightChanged: priv.updateNormalGeometry(); |
1543 | + } |
1544 | + |
1545 | Component.onCompleted: { |
1546 | - var windowState = windowStateStorage.getGeometry(root.windowId, Qt.rect(target.x, target.y, target.width, target.height)) |
1547 | - if (windowState !== undefined) { |
1548 | - target.x = windowState.x |
1549 | - target.y = windowState.y |
1550 | - target.width = windowState.width |
1551 | - target.height = windowState.height |
1552 | + var windowGeometry = windowStateStorage.getGeometry(root.windowId, Qt.rect(target.x, target.y, target.width, target.height)) |
1553 | + if (windowGeometry !== undefined) { |
1554 | + target.x = windowGeometry.x |
1555 | + target.y = windowGeometry.y |
1556 | + target.width = windowGeometry.width |
1557 | + target.height = windowGeometry.height |
1558 | + } |
1559 | + var windowState = windowStateStorage.getState(root.windowId, WindowStateStorage.WindowStateNormal) |
1560 | + if (windowState === WindowStateStorage.WindowStateMaximized) { |
1561 | + target.maximize(false) |
1562 | } |
1563 | } |
1564 | |
1565 | Component.onDestruction: { |
1566 | - windowStateStorage.saveGeometry(root.windowId, Qt.rect(target.x, target.y, target.width, target.height)) |
1567 | + windowStateStorage.saveState(root.windowId, target.state == "maximized" ? WindowStateStorage.WindowStateMaximized : WindowStateStorage.WindowStateNormal) |
1568 | + windowStateStorage.saveGeometry(root.windowId, Qt.rect(priv.normalX, priv.normalY, priv.normalWidth, priv.normalHeight)) |
1569 | } |
1570 | |
1571 | QtObject { |
1572 | |
1573 | === added file 'qml/graphics/applicationIcons/libreoffice@18.png' |
1574 | Binary files qml/graphics/applicationIcons/libreoffice@18.png 1970-01-01 00:00:00 +0000 and qml/graphics/applicationIcons/libreoffice@18.png 2015-11-05 18:02:15 +0000 differ |
1575 | === modified file 'tests/mocks/GSettings.1.0/fake_gsettings.cpp' |
1576 | --- tests/mocks/GSettings.1.0/fake_gsettings.cpp 2015-09-02 13:06:56 +0000 |
1577 | +++ tests/mocks/GSettings.1.0/fake_gsettings.cpp 2015-11-05 18:02:15 +0000 |
1578 | @@ -75,6 +75,19 @@ |
1579 | } |
1580 | } |
1581 | |
1582 | +QStringList GSettingsControllerQml::lifecycleExemptAppids() const |
1583 | +{ |
1584 | + return m_lifecycleExemptAppids; |
1585 | +} |
1586 | + |
1587 | +void GSettingsControllerQml::setLifecycleExemptAppids(const QStringList &appIds) |
1588 | +{ |
1589 | + if (m_lifecycleExemptAppids != appIds) { |
1590 | + m_lifecycleExemptAppids = appIds; |
1591 | + Q_EMIT lifecycleExemptAppidsChanged(m_lifecycleExemptAppids); |
1592 | + } |
1593 | +} |
1594 | + |
1595 | GSettingsSchemaQml::GSettingsSchemaQml(QObject *parent): QObject(parent) { |
1596 | } |
1597 | |
1598 | @@ -114,6 +127,8 @@ |
1599 | this, &GSettingsQml::usageModeChanged); |
1600 | connect(GSettingsControllerQml::instance(), &GSettingsControllerQml::lockedOutTimeChanged, |
1601 | this, &GSettingsQml::lockedOutTimeChanged); |
1602 | + connect(GSettingsControllerQml::instance(), &GSettingsControllerQml::lifecycleExemptAppidsChanged, |
1603 | + this, &GSettingsQml::lifecycleExemptAppidsChanged); |
1604 | } |
1605 | |
1606 | GSettingsSchemaQml * GSettingsQml::schema() const { |
1607 | @@ -167,3 +182,19 @@ |
1608 | GSettingsControllerQml::instance()->setLockedOutTime(timestamp); |
1609 | } |
1610 | } |
1611 | + |
1612 | +QStringList GSettingsQml::lifecycleExemptAppids() const |
1613 | +{ |
1614 | + if (m_schema->id() == "com.canonical.qtmir") { |
1615 | + return GSettingsControllerQml::instance()->lifecycleExemptAppids(); |
1616 | + } else { |
1617 | + return QStringList(); |
1618 | + } |
1619 | +} |
1620 | + |
1621 | +void GSettingsQml::setLifecycleExemptAppids(const QStringList &appIds) |
1622 | +{ |
1623 | + if (m_schema->id() == "com.canonical.qtmir") { |
1624 | + GSettingsControllerQml::instance()->setLifecycleExemptAppids(appIds); |
1625 | + } |
1626 | +} |
1627 | |
1628 | === modified file 'tests/mocks/GSettings.1.0/fake_gsettings.h' |
1629 | --- tests/mocks/GSettings.1.0/fake_gsettings.h 2015-08-19 23:41:18 +0000 |
1630 | +++ tests/mocks/GSettings.1.0/fake_gsettings.h 2015-11-05 18:02:15 +0000 |
1631 | @@ -19,6 +19,7 @@ |
1632 | |
1633 | #include <QList> |
1634 | #include <QObject> |
1635 | +#include <QStringList> |
1636 | |
1637 | class GSettingsSchemaQml: public QObject |
1638 | { |
1639 | @@ -48,6 +49,7 @@ |
1640 | Q_PROPERTY(QString pictureUri READ pictureUri WRITE setPictureUri NOTIFY pictureUriChanged) |
1641 | Q_PROPERTY(QString usageMode READ usageMode WRITE setUsageMode NOTIFY usageModeChanged) |
1642 | Q_PROPERTY(qint64 lockedOutTime READ lockedOutTime WRITE setLockedOutTime NOTIFY lockedOutTimeChanged) |
1643 | + Q_PROPERTY(QStringList lifecycleExemptAppids READ lifecycleExemptAppids WRITE setLifecycleExemptAppids NOTIFY lifecycleExemptAppidsChanged) |
1644 | |
1645 | public: |
1646 | GSettingsQml(QObject *parent = nullptr); |
1647 | @@ -56,16 +58,19 @@ |
1648 | QString pictureUri() const; |
1649 | QString usageMode() const; |
1650 | qint64 lockedOutTime() const; |
1651 | + QStringList lifecycleExemptAppids() const; |
1652 | |
1653 | void setPictureUri(const QString &str); |
1654 | void setUsageMode(const QString &usageMode); |
1655 | void setLockedOutTime(qint64 timestamp); |
1656 | + void setLifecycleExemptAppids(const QStringList &appIds); |
1657 | |
1658 | Q_SIGNALS: |
1659 | void schemaChanged(); |
1660 | void pictureUriChanged(const QString&); |
1661 | void usageModeChanged(const QString&); |
1662 | void lockedOutTimeChanged(qint64); |
1663 | + void lifecycleExemptAppidsChanged(const QStringList &); |
1664 | |
1665 | private: |
1666 | GSettingsSchemaQml* m_schema; |
1667 | @@ -90,10 +95,14 @@ |
1668 | qint64 lockedOutTime() const; |
1669 | Q_INVOKABLE void setLockedOutTime(qint64 timestamp); |
1670 | |
1671 | + QStringList lifecycleExemptAppids() const; |
1672 | + Q_INVOKABLE void setLifecycleExemptAppids(const QStringList &appIds); |
1673 | + |
1674 | Q_SIGNALS: |
1675 | void pictureUriChanged(const QString&); |
1676 | void usageModeChanged(const QString&); |
1677 | void lockedOutTimeChanged(qint64 timestamp); |
1678 | + void lifecycleExemptAppidsChanged(const QStringList&); |
1679 | |
1680 | private: |
1681 | GSettingsControllerQml(); |
1682 | @@ -101,6 +110,7 @@ |
1683 | QString m_pictureUri; |
1684 | QString m_usageMode; |
1685 | qint64 m_lockedOutTime; |
1686 | + QStringList m_lifecycleExemptAppids; |
1687 | |
1688 | static GSettingsControllerQml* s_controllerInstance; |
1689 | QList<GSettingsQml *> m_registeredGSettings; |
1690 | |
1691 | === modified file 'tests/mocks/Unity/Application/ApplicationInfo.cpp' |
1692 | --- tests/mocks/Unity/Application/ApplicationInfo.cpp 2015-08-31 10:25:07 +0000 |
1693 | +++ tests/mocks/Unity/Application/ApplicationInfo.cpp 2015-11-05 18:02:15 +0000 |
1694 | @@ -41,6 +41,7 @@ |
1695 | Qt::InvertedLandscapeOrientation) |
1696 | , m_rotatesWindowContents(false) |
1697 | , m_requestedState(RequestedRunning) |
1698 | + , m_isTouchApp(true) |
1699 | , m_manualSurfaceCreation(false) |
1700 | { |
1701 | } |
1702 | @@ -58,6 +59,7 @@ |
1703 | Qt::InvertedLandscapeOrientation) |
1704 | , m_rotatesWindowContents(false) |
1705 | , m_requestedState(RequestedRunning) |
1706 | + , m_isTouchApp(true) |
1707 | , m_manualSurfaceCreation(false) |
1708 | { |
1709 | } |
1710 | @@ -99,6 +101,7 @@ |
1711 | if (m_session) { |
1712 | m_session->setApplication(this); |
1713 | m_session->setParent(this); |
1714 | + m_session->setScreenshot(m_screenshotFileName); |
1715 | SessionManager::singleton()->registerSession(m_session); |
1716 | connect(m_session, &Session::surfaceChanged, |
1717 | this, &ApplicationInfo::onSessionSurfaceChanged); |
1718 | @@ -123,21 +126,18 @@ |
1719 | QString screenshotFileName; |
1720 | |
1721 | if (screenshotId.endsWith(".svg")) { |
1722 | - screenshotFileName = QString("%1/Dash/graphics/phone/screenshots/%2") |
1723 | - .arg(qmlDirectory()) |
1724 | + screenshotFileName = QString("qrc:///Unity/Application/screenshots/%2") |
1725 | .arg(screenshotId); |
1726 | } else { |
1727 | - screenshotFileName = QString("%1/Dash/graphics/phone/screenshots/%2@12.png") |
1728 | - .arg(qmlDirectory()) |
1729 | + screenshotFileName = QString("qrc:///Unity/Application/screenshots/%2@12.png") |
1730 | .arg(screenshotId); |
1731 | } |
1732 | |
1733 | if (screenshotFileName != m_screenshotFileName) { |
1734 | m_screenshotFileName = screenshotFileName; |
1735 | |
1736 | - QUrl screenshotUrl = QString("file://%1").arg(m_screenshotFileName); |
1737 | if (m_session) { |
1738 | - m_session->setScreenshot(screenshotUrl); |
1739 | + m_session->setScreenshot(screenshotFileName); |
1740 | } |
1741 | } |
1742 | } |
1743 | @@ -245,6 +245,16 @@ |
1744 | } |
1745 | } |
1746 | |
1747 | +bool ApplicationInfo::isTouchApp() const |
1748 | +{ |
1749 | + return m_isTouchApp; |
1750 | +} |
1751 | + |
1752 | +void ApplicationInfo::setIsTouchApp(bool isTouchApp) |
1753 | +{ |
1754 | + m_isTouchApp = isTouchApp; |
1755 | +} |
1756 | + |
1757 | void ApplicationInfo::onSessionSurfaceChanged(MirSurface* surface) |
1758 | { |
1759 | if (surface != nullptr && m_state == Starting) { |
1760 | |
1761 | === modified file 'tests/mocks/Unity/Application/ApplicationInfo.h' |
1762 | --- tests/mocks/Unity/Application/ApplicationInfo.h 2015-08-03 15:00:47 +0000 |
1763 | +++ tests/mocks/Unity/Application/ApplicationInfo.h 2015-11-05 18:02:15 +0000 |
1764 | @@ -89,6 +89,9 @@ |
1765 | bool manualSurfaceCreation() const { return m_manualSurfaceCreation; } |
1766 | void setManualSurfaceCreation(bool value); |
1767 | |
1768 | + bool isTouchApp() const override; |
1769 | + void setIsTouchApp(bool isTouchApp); // only in mock |
1770 | + |
1771 | public: |
1772 | void setSession(Session* session); |
1773 | Session* session() const { return m_session; } |
1774 | @@ -121,6 +124,7 @@ |
1775 | Qt::ScreenOrientations m_supportedOrientations; |
1776 | bool m_rotatesWindowContents; |
1777 | RequestedState m_requestedState; |
1778 | + bool m_isTouchApp; |
1779 | |
1780 | bool m_manualSurfaceCreation; |
1781 | }; |
1782 | |
1783 | === modified file 'tests/mocks/Unity/Application/ApplicationManager.cpp' |
1784 | --- tests/mocks/Unity/Application/ApplicationManager.cpp 2015-08-03 13:47:44 +0000 |
1785 | +++ tests/mocks/Unity/Application/ApplicationManager.cpp 2015-11-05 18:02:15 +0000 |
1786 | @@ -105,6 +105,8 @@ |
1787 | return app->state(); |
1788 | case RoleFocused: |
1789 | return app->focused(); |
1790 | + case RoleIsTouchApp: |
1791 | + return app->isTouchApp(); |
1792 | case RoleSession: |
1793 | return QVariant::fromValue(app->session()); |
1794 | case RoleFullscreen: |
1795 | @@ -458,6 +460,14 @@ |
1796 | application->setName("YouTube"); |
1797 | application->setIconId("youtube"); |
1798 | m_availableApplications.append(application); |
1799 | + |
1800 | + application = new ApplicationInfo(this); |
1801 | + application->setAppId("libreoffice"); |
1802 | + application->setName("LibreOffice"); |
1803 | + application->setIconId("libreoffice"); |
1804 | + application->setScreenshotId("libreoffice"); |
1805 | + application->setIsTouchApp(false); |
1806 | + m_availableApplications.append(application); |
1807 | } |
1808 | |
1809 | |
1810 | |
1811 | === modified file 'tests/mocks/Unity/Application/ApplicationManager.h' |
1812 | --- tests/mocks/Unity/Application/ApplicationManager.h 2015-06-19 18:19:33 +0000 |
1813 | +++ tests/mocks/Unity/Application/ApplicationManager.h 2015-11-05 18:02:15 +0000 |
1814 | @@ -43,7 +43,7 @@ |
1815 | static ApplicationManager *singleton(); |
1816 | |
1817 | enum MoreRoles { |
1818 | - RoleSession = RoleFocused+1, |
1819 | + RoleSession = RoleIsTouchApp+1, |
1820 | RoleFullscreen, |
1821 | }; |
1822 | enum Flag { |
1823 | |
1824 | === modified file 'tests/mocks/Unity/Application/ApplicationTestInterface.cpp' |
1825 | --- tests/mocks/Unity/Application/ApplicationTestInterface.cpp 2015-08-03 15:00:47 +0000 |
1826 | +++ tests/mocks/Unity/Application/ApplicationTestInterface.cpp 2015-11-05 18:02:15 +0000 |
1827 | @@ -40,7 +40,7 @@ |
1828 | { |
1829 | if (!existingSession) return nullptr; |
1830 | |
1831 | - QUrl screenshotUrl = QString("file://%1/Dash/graphics/phone/screenshots/%2@12.png") |
1832 | + QUrl screenshotUrl = QString("qrc:///Unity/Application/screenshots/%2@12.png") |
1833 | .arg(qmlDirectory()) |
1834 | .arg(surfaceImage); |
1835 | |
1836 | @@ -90,7 +90,7 @@ |
1837 | return 0; |
1838 | } |
1839 | |
1840 | - QUrl screenshotUrl = QString("file://%1/Dash/graphics/phone/screenshots/%2@12.png") |
1841 | + QUrl screenshotUrl = QString("qrc:///Unity/Application/screenshots/%2@12.png") |
1842 | .arg(qmlDirectory()) |
1843 | .arg(surfaceImage); |
1844 | |
1845 | |
1846 | === renamed directory 'qml/Dash/graphics/phone/screenshots' => 'tests/mocks/Unity/Application/resources/screenshots' |
1847 | === added file 'tests/mocks/Unity/Application/resources/screenshots/libreoffice@12.png' |
1848 | Binary files tests/mocks/Unity/Application/resources/screenshots/libreoffice@12.png 1970-01-01 00:00:00 +0000 and tests/mocks/Unity/Application/resources/screenshots/libreoffice@12.png 2015-11-05 18:02:15 +0000 differ |
1849 | === modified file 'tests/mocks/Unity/Application/resources/surfaces.qrc' |
1850 | --- tests/mocks/Unity/Application/resources/surfaces.qrc 2015-04-30 20:46:41 +0000 |
1851 | +++ tests/mocks/Unity/Application/resources/surfaces.qrc 2015-11-05 18:02:15 +0000 |
1852 | @@ -3,5 +3,18 @@ |
1853 | <file>VirtualKeyboard.qml</file> |
1854 | <file>MirSurfaceItem.qml</file> |
1855 | <file>vkb_portrait.png</file> |
1856 | + <file>screenshots/browser@12.png</file> |
1857 | + <file>screenshots/camera@12.png</file> |
1858 | + <file>screenshots/dialer@12.png</file> |
1859 | + <file>screenshots/facebook@12.png</file> |
1860 | + <file>screenshots/gallery@12.png</file> |
1861 | + <file>screenshots/gmail-webapp.svg</file> |
1862 | + <file>screenshots/map@12.png</file> |
1863 | + <file>screenshots/music@12.png</file> |
1864 | + <file>screenshots/twitter@12.png</file> |
1865 | + <file>screenshots/ubuntu-weather-app.svg</file> |
1866 | + <file>screenshots/unity8-dash@12.png</file> |
1867 | + <file>screenshots/vkb_portrait.png</file> |
1868 | + <file>screenshots/libreoffice@12.png</file> |
1869 | </qresource> |
1870 | </RCC> |
1871 | |
1872 | === modified file 'tests/mocks/Unity/Launcher/MockLauncherModel.cpp' |
1873 | --- tests/mocks/Unity/Launcher/MockLauncherModel.cpp 2015-08-12 08:40:47 +0000 |
1874 | +++ tests/mocks/Unity/Launcher/MockLauncherModel.cpp 2015-11-05 18:02:15 +0000 |
1875 | @@ -75,6 +75,9 @@ |
1876 | item = new MockLauncherItem("calendar-app", "/usr/share/applications/calendar-app.desktop","Calendar", "calendar", this); |
1877 | item->setPinned(true); |
1878 | m_list.append(item); |
1879 | + item = new MockLauncherItem("libreoffice", "/usr/share/applications/libreoffice.desktop","Libre Office", "libreoffice", this); |
1880 | + item->setPinned(true); |
1881 | + m_list.append(item); |
1882 | } |
1883 | |
1884 | MockLauncherModel::~MockLauncherModel() |
1885 | |
1886 | === modified file 'tests/mocks/Utils/CMakeLists.txt' |
1887 | --- tests/mocks/Utils/CMakeLists.txt 2015-09-29 14:46:24 +0000 |
1888 | +++ tests/mocks/Utils/CMakeLists.txt 2015-11-05 18:02:15 +0000 |
1889 | @@ -18,6 +18,8 @@ |
1890 | ${CMAKE_SOURCE_DIR}/plugins/Utils/windowscreenshotprovider.cpp |
1891 | ${CMAKE_SOURCE_DIR}/plugins/Utils/easingcurve.cpp |
1892 | ${CMAKE_SOURCE_DIR}/plugins/Utils/inputwatcher.cpp |
1893 | + ${CMAKE_SOURCE_DIR}/plugins/Utils/applicationsfiltermodel.cpp |
1894 | + ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h |
1895 | constants.cpp |
1896 | plugin.cpp |
1897 | windowstatestorage.cpp |
1898 | |
1899 | === modified file 'tests/mocks/Utils/plugin.cpp' |
1900 | --- tests/mocks/Utils/plugin.cpp 2015-09-29 14:46:24 +0000 |
1901 | +++ tests/mocks/Utils/plugin.cpp 2015-11-05 18:02:15 +0000 |
1902 | @@ -35,6 +35,7 @@ |
1903 | #include <windowkeysfilter.h> |
1904 | #include <windowscreenshotprovider.h> |
1905 | #include <easingcurve.h> |
1906 | +#include <applicationsfiltermodel.h> |
1907 | |
1908 | static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine) |
1909 | { |
1910 | @@ -63,6 +64,7 @@ |
1911 | qmlRegisterType<InputWatcher>(uri, 0, 1, "InputWatcher"); |
1912 | qmlRegisterSingletonType<Constants>(uri, 0, 1, "Constants", createConstants); |
1913 | qmlRegisterType<ActiveFocusLogger>(uri, 0, 1, "ActiveFocusLogger"); |
1914 | + qmlRegisterType<ApplicationsFilterModel>(uri, 0, 1, "ApplicationsFilterModel"); |
1915 | } |
1916 | |
1917 | void FakeUtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri) |
1918 | |
1919 | === modified file 'tests/mocks/Utils/windowstatestorage.cpp' |
1920 | --- tests/mocks/Utils/windowstatestorage.cpp 2015-08-24 15:39:53 +0000 |
1921 | +++ tests/mocks/Utils/windowstatestorage.cpp 2015-11-05 18:02:15 +0000 |
1922 | @@ -44,3 +44,20 @@ |
1923 | if (!m_geometry.contains(windowId)) return defaultValue; |
1924 | return m_geometry.value(windowId).toRect(); |
1925 | } |
1926 | + |
1927 | +void WindowStateStorage::clear() |
1928 | +{ |
1929 | + m_state.clear(); |
1930 | + m_geometry.clear(); |
1931 | +} |
1932 | + |
1933 | +void WindowStateStorage::saveState(const QString &windowId, WindowState state) |
1934 | +{ |
1935 | + m_state[windowId] = state; |
1936 | +} |
1937 | + |
1938 | +WindowStateStorage::WindowState WindowStateStorage::getState(const QString &windowId, WindowStateStorage::WindowState defaultValue) |
1939 | +{ |
1940 | + if (!m_state.contains(windowId)) return defaultValue; |
1941 | + return m_state.value(windowId); |
1942 | +} |
1943 | |
1944 | === modified file 'tests/mocks/Utils/windowstatestorage.h' |
1945 | --- tests/mocks/Utils/windowstatestorage.h 2015-08-24 15:39:53 +0000 |
1946 | +++ tests/mocks/Utils/windowstatestorage.h 2015-11-05 18:02:15 +0000 |
1947 | @@ -22,12 +22,23 @@ |
1948 | { |
1949 | Q_OBJECT |
1950 | Q_PROPERTY(QVariantMap geometry READ geometry WRITE setGeometry NOTIFY geometryChanged) |
1951 | + Q_ENUMS(WindowState) |
1952 | public: |
1953 | + enum WindowState { |
1954 | + WindowStateNormal, |
1955 | + WindowStateMaximized |
1956 | + }; |
1957 | WindowStateStorage(QObject *parent = 0); |
1958 | |
1959 | + Q_INVOKABLE void saveState(const QString &windowId, WindowState state); |
1960 | + Q_INVOKABLE WindowState getState(const QString &windowId, WindowState defaultValue); |
1961 | + |
1962 | Q_INVOKABLE void saveGeometry(const QString &windowId, const QRect &rect); |
1963 | Q_INVOKABLE QRect getGeometry(const QString &windowId, const QRect &defaultValue); |
1964 | |
1965 | + // Only in the mock, to easily restore a fresh state |
1966 | + Q_INVOKABLE void clear(); |
1967 | + |
1968 | Q_SIGNALS: |
1969 | void geometryChanged(const QVariantMap& geometry); |
1970 | |
1971 | @@ -35,5 +46,6 @@ |
1972 | void setGeometry(const QVariantMap& geometry); |
1973 | QVariantMap geometry() const; |
1974 | |
1975 | + QHash<QString, WindowState> m_state; |
1976 | QVariantMap m_geometry; |
1977 | }; |
1978 | |
1979 | === modified file 'tests/plugins/Unity/Launcher/launchermodeltest.cpp' |
1980 | --- tests/plugins/Unity/Launcher/launchermodeltest.cpp 2015-08-19 14:24:07 +0000 |
1981 | +++ tests/plugins/Unity/Launcher/launchermodeltest.cpp 2015-11-05 18:02:15 +0000 |
1982 | @@ -57,6 +57,7 @@ |
1983 | QColor splashColorFooter() const override { return QColor(0,0,0,0); } |
1984 | Qt::ScreenOrientations supportedOrientations() const override { return Qt::PortraitOrientation; } |
1985 | bool rotatesWindowContents() const override { return false; } |
1986 | + bool isTouchApp() const override { return true; } |
1987 | |
1988 | // Methods used for mocking (not in the interface) |
1989 | void setFocused(bool focused) { m_focused = focused; Q_EMIT focusedChanged(focused); } |
1990 | |
1991 | === modified file 'tests/qmltests/CMakeLists.txt' |
1992 | --- tests/qmltests/CMakeLists.txt 2015-10-20 08:10:03 +0000 |
1993 | +++ tests/qmltests/CMakeLists.txt 2015-11-05 18:02:15 +0000 |
1994 | @@ -11,6 +11,7 @@ |
1995 | add_unity8_qmltest(Components DraggingArea) |
1996 | add_unity8_qmltest(Components LazyImage) |
1997 | add_unity8_qmltest(Components Lockscreen) |
1998 | +add_unity8_qmltest(Components ModeSwitchWarningDialog) |
1999 | add_unity8_qmlunittest(Components PhysicalKeysMapper) |
2000 | add_unity8_qmltest(Components Rating) |
2001 | add_unity8_qmltest(Components ResponsiveGridView) |
2002 | |
2003 | === added file 'tests/qmltests/Components/tst_ModeSwitchWarningDialog.qml' |
2004 | --- tests/qmltests/Components/tst_ModeSwitchWarningDialog.qml 1970-01-01 00:00:00 +0000 |
2005 | +++ tests/qmltests/Components/tst_ModeSwitchWarningDialog.qml 2015-11-05 18:02:15 +0000 |
2006 | @@ -0,0 +1,75 @@ |
2007 | +/* |
2008 | + * Copyright 2015 Canonical Ltd. |
2009 | + * |
2010 | + * This program is free software; you can redistribute it and/or modify |
2011 | + * it under the terms of the GNU General Public License as published by |
2012 | + * the Free Software Foundation; version 3. |
2013 | + * |
2014 | + * This program is distributed in the hope that it will be useful, |
2015 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2016 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2017 | + * GNU General Public License for more details. |
2018 | + * |
2019 | + * You should have received a copy of the GNU General Public License |
2020 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2021 | + */ |
2022 | + |
2023 | +import QtQuick 2.0 |
2024 | +import QtTest 1.0 |
2025 | +import "../../../qml/Components" |
2026 | +import Unity.Test 0.1 as UT |
2027 | +import Ubuntu.Components 1.2 |
2028 | +import Ubuntu.Components.Popups 1.2 |
2029 | + |
2030 | +Rectangle { |
2031 | + id: root |
2032 | + width: units.gu(40) |
2033 | + height: units.gu(70) |
2034 | + color: "lightgrey" |
2035 | + |
2036 | + ListModel { |
2037 | + id: fakeModel |
2038 | + ListElement { icon: "../graphics/applicationIcons/facebook.png"; name: "Facebook" } |
2039 | + ListElement { icon: "../graphics/applicationIcons/gmail.png"; name: "Mail" } |
2040 | + } |
2041 | + |
2042 | + function openWarning() { |
2043 | + return PopupUtils.open(Qt.resolvedUrl("../../../qml/Components/ModeSwitchWarningDialog.qml"), root, { model: fakeModel }); |
2044 | + } |
2045 | + |
2046 | + Button { |
2047 | + anchors.centerIn: parent |
2048 | + text: "trigger warning" |
2049 | + onClicked: { |
2050 | + openWarning(); |
2051 | + } |
2052 | + } |
2053 | + |
2054 | + SignalSpy { |
2055 | + id: spy |
2056 | + signalName: "forceClose" |
2057 | + } |
2058 | + |
2059 | + UT.UnityTestCase { |
2060 | + name: "ModeSwitchWarning" |
2061 | + when: windowShown |
2062 | + |
2063 | + function test_labelChangesOnClick() { |
2064 | + var popup = openWarning(); |
2065 | + var reconnectLabel = findChild(popup, "reconnectLabel"); |
2066 | + tryCompare(reconnectLabel, "text", reconnectLabel.notClickedText) |
2067 | + mouseClick(reconnectLabel, reconnectLabel.width / 2, reconnectLabel.height / 2) |
2068 | + tryCompare(reconnectLabel, "text", reconnectLabel.clickedText) |
2069 | + } |
2070 | + |
2071 | + function test_closeButtonEmitsSignal() { |
2072 | + var popup = openWarning(); |
2073 | + spy.target = popup; |
2074 | + spy.clear(); |
2075 | + var closeButton = findChild(popup, "forceCloseButton"); |
2076 | + mouseClick(closeButton, closeButton.width / 2, closeButton.height / 2) |
2077 | + tryCompare(spy, "count", 1) |
2078 | + |
2079 | + } |
2080 | + } |
2081 | +} |
2082 | |
2083 | === modified file 'tests/qmltests/Components/tst_ZoomableImage.qml' |
2084 | --- tests/qmltests/Components/tst_ZoomableImage.qml 2015-03-18 14:34:18 +0000 |
2085 | +++ tests/qmltests/Components/tst_ZoomableImage.qml 2015-11-05 18:02:15 +0000 |
2086 | @@ -36,7 +36,7 @@ |
2087 | } |
2088 | |
2089 | property var widgetData2: { |
2090 | - "source": "../../../qml/Dash/graphics/phone/screenshots/gallery@12.png", |
2091 | + "source": "../../mocks/Unity/Application/resources/screenshots/gallery@12.png", |
2092 | "zoomable": true |
2093 | } |
2094 | |
2095 | |
2096 | === modified file 'tests/qmltests/Stages/tst_PhoneStage.qml' |
2097 | --- tests/qmltests/Stages/tst_PhoneStage.qml 2015-08-12 15:08:09 +0000 |
2098 | +++ tests/qmltests/Stages/tst_PhoneStage.qml 2015-11-05 18:02:15 +0000 |
2099 | @@ -34,8 +34,6 @@ |
2100 | maximizedAppTopMargin: units.gu(3) + units.dp(2) |
2101 | interactive: true |
2102 | shellOrientation: Qt.PortraitOrientation |
2103 | - shellPrimaryOrientation: Qt.PortraitOrientation |
2104 | - nativeOrientation: Qt.PortraitOrientation |
2105 | } |
2106 | |
2107 | Binding { |
2108 | |
2109 | === modified file 'tests/qmltests/Stages/tst_SpreadDelegate.qml' |
2110 | --- tests/qmltests/Stages/tst_SpreadDelegate.qml 2015-03-06 04:44:11 +0000 |
2111 | +++ tests/qmltests/Stages/tst_SpreadDelegate.qml 2015-11-05 18:02:15 +0000 |
2112 | @@ -18,6 +18,7 @@ |
2113 | import QtTest 1.0 |
2114 | import Unity.Test 0.1 as UT |
2115 | import ".." |
2116 | +import "../../../qml/Components" |
2117 | import "../../../qml/Stages" |
2118 | import Ubuntu.Components 0.1 |
2119 | import Ubuntu.Components.ListItems 1.0 as ListItem |
2120 | @@ -73,8 +74,11 @@ |
2121 | return Qt.LandscapeOrientation; |
2122 | } |
2123 | } |
2124 | - shellPrimaryOrientation: Qt.PortraitOrientation |
2125 | - nativeOrientation: Qt.PortraitOrientation |
2126 | + |
2127 | + orientations: Orientations { |
2128 | + // the default values will do |
2129 | + } |
2130 | + |
2131 | maximizedAppTopMargin: units.gu(3) |
2132 | Component.onDestruction: { |
2133 | spreadDelegateLoader.itemDestroyed = true; |
2134 | |
2135 | === modified file 'tests/qmltests/Stages/tst_TabletStage.qml' |
2136 | --- tests/qmltests/Stages/tst_TabletStage.qml 2015-09-02 14:26:43 +0000 |
2137 | +++ tests/qmltests/Stages/tst_TabletStage.qml 2015-11-05 18:02:15 +0000 |
2138 | @@ -22,6 +22,7 @@ |
2139 | import Unity.Test 0.1 |
2140 | |
2141 | import "../../../qml/Stages" |
2142 | +import "../../../qml/Components" |
2143 | |
2144 | Rectangle { |
2145 | id: root |
2146 | @@ -50,10 +51,9 @@ |
2147 | maximizedAppTopMargin: units.gu(3) + units.dp(2) |
2148 | interactive: true |
2149 | shellOrientation: Qt.LandscapeOrientation |
2150 | - shellPrimaryOrientation: Qt.LandscapeOrientation |
2151 | - nativeOrientation: Qt.LandscapeOrientation |
2152 | nativeWidth: width |
2153 | nativeHeight: height |
2154 | + orientations: Orientations{} // Defaults are fine for testing |
2155 | focus: true |
2156 | } |
2157 | } |
2158 | |
2159 | === modified file 'tests/qmltests/Stages/tst_WindowResizeArea.qml' |
2160 | --- tests/qmltests/Stages/tst_WindowResizeArea.qml 2015-10-08 14:27:12 +0000 |
2161 | +++ tests/qmltests/Stages/tst_WindowResizeArea.qml 2015-11-05 18:02:15 +0000 |
2162 | @@ -44,8 +44,11 @@ |
2163 | width: units.gu(20) |
2164 | property int windowHeight: height |
2165 | property int windowWidth: width |
2166 | - onWindowHeightChanged: height = windowHeight |
2167 | - onWindowWidthChanged: width = windowWidth |
2168 | + state: "normal" |
2169 | + |
2170 | + function maximize() { |
2171 | + state = "maximized" |
2172 | + } |
2173 | |
2174 | WindowResizeArea { |
2175 | id: windowResizeArea |
2176 | @@ -195,5 +198,35 @@ |
2177 | tryCompare(fakeWindow, "width", initialWindowWidth); |
2178 | tryCompare(fakeWindow, "height", initialWindowHeight); |
2179 | } |
2180 | + |
2181 | + function test_saveRestoreMaximized() { |
2182 | + var initialWindowX = fakeWindow.x; |
2183 | + var initialWindowY = fakeWindow.y; |
2184 | + |
2185 | + var moveDelta = units.gu(5); |
2186 | + |
2187 | + fakeWindow.x = initialWindowX + moveDelta |
2188 | + fakeWindow.y = initialWindowY + moveDelta |
2189 | + |
2190 | + // Now change the state to maximized. The window should not keep updating the stored values |
2191 | + fakeWindow.state = "maximized" |
2192 | + fakeWindow.x = 31415 // 0 is too risky to pass the test even when broken |
2193 | + fakeWindow.y = 31415 |
2194 | + |
2195 | + // This will destroy the window and recreate it |
2196 | + windowLoader.active = false; |
2197 | + waitForRendering(root); |
2198 | + windowLoader.active = true; |
2199 | + |
2200 | + // Make sure it's again where we left it in normal state before destroying |
2201 | + tryCompare(fakeWindow, "x", initialWindowX + moveDelta) |
2202 | + tryCompare(fakeWindow, "y", initialWindowX + moveDelta) |
2203 | + |
2204 | + // Make sure maximize() has been called after restoring |
2205 | + tryCompare(fakeWindow, "state", "maximized") |
2206 | + |
2207 | + // clean up |
2208 | + fakeWindow.state = "normal" |
2209 | + } |
2210 | } |
2211 | } |
2212 | |
2213 | === modified file 'tests/qmltests/tst_OrientedShell.qml' |
2214 | --- tests/qmltests/tst_OrientedShell.qml 2015-10-05 22:04:32 +0000 |
2215 | +++ tests/qmltests/tst_OrientedShell.qml 2015-11-05 18:02:15 +0000 |
2216 | @@ -840,7 +840,7 @@ |
2217 | // shell should remain in its primery orientation as the app in the main stage |
2218 | // is the one that dictates its orientation. In this case it's unity8-dash |
2219 | // which supports only primary orientation |
2220 | - compare(shell.orientation, orientedShell.primaryOrientation); |
2221 | + compare(shell.orientation, orientedShell.orientations.primary); |
2222 | } |
2223 | |
2224 | function test_sideStageAppsRemainPortraitInSpread_data() { |
2225 | |
2226 | === modified file 'tests/qmltests/tst_Shell.qml' |
2227 | --- tests/qmltests/tst_Shell.qml 2015-10-20 08:10:03 +0000 |
2228 | +++ tests/qmltests/tst_Shell.qml 2015-11-05 18:02:15 +0000 |
2229 | @@ -29,8 +29,11 @@ |
2230 | import Unity.Test 0.1 |
2231 | import Powerd 0.1 |
2232 | import Wizard 0.1 as Wizard |
2233 | +import Utils 0.1 |
2234 | |
2235 | import "../../qml" |
2236 | +import "../../qml/Components" |
2237 | +import "../../qml/Components/PanelState" |
2238 | import "Stages" |
2239 | |
2240 | Rectangle { |
2241 | @@ -97,8 +100,7 @@ |
2242 | id: __shell |
2243 | usageScenario: usageScenarioSelector.model[usageScenarioSelector.selectedIndex] |
2244 | orientation: Qt.PortraitOrientation |
2245 | - primaryOrientation: Qt.PortraitOrientation |
2246 | - nativeOrientation: Qt.PortraitOrientation |
2247 | + orientations: Orientations{} // Defaults are fine for testing |
2248 | Component.onDestruction: { |
2249 | shellLoader.itemDestroyed = true; |
2250 | } |
2251 | @@ -302,6 +304,7 @@ |
2252 | mouseEmulation.checked = true; |
2253 | tryCompare(shell, "enabled", true); // make sure greeter didn't leave us in disabled state |
2254 | tearDown(); |
2255 | + WindowStateStorage.clear(); |
2256 | } |
2257 | |
2258 | function loadShell(formFactor) { |
2259 | @@ -377,6 +380,8 @@ |
2260 | LightDM.Greeter.authenticate(""); // reset greeter |
2261 | |
2262 | sessionSpy.clear(); |
2263 | + |
2264 | + GSettingsController.setLifecycleExemptAppids([]); |
2265 | } |
2266 | |
2267 | function killApps() { |
2268 | @@ -1707,5 +1712,177 @@ |
2269 | |
2270 | keyRelease(Qt.Key_Control); |
2271 | } |
2272 | + |
2273 | + // regression test for http://pad.lv/1443319 |
2274 | + function test_closeMaximizedAndRestart() { |
2275 | + loadDesktopShellWithApps(); |
2276 | + |
2277 | + var appRepeater = findChild(shell, "appRepeater") |
2278 | + var appId = ApplicationManager.get(0).appId; |
2279 | + var appDelegate = appRepeater.itemAt(0); |
2280 | + var maximizeButton = findChild(appDelegate, "maximizeWindowButton"); |
2281 | + |
2282 | + wait(5000) |
2283 | + tryCompare(appDelegate, "state", "normal"); |
2284 | + tryCompare(PanelState, "buttonsVisible", false) |
2285 | + |
2286 | + wait(5000) |
2287 | + mouseClick(maximizeButton, maximizeButton.width / 2, maximizeButton.height / 2); |
2288 | + tryCompare(appDelegate, "state", "maximized"); |
2289 | + tryCompare(PanelState, "buttonsVisible", true) |
2290 | + |
2291 | + ApplicationManager.stopApplication(appId); |
2292 | + tryCompare(PanelState, "buttonsVisible", false) |
2293 | + |
2294 | + ApplicationManager.startApplication(appId); |
2295 | + tryCompare(PanelState, "buttonsVisible", true) |
2296 | + } |
2297 | + |
2298 | + // bug http://pad.lv/1431566 |
2299 | + function test_switchToStagedHidesPanelButtons() { |
2300 | + loadDesktopShellWithApps(); |
2301 | + var appRepeater = findChild(shell, "appRepeater") |
2302 | + var appId = ApplicationManager.get(0).appId; |
2303 | + var appDelegate = appRepeater.itemAt(0); |
2304 | + var panelButtons = findChild(shell, "panelWindowControlButtons") |
2305 | + |
2306 | + tryCompare(appDelegate, "state", "normal"); |
2307 | + tryCompare(panelButtons, "visible", false); |
2308 | + |
2309 | + appDelegate.maximize(false); |
2310 | + tryCompare(panelButtons, "visible", true); |
2311 | + |
2312 | + shell.usageScenario = "phone"; |
2313 | + waitForRendering(shell); |
2314 | + tryCompare(panelButtons, "visible", false); |
2315 | + |
2316 | + shell.usageScenario = "desktop"; |
2317 | + waitForRendering(shell); |
2318 | + tryCompare(panelButtons, "visible", true); |
2319 | + } |
2320 | + |
2321 | + function test_lockingGreeterHidesPanelButtons() { |
2322 | + loadDesktopShellWithApps(); |
2323 | + var appRepeater = findChild(shell, "appRepeater") |
2324 | + var appId = ApplicationManager.get(0).appId; |
2325 | + var appDelegate = appRepeater.itemAt(0); |
2326 | + var panelButtons = findChild(shell, "panelWindowControlButtons") |
2327 | + |
2328 | + tryCompare(appDelegate, "state", "normal"); |
2329 | + tryCompare(panelButtons, "visible", false); |
2330 | + |
2331 | + appDelegate.maximize(false); |
2332 | + tryCompare(panelButtons, "visible", true); |
2333 | + |
2334 | + LightDM.Greeter.showGreeter(); |
2335 | + waitForRendering(shell); |
2336 | + tryCompare(panelButtons, "visible", false); |
2337 | + |
2338 | + LightDM.Greeter.hideGreeter(); |
2339 | + waitForRendering(shell); |
2340 | + tryCompare(panelButtons, "visible", true); |
2341 | + } |
2342 | + |
2343 | + function test_lifecyclePolicyForNonTouchApp_data() { |
2344 | + return [ |
2345 | + {tag: "phone", formFactor: "phone", usageScenario: "phone"}, |
2346 | + {tag: "tablet", formFactor: "tablet", usageScenario: "tablet"} |
2347 | + ] |
2348 | + } |
2349 | + |
2350 | + function test_lifecyclePolicyForNonTouchApp(data) { |
2351 | + loadShell(data.formFactor); |
2352 | + shell.usageScenario = data.usageScenario; |
2353 | + |
2354 | + var app1 = ApplicationManager.startApplication("libreoffice"); |
2355 | + waitUntilAppWindowIsFullyLoaded(app1); |
2356 | + var app2 = ApplicationManager.startApplication("dialer-app"); |
2357 | + waitUntilAppWindowIsFullyLoaded(app2); |
2358 | + |
2359 | + // Make sure app1 is unfocused but still running |
2360 | + compare(app1.session.surface.activeFocus, false); |
2361 | + compare(app1.isTouchApp, false); // sanity check our mock, which sets this for us |
2362 | + compare(app1.requestedState, ApplicationInfoInterface.RequestedRunning); |
2363 | + } |
2364 | + |
2365 | + function test_lifecyclePolicyExemption_data() { |
2366 | + return [ |
2367 | + {tag: "phone", formFactor: "phone", usageScenario: "phone", suspendsApps: true}, |
2368 | + {tag: "tablet", formFactor: "tablet", usageScenario: "tablet", suspendsApps: true} |
2369 | + ] |
2370 | + } |
2371 | + |
2372 | + function test_lifecyclePolicyExemption(data) { |
2373 | + loadShell(data.formFactor); |
2374 | + shell.usageScenario = data.usageScenario; |
2375 | + |
2376 | + GSettingsController.setLifecycleExemptAppids(["webbrowser-app"]); |
2377 | + |
2378 | + var app1 = ApplicationManager.startApplication("webbrowser-app"); |
2379 | + waitUntilAppWindowIsFullyLoaded(app1); |
2380 | + var app2 = ApplicationManager.startApplication("dialer-app"); |
2381 | + waitUntilAppWindowIsFullyLoaded(app2); |
2382 | + |
2383 | + // Make sure app1 is unfocused but still running |
2384 | + compare(app1.session.surface.activeFocus, false); |
2385 | + compare(app1.requestedState, ApplicationInfoInterface.RequestedRunning); |
2386 | + } |
2387 | + |
2388 | + function test_switchToStagedForcesLegacyAppClosing_data() { |
2389 | + return [ |
2390 | + {tag: "forceClose", replug: false }, |
2391 | + {tag: "replug", replug: true } |
2392 | + ]; |
2393 | + } |
2394 | + |
2395 | + function test_switchToStagedForcesLegacyAppClosing(data) { |
2396 | + loadShell("desktop") |
2397 | + shell.usageScenario = "desktop" |
2398 | + waitForRendering(shell); |
2399 | + |
2400 | + ApplicationManager.startApplication("camera-app") |
2401 | + |
2402 | + shell.usageScenario = "phone" |
2403 | + waitForRendering(shell); |
2404 | + |
2405 | + // No legacy app running yet... Popup must *not* show. |
2406 | + var popup = findChild(root, "modeSwitchWarningDialog"); |
2407 | + compare(popup, null); |
2408 | + |
2409 | + shell.usageScenario = "desktop" |
2410 | + waitForRendering(shell); |
2411 | + |
2412 | + // Now start a legacy app |
2413 | + ApplicationManager.startApplication("libreoffice") |
2414 | + |
2415 | + shell.usageScenario = "phone" |
2416 | + waitForRendering(shell); |
2417 | + |
2418 | + // The popup must appear now |
2419 | + popup = findChild(root, "modeSwitchWarningDialog"); |
2420 | + compare(popup !== null, true); |
2421 | + |
2422 | + if (data.replug) { |
2423 | + shell.usageScenario = "desktop" |
2424 | + waitForRendering(shell); |
2425 | + |
2426 | + } else { |
2427 | + var forceCloseButton = findChild(popup, "forceCloseButton"); |
2428 | + mouseClick(forceCloseButton, forceCloseButton.width / 2, forceCloseButton.height / 2); |
2429 | + waitForRendering(root); |
2430 | + } |
2431 | + |
2432 | + // Popup must be gone now |
2433 | + popup = findChild(root, "modeSwitchWarningDialog"); |
2434 | + compare(popup === null, true); |
2435 | + |
2436 | + if (data.replug) { |
2437 | + // Libreoffice must still be running |
2438 | + compare(ApplicationManager.findApplication("libreoffice") !== null, true); |
2439 | + } else { |
2440 | + // Libreoffice must be gone now |
2441 | + compare(ApplicationManager.findApplication("libreoffice") === null, true); |
2442 | + } |
2443 | + } |
2444 | } |
2445 | } |