on xenial help sign in
Get rid of all mentions to screenshot in the Unity.Application API
845cc0eDaniel d'Andrada
qml/Stages/ApplicationWindow.qml+14−7
@@ -41,7 +41,7 @@ Item {
41 && root.applicationState === ApplicationInfo.Stopped
41 && root.applicationState === ApplicationInfo.Stopped
42 on_NeedToTakeScreenshotChanged: {
42 on_NeedToTakeScreenshotChanged: {
43 if (_needToTakeScreenshot) {
43 if (_needToTakeScreenshot) {
44− application.updateScreenshot();
44+ screenshotImage.take();
45 }
45 }
46 }
46 }
47
47
@@ -96,8 +96,18 @@ Item {
96
96
97 Image {
97 Image {
98 id: screenshotImage
98 id: screenshotImage
99− source: root.application ? root.application.screenshot : ""
99+ objectName: "screenshotImage"
100+ source: ""
100 anchors.fill: parent
101 anchors.fill: parent
102+
103+ function take() {
104+ // Format: "image://application/$APP_ID/$CURRENT_TIME_MS"
105+ // eg: "image://application/calculator-app/123456"
106+ var timeMs = new Date().getTime();
107+ source = "image://application/" + root.application.appId + "/" + timeMs;
108+ }
109+
110+ onSourceChanged: { console.log("screenshotImage.source = " + source); }
101 }
111 }
102
112
103 Loader {
113 Loader {
@@ -216,11 +226,8 @@ Item {
216 UbuntuNumberAnimation { target: screenshotImage; property: "opacity";
226 UbuntuNumberAnimation { target: screenshotImage; property: "opacity";
217 from: 1.0; to: 0.0
227 from: 1.0; to: 0.0
218 duration: UbuntuAnimation.BriskDuration }
228 duration: UbuntuAnimation.BriskDuration }
219− PropertyAction { target: screenshotImage
229+ PropertyAction { target: screenshotImage; property: "visible"; value: false }
220− property: "visible"; value: false }
230+ PropertyAction { target: screenshotImage; property: "source"; value: "" }
221− ScriptAction { script: {
222− if (root.application.screenshot) { root.application.discardScreenshot(); }
223− } }
224 }
231 }
225 }
232 }
226 ]
233 ]
tests/mocks/Unity/Application/ApplicationInfo.cpp+18−22
@@ -35,6 +35,7 @@ ApplicationInfo::ApplicationInfo(const QString &appId, QObject *parent)
35 , m_focused(false)
35 , m_focused(false)
36 , m_fullscreen(false)
36 , m_fullscreen(false)
37 , m_surface(0)
37 , m_surface(0)
38+ , m_manualSurfaceCreation(false)
38 , m_parentItem(0)
39 , m_parentItem(0)
39{
40{
40}
41}
@@ -46,6 +47,7 @@ ApplicationInfo::ApplicationInfo(QObject *parent)
46 , m_focused(false)
47 , m_focused(false)
47 , m_fullscreen(false)
48 , m_fullscreen(false)
48 , m_surface(0)
49 , m_surface(0)
50+ , m_manualSurfaceCreation(false)
49 , m_parentItem(0)
51 , m_parentItem(0)
50{
52{
51}
53}
@@ -53,6 +55,9 @@ ApplicationInfo::ApplicationInfo(QObject *parent)
53ApplicationInfo::~ApplicationInfo()
55ApplicationInfo::~ApplicationInfo()
54{
56{
55 if (m_surface) {
57 if (m_surface) {
58+ // break the cyclic reference before destroying it
59+ m_surface->setApplication(nullptr);
60+
56 Q_EMIT SurfaceManager::singleton()->surfaceDestroyed(m_surface);
61 Q_EMIT SurfaceManager::singleton()->surfaceDestroyed(m_surface);
57 m_surface->deleteLater();
62 m_surface->deleteLater();
58 }
63 }
@@ -62,10 +67,12 @@ void ApplicationInfo::createSurface()
62{
67{
63 if (m_surface || state() == ApplicationInfo::Stopped) return;
68 if (m_surface || state() == ApplicationInfo::Stopped) return;
64
69
70+ QUrl screenshotUrl = QString("file://%1").arg(m_screenshotFileName);
71+
65 setSurface(new MirSurfaceItem(name(),
72 setSurface(new MirSurfaceItem(name(),
66 MirSurfaceItem::Normal,
73 MirSurfaceItem::Normal,
67 fullscreen() ? MirSurfaceItem::Fullscreen : MirSurfaceItem::Maximized,
74 fullscreen() ? MirSurfaceItem::Fullscreen : MirSurfaceItem::Maximized,
68− m_screenshotUrl));
75+ screenshotUrl));
69}
76}
70
77
71void ApplicationInfo::setSurface(MirSurfaceItem* surface)
78void ApplicationInfo::setSurface(MirSurfaceItem* surface)
@@ -144,17 +151,6 @@ MirSurfaceItem* ApplicationInfo::promptSurfaceAt(QQmlListProperty<MirSurfaceItem
144 return p->m_promptSurfaces[index];
151 return p->m_promptSurfaces[index];
145}
152}
146
153
147−void ApplicationInfo::updateScreenshot()
148−{
149− qDebug() << "ApplicationInfo::updateScreenshot()";
150− setScreenshot(m_screenshotUrl);
151−}
152−
153−void ApplicationInfo::discardScreenshot()
154−{
155− setScreenshot(QUrl());
156−}
157−
158void ApplicationInfo::setIconId(const QString &iconId)
154void ApplicationInfo::setIconId(const QString &iconId)
159{
155{
160 setIcon(QString("file://%1/graphics/applicationIcons/%2@18.png")
156 setIcon(QString("file://%1/graphics/applicationIcons/%2@18.png")
@@ -164,7 +160,7 @@ void ApplicationInfo::setIconId(const QString &iconId)
164
160
165void ApplicationInfo::setScreenshotId(const QString &screenshotId)
161void ApplicationInfo::setScreenshotId(const QString &screenshotId)
166{
162{
167− m_screenshotUrl = QString("file://%1/Dash/graphics/phone/screenshots/%2@12.png")
163+ m_screenshotFileName = QString("%1/Dash/graphics/phone/screenshots/%2@12.png")
168 .arg(qmlDirectory())
164 .arg(qmlDirectory())
169 .arg(screenshotId);
165 .arg(screenshotId);
170}
166}
@@ -199,7 +195,7 @@ void ApplicationInfo::setState(State value)
199 m_state = value;
195 m_state = value;
200 Q_EMIT stateChanged(value);
196 Q_EMIT stateChanged(value);
201
197
202− if (m_state == ApplicationInfo::Running) {
198+ if (!m_manualSurfaceCreation && m_state == ApplicationInfo::Running) {
203 QTimer::singleShot(1000, this, SLOT(createSurface()));
199 QTimer::singleShot(1000, this, SLOT(createSurface()));
204 }
200 }
205 }
201 }
@@ -213,14 +209,6 @@ void ApplicationInfo::setFocused(bool value)
213 }
209 }
214}
210}
215
211
216−void ApplicationInfo::setScreenshot(const QUrl &value)
217−{
218− if (value != m_screenshot) {
219− m_screenshot = value;
220− Q_EMIT screenshotChanged(value);
221− }
222−}
223−
224void ApplicationInfo::setFullscreen(bool value)
212void ApplicationInfo::setFullscreen(bool value)
225{
213{
226 if (value != m_fullscreen) {
214 if (value != m_fullscreen) {
@@ -228,3 +216,11 @@ void ApplicationInfo::setFullscreen(bool value)
228 Q_EMIT fullscreenChanged(value);
216 Q_EMIT fullscreenChanged(value);
229 }
217 }
230}
218}
219+
220+void ApplicationInfo::setManualSurfaceCreation(bool value)
221+{
222+ if (value != m_manualSurfaceCreation) {
223+ m_manualSurfaceCreation = value;
224+ Q_EMIT manualSurfaceCreationChanged(value);
225+ }
226+}
tests/mocks/Unity/Application/ApplicationInfo.h+13−8
@@ -37,14 +37,14 @@ class ApplicationInfo : public ApplicationInfoInterface {
37
37
38 // Only exists in this fake implementation
38 // Only exists in this fake implementation
39
39
40+ // whether the test code will explicitly control the creation of the application surface
41+ Q_PROPERTY(bool manualSurfaceCreation READ manualSurfaceCreation WRITE setManualSurfaceCreation NOTIFY manualSurfaceCreationChanged)
42+
40public:
43public:
41 ApplicationInfo(QObject *parent = NULL);
44 ApplicationInfo(QObject *parent = NULL);
42 ApplicationInfo(const QString &appId, QObject *parent = NULL);
45 ApplicationInfo(const QString &appId, QObject *parent = NULL);
43 ~ApplicationInfo();
46 ~ApplicationInfo();
44
47
45− Q_INVOKABLE void updateScreenshot() override;
46− Q_INVOKABLE void discardScreenshot() override;
47−
48 void setIconId(const QString &iconId);
48 void setIconId(const QString &iconId);
49 void setScreenshotId(const QString &screenshotId);
49 void setScreenshotId(const QString &screenshotId);
50
50
@@ -67,7 +67,7 @@ public:
67 void setFocused(bool value);
67 void setFocused(bool value);
68 bool focused() const override { return m_focused; }
68 bool focused() const override { return m_focused; }
69
69
70− QUrl screenshot() const override { return m_screenshot; }
70+ QString screenshot() const { return m_screenshotFileName; }
71
71
72 void setFullscreen(bool value);
72 void setFullscreen(bool value);
73 bool fullscreen() const { return m_fullscreen; }
73 bool fullscreen() const { return m_fullscreen; }
@@ -81,13 +81,17 @@ public:
81 QList<MirSurfaceItem*> promptSurfaceList() const;
81 QList<MirSurfaceItem*> promptSurfaceList() const;
82 QQmlListProperty<MirSurfaceItem> promptSurfaces();
82 QQmlListProperty<MirSurfaceItem> promptSurfaces();
83
83
84+ bool manualSurfaceCreation() const { return m_manualSurfaceCreation; }
85+ void setManualSurfaceCreation(bool value);
86+
84Q_SIGNALS:
87Q_SIGNALS:
85 void surfaceChanged(MirSurfaceItem*);
88 void surfaceChanged(MirSurfaceItem*);
86 void promptSurfacesChanged();
89 void promptSurfacesChanged();
87 void fullscreenChanged(bool value);
90 void fullscreenChanged(bool value);
91+ void manualSurfaceCreationChanged(bool value);
88
92
89−private Q_SLOTS:
93+public Q_SLOTS:
90− void createSurface();
94+ Q_INVOKABLE void createSurface();
91
95
92private:
96private:
93 static int promptSurfaceCount(QQmlListProperty<MirSurfaceItem> *prop);
97 static int promptSurfaceCount(QQmlListProperty<MirSurfaceItem> *prop);
@@ -95,7 +99,7 @@ private:
95 void setIcon(const QUrl &value);
99 void setIcon(const QUrl &value);
96 void setScreenshot(const QUrl &value);
100 void setScreenshot(const QUrl &value);
97
101
98− QUrl m_screenshotUrl;
102+ QString m_screenshotFileName;
99
103
100 QString m_appId;
104 QString m_appId;
101 QString m_name;
105 QString m_name;
@@ -103,10 +107,11 @@ private:
103 Stage m_stage;
107 Stage m_stage;
104 State m_state;
108 State m_state;
105 bool m_focused;
109 bool m_focused;
106− QUrl m_screenshot;
107 bool m_fullscreen;
110 bool m_fullscreen;
108 MirSurfaceItem* m_surface;
111 MirSurfaceItem* m_surface;
109
112
113+ bool m_manualSurfaceCreation;
114+
110 QQuickItem *m_parentItem;
115 QQuickItem *m_parentItem;
111 QList<MirSurfaceItem*> m_promptSurfaces;
116 QList<MirSurfaceItem*> m_promptSurfaces;
112};
117};
tests/mocks/Unity/Application/ApplicationManager.cpp+17−32
@@ -105,8 +105,6 @@ QVariant ApplicationManager::data(const QModelIndex& index, int role) const {
105 return app->state();
105 return app->state();
106 case RoleFocused:
106 case RoleFocused:
107 return app->focused();
107 return app->focused();
108− case RoleScreenshot:
109− return app->screenshot();
110 case RoleSurface:
108 case RoleSurface:
111 return QVariant::fromValue(app->surface());
109 return QVariant::fromValue(app->surface());
112 case RoleFullscreen:
110 case RoleFullscreen:
@@ -226,6 +224,21 @@ ApplicationInfo* ApplicationManager::startApplication(const QString &appId,
226 const QStringList &arguments)
224 const QStringList &arguments)
227{
225{
228 Q_UNUSED(arguments)
226 Q_UNUSED(arguments)
227+ ApplicationInfo *application = add(appId);
228+ if (!application)
229+ return 0;
230+
231+ if (flags.testFlag(ApplicationManager::ForceMainStage)
232+ && application->stage() == ApplicationInfo::SideStage) {
233+ application->setStage(ApplicationInfo::MainStage);
234+ }
235+ application->setState(ApplicationInfo::Running);
236+
237+ return application;
238+}
239+
240+ApplicationInfo* ApplicationManager::add(QString appId)
241+{
229 ApplicationInfo *application = 0;
242 ApplicationInfo *application = 0;
230
243
231 for (ApplicationInfo *availableApp : m_availableApplications) {
244 for (ApplicationInfo *availableApp : m_availableApplications) {
@@ -235,15 +248,8 @@ ApplicationInfo* ApplicationManager::startApplication(const QString &appId,
235 }
248 }
236 }
249 }
237
250
238− if (!application)
251+ if (application)
239− return 0;
240−
241− if (flags.testFlag(ApplicationManager::ForceMainStage)
242− && application->stage() == ApplicationInfo::SideStage) {
243− application->setStage(ApplicationInfo::MainStage);
244− }
245− add(application);
252+ add(application);
246− application->setState(ApplicationInfo::Running);
247
253
248 return application;
254 return application;
249}
255}
@@ -266,27 +272,6 @@ bool ApplicationManager::stopApplication(const QString &appId)
266 return true;
272 return true;
267}
273}
268
274
269−bool ApplicationManager::updateScreenshot(const QString &appId)
270−{
271− int idx = -1;
272− ApplicationInfo *application = nullptr;
273− for (int i = 0; i < m_availableApplications.count(); ++i) {
274− application = m_availableApplications.at(i);
275− if (application->appId() == appId) {
276− idx = i;
277− break;
278− }
279− }
280−
281− if (idx == -1) {
282− return false;
283− }
284−
285− QModelIndex appIndex = index(idx);
286− Q_EMIT dataChanged(appIndex, appIndex, QVector<int>() << RoleScreenshot);
287− return true;
288−}
289−
290QString ApplicationManager::focusedApplicationId() const {
275QString ApplicationManager::focusedApplicationId() const {
291 for (ApplicationInfo *app : m_runningApplications) {
276 for (ApplicationInfo *app : m_runningApplications) {
292 if (app->focused()) {
277 if (app->focused()) {
tests/mocks/Unity/Application/ApplicationManager.h+2−2
@@ -52,7 +52,7 @@ class ApplicationManager : public ApplicationManagerInterface {
52 static ApplicationManager *singleton();
52 static ApplicationManager *singleton();
53
53
54 enum MoreRoles {
54 enum MoreRoles {
55− RoleSurface = RoleScreenshot+1,
55+ RoleSurface = RoleFocused+1,
56 RoleFullscreen,
56 RoleFullscreen,
57 RoleApplication,
57 RoleApplication,
58 };
58 };
@@ -98,7 +98,6 @@ class ApplicationManager : public ApplicationManagerInterface {
98 Q_INVOKABLE ApplicationInfo *startApplication(const QString &appId, const QStringList &arguments = QStringList()) override;
98 Q_INVOKABLE ApplicationInfo *startApplication(const QString &appId, const QStringList &arguments = QStringList()) override;
99 Q_INVOKABLE ApplicationInfo *startApplication(const QString &appId, ExecFlags flags, const QStringList &arguments = QStringList());
99 Q_INVOKABLE ApplicationInfo *startApplication(const QString &appId, ExecFlags flags, const QStringList &arguments = QStringList());
100 Q_INVOKABLE bool stopApplication(const QString &appId) override;
100 Q_INVOKABLE bool stopApplication(const QString &appId) override;
101− Q_INVOKABLE bool updateScreenshot(const QString &appId) override;
102
101
103 QString focusedApplicationId() const override;
102 QString focusedApplicationId() const override;
104 bool suspended() const;
103 bool suspended() const;
@@ -106,6 +105,7 @@ class ApplicationManager : public ApplicationManagerInterface {
106
105
107 // Only for testing
106 // Only for testing
108 Q_INVOKABLE QStringList availableApplications();
107 Q_INVOKABLE QStringList availableApplications();
108+ Q_INVOKABLE ApplicationInfo* add(QString appId);
109
109
110 QModelIndex findIndex(ApplicationInfo* application);
110 QModelIndex findIndex(ApplicationInfo* application);
111
111
tests/mocks/Unity/Application/ApplicationScreenshotProvider.cpp+4−4
@@ -34,6 +34,8 @@ ApplicationScreenshotProvider::ApplicationScreenshotProvider(ApplicationManager
34QImage ApplicationScreenshotProvider::requestImage(const QString &imageId, QSize * size,
34QImage ApplicationScreenshotProvider::requestImage(const QString &imageId, QSize * size,
35 const QSize &requestedSize)
35 const QSize &requestedSize)
36{
36{
37+ qDebug() << "AppScreenshotProvider::requestImage" << imageId;
38+
37 // We ignore requestedSize here intentionally to avoid keeping scaled copies around
39 // We ignore requestedSize here intentionally to avoid keeping scaled copies around
38 Q_UNUSED(requestedSize)
40 Q_UNUSED(requestedSize)
39
41
@@ -44,11 +46,9 @@ QImage ApplicationScreenshotProvider::requestImage(const QString &imageId, QSize
44 return QImage();
46 return QImage();
45 }
47 }
46
48
47− QString filePath = QString("%1/Dash/graphics/phone/screenshots/%2@12.png").arg(qmlDirectory()).arg(app->icon().toString());
48−
49 QImage image;
49 QImage image;
50− if (!image.load(filePath)) {
50+ if (!image.load(app->screenshot())) {
51− qWarning() << "failed loading app image" << filePath;
51+ qWarning() << "failed loading app image" << app->screenshot();
52 }
52 }
53
53
54
54
tests/mocks/Unity/Application/MirSurfaceItem.cpp+4−9
@@ -46,14 +46,9 @@ MirSurfaceItem::MirSurfaceItem(const QString& name,
46
46
47 QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
47 QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
48
48
49− // The virtual keyboard (input method) has a big transparent area so that
50− // content behind it show through
51− //setFillColor(Qt::transparent);
52−
53 connect(this, &QQuickItem::focusChanged,
49 connect(this, &QQuickItem::focusChanged,
54 this, &MirSurfaceItem::onFocusChanged);
50 this, &MirSurfaceItem::onFocusChanged);
55
51
56−
57 // The assumptions I make here really should hold.
52 // The assumptions I make here really should hold.
58 QQuickView *quickView =
53 QQuickView *quickView =
59 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
54 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
@@ -233,13 +228,13 @@ void MirSurfaceItem::onComponentStatusChanged(QQmlComponent::Status status)
233
228
234void MirSurfaceItem::createQmlContentItem()
229void MirSurfaceItem::createQmlContentItem()
235{
230{
231+ qDebug() << "MirSurfaceItem::createQmlContentItem()";
232+
236 m_qmlItem = qobject_cast<QQuickItem*>(m_qmlContentComponent->create());
233 m_qmlItem = qobject_cast<QQuickItem*>(m_qmlContentComponent->create());
237 m_qmlItem->setParentItem(this);
234 m_qmlItem->setParentItem(this);
238
235
239− {
236+ setImplicitWidth(m_qmlItem->width());
240− QQmlProperty anchorsFill(m_qmlItem, "anchors.fill");
237+ setImplicitHeight(m_qmlItem->height());
241− anchorsFill.write(QVariant::fromValue(this));
242− }
243
238
244 {
239 {
245 QQmlProperty screenshotSource(m_qmlItem, "screenshotSource");
240 QQmlProperty screenshotSource(m_qmlItem, "screenshotSource");
tests/mocks/Unity/Application/MirSurfaceItem.qml+9−1
@@ -17,13 +17,20 @@
17import QtQuick 2.0
17import QtQuick 2.0
18
18
19Rectangle {
19Rectangle {
20+ objectName: "fakeSurfaceQML"
20 id: root
21 id: root
21 color: "yellow"
22 color: "yellow"
22
23
24+ width: units.gu(40)
25+ height: units.gu(70)
26+
23 property alias screenshotSource: screenshotImage.source
27 property alias screenshotSource: screenshotImage.source
24
28
25 property bool wantInputMethod: false
29 property bool wantInputMethod: false
26
30
31+ property int touchPressCount: 0
32+ property int touchReleaseCount: 0
33+
27 Image {
34 Image {
28 id: screenshotImage
35 id: screenshotImage
29 anchors.fill: parent
36 anchors.fill: parent
@@ -41,6 +48,7 @@ Rectangle {
41
48
42 MultiPointTouchArea {
49 MultiPointTouchArea {
43 anchors.fill: parent
50 anchors.fill: parent
44− onPressed: { root.wantInputMethod = true }
51+ onPressed: { root.wantInputMethod = true; root.touchPressCount++; }
52+ onReleased: { root.touchReleaseCount++; }
45 }
53 }
46}
54}
tests/mocks/Unity/Application/VirtualKeyboard.qml+2
@@ -17,6 +17,8 @@
17import QtQuick 2.0
17import QtQuick 2.0
18
18
19Item {
19Item {
20+ width: units.gu(40)
21+ height: units.gu(70)
20
22
21 property alias screenshotSource: screenshotImage.source
23 property alias screenshotSource: screenshotImage.source
22
24
tests/plugins/Unity/Launcher/launchermodeltest.cpp−4
@@ -41,9 +41,6 @@ public:
41 bool focused() const { return m_focused; }
41 bool focused() const { return m_focused; }
42 QUrl screenshot() const { return QUrl(); }
42 QUrl screenshot() const { return QUrl(); }
43
43
44− Q_INVOKABLE void updateScreenshot() override {}
45− Q_INVOKABLE void discardScreenshot() override {}
46−
47 // Methods used for mocking (not in the interface)
44 // Methods used for mocking (not in the interface)
48 void setFocused(bool focused) { m_focused = focused; Q_EMIT focusedChanged(focused); }
45 void setFocused(bool focused) { m_focused = focused; Q_EMIT focusedChanged(focused); }
49private:
46private:
@@ -96,7 +93,6 @@ public:
96 m_list.takeAt(index)->deleteLater();
93 m_list.takeAt(index)->deleteLater();
97 endRemoveRows();
94 endRemoveRows();
98 }
95 }
99− bool updateScreenshot(const QString &appId) { Q_UNUSED(appId); return true; }
100 bool requestFocusApplication(const QString &appId) { Q_UNUSED(appId); return true; }
96 bool requestFocusApplication(const QString &appId) { Q_UNUSED(appId); return true; }
101 bool suspended() const { return false; }
97 bool suspended() const { return false; }
102 void setSuspended(bool) {}
98 void setSuspended(bool) {}
tests/qmltests/Stages/tst_ApplicationWindow.qml+24−69
@@ -29,68 +29,17 @@ Rectangle {
29 width: units.gu(70)
29 width: units.gu(70)
30 height: units.gu(70)
30 height: units.gu(70)
31
31
32− Component {
32+ Component.onCompleted: {
33− id: fakeSurfaceComponent
33+ root.fakeApplication = ApplicationManager.add("gallery-app");
34− Image {
34+ root.fakeApplication.manualSurfaceCreation = true;
35− source: "../../../qml/Dash/graphics/phone/screenshots/gallery@12.png"
35+ root.fakeApplication.setState(ApplicationInfo.Starting);
36− width: applicationWindowLoader.width
37− height: applicationWindowLoader.height
38−
39− property var application: fakeApplication
40− property int touchPressCount: 0
41− property int touchReleaseCount: 0
42−
43− Text {
44− anchors.fill: parent
45− text: "SURFACE"
46− color: "yellow"
47− font.bold: true
48− fontSizeMode: Text.Fit
49− minimumPixelSize: 10; font.pixelSize: 200
50− verticalAlignment: Text.AlignVCenter
51− }
52−
53− MultiPointTouchArea {
54− anchors.fill: parent
55− onPressed: { touchPressCount++; }
56− onReleased: { touchReleaseCount++; }
57− }
58−
59− signal removed()
60−
61− function release() {
62− fakeApplication.surface = null;
63− parent = null;
64− removed();
65− surfaceCheckbox.checked = false;
66− }
67− }
68 }
36 }
37+ property QtObject fakeApplication: null
69
38
70− QtObject {
39+ Connections {
71− id: fakeApplication
40+ target: fakeApplication
72− property url screenshot: ""
41+ onSurfaceChanged: {
73−
42+ surfaceCheckbox.checked = fakeApplication.surface !== null;
74− function updateScreenshot() {
75− fakeScreenshotTimer.start();
76− }
77−
78− function discardScreenshot() {
79− screenshot = "";
80− }
81−
82− property alias state: appStateSelector.selectedApplicationState
83− property string name: "Gallery"
84− property url icon: "../../../qml/graphics/applicationIcons/gallery.png"
85− property var surface: null
86− property bool fullscreen: true
87− property list<Item> childSurfaces
88− }
89− Timer {
90− id: fakeScreenshotTimer
91− interval: 100
92− onTriggered: {
93− fakeApplication.screenshot = "../../../qml/Dash/graphics/phone/screenshots/gallery@12.png";
94 }
43 }
95 }
44 }
96
45
@@ -133,7 +82,7 @@ Rectangle {
133 return;
82 return;
134
83
135 if (checked && !fakeApplication.surface) {
84 if (checked && !fakeApplication.surface) {
136− fakeApplication.surface = fakeSurfaceComponent.createObject(null, {});
85+ fakeApplication.createSurface();
137 } else if (!checked && fakeApplication.surface) {
86 } else if (!checked && fakeApplication.surface) {
138 fakeApplication.surface.release();
87 fakeApplication.surface.release();
139 }
88 }
@@ -160,6 +109,10 @@ Rectangle {
160 return ApplicationInfo.Stopped;
109 return ApplicationInfo.Stopped;
161 }
110 }
162 }
111 }
112+ onSelectedApplicationStateChanged: {
113+ // state is a read-only property, thus we have to call the setter function
114+ fakeApplication.setState(selectedApplicationState);
115+ }
163 }
116 }
164 }
117 }
165 }
118 }
@@ -199,9 +152,8 @@ Rectangle {
199 appStateSelector.selectedIndex = 0;
152 appStateSelector.selectedIndex = 0;
200 surfaceCheckbox.checked = false;
153 surfaceCheckbox.checked = false;
201
154
202− fakeScreenshotTimer.stop();
203− fakeApplication.screenshot = "";
155+ if (fakeApplication.surface)
204− fakeApplication.surface = null;
156+ fakeApplication.surface.release();
205
157
206 applicationWindowLoader.active = true;
158 applicationWindowLoader.active = true;
207 }
159 }
@@ -270,6 +222,7 @@ Rectangle {
270
222
271 function test_restartApp() {
223 function test_restartApp() {
272 var stateGroup = findInvisibleChild(applicationWindowLoader.item, "applicationWindowStateGroup");
224 var stateGroup = findInvisibleChild(applicationWindowLoader.item, "applicationWindowStateGroup");
225+ var screenshotImage = findChild(applicationWindowLoader.item, "screenshotImage");
273
226
274 surfaceCheckbox.checked = true;
227 surfaceCheckbox.checked = true;
275 setApplicationState(appRunning);
228 setApplicationState(appRunning);
@@ -298,7 +251,7 @@ Rectangle {
298 surfaceCheckbox.checked = true;
251 surfaceCheckbox.checked = true;
299
252
300 tryCompare(stateGroup, "state", "surface");
253 tryCompare(stateGroup, "state", "surface");
301− tryCompare(fakeApplication, "screenshot", "");
254+ tryCompare(screenshotImage, "status", Image.Null);
302 }
255 }
303
256
304 function test_appCrashed() {
257 function test_appCrashed() {
@@ -347,14 +300,16 @@ Rectangle {
347 // wait until any transition animation has finished
300 // wait until any transition animation has finished
348 tryCompare(stateGroup, "transitioning", false, 2000);
301 tryCompare(stateGroup, "transitioning", false, 2000);
349
302
303+ // Because doing stuff in C++ is a PITA we keep the counter in the interal qml impl.
304+ var fakeSurface = findChild(fakeApplication.surface, "fakeSurfaceQML");
350− fakeApplication.surface.touchPressCount = 0;
305+ fakeSurface.touchPressCount = 0;
351− fakeApplication.surface.touchReleaseCount = 0;
306+ fakeSurface.touchReleaseCount = 0;
352
307
353 tap(applicationWindowLoader.item,
308 tap(applicationWindowLoader.item,
354 applicationWindowLoader.item.width / 2, applicationWindowLoader.item.height / 2);
309 applicationWindowLoader.item.width / 2, applicationWindowLoader.item.height / 2);
355
310
356− verify(fakeApplication.surface.touchPressCount === 1);
311+ verify(fakeSurface.touchPressCount === 1);
357− verify(fakeApplication.surface.touchReleaseCount === 1);
312+ verify(fakeSurface.touchReleaseCount === 1);
358 }
313 }
359 }
314 }
360}
315}
tests/qmltests/Stages/tst_SpreadDelegate.qml+3−23
@@ -29,30 +29,10 @@ Rectangle {
29 width: units.gu(70)
29 width: units.gu(70)
30 height: units.gu(70)
30 height: units.gu(70)
31
31
32− QtObject {
32+ Component.onCompleted: {
33− id: fakeApplication
33+ root.fakeApplication = ApplicationManager.startApplication("gallery-app");
34− property url screenshot: ""
35−
36− function updateScreenshot() {}
37− function discardScreenshot() {}
38−
39− property int state: ApplicationInfo.Running
40− property string name: "Gallery"
41− property url icon: "../../../qml/graphics/applicationIcons/gallery.png"
42−
43− property var surface: Image {
44− source: "../../../qml/Dash/graphics/phone/screenshots/gallery@12.png"
45− width: spreadDelegateLoader.width
46− height: spreadDelegateLoader.height
47−
48− property var application: fakeApplication
49−
50− signal removed()
51− function release() {}
52− }
53−
54− property bool fullscreen: true
55 }
34 }
35+ property QtObject fakeApplication: null
56
36
57 Component {
37 Component {
58 id: spreadDelegateComponent
38 id: spreadDelegateComponent