on xenial help sign in
use model for surfaces
commit698b707438654c99a310b1364723e1ca4bbef5cd authorNick Dedekind <nicholas.dedekind@gmail.com> dateTue 12 Aug 2014, 15:48 (12 years ago) parent38eaad1
18 files changed+588−263
qml/Stages/AppSurfaceContainer.qml+37−14 qml/Stages/SpreadDelegate.qml+2−1 qml/Stages/SurfaceContainer.qml+23−28 tests/mocks/Unity/Application/ApplicationDBusAdaptor.cpp−81 tests/mocks/Unity/Application/ApplicationInfo.cpp+22−42 tests/mocks/Unity/Application/ApplicationInfo.h+7−7 tests/mocks/Unity/Application/ApplicationManager.cpp+2−6 tests/mocks/Unity/Application/ApplicationTestInterface.cpp+99 tests/mocks/Unity/Application/ApplicationDBusAdaptor.h → tests/mocks/Unity/Application/ApplicationTestInterface.h+8−9 tests/mocks/Unity/Application/CMakeLists.txt+2−1 tests/mocks/Unity/Application/MirSurfaceItem.cpp+25−48 tests/mocks/Unity/Application/MirSurfaceItem.h+22−16 tests/mocks/Unity/Application/MirSurfaceItemModel.cpp+102 tests/mocks/Unity/Application/MirSurfaceItemModel.h+62 tests/mocks/Unity/Application/SurfaceManager.cpp+17−4 tests/mocks/Unity/Application/SurfaceManager.h+9−1 tests/mocks/Unity/Application/plugin.cpp+21−5 tests/qmltests/tst_Shell.qml+128
qml/Stages/AppSurfaceContainer.qml+37−14
@@ -18,7 +18,7 @@ import QtQuick 2.0
1818import "Animations"
1919
2020SurfaceContainer {
21− id: container
21+ id: root
2222 property var promptSurfaces
2323
2424 property bool appHasCreatedASurface: false
@@ -40,32 +40,55 @@ SurfaceContainer {
4040 Timer { //FIXME - need to delay removing splash screen to allow surface resize to complete
4141 id: surfaceRevealDelay
4242 interval: 100
43− onTriggered: surfaceContainer.revealSurface()
43+ onTriggered: root.revealSurface()
4444 }
4545
4646 Loader {
47− z: 3
4847 id: splashLoader
4948 anchors.fill: parent
49+ z: 3
5050 }
5151
5252 Repeater {
53− model: container.promptSurfaces
53+ id: promptRepeater
54+ model: root.promptSurfaces
5455
5556 delegate: SurfaceContainer {
57+ objectName: "promptDelegate" + index
58+ id: prompt
59+
5660 anchors {
57− fill: container
58− topMargin: container.surface.anchors.topMargin
59− rightMargin: container.surface.anchors.rightMargin
60− bottomMargin: container.surface.anchors.bottomMargin
61− leftMargin: container.surface.anchors.leftMargin
61+ fill: root
62+ topMargin: root.surface.anchors.topMargin
63+ rightMargin: root.surface.anchors.rightMargin
64+ bottomMargin: root.surface.anchors.bottomMargin
65+ leftMargin: root.surface.anchors.leftMargin
6266 }
63−
6467 z: 4 + index
68+
6569 surface: modelData
6670
6771 Component.onCompleted: {
68− animateIn();
72+ prompt.animateIn(swipeFromBottom);
73+ }
74+
75+ Connections {
76+ target: prompt.surface
77+ onRemoved: {
78+ // remove all prompts after this one.
79+ if (index !== promptRepeater.count-1) {
80+ var nextSurface = promptRepeater.itemAt(index+1).surface;
81+ nextSurface.removed();
82+ }
83+
84+ prompt.removing = true;
85+ prompt.animateOut();
86+ }
87+ }
88+
89+ Component {
90+ id: swipeFromBottom
91+ SwipeFromBottomAnimation {}
6992 }
7093 }
7194 }
@@ -75,19 +98,19 @@ SurfaceContainer {
7598 states: [
7699 State {
77100 name: "noSurfaceYet"
78− when: !surfaceContainer.appHasCreatedASurface
101+ when: !root.appHasCreatedASurface
79102 StateChangeScript {
80103 script: { splashLoader.setSource("Splash.qml", { "name": model.name, "image": model.icon }); }
81104 }
82105 },
83106 State {
84107 name: "hasSurface"
85− when: surfaceContainer.appHasCreatedASurface && (surfaceContainer.surface !== null)
108+ when: root.appHasCreatedASurface && (root.surface !== null)
86109 StateChangeScript { script: { surfaceRevealDelay.start(); } }
87110 },
88111 State {
89112 name: "surfaceLostButAppStillAlive"
90− when: surfaceContainer.appHasCreatedASurface && (surfaceContainer.surface === null)
113+ when: root.appHasCreatedASurface && (root.surface === null)
91114 // TODO - use app snapshot
92115 }
93116 ]
qml/Stages/SpreadDelegate.qml+2−1
@@ -46,7 +46,8 @@ Item {
4646 target: surfaceContainer.surface
4747 property: "anchors.topMargin"
4848 value: {
49− return surfaceContainer.surface.state === MirSurfaceItem.Fullscreen ? 0 : maximizedAppTopMargin;
49+ return surfaceContainer.surface == null ||
50+ surfaceContainer.surface.state === MirSurfaceItem.Fullscreen ? 0 : maximizedAppTopMargin;
5051 }
5152 }
5253
qml/Stages/SurfaceContainer.qml+23−28
@@ -18,56 +18,51 @@ import QtQuick 2.0
1818import "Animations"
1919
2020Item {
21− id: container
21+ id: root
22+ objectName: "surfaceContainer"
2223 property Item surface: null
24+ property var childSurfaces: surface ? surface.childSurfaces : 0
2325 property bool removing: false
2426
2527 onSurfaceChanged: {
2628 if (surface) {
27− surface.parent = container;
29+ surface.parent = root;
2830 surface.z = 1;
2931 state = "initial"
3032 }
3133 }
3234
33− Connections {
34− target: surface
35− onRemoved: {
36− container.removing = true;
37−
38− var childSurfaces = surface.childSurfaces;
39− for (var i=0; i<childSurfaces.length; i++) {
40− childSurfaces[i].removed();
41− }
42−
43− animateOut();
44− }
45− }
46−
4735 Repeater {
48− model: surface.childSurfaces
36+ model: root.childSurfaces
4937
5038 delegate: Loader {
51− z: 2
39+ objectName: "childDelegate" + index
5240 anchors {
53− fill: container
54− topMargin: container.surface.anchors.topMargin
55− rightMargin: container.surface.anchors.rightMargin
56− bottomMargin: container.surface.anchors.bottomMargin
57− leftMargin: container.surface.anchors.leftMargin
41+ fill: root
42+ topMargin: root.surface.anchors.topMargin
43+ rightMargin: root.surface.anchors.rightMargin
44+ bottomMargin: root.surface.anchors.bottomMargin
45+ leftMargin: root.surface.anchors.leftMargin
5846 }
47+ z: 2
5948
6049 // Only way to do recursive qml items.
6150 source: Qt.resolvedUrl("SurfaceContainer.qml")
6251 onLoaded: {
6352 item.surface = modelData;
64− item.animateIn();
53+ }
54+
55+ Connections {
56+ target: modelData
57+ onRemoved: {
58+ modelData.release()
59+ }
6560 }
6661 }
6762 }
6863
69− function animateIn() {
70− var animation = swipeFromBottom.createObject(container, { "surface": container.surface });
64+ function animateIn(animationComponent) {
65+ var animation = animationComponent.createObject(root, { "surface": root.surface });
7166 animation.start();
7267
7368 var tmp = d.animations;
@@ -82,7 +77,7 @@ Item {
8277 popped.end();
8378 d.animations = tmp;
8479 } else {
85− container.state = "initial";
80+ root.state = "initial";
8681 }
8782 }
8883
@@ -100,7 +95,7 @@ Item {
10095 states: [
10196 State {
10297 name: "initial"
103− PropertyChanges { target: surface; anchors.fill: container }
98+ PropertyChanges { target: surface; anchors.fill: root }
10499 }
105100 ]
106101}
tests/mocks/Unity/Application/ApplicationDBusAdaptor.cppdeleted−81
@@ -1,81 +0,0 @@
1−/*
2− * Copyright (C) 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 General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include "ApplicationInfo.h"
18−#include "ApplicationDBusAdaptor.h"
19−#include "ApplicationManager.h"
20−#include "SurfaceManager.h"
21−#include "MirSurfaceItem.h"
22−
23−quint32 nextId = 0;
24−
25−ApplicationDBusAdaptor::ApplicationDBusAdaptor(ApplicationManager* applicationManager)
26− : QDBusAbstractAdaptor(applicationManager)
27− , m_applicationManager(applicationManager)
28−{
29−}
30−
31−MirSurfaceItem* topSurface(MirSurfaceItem* surface)
32−{
33− if (!surface)
34− return nullptr;
35−
36− MirSurfaceItem* child = NULL;
37− Q_FOREACH (MirSurfaceItem *childSurface, surface->childSurfaceList()) {
38− child = topSurface(childSurface);
39− if (child) {
40− break;
41− }
42− }
43− return child ? child : surface;
44−}
45−
46−quint32 ApplicationDBusAdaptor::addPromptSurface(const QString &appId, const QString &surfaceImage)
47−{
48− qDebug() << "ApplicationDBusAdaptor::addPromptSurface to " << appId;
49−
50− ApplicationInfo* application = m_applicationManager->findApplication(appId);
51− if (!application) {
52− qDebug() << "ApplicationDBusAdaptor::addChildSurface - No application found for " << appId;
53− return 0;
54− }
55− quint32 surfaceId = ++nextId;
56− MirSurfaceItem* surface = new MirSurfaceItem(QString("%1-ChildSurface%2").arg(appId).arg(surfaceId),
57− MirSurfaceItem::Normal,
58− MirSurfaceItem::Maximized,
59− QUrl(surfaceImage));
60− m_childItems[surfaceId] = surface;
61−
62− if (application->promptSurfaceList().count() > 0) {
63− surface->setParentSurface(topSurface(application->promptSurfaceList()[0]));
64− } else {
65− application->addPromptSurface(surface);
66− }
67−
68− return surfaceId;
69−}
70−
71−void ApplicationDBusAdaptor::removeChildSurface(int surfaceId)
72−{
73− qDebug() << "ApplicationDBusAdaptor::removeChildSurface - " << surfaceId;
74−
75− if (!m_childItems.contains(surfaceId)) {
76− qDebug() << "ApplicationDBusAdaptor::removeChildSurface - No added surface for " << surfaceId;
77− return;
78− }
79− MirSurfaceItem* surface = m_childItems.take(surfaceId);
80− Q_EMIT surface->removed();
81−}
tests/mocks/Unity/Application/ApplicationInfo.cpp+22−42
@@ -16,7 +16,7 @@
1616
1717#include "ApplicationInfo.h"
1818#include "MirSurfaceItem.h"
19−#include "SurfaceManager.h"
19+#include "MirSurfaceItemModel.h"
2020
2121#include <QGuiApplication>
2222#include <QQuickItem>
@@ -33,6 +33,7 @@ ApplicationInfo::ApplicationInfo(const QString &appId, QObject *parent)
3333 , m_fullscreen(false)
3434 , m_parentItem(0)
3535 , m_surface(0)
36+ , m_promptSurfaces(new MirSurfaceItemModel(this))
3637{
3738 connect(this, &ApplicationInfo::stateChanged, this, &ApplicationInfo::onStateChanged);
3839}
@@ -45,16 +46,20 @@ ApplicationInfo::ApplicationInfo(QObject *parent)
4546 , m_fullscreen(false)
4647 , m_parentItem(0)
4748 , m_surface(0)
49+ , m_promptSurfaces(new MirSurfaceItemModel(this))
4850{
4951 connect(this, &ApplicationInfo::stateChanged, this, &ApplicationInfo::onStateChanged);
5052}
5153
5254ApplicationInfo::~ApplicationInfo()
5355{
54− if (m_surface) {
55− Q_EMIT SurfaceManager::singleton()->surfaceDestroyed(m_surface);
56− m_surface->deleteLater();
56+ QList<MirSurfaceItem*> promptSurfaces(m_promptSurfaces->list());
57+ for (MirSurfaceItem* promptSurface : promptSurfaces) {
58+ delete promptSurface;
5759 }
60+
61+ delete m_surface;
62+ delete m_promptSurfaces;
5863}
5964
6065void ApplicationInfo::onStateChanged(State state)
@@ -70,7 +75,7 @@ void ApplicationInfo::createSurface()
7075{
7176 if (m_surface || state() == ApplicationInfo::Stopped) return;
7277
73− setSurface(new MirSurfaceItem(name(),
78+ setSurface(SurfaceManager::singleton()->createSurface(name(),
7479 MirSurfaceItem::Normal,
7580 fullscreen() ? MirSurfaceItem::Fullscreen : MirSurfaceItem::Maximized,
7681 screenshot()));
@@ -85,7 +90,6 @@ void ApplicationInfo::setSurface(MirSurfaceItem* surface)
8590 if (m_surface) {
8691 m_surface->setApplication(nullptr);
8792 m_surface->setParent(nullptr);
88− SurfaceManager::singleton()->unregisterSurface(m_surface);
8993 }
9094
9195 m_surface = surface;
@@ -93,61 +97,37 @@ void ApplicationInfo::setSurface(MirSurfaceItem* surface)
9397 if (m_surface) {
9498 m_surface->setApplication(this);
9599 m_surface->setParent(this);
96− SurfaceManager::singleton()->registerSurface(m_surface);
97100 }
98101
99102 Q_EMIT surfaceChanged(m_surface);
100− SurfaceManager::singleton()->registerSurface(m_surface);
101103}
102104
103105void ApplicationInfo::addPromptSurface(MirSurfaceItem* surface)
104106{
105− qDebug() << "ApplicationInfo::addPromptSurface " << surface->name() << " to " << name();
106− if (surface == m_surface || m_promptSurfaces.contains(surface)) return;
107+ insertPromptSurface(m_promptSurfaces->count(), surface);
108+}
109+
110+void ApplicationInfo::insertPromptSurface(uint index, MirSurfaceItem* surface)
111+{
112+ qDebug() << "ApplicationInfo::insertPromptSurface - " << surface->name() << " to " << name() << " @ " << index;
107113
108114 surface->setApplication(this);
109− m_promptSurfaces.append(surface);
110− Q_EMIT promptSurfacesChanged();
115+ m_promptSurfaces->insertSurface(index, surface);
111116}
112117
113118void ApplicationInfo::removeSurface(MirSurfaceItem* surface)
114119{
120+ qDebug() << "Application::removeSurface - " << surface->name() << " from " << name();
121+
115122 if (m_surface == surface) {
116123 setSurface(nullptr);
117− } else if (m_promptSurfaces.contains(surface)) {
118− qDebug() << "Application::removeSurface " << surface->name() << " from " << name();
119−
120− m_promptSurfaces.removeAll(surface);
124+ } else {
125+ m_promptSurfaces->removeSurface(surface);
121126 surface->setApplication(nullptr);
122−
123− Q_EMIT promptSurfacesChanged();
124127 }
125128}
126129
127−QList<MirSurfaceItem*> ApplicationInfo::promptSurfaceList() const
130+MirSurfaceItemModel* ApplicationInfo::promptSurfaces() const
128131{
129132 return m_promptSurfaces;
130133}
131−
132−QQmlListProperty<MirSurfaceItem> ApplicationInfo::promptSurfaces()
133−{
134− return QQmlListProperty<MirSurfaceItem>(this,
135− 0,
136− ApplicationInfo::promptSurfaceCount,
137− ApplicationInfo::promptSurfaceAt);
138−}
139−
140−int ApplicationInfo::promptSurfaceCount(QQmlListProperty<MirSurfaceItem> *prop)
141−{
142− ApplicationInfo *p = qobject_cast<ApplicationInfo*>(prop->object);
143− return p->m_promptSurfaces.count();
144−}
145−
146−MirSurfaceItem* ApplicationInfo::promptSurfaceAt(QQmlListProperty<MirSurfaceItem> *prop, int index)
147−{
148− ApplicationInfo *p = qobject_cast<ApplicationInfo*>(prop->object);
149−
150− if (index < 0 || index >= p->m_promptSurfaces.count())
151− return nullptr;
152− return p->m_promptSurfaces[index];
153−}
tests/mocks/Unity/Application/ApplicationInfo.h+7−7
@@ -17,11 +17,14 @@
1717#ifndef APPLICATION_H
1818#define APPLICATION_H
1919
20+#include "SurfaceManager.h"
21+
2022#include <QObject>
2123#include <QQmlComponent>
2224
2325class QQuickItem;
2426class MirSurfaceItem;
27+class MirSurfaceItemModel;
2528
2629// unity-api
2730#include <unity/shell/application/ApplicationInfoInterface.h>
@@ -38,7 +41,7 @@ class ApplicationInfo : public ApplicationInfoInterface {
3841 Q_PROPERTY(bool fullscreen READ fullscreen WRITE setFullscreen NOTIFY fullscreenChanged)
3942 Q_PROPERTY(Stage stage READ stage WRITE setStage NOTIFY stageChanged)
4043 Q_PROPERTY(MirSurfaceItem* surface READ surface NOTIFY surfaceChanged)
41− Q_PROPERTY(QQmlListProperty<MirSurfaceItem> promptSurfaces READ promptSurfaces NOTIFY promptSurfacesChanged DESIGNABLE false)
44+ Q_PROPERTY(MirSurfaceItemModel* promptSurfaces READ promptSurfaces NOTIFY promptSurfacesChanged DESIGNABLE false)
4245
4346 // Only exists in this fake implementation
4447
@@ -89,8 +92,8 @@ public:
8992 void removeSurface(MirSurfaceItem* surface);
9093
9194 void addPromptSurface(MirSurfaceItem* surface);
92− QList<MirSurfaceItem*> promptSurfaceList() const;
93− QQmlListProperty<MirSurfaceItem> promptSurfaces();
95+ void insertPromptSurface(uint index, MirSurfaceItem* surface);
96+ MirSurfaceItemModel* promptSurfaces() const;
9497
9598Q_SIGNALS:
9699 void surfaceChanged(MirSurfaceItem*);
@@ -102,12 +105,9 @@ private Q_SLOTS:
102105 void createSurface();
103106
104107private:
105− static int promptSurfaceCount(QQmlListProperty<MirSurfaceItem> *prop);
106− static MirSurfaceItem* promptSurfaceAt(QQmlListProperty<MirSurfaceItem> *prop, int index);
107−
108108 QQuickItem *m_parentItem;
109109 MirSurfaceItem* m_surface;
110− QList<MirSurfaceItem*> m_promptSurfaces;
110+ MirSurfaceItemModel* m_promptSurfaces;
111111};
112112
113113Q_DECLARE_METATYPE(ApplicationInfo*)
tests/mocks/Unity/Application/ApplicationManager.cpp+2−6
@@ -15,9 +15,10 @@
1515 */
1616
1717#include "ApplicationManager.h"
18−#include "ApplicationDBusAdaptor.h"
1918#include "ApplicationInfo.h"
2019#include "MirSurfaceItem.h"
20+#include "MirSurfaceItemModel.h"
21+#include "ApplicationTestInterface.h"
2122
2223#include <paths.h>
2324
@@ -36,11 +37,6 @@ ApplicationManager *ApplicationManager::singleton()
3637{
3738 if (!the_application_manager) {
3839 the_application_manager = new ApplicationManager();
39− new ApplicationDBusAdaptor(the_application_manager);
40−
41− QDBusConnection connection = QDBusConnection::sessionBus();
42− connection.registerService("com.canonical.Unity8");
43− connection.registerObject("/com/canonical/Unity8/Mocks", the_application_manager);
4440 }
4541 return the_application_manager;
4642}
tests/mocks/Unity/Application/ApplicationTestInterface.cppnew file+99
@@ -0,0 +1,99 @@
1+/*
2+ * Copyright (C) 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 General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "ApplicationInfo.h"
18+#include "ApplicationTestInterface.h"
19+#include "ApplicationManager.h"
20+#include "SurfaceManager.h"
21+#include "MirSurfaceItem.h"
22+#include "MirSurfaceItemModel.h"
23+
24+quint32 nextId = 0;
25+
26+ApplicationTestInterface::ApplicationTestInterface(QObject* parent)
27+ : QDBusAbstractAdaptor(parent)
28+{
29+ QDBusConnection connection = QDBusConnection::sessionBus();
30+ connection.registerService("com.canonical.Unity8");
31+ connection.registerObject("/com/canonical/Unity8/Mocks", parent);
32+}
33+
34+quint32 ApplicationTestInterface::addPromptSurface(const QString &appId, const QString &surfaceImage)
35+{
36+ qDebug() << "ApplicationTestInterface::addPromptSurface to " << appId;
37+
38+ ApplicationInfo* application = ApplicationManager::singleton()->findApplication(appId);
39+ if (!application) {
40+ qDebug() << "ApplicationTestInterface::addPromptSurface - No application found for " << appId;
41+ return 0;
42+ }
43+ quint32 surfaceId = ++nextId;
44+ MirSurfaceItem* surface = SurfaceManager::singleton()->createSurface(
45+ QString("%1-Prompt%2").arg(appId)
46+ .arg(surfaceId),
47+ MirSurfaceItem::Normal,
48+ MirSurfaceItem::Maximized,
49+ QUrl(surfaceImage));
50+ m_childItems[surfaceId] = surface;
51+ application->addPromptSurface(surface);
52+
53+ return surfaceId;
54+}
55+
56+quint32 ApplicationTestInterface::addChildSurface(const QString& appId, const quint32 existingSurfaceId, const QString& surfaceImage)
57+{
58+ qDebug() << "ApplicationTestInterface::addChildSurface to " << appId;
59+
60+ ApplicationInfo* application = ApplicationManager::singleton()->findApplication(appId);
61+ if (!application) {
62+ qDebug() << "ApplicationTestInterface::addChildSurface - No application found for " << appId;
63+ return 0;
64+ }
65+
66+ MirSurfaceItem* parentSurface = nullptr;
67+ if (m_childItems.contains(existingSurfaceId)) {
68+ parentSurface = m_childItems[existingSurfaceId];
69+ } else if (application->surface()) {
70+ parentSurface = application->surface();
71+ } else {
72+ qDebug() << "ApplicationTestInterface::addChildSurface - No surface for " << appId << ":" << existingSurfaceId;
73+ return 0;
74+ }
75+
76+ quint32 surfaceId = ++nextId;
77+ MirSurfaceItem* surface = SurfaceManager::singleton()->createSurface(
78+ QString("%1-Child%2").arg(parentSurface->name())
79+ .arg(surfaceId),
80+ MirSurfaceItem::Normal,
81+ MirSurfaceItem::Maximized,
82+ QUrl(surfaceImage));
83+ parentSurface->addChildSurface(surface);
84+ m_childItems[surfaceId] = surface;
85+
86+ return surfaceId;
87+}
88+
89+void ApplicationTestInterface::removeSurface(int surfaceId)
90+{
91+ qDebug() << "ApplicationTestInterface::removeSurface - " << surfaceId;
92+
93+ if (!m_childItems.contains(surfaceId)) {
94+ qDebug() << "ApplicationTestInterface::removeSurface - No added surface for " << surfaceId;
95+ return;
96+ }
97+ MirSurfaceItem* surface = m_childItems.take(surfaceId);
98+ Q_EMIT surface->removed();
99+}
tests/mocks/Unity/Application/ApplicationDBusAdaptor.h → tests/mocks/Unity/Application/ApplicationTestInterface.hrenamed+8−9
@@ -14,8 +14,8 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−#ifndef APPLICATIONDBUSADAPTOR_H
18−#define APPLICATIONDBUSADAPTOR_H
17+#ifndef APPLICATIONTESTINTERFACE_H
18+#define APPLICATIONTESTINTERFACE_H
1919
2020#include <QtDBus/QtDBus>
2121
@@ -23,21 +23,20 @@ class ApplicationManager;
2323class SurfaceManager;
2424class MirSurfaceItem;
2525
26−class ApplicationDBusAdaptor : public QDBusAbstractAdaptor
26+class ApplicationTestInterface : public QDBusAbstractAdaptor
2727{
2828 Q_OBJECT
2929 Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity8.Mocks.Application")
3030public:
31− ApplicationDBusAdaptor(ApplicationManager* applicationManager);
31+ ApplicationTestInterface(QObject* parent = 0);
3232
3333public Q_SLOTS:
34− quint32 addPromptSurface(const QString& appId, const QString& surfaceImage);
35− void removeChildSurface(int surfaceId);
34+ Q_INVOKABLE quint32 addPromptSurface(const QString& appId, const QString& surfaceImage);
35+ Q_INVOKABLE quint32 addChildSurface(const QString& appId, const quint32 existingSurfaceId, const QString& surfaceImage);
36+ Q_INVOKABLE void removeSurface(int surfaceId);
3637
3738private:
38− ApplicationManager* m_applicationManager;
39−
4039 QHash<quint32, MirSurfaceItem*> m_childItems;
4140};
4241
43−#endif // APPLICATIONDBUSADAPTOR_H
42+#endif // APPLICATIONTESTINTERFACE_H
tests/mocks/Unity/Application/CMakeLists.txt+2−1
@@ -2,12 +2,13 @@ pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application)
22
33set(FakeUnityApplicationQml_SOURCES
44 plugin.cpp
5− ApplicationDBusAdaptor.cpp
65 ApplicationInfo.cpp
76 ApplicationImage.cpp
87 ApplicationManager.cpp
98 ApplicationScreenshotProvider.cpp
9+ ApplicationTestInterface.cpp
1010 MirSurfaceItem.cpp
11+ MirSurfaceItemModel.cpp
1112 SurfaceManager.cpp
1213 VirtualKeyboard.cpp
1314 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
tests/mocks/Unity/Application/MirSurfaceItem.cpp+25−48
@@ -15,6 +15,7 @@
1515 */
1616
1717#include "MirSurfaceItem.h"
18+#include "MirSurfaceItemModel.h"
1819#include "ApplicationInfo.h"
1920
2021#include <QPainter>
@@ -32,6 +33,7 @@ MirSurfaceItem::MirSurfaceItem(const QString& name,
3233 , m_state(state)
3334 , m_img(screenshot.isLocalFile() ? screenshot.toLocalFile() : screenshot.toString())
3435 , m_parentSurface(nullptr)
36+ , m_children(new MirSurfaceItemModel(this))
3537 , m_haveInputMethod(false)
3638{
3739 qDebug() << "MirSurfaceItem::MirSurfaceItem() " << this->name();
@@ -49,16 +51,19 @@ MirSurfaceItem::MirSurfaceItem(const QString& name,
4951MirSurfaceItem::~MirSurfaceItem()
5052{
5153 qDebug() << "MirSurfaceItem::~MirSurfaceItem() " << name();
54+ Q_EMIT aboutToBeDestroyed();
5255
53− QList<MirSurfaceItem*> children(m_children);
56+ QList<MirSurfaceItem*> children(m_children->list());
5457 for (MirSurfaceItem* child : children) {
55− child->setParentSurface(nullptr);
58+ delete child;
5659 }
57− if (m_parentSurface)
60+ if (m_parentSurface) {
5861 m_parentSurface->removeChildSurface(this);
59−
60− if (m_application)
62+ }
63+ if (m_application) {
6164 m_application->removeSurface(this);
65+ }
66+ delete m_children;
6267}
6368
6469void MirSurfaceItem::paint(QPainter * painter)
@@ -70,10 +75,8 @@ void MirSurfaceItem::paint(QPainter * painter)
7075
7176void MirSurfaceItem::release()
7277{
73− QList<MirSurfaceItem*> children(m_children);
74− for (MirSurfaceItem* child : children) {
75− child->release();
76− }
78+ qDebug() << "MirSurfaceItem::release " << name();
79+
7780 if (m_parentSurface) {
7881 m_parentSurface->removeChildSurface(this);
7982 }
@@ -96,62 +99,36 @@ void MirSurfaceItem::setParentSurface(MirSurfaceItem* surface)
9699 if (m_parentSurface == surface || surface == this)
97100 return;
98101
99− if (m_parentSurface) {
100− m_parentSurface->removeChildSurface(this);
101− }
102−
103102 m_parentSurface = surface;
104−
105− if (m_parentSurface) {
106− m_parentSurface->addChildSurface(this);
107− }
108103 Q_EMIT parentSurfaceChanged(surface);
109104}
110105
111106void MirSurfaceItem::addChildSurface(MirSurfaceItem* surface)
112107{
113− qDebug() << "MirSurfaceItem::addChildSurface " << surface->name() << " to " << name();
114−
115− m_children.append(surface);
116− Q_EMIT childSurfacesChanged();
108+ insertChildSurface(m_children->count(), surface);
117109}
118110
119−void MirSurfaceItem::removeChildSurface(MirSurfaceItem* surface)
111+void MirSurfaceItem::insertChildSurface(uint index, MirSurfaceItem* surface)
120112{
121− qDebug() << "MirSurfaceItem::removeChildSurface " << surface->name() << " from " << name();
113+ qDebug() << "MirSurfaceItem::insertChildSurface - " << surface->name() << " to " << name() << " @ " << index;
122114
123− if (m_children.contains(surface)) {
124− m_children.removeOne(surface);
125− Q_EMIT childSurfacesChanged();
126− }
127−}
128−
129−QList<MirSurfaceItem*> MirSurfaceItem::childSurfaceList()
130−{
131− return m_children;
115+ surface->setParentSurface(this);
116+ m_children->insertSurface(index, surface);
132117}
133118
134−QQmlListProperty<MirSurfaceItem> MirSurfaceItem::childSurfaces()
119+void MirSurfaceItem::removeChildSurface(MirSurfaceItem* surface)
135120{
136− return QQmlListProperty<MirSurfaceItem>(this,
137− 0,
138− MirSurfaceItem::childSurfaceCount,
139− MirSurfaceItem::childSurfaceAt);
140−}
121+ qDebug() << "MirSurfaceItem::removeChildSurface - " << surface->name() << " from " << name();
141122
142−int MirSurfaceItem::childSurfaceCount(QQmlListProperty<MirSurfaceItem> *prop)
143−{
144− MirSurfaceItem *p = qobject_cast<MirSurfaceItem*>(prop->object);
145− return p->m_children.count();
123+ if (m_children->contains(surface)) {
124+ m_children->removeSurface(surface);
125+ surface->setParentSurface(nullptr);
126+ }
146127}
147128
148−MirSurfaceItem* MirSurfaceItem::childSurfaceAt(QQmlListProperty<MirSurfaceItem> *prop, int index)
129+MirSurfaceItemModel* MirSurfaceItem::childSurfaces() const
149130{
150− MirSurfaceItem *p = qobject_cast<MirSurfaceItem*>(prop->object);
151−
152− if (index < 0 || index >= p->m_children.count())
153− return nullptr;
154− return p->m_children[index];
131+ return m_children;
155132}
156133
157134
tests/mocks/Unity/Application/MirSurfaceItem.h+22−16
@@ -20,7 +20,10 @@
2020#include <QQuickPaintedItem>
2121#include <QImage>
2222
23+#include <functional>
24+
2325class ApplicationInfo;
26+class MirSurfaceItemModel;
2427
2528class MirSurfaceItem : public QQuickPaintedItem
2629{
@@ -32,7 +35,7 @@ class MirSurfaceItem : public QQuickPaintedItem
3235 Q_PROPERTY(State state READ state NOTIFY stateChanged)
3336 Q_PROPERTY(QString name READ name NOTIFY nameChanged)
3437 Q_PROPERTY(MirSurfaceItem* parentSurface READ parentSurface NOTIFY parentSurfaceChanged)
35− Q_PROPERTY(QQmlListProperty<MirSurfaceItem> childSurfaces READ childSurfaces NOTIFY childSurfacesChanged DESIGNABLE false)
38+ Q_PROPERTY(MirSurfaceItemModel* childSurfaces READ childSurfaces NOTIFY childSurfacesChanged DESIGNABLE false)
3639
3740public:
3841 enum Type {
@@ -55,11 +58,6 @@ public:
5558 Fullscreen,
5659 };
5760
58− explicit MirSurfaceItem(const QString& name,
59− Type type,
60− State state,
61− const QUrl& screenshot,
62− QQuickItem *parent = 0);
6361 ~MirSurfaceItem();
6462
6563 //getters
@@ -68,10 +66,8 @@ public:
6866 State state() const { return m_state; }
6967 QString name() const { return m_name; }
7068 MirSurfaceItem* parentSurface() const { return m_parentSurface; }
71− QList<MirSurfaceItem*> childSurfaceList();
7269
7370 void setApplication(ApplicationInfo* item);
74− void setParentSurface(MirSurfaceItem* item);
7571
7672 Q_INVOKABLE void setState(State newState);
7773 Q_INVOKABLE void release();
@@ -79,6 +75,10 @@ public:
7975 void paint(QPainter * painter) override;
8076 void touchEvent(QTouchEvent * event) override;
8177
78+ void addChildSurface(MirSurfaceItem* surface);
79+ void insertChildSurface(uint index, MirSurfaceItem* surface);
80+ void removeChildSurface(MirSurfaceItem* surface);
81+
8282Q_SIGNALS:
8383 void typeChanged(Type);
8484 void stateChanged(State);
@@ -91,20 +91,24 @@ Q_SIGNALS:
9191 void inputMethodRequested();
9292 void inputMethodDismissed();
9393
94+ void aboutToBeDestroyed();
95+
9496private Q_SLOTS:
9597 void onFocusChanged();
9698
9799protected:
98− const QImage &screenshotImage() { return m_img; }
100+ explicit MirSurfaceItem(const QString& name,
101+ Type type,
102+ State state,
103+ const QUrl& screenshot,
104+ QQuickItem *parent = 0);
99105
100−private:
101− void addChildSurface(MirSurfaceItem* surface);
102− void removeChildSurface(MirSurfaceItem* surface);
106+ const QImage &screenshotImage() { return m_img; }
103107
104− QQmlListProperty<MirSurfaceItem> childSurfaces();
105− static int childSurfaceCount(QQmlListProperty<MirSurfaceItem> *prop);
106− static MirSurfaceItem* childSurfaceAt(QQmlListProperty<MirSurfaceItem> *prop, int index);
108+ MirSurfaceItemModel* childSurfaces() const;
109+ void setParentSurface(MirSurfaceItem* surface);
107110
111+private:
108112 ApplicationInfo* m_application;
109113 const QString m_name;
110114 const Type m_type;
@@ -112,8 +116,10 @@ private:
112116 const QImage m_img;
113117
114118 MirSurfaceItem* m_parentSurface;
115− QList<MirSurfaceItem*> m_children;
119+ MirSurfaceItemModel* m_children;
116120 bool m_haveInputMethod;
121+
122+ friend class SurfaceManager;
117123};
118124
119125Q_DECLARE_METATYPE(MirSurfaceItem*)
tests/mocks/Unity/Application/MirSurfaceItemModel.cppnew file+102
@@ -0,0 +1,102 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it under
5+ * the terms of the GNU Lesser General Public License version 3, as published by
6+ * the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+ * 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+#include <QQmlEngine>
18+
19+// local
20+#include "MirSurfaceItemModel.h"
21+#include "MirSurfaceItem.h"
22+
23+MirSurfaceItemModel::MirSurfaceItemModel(
24+ QObject *parent)
25+ : QAbstractListModel(parent)
26+{
27+ QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
28+}
29+
30+void MirSurfaceItemModel::insertSurface(uint index, MirSurfaceItem* surface)
31+{
32+ index = qMax(index, (uint)count());
33+
34+ int existingSurfaceIndex = m_surfaceItems.indexOf(surface);
35+ if (existingSurfaceIndex != -1) {
36+ move(existingSurfaceIndex, index);
37+ } else {
38+ beginInsertRows(QModelIndex(), index, index);
39+ m_surfaceItems.insert(index, surface);
40+ endInsertRows();
41+ Q_EMIT countChanged();
42+ }
43+}
44+
45+void MirSurfaceItemModel::removeSurface(MirSurfaceItem* surface)
46+{
47+ int existingSurfaceIndex = m_surfaceItems.indexOf(surface);
48+ if (existingSurfaceIndex != -1) {
49+ beginRemoveRows(QModelIndex(), existingSurfaceIndex, existingSurfaceIndex);
50+ m_surfaceItems.removeAt(existingSurfaceIndex);
51+ endRemoveRows();
52+ Q_EMIT countChanged();
53+ }
54+}
55+
56+void MirSurfaceItemModel::move(int from, int to)
57+{
58+ if (from == to) return;
59+
60+ if (from >= 0 && from < m_surfaceItems.size() && to >= 0 && to < m_surfaceItems.size()) {
61+ QModelIndex parent;
62+ /* When moving an item down, the destination index needs to be incremented
63+ by one, as explained in the documentation:
64+ http://qt-project.org/doc/qt-5.0/qtcore/qabstractitemmodel.html#beginMoveRows */
65+
66+ beginMoveRows(parent, from, from, parent, to + (to > from ? 1 : 0));
67+ m_surfaceItems.move(from, to);
68+ endMoveRows();
69+ }
70+}
71+
72+QHash<int, QByteArray> MirSurfaceItemModel::roleNames() const
73+{
74+ QHash<int, QByteArray> roleNames;
75+ roleNames.insert(RoleSurface, "surface");
76+ return roleNames;
77+}
78+
79+int MirSurfaceItemModel::rowCount(const QModelIndex & /*parent*/) const
80+{
81+ return m_surfaceItems.count();
82+}
83+
84+QVariant MirSurfaceItemModel::data(const QModelIndex & index, int role) const
85+{
86+ if (index.row() >= 0 && index.row() < m_surfaceItems.count()) {
87+ MirSurfaceItem *surfaceItem = m_surfaceItems.at(index.row());
88+ switch (role) {
89+ case RoleSurface:
90+ return QVariant::fromValue(surfaceItem);
91+ default:
92+ return QVariant();
93+ }
94+ } else {
95+ return QVariant();
96+ }
97+}
98+
99+MirSurfaceItem* MirSurfaceItemModel::getSurface(int index)
100+{
101+ return m_surfaceItems[index];
102+}
tests/mocks/Unity/Application/MirSurfaceItemModel.hnew file+62
@@ -0,0 +1,62 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it under
5+ * the terms of the GNU Lesser General Public License version 3, as published by
6+ * the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+ * 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+#ifndef MIRSURFACEITEMMODEL_H
18+#define MIRSURFACEITEMMODEL_H
19+
20+// Qt
21+#include <QAbstractListModel>
22+
23+class MirSurfaceItem;
24+
25+class MirSurfaceItemModel : public QAbstractListModel
26+{
27+ Q_OBJECT
28+ Q_ENUMS(Roles)
29+ Q_PROPERTY(int count READ count NOTIFY countChanged)
30+
31+public:
32+ enum Roles {
33+ RoleSurface = Qt::UserRole,
34+ };
35+
36+ explicit MirSurfaceItemModel(QObject *parent = 0);
37+
38+ const QList<MirSurfaceItem*>& list() const { return m_surfaceItems; }
39+ bool contains(MirSurfaceItem* surface) const { return m_surfaceItems.contains(surface); }
40+ int count() const { return rowCount(); }
41+
42+ void insertSurface(uint index, MirSurfaceItem* surface);
43+ void removeSurface(MirSurfaceItem* surface);
44+
45+ // from QAbstractItemModel
46+ int rowCount(const QModelIndex & parent = QModelIndex()) const override;
47+ QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override;
48+ QHash<int, QByteArray> roleNames() const override;
49+
50+ Q_INVOKABLE MirSurfaceItem* getSurface(int index);
51+
52+Q_SIGNALS:
53+ void countChanged();
54+
55+private:
56+ void move(int from, int to);
57+ QList<MirSurfaceItem*> m_surfaceItems;
58+};
59+
60+Q_DECLARE_METATYPE(MirSurfaceItemModel*)
61+
62+#endif // MIRSURFACEITEMMODEL_H
tests/mocks/Unity/Application/SurfaceManager.cpp+17−4
@@ -36,19 +36,32 @@ SurfaceManager::SurfaceManager(QObject *parent) :
3636{
3737}
3838
39+MirSurfaceItem *SurfaceManager::createSurface(const QString& name,
40+ MirSurfaceItem::Type type,
41+ MirSurfaceItem::State state,
42+ const QUrl& screenshot)
43+{
44+ MirSurfaceItem* surface = new MirSurfaceItem(name,
45+ type,
46+ state,
47+ screenshot);
48+ registerSurface(surface);
49+ connect(surface, &MirSurfaceItem::aboutToBeDestroyed, this, &SurfaceManager::onSurfaceAboutToBeDestroyed);
50+ Q_EMIT surfaceCreated(surface);
51+ return surface;
52+}
53+
3954void SurfaceManager::registerSurface(MirSurfaceItem *surface)
4055{
4156 connect(surface, &MirSurfaceItem::inputMethodRequested,
4257 this, &SurfaceManager::showInputMethod);
4358 connect(surface, &MirSurfaceItem::inputMethodDismissed,
4459 this, &SurfaceManager::hideInputMethod);
45− Q_EMIT surfaceCreated(surface);
4660}
4761
48−void SurfaceManager::unregisterSurface(MirSurfaceItem *surface)
62+void SurfaceManager::onSurfaceAboutToBeDestroyed()
4963{
50− disconnect(surface, 0, this, 0);
51− Q_EMIT surfaceDestroyed(surface);
64+ Q_EMIT surfaceDestroyed(qobject_cast<MirSurfaceItem*>(sender()));
5265}
5366
5467void SurfaceManager::showInputMethod()
tests/mocks/Unity/Application/SurfaceManager.h+9−1
@@ -19,7 +19,8 @@
1919
2020#include <QObject>
2121
22−class MirSurfaceItem;
22+#include "MirSurfaceItem.h"
23+
2324class VirtualKeyboard;
2425
2526class SurfaceManager : public QObject
@@ -30,6 +31,11 @@ public:
3031
3132 static SurfaceManager *singleton();
3233
34+ MirSurfaceItem *createSurface(const QString& name,
35+ MirSurfaceItem::Type type,
36+ MirSurfaceItem::State state,
37+ const QUrl& screenshot);
38+
3339 // Internal mock use
3440 void registerSurface(MirSurfaceItem *surface);
3541 void unregisterSurface(MirSurfaceItem *surface);
@@ -46,6 +52,8 @@ private Q_SLOTS:
4652 void showInputMethod();
4753 void hideInputMethod();
4854
55+ void onSurfaceAboutToBeDestroyed();
56+
4957private:
5058 static SurfaceManager *the_surface_manager;
5159 VirtualKeyboard *m_virtualKeyboard;
tests/mocks/Unity/Application/plugin.cpp+21−5
@@ -20,7 +20,9 @@
2020#include "ApplicationManager.h"
2121#include "ApplicationScreenshotProvider.h"
2222#include "MirSurfaceItem.h"
23+#include "MirSurfaceItemModel.h"
2324#include "SurfaceManager.h"
25+#include "ApplicationTestInterface.h"
2426
2527#include <qqml.h>
2628#include <QQmlEngine>
@@ -37,20 +39,32 @@ static QObject* surfaceManagerSingleton(QQmlEngine* engine, QJSEngine* scriptEng
3739 return SurfaceManager::singleton();
3840}
3941
42+ApplicationTestInterface* s_appTestInterface = nullptr;
43+
44+static QObject* applicationTestInterface(QQmlEngine* engine, QJSEngine* scriptEngine) {
45+ Q_UNUSED(engine);
46+ Q_UNUSED(scriptEngine);
47+ if (!s_appTestInterface) {
48+ s_appTestInterface = new ApplicationTestInterface(engine);
49+ }
50+ return s_appTestInterface;
51+}
52+
4053void FakeUnityApplicationQmlPlugin::registerTypes(const char *uri)
4154{
4255 qRegisterMetaType<MirSurfaceItem*>("MirSurfaceItem*");
56+ qRegisterMetaType<MirSurfaceItemModel*>("MirSurfaceItemModel*");
4357
4458 qmlRegisterUncreatableType<unity::shell::application::ApplicationManagerInterface>(uri, 0, 1, "ApplicationManagerInterface", "Abstract interface. Cannot be created in QML");
45− qmlRegisterSingletonType<ApplicationManager>(uri, 0, 1, "ApplicationManager", applicationManagerSingleton);
46− qmlRegisterSingletonType<SurfaceManager>(uri, 0, 1, "SurfaceManager", surfaceManagerSingleton);
47−
4859 qmlRegisterUncreatableType<unity::shell::application::ApplicationInfoInterface>(uri, 0, 1, "ApplicationInfoInterface", "Abstract interface. Cannot be created in QML");
49− qmlRegisterType<ApplicationInfo>(uri, 0, 1, "ApplicationInfo");
50−
5160 qmlRegisterUncreatableType<MirSurfaceItem>(uri, 0, 1, "MirSurfaceItem", "MirSurfaceItem can't be instantiated from QML");
5261
62+ qmlRegisterType<ApplicationInfo>(uri, 0, 1, "ApplicationInfo");
5363 qmlRegisterType<ApplicationImage>(uri, 0, 1, "ApplicationImage");
64+
65+ qmlRegisterSingletonType<ApplicationManager>(uri, 0, 1, "ApplicationManager", applicationManagerSingleton);
66+ qmlRegisterSingletonType<SurfaceManager>(uri, 0, 1, "SurfaceManager", surfaceManagerSingleton);
67+ qmlRegisterSingletonType<ApplicationTestInterface>(uri, 0, 1, "ApplicationTest", applicationTestInterface);
5468}
5569
5670void FakeUnityApplicationQmlPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
@@ -58,4 +72,6 @@ void FakeUnityApplicationQmlPlugin::initializeEngine(QQmlEngine *engine, const c
5872 QQmlExtensionPlugin::initializeEngine(engine, uri);
5973
6074 engine->addImageProvider(QLatin1String("application"), new ApplicationScreenshotProvider(ApplicationManager::singleton()));
75+ // make sure we initialise our test interface.
76+ applicationTestInterface(engine, nullptr);
6177}
tests/qmltests/tst_Shell.qml+128
@@ -61,6 +61,12 @@ Item {
6161 signalName: "setCurrentScopeCalled"
6262 }
6363
64+ SignalSpy {
65+ id: surfaceSpy
66+ target: SurfaceManager
67+ signalName: "surfaceDestroyed"
68+ }
69+
6470 UT.UnityTestCase {
6571 name: "Shell"
6672 when: windowShown
@@ -431,5 +437,127 @@ Item {
431437
432438 touchRelease(shell);
433439 }
440+
441+ function test_promptSurfaces_data() {
442+ return [ { tag: "1", count: 1 },
443+ { tag: "4", count: 4 } ];
444+ }
445+
446+ function test_promptSurfaces(data) {
447+ ApplicationManager.requestFocusApplication("unity8-dash");
448+ waitUntilDashIsFocused();
449+
450+ var appDelegate = findChild(shell, "appDelegate0")
451+ var surfaceContainer = findChild(appDelegate, "surfaceContainer");
452+
453+ var i;
454+ var surfaces = [];
455+ compare(surfaceContainer.promptSurfaces.count, 0);
456+ for (i = 0; i < data.count; i++) {
457+ surfaces.push(ApplicationTest.addPromptSurface("unity8-dash", Qt.resolvedUrl("Dash/artwork/music-player-design.png")));
458+ compare(surfaceContainer.promptSurfaces.count, i+1);
459+ }
460+
461+ surfaceSpy.clear();
462+ for (i = data.count-1; i >= 0; i--) {
463+ ApplicationTest.removeSurface(surfaces[i]);
464+ tryCompare(surfaceContainer.promptSurfaces, "count", i);
465+ }
466+ tryCompare(surfaceSpy, "count", data.count)
467+ }
468+
469+ function test_removeFirstPromptSurface_data() {
470+ return [ { tag: "1", count: 1 },
471+ { tag: "4", count: 4 } ];
472+ }
473+
474+ function test_removeFirstPromptSurface(data) {
475+ ApplicationManager.requestFocusApplication("unity8-dash");
476+ waitUntilDashIsFocused();
477+
478+ var appDelegate = findChild(shell, "appDelegate0")
479+ var surfaceContainer = findChild(appDelegate, "surfaceContainer");
480+
481+ var i;
482+ var surfaces = [];
483+ compare(surfaceContainer.promptSurfaces.count, 0);
484+ for (i = 0; i < data.count; i++) {
485+ surfaces.push(ApplicationTest.addPromptSurface("unity8-dash", Qt.resolvedUrl("Dash/artwork/music-player-design.png")));
486+ compare(surfaceContainer.promptSurfaces.count, i+1);
487+ }
488+
489+ surfaceSpy.clear();
490+ ApplicationTest.removeSurface(surfaces[0]);
491+ tryCompare(surfaceContainer.promptSurfaces, "count", 0);
492+ tryCompare(surfaceSpy, "count", data.count)
493+ }
494+
495+ function test_childSurfaces_data() {
496+ return [ { tag: "1", count: 1 },
497+ { tag: "4", count: 4 } ];
498+ }
499+
500+ function test_childSurfaces(data) {
501+ ApplicationManager.requestFocusApplication("unity8-dash");
502+ waitUntilDashIsFocused();
503+
504+ var appDelegate = findChild(shell, "appDelegate0")
505+ var surfaceContainer = findChild(appDelegate, "surfaceContainer");
506+
507+ var i;
508+ var surfaces = [];
509+ compare(surfaceContainer.childSurfaces.count, 0);
510+ for (i = 0; i < data.count; i++) {
511+ surfaces.push(ApplicationTest.addChildSurface("unity8-dash", 0, Qt.resolvedUrl("Dash/artwork/music-player-design.png")));
512+ compare(surfaceContainer.childSurfaces.count, i+1);
513+ }
514+
515+ surfaceSpy.clear();
516+ for (i = data.count-1; i >= 0; i--) {
517+ ApplicationTest.removeSurface(surfaces[i]);
518+ tryCompare(surfaceContainer.childSurfaces, "count", i);
519+ }
520+ tryCompare(surfaceSpy, "count", data.count)
521+ }
522+
523+ function test_tieredChildSurfaces_data() {
524+ return [
525+ { tag: "2", count: 2 },
526+ { tag: "10", count: 10 }
527+ ];
528+ }
529+
530+ function test_tieredChildSurfaces(data) {
531+ ApplicationManager.requestFocusApplication("unity8-dash");
532+ waitUntilDashIsFocused();
533+
534+ var delegate = findChild(shell, "appDelegate0")
535+ var surfaceContainer = findChild(delegate, "surfaceContainer");
536+
537+ var i;
538+ var surfaces = [];
539+ var lastSurfaceId = 0;
540+ compare(surfaceContainer.childSurfaces.count, 0);
541+ for (i = 0; i < data.count; i++) {
542+ lastSurfaceId = ApplicationTest.addChildSurface("unity8-dash", lastSurfaceId, Qt.resolvedUrl("Dash/artwork/music-player-design.png"))
543+ surfaces.push(lastSurfaceId);
544+
545+ compare(surfaceContainer.childSurfaces.count, 1);
546+
547+ delegate = findChild(surfaceContainer, "childDelegate0");
548+ surfaceContainer = findChild(delegate, "surfaceContainer");
549+ }
550+
551+ surfaceSpy.clear();
552+ for (i = data.count-1; i >= 0; i--) {
553+ ApplicationTest.removeSurface(surfaces[i]);
554+ }
555+
556+ delegate = findChild(shell, "appDelegate0")
557+ surfaceContainer = findChild(delegate, "surfaceContainer");
558+
559+ compare(surfaceContainer.childSurfaces.count, 0);
560+ tryCompare(surfaceSpy, "count", data.count)
561+ }
434562 }
435563}