on xenial help sign in
fixes for trunk merge
commit6dc1918e7967457bacce038408141b3ceeef4a2e authorNick Dedekind <nicholas.dedekind@gmail.com> dateTue 26 Aug 2014, 20:45 (12 years ago) parent1bcbfcc
20 files changed+268−290
qml/Stages/ApplicationSessionContainer.qml−73 qml/Stages/ApplicationWindow.qml+2−1 qml/Stages/SessionContainer.qml+19−15 qml/Stages/SurfaceContainer.qml+1−1 tests/mocks/Unity/Application/ApplicationInfo.cpp+19−6 tests/mocks/Unity/Application/ApplicationInfo.h+26−3 tests/mocks/Unity/Application/ApplicationManager.cpp+1−1 tests/mocks/Unity/Application/ApplicationTestInterface.cpp+12−2 tests/mocks/Unity/Application/MirSessionItem.cpp+13−3 tests/mocks/Unity/Application/MirSessionItem.h+14−2 tests/mocks/Unity/Application/MirSurfaceItem.cpp+5−2 tests/mocks/Unity/Application/MirSurfaceItem.h+2−3 tests/mocks/Unity/Application/SessionManager.cpp−1 tests/mocks/Unity/Application/SessionManager.h+1−1 tests/mocks/Unity/Application/SurfaceManager.h+1−1 tests/mocks/Unity/Application/plugin.cpp+3 tests/qmltests/Stages/tst_ApplicationWindow.qml+18−15 tests/qmltests/Stages/tst_SessionContainer.qml+37−33 tests/qmltests/Stages/tst_SurfaceContainer.qml+88−121 tests/qmltests/tst_Shell.qml+6−6
qml/Stages/ApplicationSessionContainer.qmldeleted−73
@@ -1,73 +0,0 @@
1−/*
2− * Copyright 2014 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU Lesser General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU Lesser General Public License for more details.
12− *
13− * You should have received a copy of the GNU Lesser General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15−*/
16−
17−import QtQuick 2.0
18−import "Animations"
19−
20−SessionContainer {
21− id: root
22− property bool appHasCreatedASurface: false
23−
24− onSurfaceChanged: {
25− if (surface) {
26− if (!appHasCreatedASurface) {
27− surface.visible = false; // hide until splash screen removed
28− appHasCreatedASurface = true;
29− }
30− }
31− }
32−
33− function revealSurface() {
34− surface.visible = true;
35− splashLoader.source = "";
36− }
37−
38− Timer { //FIXME - need to delay removing splash screen to allow surface resize to complete
39− id: surfaceRevealDelay
40− interval: 100
41− onTriggered: root.revealSurface()
42− }
43−
44− Loader {
45− id: splashLoader
46− anchors.fill: parent
47− z: 3
48− }
49−
50− StateGroup {
51− id: appSurfaceState
52− states: [
53− State {
54− name: "noSurfaceYet"
55− when: !root.appHasCreatedASurface
56− StateChangeScript {
57− script: { splashLoader.setSource("Splash.qml", { "name": model.name, "image": model.icon }); }
58− }
59− },
60− State {
61− name: "hasSurface"
62− when: root.appHasCreatedASurface && (root.surface !== null)
63− StateChangeScript { script: { surfaceRevealDelay.start(); } }
64− },
65− State {
66− name: "surfaceLostButAppStillAlive"
67− when: root.appHasCreatedASurface && (root.surface === null)
68− // TODO - use app snapshot
69− }
70− ]
71− state: "noSurfaceYet"
72− }
73−}
qml/Stages/ApplicationWindow.qml+2−1
@@ -26,6 +26,7 @@ SessionContainer {
2626
2727 // to be set from outside
2828 property QtObject application
29+ session: application ? application.session : null
2930
3031 QtObject {
3132 id: d
@@ -104,7 +105,7 @@ SessionContainer {
104105 id: splashLoader
105106 visible: active
106107 active: false
107− anchors.fill: surfaceContainer
108+ anchors.fill: parent
108109 sourceComponent: Component {
109110 Splash { name: d.name; image: d.icon }
110111 }
qml/Stages/SessionContainer.qml+19−15
@@ -23,7 +23,7 @@ Item {
2323 property Item session
2424 property var childSessions: session ? session.childSessions : 0
2525 property bool removing: false
26− property alias surface: surfaceContainer.surface
26+ property alias surface: _surfaceContainer.surface
2727 property bool interactive: true
2828
2929 onSessionChanged: {
@@ -32,16 +32,17 @@ Item {
3232 session.z = 1;
3333 }
3434 }
35+ Binding {
36+ target: session
37+ property: "anchors.fill"; value: root
38+ }
3539
40+ readonly property alias surfaceContainer: _surfaceContainer
3641 SurfaceContainer {
37− id: surfaceContainer
38− anchors.fill: parent
39− z: 2;
40−
42+ id: _surfaceContainer
43+ anchors.fill: session
44+ z: 2
4145 surface: session ? session.surface : null
42− onSurfaceChanged: {
43−// root.animateIn(swipeFromBottom);
44− }
4546 }
4647
4748 Binding {
@@ -69,16 +70,24 @@ Item {
6970 source: Qt.resolvedUrl("SessionContainer.qml")
7071 onLoaded: {
7172 item.session = modelData;
72− item.interactive = Qt.bindind(function() { return root.interactive; } );
73+ item.interactive = Qt.binding(function() { return root.interactive; } );
7374 }
7475
7576 Connections {
7677 target: modelData
78+ onSurfaceChanged: {
79+ item.animateIn(swipeFromBottom);
80+ }
7781 onRemoved: {
7882 item.removing = true;
79−// item.animateOut();
83+ item.animateOut();
8084 }
8185 }
86+
87+ Component {
88+ id: swipeFromBottom
89+ SwipeFromBottomAnimation {}
90+ }
8291 }
8392 }
8493
@@ -105,9 +114,4 @@ Item {
105114 property var animations: []
106115 property var currentAnimation: animations.length > 0 ? animations[animations.length-1] : undefined
107116 }
108−
109− Component {
110− id: swipeFromBottom
111− SwipeFromBottomAnimation {}
112− }
113117}
qml/Stages/SurfaceContainer.qml+1−1
@@ -31,7 +31,7 @@ Item {
3131 }
3232 Binding {
3333 target: surface
34− property: "anchors.fill"; value: container
34+ property: "anchors.fill"; value: root
3535 }
3636
3737 Connections {
tests/mocks/Unity/Application/ApplicationInfo.cpp+19−6
@@ -18,10 +18,13 @@
1818#include "MirSessionItem.h"
1919#include "SessionManager.h"
2020
21+#include <paths.h>
22+
2123#include <QGuiApplication>
2224#include <QQuickItem>
2325#include <QQuickView>
2426#include <QQmlComponent>
27+#include <QTimer>
2528
2629ApplicationInfo::ApplicationInfo(const QString &appId, QObject *parent)
2730 : ApplicationInfoInterface(appId, parent)
@@ -31,8 +34,8 @@ ApplicationInfo::ApplicationInfo(const QString &appId, QObject *parent)
3134 , m_focused(false)
3235 , m_fullscreen(false)
3336 , m_session(0)
37+ , m_manualSessionCreation(false)
3438{
35− createSession();
3639}
3740
3841ApplicationInfo::ApplicationInfo(QObject *parent)
@@ -43,8 +46,8 @@ ApplicationInfo::ApplicationInfo(QObject *parent)
4346 , m_fullscreen(false)
4447 , m_parentItem(0)
4548 , m_session(0)
49+ , m_manualSessionCreation(false)
4650{
47− createSession();
4851}
4952
5053ApplicationInfo::~ApplicationInfo()
@@ -54,8 +57,9 @@ ApplicationInfo::~ApplicationInfo()
5457
5558void ApplicationInfo::createSession()
5659{
57− QUrl screenshotUrl = QString("file://%1").arg(m_screenshotFileName);
60+ if (m_session) { return; }
5861
62+ QUrl screenshotUrl = QString("file://%1").arg(m_screenshotFileName);
5963 setSession(SessionManager::singleton()->createSession(appId(), screenshotUrl));
6064}
6165
@@ -99,7 +103,7 @@ void ApplicationInfo::setScreenshotId(const QString &screenshotId)
99103
100104 QUrl screenshotUrl = QString("file://%1").arg(m_screenshotFileName);
101105 if (m_session) {
102− m_session->setScreenshot(screenshot);
106+ m_session->setScreenshot(screenshotUrl);
103107 }
104108 }
105109}
@@ -134,8 +138,9 @@ void ApplicationInfo::setState(State value)
134138 m_state = value;
135139 Q_EMIT stateChanged(value);
136140
137− if (!m_manualSurfaceCreation && m_state == ApplicationInfo::Running) {
138− QTimer::singleShot(1000, this, SLOT(createSurface()));
141+ if (!m_manualSessionCreation && m_state == ApplicationInfo::Running) {
142+
143+ QTimer::singleShot(500, this, SLOT(createSession()));
139144 }
140145 }
141146}
@@ -155,3 +160,11 @@ void ApplicationInfo::setFullscreen(bool value)
155160 Q_EMIT fullscreenChanged(value);
156161 }
157162}
163+
164+void ApplicationInfo::setManualSessionCreation(bool value)
165+{
166+ if (value != m_manualSessionCreation) {
167+ m_manualSessionCreation = value;
168+ Q_EMIT manualSessionCreationChanged(value);
169+ }
170+}
tests/mocks/Unity/Application/ApplicationInfo.h+26−3
@@ -21,7 +21,6 @@
2121#include "MirSurfaceItemModel.h"
2222
2323#include <QObject>
24−#include <QQmlComponent>
2524
2625class QQuickItem;
2726class MirSurfaceItem;
@@ -37,8 +36,14 @@ class ApplicationInfo : public ApplicationInfoInterface {
3736 Q_PROPERTY(bool fullscreen READ fullscreen WRITE setFullscreen NOTIFY fullscreenChanged)
3837 Q_PROPERTY(MirSessionItem* session READ session NOTIFY sessionChanged)
3938
39+ // Only exists in this fake implementation
40+
41+ // whether the test code will explicitly control the creation of the application surface
42+ Q_PROPERTY(bool manualSessionCreation READ manualSessionCreation WRITE setManualSessionCreation NOTIFY manualSessionCreationChanged)
43+
4044public:
4145 ApplicationInfo(const QString &appId, QObject *parent = NULL);
46+ ApplicationInfo(QObject *parent = NULL);
4247 ~ApplicationInfo();
4348
4449 void setIconId(const QString &iconId);
@@ -67,6 +72,9 @@ public:
6772 void setFullscreen(bool value);
6873 bool fullscreen() const { return m_fullscreen; }
6974
75+ bool manualSessionCreation() const { return m_manualSessionCreation; }
76+ void setManualSessionCreation(bool value);
77+
7078public:
7179 void setSession(MirSessionItem* session);
7280 MirSessionItem* session() const { return m_session; }
@@ -74,13 +82,28 @@ public:
7482Q_SIGNALS:
7583 void sessionChanged(MirSessionItem*);
7684 void fullscreenChanged(bool value);
77− void manualSurfaceCreationChanged(bool value);
85+ void manualSessionCreationChanged(bool value);
86+
87+public Q_SLOTS:
88+ Q_INVOKABLE void createSession();
7889
7990private:
80− void createSession();
91+ void setIcon(const QUrl &value);
92+
93+ QString m_screenshotFileName;
94+
95+ QString m_appId;
96+ QString m_name;
97+ QUrl m_icon;
98+ Stage m_stage;
99+ State m_state;
100+ bool m_focused;
101+ bool m_fullscreen;
81102
82103 QQuickItem *m_parentItem;
83104 MirSessionItem* m_session;
105+
106+ bool m_manualSessionCreation;
84107};
85108
86109Q_DECLARE_METATYPE(ApplicationInfo*)
tests/mocks/Unity/Application/ApplicationManager.cpp+1−1
@@ -336,7 +336,7 @@ void ApplicationManager::buildListOfAvailableApplications()
336336{
337337 ApplicationInfo *application;
338338
339− application = new ApplicationInfo(("unity8-dash", this);
339+ application = new ApplicationInfo("unity8-dash", this);
340340 application->setName("Unity 8 Mock Dash");
341341 application->setScreenshotId("unity8-dash");
342342 application->setStage(ApplicationInfo::MainStage);
tests/mocks/Unity/Application/ApplicationTestInterface.cpp+12−2
@@ -22,6 +22,8 @@
2222#include "MirSessionItem.h"
2323#include "MirSurfaceItem.h"
2424
25+#include <paths.h>
26+
2527quint32 nextId = 0;
2628
2729ApplicationTestInterface::ApplicationTestInterface(QObject* parent)
@@ -52,11 +54,15 @@ quint32 ApplicationTestInterface::addChildSession(const QString& appId, quint32
5254 return 0;
5355 }
5456
57+ QUrl screenshotUrl = QString("file://%1/Dash/graphics/phone/screenshots/%2@12.png")
58+ .arg(qmlDirectory())
59+ .arg(surfaceImage);
60+
5561 quint32 sessionId = ++nextId;
5662 MirSessionItem* session = SessionManager::singleton()->createSession(
5763 QString("%1-Child%2").arg(parentSession->name())
5864 .arg(sessionId),
59− QUrl(surfaceImage));
65+ screenshotUrl);
6066 parentSession->addChildSession(session);
6167 session->createSurface();
6268 m_childSessions[sessionId] = session;
@@ -98,13 +104,17 @@ quint32 ApplicationTestInterface::addChildSurface(const QString& appId, quint32
98104 return 0;
99105 }
100106
107+ QUrl screenshotUrl = QString("file://%1/Dash/graphics/phone/screenshots/%2@12.png")
108+ .arg(qmlDirectory())
109+ .arg(surfaceImage);
110+
101111 quint32 surfaceId = ++nextId;
102112 MirSurfaceItem* surface = SurfaceManager::singleton()->createSurface(
103113 QString("%1-Child%2").arg(parentSurface->name())
104114 .arg(surfaceId),
105115 MirSurfaceItem::Normal,
106116 MirSurfaceItem::Maximized,
107− QUrl(surfaceImage));
117+ screenshotUrl);
108118 parentSurface->addChildSurface(surface);
109119 m_childSurfaces[surfaceId] = surface;
110120
tests/mocks/Unity/Application/MirSessionItem.cpp+13−3
@@ -32,6 +32,7 @@ MirSessionItem::MirSessionItem(const QString &name,
3232 , m_surface(nullptr)
3333 , m_parentSession(nullptr)
3434 , m_children(new MirSessionItemModel(this))
35+ , m_manualSurfaceCreation(false)
3536{
3637 qDebug() << "MirSessionItem::MirSessionItem() " << this->name();
3738
@@ -85,12 +86,13 @@ void MirSessionItem::setApplication(ApplicationInfo* application)
8586
8687 if (m_application) {
8788 connect(m_application, &ApplicationInfo::stateChanged, this, [this](ApplicationInfo::State state) {
88− if (state == ApplicationInfo::Running) {
89+ if (!m_manualSurfaceCreation && state == ApplicationInfo::Running) {
8990 QTimer::singleShot(500, this, SLOT(createSurface()));
90− } else if (state == ApplicationInfo::Stopped) {
91− setSurface(nullptr);
9291 }
9392 });
93+ if (!m_manualSurfaceCreation && m_application->state() == ApplicationInfo::Running) {
94+ QTimer::singleShot(500, this, SLOT(createSurface()));
95+ }
9496 }
9597}
9698
@@ -171,3 +173,11 @@ MirSessionItemModel* MirSessionItem::childSessions() const
171173{
172174 return m_children;
173175}
176+
177+void MirSessionItem::setManualSurfaceCreation(bool value)
178+{
179+ if (value != m_manualSurfaceCreation) {
180+ m_manualSurfaceCreation = value;
181+ Q_EMIT manualSurfaceCreationChanged(value);
182+ }
183+}
tests/mocks/Unity/Application/MirSessionItem.h+14−2
@@ -26,10 +26,16 @@ class ApplicationInfo;
2626class MirSessionItem : public QQuickItem
2727{
2828 Q_OBJECT
29+ Q_PROPERTY(QString name READ name CONSTANT)
2930 Q_PROPERTY(MirSurfaceItem* surface READ surface NOTIFY surfaceChanged)
3031 Q_PROPERTY(MirSessionItem* parentSession READ parentSession NOTIFY parentSessionChanged DESIGNABLE false)
3132 Q_PROPERTY(MirSessionItemModel* childSessions READ childSessions DESIGNABLE false CONSTANT)
3233
34+ // Only exists in this fake implementation
35+
36+ // whether the test code will explicitly control the creation of the application surface
37+ Q_PROPERTY(bool manualSurfaceCreation READ manualSurfaceCreation WRITE setManualSurfaceCreation NOTIFY manualSurfaceCreationChanged)
38+
3339public:
3440 explicit MirSessionItem(const QString &name,
3541 const QUrl& screenshot,
@@ -48,18 +54,22 @@ public:
4854 void setSurface(MirSurfaceItem* surface);
4955 void setScreenshot(const QUrl& m_screenshot);
5056
51− void addChildSession(MirSessionItem* session);
57+ Q_INVOKABLE void addChildSession(MirSessionItem* session);
5258 void insertChildSession(uint index, MirSessionItem* session);
5359 void removeChildSession(MirSessionItem* session);
5460
61+ bool manualSurfaceCreation() const { return m_manualSurfaceCreation; }
62+ void setManualSurfaceCreation(bool value);
63+
5564Q_SIGNALS:
5665 void surfaceChanged(MirSurfaceItem*);
5766 void parentSessionChanged(MirSessionItem*);
5867 void removed();
5968 void aboutToBeDestroyed();
69+ void manualSurfaceCreationChanged(bool value);
6070
6171public Q_SLOTS:
62− void createSurface();
72+ Q_INVOKABLE void createSurface();
6373
6474private:
6575 MirSessionItemModel* childSessions() const;
@@ -71,6 +81,8 @@ private:
7181 MirSurfaceItem* m_surface;
7282 MirSessionItem* m_parentSession;
7383 MirSessionItemModel* m_children;
84+
85+ bool m_manualSurfaceCreation;
7486};
7587
7688Q_DECLARE_METATYPE(MirSessionItem*)
tests/mocks/Unity/Application/MirSurfaceItem.cpp+5−2
@@ -129,8 +129,11 @@ void MirSurfaceItem::setSession(MirSessionItem* session)
129129
130130void MirSurfaceItem::setScreenshot(const QUrl& screenshot)
131131{
132− m_img.load(screenshot.isLocalFile() ? screenshot.toLocalFile() : screenshot.toString());
133− update();
132+ m_screenshotUrl = screenshot;
133+ if (m_qmlItem) {
134+ QQmlProperty screenshotSource(m_qmlItem, "screenshotSource");
135+ screenshotSource.write(QVariant::fromValue(m_screenshotUrl));
136+ }
134137}
135138
136139void MirSurfaceItem::setParentSurface(MirSurfaceItem* surface)
tests/mocks/Unity/Application/MirSurfaceItem.h+2−3
@@ -32,7 +32,7 @@ class MirSurfaceItem : public QQuickItem
3232
3333 Q_PROPERTY(Type type READ type NOTIFY typeChanged)
3434 Q_PROPERTY(State state READ state NOTIFY stateChanged)
35− Q_PROPERTY(QString name READ name NOTIFY nameChanged)
35+ Q_PROPERTY(QString name READ name CONSTANT)
3636 Q_PROPERTY(MirSurfaceItem* parentSurface READ parentSurface NOTIFY parentSurfaceChanged DESIGNABLE false)
3737 Q_PROPERTY(MirSurfaceItemModel* childSurfaces READ childSurfaces DESIGNABLE false CONSTANT)
3838
@@ -72,14 +72,13 @@ public:
7272 Q_INVOKABLE void setState(State newState);
7373 Q_INVOKABLE void release();
7474
75− void addChildSurface(MirSurfaceItem* surface);
75+ Q_INVOKABLE void addChildSurface(MirSurfaceItem* surface);
7676 void insertChildSurface(uint index, MirSurfaceItem* surface);
7777 void removeChildSurface(MirSurfaceItem* surface);
7878
7979Q_SIGNALS:
8080 void typeChanged(Type);
8181 void stateChanged(State);
82− void nameChanged(QString);
8382 void parentSurfaceChanged(MirSurfaceItem*);
8483
8584 void removed();
tests/mocks/Unity/Application/SessionManager.cpp−1
@@ -17,7 +17,6 @@
1717#include "SessionManager.h"
1818
1919#include "MirSurfaceItem.h"
20−#include "VirtualKeyboard.h"
2120
2221SessionManager *SessionManager::the_session_manager = nullptr;
2322
tests/mocks/Unity/Application/SessionManager.h+1−1
@@ -29,7 +29,7 @@ public:
2929
3030 static SessionManager *singleton();
3131
32− MirSessionItem* createSession(const QString& name, const QUrl& screenshot);
32+ Q_INVOKABLE MirSessionItem* createSession(const QString& name, const QUrl& screenshot);
3333
3434Q_SIGNALS:
3535 void sessionStarting(MirSessionItem *session);
tests/mocks/Unity/Application/SurfaceManager.h+1−1
@@ -29,7 +29,7 @@ public:
2929
3030 static SurfaceManager *singleton();
3131
32− MirSurfaceItem *createSurface(const QString& name,
32+ Q_INVOKABLE MirSurfaceItem *createSurface(const QString& name,
3333 MirSurfaceItem::Type type,
3434 MirSurfaceItem::State state,
3535 const QUrl& screenshot);
tests/mocks/Unity/Application/plugin.cpp+3
@@ -75,6 +75,9 @@ void FakeUnityApplicationQmlPlugin::registerTypes(const char *uri)
7575 qmlRegisterSingletonType<SurfaceManager>(uri, 0, 1, "SurfaceManager", surfaceManagerSingleton);
7676 qmlRegisterSingletonType<SessionManager>(uri, 0, 1, "SessionManager", sessionManagerSingleton);
7777 qmlRegisterSingletonType<ApplicationTestInterface>(uri, 0, 1, "ApplicationTest", applicationTestInterface);
78+
79+ qRegisterMetaType<MirSurfaceItem::Type>("MirSurfaceItem::Type");
80+ qRegisterMetaType<MirSurfaceItem::State>("MirSurfaceItem::State");
7881}
7982
8083void FakeUnityApplicationQmlPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
tests/qmltests/Stages/tst_ApplicationWindow.qml+18−15
@@ -31,15 +31,18 @@ Rectangle {
3131
3232 Component.onCompleted: {
3333 root.fakeApplication = ApplicationManager.add("gallery-app");
34− root.fakeApplication.manualSurfaceCreation = true;
34+ root.fakeApplication.manualSessionCreation = true;
35+ root.fakeApplication.createSession();
36+ root.fakeApplication.session.manualSessionCreation = true;
3537 root.fakeApplication.setState(ApplicationInfo.Starting);
3638 }
3739 property QtObject fakeApplication: null
40+ readonly property var fakeSession: fakeApplication ? fakeApplication.session : null
3841
3942 Connections {
40− target: fakeApplication
43+ target: fakeSession
4144 onSurfaceChanged: {
42− surfaceCheckbox.checked = fakeApplication.surface !== null;
45+ surfaceCheckbox.checked = fakeSession.surface !== null;
4346 }
4447 }
4548
@@ -81,10 +84,10 @@ Rectangle {
8184 if (applicationWindowLoader.status !== Loader.Ready)
8285 return;
8386
84− if (checked && !fakeApplication.surface) {
85− fakeApplication.createSurface();
86− } else if (!checked && fakeApplication.surface) {
87− fakeApplication.surface.release();
87+ if (checked && !fakeSession.surface) {
88+ fakeSession.createSurface();
89+ } else if (!checked && fakeSession.surface) {
90+ fakeSession.surface.release();
8891 }
8992 }
9093 }
@@ -241,7 +244,7 @@ Rectangle {
241244 setApplicationState(appStopped);
242245
243246 tryCompare(stateGroup, "state", "screenshot");
244− tryCompare(fakeApplication, "surface", null);
247+ tryCompare(fakeSession, "surface", null);
245248 }
246249
247250 function test_restartApp() {
@@ -259,14 +262,14 @@ Rectangle {
259262
260263 tryCompare(stateGroup, "state", "screenshot");
261264 waitUntilTransitionsEnd();
262− tryCompare(fakeApplication, "surface", null);
265+ tryCompare(fakeSession, "surface", null);
263266
264267 // and restart it
265268 setApplicationState(appStarting);
266269
267270 waitUntilTransitionsEnd();
268271 verify(stateGroup.state === "screenshot");
269− verify(fakeApplication.surface === null);
272+ verify(fakeSession.surface === null);
270273
271274 setApplicationState(appRunning);
272275
@@ -289,7 +292,7 @@ Rectangle {
289292 setApplicationState(appStopped);
290293
291294 tryCompare(stateGroup, "state", "screenshot");
292− tryCompare(fakeApplication, "surface", null);
295+ tryCompare(fakeSession, "surface", null);
293296 }
294297
295298 function test_keepSurfaceWhileInvisible() {
@@ -297,19 +300,19 @@ Rectangle {
297300 setApplicationState(appRunning);
298301 tryCompare(stateGroup, "state", "surface");
299302 waitUntilTransitionsEnd();
300− verify(fakeApplication.surface !== null);
303+ verify(fakeSession.surface !== null);
301304
302305 applicationWindowLoader.item.visible = false;
303306
304307 waitUntilTransitionsEnd();
305308 verify(stateGroup.state === "surface");
306− verify(fakeApplication.surface !== null);
309+ verify(fakeSession.surface !== null);
307310
308311 applicationWindowLoader.item.visible = true;
309312
310313 waitUntilTransitionsEnd();
311314 verify(stateGroup.state === "surface");
312− verify(fakeApplication.surface !== null);
315+ verify(fakeSession.surface !== null);
313316 }
314317
315318 function test_touchesReachSurfaceWhenItsShown() {
@@ -321,7 +324,7 @@ Rectangle {
321324 waitUntilTransitionsEnd();
322325
323326 // Because doing stuff in C++ is a PITA we keep the counter in the interal qml impl.
324− var fakeSurface = findChild(fakeApplication.surface, "fakeSurfaceQML");
327+ var fakeSurface = findChild(fakeSession.surface, "fakeSurfaceQML");
325328 fakeSurface.touchPressCount = 0;
326329 fakeSurface.touchReleaseCount = 0;
327330
tests/qmltests/Stages/tst_SessionContainer.qml+37−33
@@ -21,20 +21,21 @@ import Unity.Application 0.1
2121import "../../../qml/Stages"
2222
2323Item {
24− id: shell
24+ id: root
2525 width: units.gu(40)
2626 height: units.gu(80)
2727
28− Repeater {
29− anchors.fill: parent
30− model: ApplicationManager
3128
32− delegate: SessionContainer {
33− id: container
34− anchors.fill: parent
35− objectName: appId
29+ property QtObject fakeApplication: null
30+
31+ SessionContainer {
32+ id: sessionContainer
33+ anchors.fill: parent
3634
37− session: model.session
35+ session: SessionManager.createSession("music-player", Qt.resolvedUrl("../Dash/artwork/music-player-design.png"));
36+ onSessionChanged: {
37+ session.manualSurfaceCreation = true;
38+ session.createSurface();
3839 }
3940 }
4041
@@ -54,60 +55,63 @@ Item {
5455
5556 when: windowShown
5657
57− function test_add_child_session_data() {
58+ function test_addChildSession_data() {
5859 return [ { tag: "count=1", count: 1 },
5960 { tag: "count=4", count: 4 } ];
6061 }
6162
62− function test_add_child_session(data) {
63− var unity8dash = findChild(shell, "unity8-dash");
64− verify(unity8dash !== null);
65− compare(unity8dash.childSessions.count(), 0);
63+ function test_addChildSession(data) {
64+ compare(sessionContainer.childSessions.count(), 0);
6665
6766 var i;
6867 var sessions = [];
6968 for (i = 0; i < data.count; i++) {
70− sessions.push(ApplicationTest.addChildSession("unity8-dash", 0, Qt.resolvedUrl("../Dash/artwork/music-player-design.png")));
71− compare(unity8dash.childSessions.count(), i+1);
69+ var session = SessionManager.createSession(sessionContainer.session.name + "-Child" + i,
70+ Qt.resolvedUrl("../Dash/artwork/music-player-design.png"))
71+ sessionContainer.session.addChildSession(session);
72+ compare(sessionContainer.childSessions.count(), i+1);
73+
74+ sessions.push(session);
7275 }
7376
7477 for (i = data.count-1; i >= 0; i--) {
75− ApplicationTest.removeSession(sessions[i]);
76− tryCompareFunction(function() { return unity8dash.childSessions.count(); }, i);
78+ sessions[i].release();
79+ tryCompareFunction(function() { return sessionContainer.childSessions.count(); }, i);
7780 }
7881 tryCompare(sessionSpy, "count", data.count)
7982 }
8083
81− function test_nest_child_sessions_data() {
84+ function test_nestedChildSessions_data() {
8285 return [ { tag: "depth=2", depth: 2 },
8386 { tag: "depth=8", depth: 8 }
8487 ];
8588 }
8689
87− function test_nest_child_sessions(data) {
88− var unity8dash = findChild(shell, "unity8-dash");
89− verify(unity8dash !== null);
90− compare(unity8dash.childSessions.count(), 0);
90+ function test_nestedChildSessions(data) {
91+ compare(sessionContainer.childSessions.count(), 0);
9192
9293 var i;
9394 var sessions = [];
94− var lastSessionId = 0;
95+ var lastSession = sessionContainer.session;
9596 var delegate;
96− var sessionContainer = unity8dash;
97+ var container = sessionContainer;
9798 for (i = 0; i < data.depth; i++) {
98− lastSessionId = ApplicationTest.addChildSession("unity8-dash", lastSessionId, Qt.resolvedUrl("Dash/artwork/music-player-design.png"))
99− sessions.push(lastSessionId);
100− compare(sessionContainer.childSessions.count(), 1);
101−
102− delegate = findChild(sessionContainer, "childDelegate0");
103− sessionContainer = findChild(delegate, "sessionContainer");
99+ var session = SessionManager.createSession(lastSession.name + "-Child" + i,
100+ Qt.resolvedUrl("../Dash/artwork/music-player-design.png"))
101+ lastSession.addChildSession(session);
102+ compare(container.childSessions.count(), 1);
103+ sessions.push(session);
104+
105+ delegate = findChild(container, "childDelegate0");
106+ container = findChild(delegate, "sessionContainer");
107+ lastSession = session;
104108 }
105109
106110 for (i = data.depth-1; i >= 0; i--) {
107− ApplicationTest.removeSession(sessions[i]);
111+ sessions[i].release();
108112 }
109113
110− tryCompareFunction(function() { return unity8dash.childSessions.count(); }, 0);
114+ tryCompareFunction(function() { return sessionContainer.childSessions.count(); }, 0);
111115 tryCompare(sessionSpy, "count", data.depth)
112116 }
113117 }
tests/qmltests/Stages/tst_SurfaceContainer.qml+88−121
@@ -28,59 +28,15 @@ Rectangle {
2828 width: units.gu(70)
2929 height: units.gu(70)
3030
31− Component {
32− id: fakeSurfaceComponent
33− Rectangle {
34− color: "green"
35−
36− Rectangle {
37− color: "blue"
38− anchors.fill: parent
39− anchors.margins: units.gu(2)
40− Text {
41− anchors.fill: parent
42− text: "Surface"
43− color: "green"
44− font.bold: true
45− fontSizeMode: Text.Fit
46− minimumPixelSize: 10; font.pixelSize: 200
47− verticalAlignment: Text.AlignVCenter
48− }
49− }
50−
51− width: units.gu(1)
52− height: units.gu(1)
53−
54− property int type: MirSurfaceItem.Normal
55− property int state: MirSurfaceItem.Restored
56− property string name: "Fake Surface"
57− property Item parentSurface: null
58− property list<Item> childSurfaces
59− function release() {}
60− signal removed();
61− }
62− }
63−
64− Item {
65− id: tempSurfaceHolder
66− }
67−
68− Component {
69− id: surfaceContainerComponent
70− SurfaceContainer {
71− anchors.fill: parent
72− }
73− }
74− Loader {
75− id: surfaceContainerLoader
31+ SurfaceContainer {
32+ id: surfaceContainer
7633 anchors {
7734 top: parent.top
78− topMargin: fullscreenCheckbox.checked ? 0 : units.gu(3) + units.dp(2)
7935 bottom: parent.bottom
8036 left: parent.left
37+ topMargin: fullscreenCheckbox.checked ? 0 : units.gu(3) + units.dp(2)
8138 }
8239 width: units.gu(40)
83− sourceComponent: surfaceContainerComponent
8440 }
8541
8642 Rectangle {
@@ -88,7 +44,7 @@ Rectangle {
8844 anchors {
8945 top: parent.top
9046 bottom: parent.bottom
91− left: surfaceContainerLoader.right
47+ left: surfaceContainer.right
9248 right: parent.right
9349 }
9450
@@ -98,19 +54,16 @@ Rectangle {
9854 Row {
9955 anchors { left: parent.left; right: parent.right }
10056 CheckBox {
101− id: surfaceCheckbox; checked: false;
57+ id: surfaceCheckbox;
58+ checked: false;
10259 onCheckedChanged: {
103− if (surfaceContainerLoader.status !== Loader.Ready)
104− return;
105−
10660 if (checked) {
107− var fakeSurface = fakeSurfaceComponent.createObject(tempSurfaceHolder);
108− surfaceContainerLoader.item.surface = fakeSurface;
61+ surfaceContainer.surface = SurfaceManager.createSurface("fake-surface",
62+ MirSurfaceItem.Normal,
63+ MirSurfaceItem.Restored,
64+ Qt.resolvedUrl("../Dash/artwork/music-player-design.png"));
10965 } else {
110− var fakeSurface = surfaceContainerLoader.item.surface;
111− surfaceContainerLoader.item.surface = null;
112− fakeSurface.parent = null;
113− fakeSurface.destroy();
66+ surfaceContainer.surface.release();
11467 }
11568 }
11669 }
@@ -124,6 +77,12 @@ Rectangle {
12477 }
12578 }
12679
80+ SignalSpy {
81+ id: surfaceSpy
82+ target: SurfaceManager
83+ signalName: "surfaceDestroyed"
84+ }
85+
12786 UT.UnityTestCase {
12887 id: testCase
12988 name: "SurfaceContainer"
@@ -131,9 +90,10 @@ Rectangle {
13190
13291 function cleanup() {
13392 // reload our test subject to get it in a fresh state once again
134− surfaceContainerLoader.active = false;
13593 surfaceCheckbox.checked = false;
136− surfaceContainerLoader.active = true;
94+ tryCompare(surfaceContainer, "surface", null);
95+ surfaceSpy.clear();
96+
13797 }
13898
13999 /*
@@ -146,68 +106,75 @@ Rectangle {
146106 surfaceCheckbox.checked = true;
147107 surfaceCheckbox.checked = false;
148108 surfaceCheckbox.checked = true;
149− var fakeSurface = surfaceContainerLoader.item.surface;
150− compare(fakeSurface.width, surfaceContainerLoader.item.width);
151− compare(fakeSurface.height, surfaceContainerLoader.item.height);
109+ var fakeSurface = surfaceContainer.surface;
110+ compare(fakeSurface.width, surfaceContainer.width);
111+ compare(fakeSurface.height, surfaceContainer.height);
152112 }
153113
154− // function test_childSurfaces_data() {
155− // return [ { tag: "1", count: 1 },
156− // { tag: "4", count: 4 } ];
157− // }
158−
159− // function test_childSurfaces(data) {
160− // var unity8dash = findChild(shell, "unity8-dash");
161− // compare(unity8dash.childSurfaces.count(), 0);
162−
163− // var i;
164− // var surfaces = [];
165− // for (i = 0; i < data.count; i++) {
166− // surfaces.push(ApplicationTest.addChildSurface("unity8-dash", 0, 0, Qt.resolvedUrl("Dash/artwork/music-player-design.png")));
167− // compare(unity8dash.childSurfaces.count(), i+1);
168− // }
169−
170− // surfaceSpy.clear();
171− // for (i = data.count-1; i >= 0; i--) {
172− // ApplicationTest.removeSurface(surfaces[i]);
173− // tryCompareFunction(function() { return unity8dash.childSurfaces.count(); }, i);
174− // }
175− // tryCompare(surfaceSpy, "count", data.count)
176− // }
177−
178− // function test_tieredChildSurfaces_data() {
179− // return [
180− // { tag: "2", count: 2 },
181− // { tag: "10", count: 10 }
182− // ];
183− // }
184−
185− // function test_tieredChildSurfaces(data) {
186− // var unity8dash = findChild(shell, "unity8-dash");
187− // compare(unity8dash.childSurfaces.count(), 0);
188−
189− // var i;
190− // var surfaces = [];
191− // var lastSurfaceId = 0;
192− // var delegate;
193− // var surfaceContainer = unity8dash;
194− // for (i = 0; i < data.count; i++) {
195− // lastSurfaceId = ApplicationTest.addChildSurface("unity8-dash", 0, lastSurfaceId, Qt.resolvedUrl("Dash/artwork/music-player-design.png"))
196− // surfaces.push(lastSurfaceId);
197−
198− // compare(surfaceContainer.childSurfaces.count(), 1);
199−
200− // delegate = findChild(surfaceContainer, "childDelegate0");
201− // surfaceContainer = findChild(delegate, "surfaceContainer");
202− // }
203−
204− // surfaceSpy.clear();
205− // for (i = data.count-1; i >= 0; i--) {
206− // ApplicationTest.removeSurface(surfaces[i]);
207− // }
208−
209− // compare(unity8dash.childSurfaces.count(), 0);
210− // tryCompare(surfaceSpy, "count", data.count)
211− // }
114+ function test_childSurfaces_data() {
115+ return [ { tag: "1", count: 1 },
116+ { tag: "4", count: 4 } ];
117+ }
118+
119+ function test_childSurfaces(data) {
120+ surfaceCheckbox.checked = true;
121+
122+ var i;
123+ var surfaces = [];
124+ for (i = 0; i < data.count; i++) {
125+ var surface = SurfaceManager.createSurface(surfaceContainer.surface.name + "-Child" + i,
126+ MirSurfaceItem.Normal,
127+ MirSurfaceItem.Restored,
128+ Qt.resolvedUrl("../Dash/artwork/music-player-design.png"));
129+ surfaceContainer.surface.addChildSurface(surface);
130+ compare(surfaceContainer.childSurfaces.count(), i+1);
131+
132+ surfaces.push(surface);
133+ }
134+
135+ for (i = data.count-1; i >= 0; i--) {
136+ surfaces[i].release();
137+ tryCompareFunction(function() { return surfaceContainer.childSurfaces.count(); }, i);
138+ }
139+ tryCompare(surfaceSpy, "count", data.count);
140+ }
141+
142+ function test_nestedChildSurfaces_data() {
143+ return [
144+ { tag: "2", count: 2 },
145+ { tag: "10", count: 10 }
146+ ];
147+ }
148+
149+ function test_nestedChildSurfaces(data) {
150+ surfaceCheckbox.checked = true;
151+
152+ var i;
153+ var surfaces = [];
154+ var lastSurface = surfaceContainer.surface;
155+ var delegate;
156+ var container = surfaceContainer;
157+ for (i = 0; i < data.count; i++) {
158+ var surface = SurfaceManager.createSurface(surfaceContainer.surface.name + "-Child" + i,
159+ MirSurfaceItem.Normal,
160+ MirSurfaceItem.Restored,
161+ Qt.resolvedUrl("../Dash/artwork/music-player-design.png"));
162+ lastSurface.addChildSurface(surface);
163+ compare(container.childSurfaces.count(), 1);
164+ surfaces.push(surface);
165+
166+ delegate = findChild(container, "childDelegate0");
167+ container = findChild(delegate, "surfaceContainer");
168+ lastSurface = surface;
169+ }
170+
171+ surfaceSpy.clear();
172+ for (i = data.count-1; i >= 0; i--) {
173+ surfaces[i].release();
174+ }
175+
176+ compare(surfaceContainer.childSurfaces.count(), 0);
177+ tryCompare(surfaceSpy, "count", data.count)
178+ }
212179 }
213180}
tests/qmltests/tst_Shell.qml+6−6
@@ -237,9 +237,9 @@ Item {
237237 function test_surfaceLosesFocusWhilePanelIsOpen() {
238238 var app = ApplicationManager.startApplication("dialer-app");
239239 // wait until the app is fully loaded (ie, real surface replaces splash screen)
240− tryCompareFunction(function() { return app.surface != null }, true);
240+ tryCompareFunction(function() { return app.session !== null && app.session.surface !== null }, true);
241241
242− tryCompare(app.surface, "focus", true);
242+ tryCompare(app.session.surface, "focus", true);
243243
244244 // Drag the indicators panel half-open
245245 var touchX = shell.width / 2;
@@ -250,7 +250,7 @@ Item {
250250 true /* beginTouch */, false /* endTouch */);
251251 verify(indicators.partiallyOpened);
252252
253− tryCompare(app.surface, "focus", false);
253+ tryCompare(app.session.surface, "focus", false);
254254
255255 // And finish getting it open
256256 touchFlick(indicators,
@@ -259,11 +259,11 @@ Item {
259259 false /* beginTouch */, true /* endTouch */);
260260 tryCompare(indicators, "fullyOpened", true);
261261
262− tryCompare(app.surface, "focus", false);
262+ tryCompare(app.session.surface, "focus", false);
263263
264264 dragToCloseIndicatorsPanel();
265265
266− tryCompare(app.surface, "focus", true);
266+ tryCompare(app.session.surface, "focus", true);
267267 }
268268
269269 // Wait for the whole UI to settle down
@@ -361,7 +361,7 @@ Item {
361361
362362 var app = ApplicationManager.startApplication("dialer-app");
363363 // wait until the app is fully loaded (ie, real surface replaces splash screen)
364− tryCompareFunction(function() { return app.surface != null }, true);
364+ tryCompareFunction(function() { return app.session !== null && app.session.surface !== null }, true);
365365
366366 // Minimize the application we just launched
367367 swipeFromLeftEdge(units.gu(26) + 1);