Merge lp:~dandrader/unity8/detachPromptSurfaces into lp:unity8

Proposed by Daniel d'Andrada
Status: Superseded
Proposed branch: lp:~dandrader/unity8/detachPromptSurfaces
Merge into: lp:unity8
Diff against target: 975 lines (+241/-376)
14 files modified
debian/control (+3/-3)
qml/Stages/ApplicationWindow.qml (+31/-1)
qml/Stages/SurfaceContainer.qml (+4/-63)
tests/mocks/Unity/Application/ApplicationInfo.cpp (+8/-0)
tests/mocks/Unity/Application/ApplicationInfo.h (+2/-0)
tests/mocks/Unity/Application/MirSurface.cpp (+1/-21)
tests/mocks/Unity/Application/MirSurface.h (+0/-5)
tests/mocks/Unity/Application/MirSurfaceListModel.cpp (+28/-0)
tests/mocks/Unity/Application/MirSurfaceListModel.h (+5/-0)
tests/plugins/Unity/Launcher/launchermodeltest.cpp (+1/-0)
tests/qmltests/Stages/ApplicationCheckBox.qml (+33/-3)
tests/qmltests/Stages/RecursingChildSessionControl.qml (+0/-94)
tests/qmltests/Stages/tst_ApplicationWindow.qml (+91/-25)
tests/qmltests/Stages/tst_SurfaceContainer.qml (+34/-161)
To merge this branch: bzr merge lp:~dandrader/unity8/detachPromptSurfaces
Reviewer Review Type Date Requested Status
Nick Dedekind (community) Needs Fixing
Unity8 CI Bot continuous-integration Needs Fixing
Review via email: mp+294959@code.launchpad.net

This proposal has been superseded by a proposal from 2016-05-18.

Commit message

Move prompt surfaces from MirSurface to Application

prompt surfaces can show up even before an application creates its first surface

Description of the change

* Are there any related MPs required for this MP to build/function as expected? Please list.
https://code.launchpad.net/~dandrader/unity-api/detachPromptSurfaces/+merge/294955
https://code.launchpad.net/~dandrader/qtmir/detachPromptSurfaces/+merge/294954

* Did you perform an exploratory manual test run of your code change and any related functionality?
Yes

* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
Not applicable

* If you changed the UI, has there been a design review?
Not applicable

To post a comment you must log in.
2397. By Daniel d'Andrada

Update unity-api versions

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
2398. By Daniel d'Andrada

Simplify code

2399. By Daniel d'Andrada

fix issues

2400. By Daniel d'Andrada

Disable debug messages

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Nick Dedekind (nick-dedekind) :
review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

On 18/05/2016 07:40, Nick Dedekind wrote:
>> + if (root.application && root.surface === root.application.surfaceList.first) {
> uh. I dont actually think this is right. If we're have a multisurface app, we may end up missing the prompt because we're looking at the wrong surface. So the app may just seem like it's not starting up.
>

The surface list is ordered by focus recency. Ie, when a surface is
focused it's raise to the top of the list. So

surfaceList.first will always point to the currently (or most recently) focused surface of this application.

Please run "make tryDesktopStage" and play with multiple surface applications and prompts.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2016-05-04 18:09:25 +0000
3+++ debian/control 2016-05-17 20:00:40 +0000
4@@ -30,7 +30,7 @@
5 libqt5xmlpatterns5-dev,
6 libsystemsettings-dev,
7 libudev-dev,
8- libunity-api-dev (>= 7.111),
9+ libunity-api-dev (>= 7.112),
10 libusermetricsoutput1-dev,
11 # Need those X11 libs touch emulation from mouse events in manual QML tests on a X11 desktop
12 libx11-dev[!armhf],
13@@ -133,7 +133,7 @@
14 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1845) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1845),
15 qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl,
16 ubuntu-thumbnailer-impl-0,
17- unity-application-impl-15,
18+ unity-application-impl-16,
19 unity-notifications-impl-3,
20 unity-plugin-scopes | unity-scopes-impl,
21 unity-scopes-impl-12,
22@@ -179,7 +179,7 @@
23 Depends: ${misc:Depends},
24 ${shlibs:Depends},
25 Provides: unity-application-impl,
26- unity-application-impl-15,
27+ unity-application-impl-16,
28 Replaces: unity8-autopilot (<< 8.02+15.04.20150422-0ubuntu1)
29 Description: Fake environment for running Unity 8 shell
30 Provides fake implementations of some QML modules used by Unity 8 shell
31
32=== modified file 'qml/Stages/ApplicationWindow.qml'
33--- qml/Stages/ApplicationWindow.qml 2016-04-27 15:01:10 +0000
34+++ qml/Stages/ApplicationWindow.qml 2016-05-17 20:00:40 +0000
35@@ -120,6 +120,17 @@
36 || (application.supportedOrientations & Qt.InvertedLandscapeOrientation))
37
38 property bool surfaceOldEnoughToBeResized: false
39+
40+ property var focusedSurface: {
41+ if (promptSurfacesRepeater.count == 0) {
42+ return surfaceContainer;
43+ } else {
44+ return promptSurfacesRepeater.itemAt(promptSurfacesRepeater.count - 1);
45+ }
46+ }
47+ onFocusedSurfaceChanged: {
48+ focusedSurface.focus = true;
49+ }
50 }
51
52 Binding {
53@@ -183,7 +194,26 @@
54 requestedWidth: root.requestedWidth
55 requestedHeight: root.requestedHeight
56 surfaceOrientationAngle: application && application.rotatesWindowContents ? root.surfaceOrientationAngle : 0
57- focus: true
58+ }
59+
60+ Repeater {
61+ id: promptSurfacesRepeater
62+ objectName: "promptSurfacesRepeater"
63+ // show only along with the top-most application surface
64+ model: {
65+ if (root.application && root.surface === root.application.surfaceList.first) {
66+ return root.application.promptSurfaceList;
67+ } else {
68+ return null;
69+ }
70+ }
71+ delegate: SurfaceContainer {
72+ interactive: index == (promptSurfacesRepeater.count - 1) && root.interactive
73+ surface: model.surface
74+ width: root.width
75+ height: root.height
76+ isPromptSurface: true
77+ }
78 }
79
80 // SurfaceContainer size drives ApplicationWindow size
81
82=== modified file 'qml/Stages/SurfaceContainer.qml'
83--- qml/Stages/SurfaceContainer.qml 2016-04-04 13:38:56 +0000
84+++ qml/Stages/SurfaceContainer.qml 2016-05-17 20:00:40 +0000
85@@ -33,7 +33,7 @@
86 property bool interactive
87 property int surfaceOrientationAngle: 0
88 property bool resizeSurface: true
89- property bool inPromptSession: false
90+ property bool isPromptSurface: false
91
92 onSurfaceChanged: {
93 // Not a binding because animations might remove the surface from the surfaceItem
94@@ -56,6 +56,8 @@
95 id: surfaceItem
96 objectName: "surfaceItem"
97
98+ focus: true
99+
100 fillMode: MirSurfaceItem.PadOrCrop
101 consumesInput: true
102
103@@ -122,59 +124,12 @@
104 when: root.requestedHeight < 0
105 }
106
107- Repeater {
108- id: childSurfacesRepeater
109- objectName: "childSurfacesRepeater"
110- model: root.surface ? root.surface.promptSurfaceList : null
111-
112- delegate: Loader {
113- objectName: "childDelegate" + index
114- anchors.fill: root
115-
116- // Only way to do recursive qml items.
117- source: Qt.resolvedUrl("SurfaceContainer.qml")
118-
119- z: index
120-
121- // Since a Loader is a FocusScope, propagate its focus to the loaded Item
122- Binding {
123- target: item; when: item
124- property: "focus"; value: focus
125- }
126-
127- Binding {
128- target: item; when: item
129- property: "interactive"; value: index == (childSurfacesRepeater.count - 1) && root.interactive
130- }
131-
132- Binding {
133- target: item; when: item
134- property: "surface"; value: model.surface
135- }
136-
137- Binding {
138- target: item; when: item
139- property: "width"; value: root.width
140- }
141-
142- Binding {
143- target: item; when: item
144- property: "height"; value: root.height
145- }
146-
147- Binding {
148- target: item; when: item
149- property: "inPromptSession"; value: true
150- }
151- }
152- }
153-
154 Loader {
155 id: animationsLoader
156 objectName: "animationsLoader"
157 active: root.surface
158 source: {
159- if (root.inPromptSession) {
160+ if (root.isPromptSurface) {
161 return "PromptSurfaceAnimations.qml";
162 } else {
163 // Let ApplicationWindow do the animations
164@@ -194,18 +149,4 @@
165 value: root
166 }
167 }
168-
169- QtObject {
170- id: d
171- property var focusedChild: {
172- if (childSurfacesRepeater.count == 0) {
173- return surfaceItem;
174- } else {
175- return childSurfacesRepeater.itemAt(childSurfacesRepeater.count - 1);
176- }
177- }
178- onFocusedChildChanged: {
179- focusedChild.focus = true;
180- }
181- }
182 }
183
184=== modified file 'tests/mocks/Unity/Application/ApplicationInfo.cpp'
185--- tests/mocks/Unity/Application/ApplicationInfo.cpp 2016-04-27 15:01:10 +0000
186+++ tests/mocks/Unity/Application/ApplicationInfo.cpp 2016-05-17 20:00:40 +0000
187@@ -194,6 +194,10 @@
188 MirSurface *surface = static_cast<MirSurface*>(m_surfaceList.get(i));
189 surface->setLive(false);
190 }
191+ for (int i = 0; i < m_promptSurfaceList.count(); ++i) {
192+ auto surface = static_cast<MirSurface*>(m_promptSurfaceList.get(i));
193+ surface->setLive(false);
194+ }
195 }
196
197 m_state = value;
198@@ -238,6 +242,10 @@
199 if (value != m_manualSurfaceCreation) {
200 m_manualSurfaceCreation = value;
201 Q_EMIT manualSurfaceCreationChanged(value);
202+
203+ if (m_manualSurfaceCreation && m_surfaceCreationTimer.isActive()) {
204+ m_surfaceCreationTimer.stop();
205+ }
206 }
207 }
208
209
210=== modified file 'tests/mocks/Unity/Application/ApplicationInfo.h'
211--- tests/mocks/Unity/Application/ApplicationInfo.h 2016-04-27 15:01:10 +0000
212+++ tests/mocks/Unity/Application/ApplicationInfo.h 2016-05-17 20:00:40 +0000
213@@ -108,6 +108,7 @@
214 Q_INVOKABLE void setShellChrome(Mir::ShellChrome shellChrome);
215
216 MirSurfaceListInterface* surfaceList() override { return &m_surfaceList; }
217+ MirSurfaceListInterface* promptSurfaceList() override { return &m_promptSurfaceList; }
218
219 void setFocused(bool value);
220
221@@ -148,6 +149,7 @@
222 bool m_exemptFromLifecycle{false};
223 QSize m_initialSurfaceSize;
224 MirSurfaceListModel m_surfaceList;
225+ MirSurfaceListModel m_promptSurfaceList;
226 int m_liveSurfaceCount{0};
227 QTimer m_surfaceCreationTimer;
228 QList<MirSurface*> m_closingSurfaces;
229
230=== modified file 'tests/mocks/Unity/Application/MirSurface.cpp'
231--- tests/mocks/Unity/Application/MirSurface.cpp 2016-04-27 15:01:10 +0000
232+++ tests/mocks/Unity/Application/MirSurface.cpp 2016-05-17 20:00:40 +0000
233@@ -408,27 +408,6 @@
234 }
235 }
236
237-void MirSurface::createPromptSurface()
238-{
239- QStringList screenshotIds = {"gallery", "map", "facebook", "camera", "browser", "music", "twitter"};
240- int i = rand() % screenshotIds.count();
241-
242- QUrl screenshotUrl = QString("qrc:///Unity/Application/screenshots/%1@12.png")
243- .arg(screenshotIds[i]);
244-
245- auto surface = new MirSurface(QString("prompt foo"),
246- Mir::NormalType,
247- Mir::RestoredState,
248- screenshotUrl);
249-
250- m_promptSurfaceList.appendSurface(surface);
251-}
252-
253-MirSurfaceListInterface* MirSurface::promptSurfaceList()
254-{
255- return &m_promptSurfaceList;
256-}
257-
258 void MirSurface::requestFocus()
259 {
260 DEBUG_MSG("");
261@@ -485,6 +464,7 @@
262
263 if (m_focusedSurface) {
264 Q_EMIT m_focusedSurface->focusedChanged(true);
265+ m_focusedSurface->raise();
266 }
267 }
268
269
270=== modified file 'tests/mocks/Unity/Application/MirSurface.h'
271--- tests/mocks/Unity/Application/MirSurface.h 2016-04-27 15:01:10 +0000
272+++ tests/mocks/Unity/Application/MirSurface.h 2016-05-17 20:00:40 +0000
273@@ -107,8 +107,6 @@
274
275 Q_INVOKABLE void close() override;
276
277- unity::shell::application::MirSurfaceListInterface* promptSurfaceList() override;
278-
279 Q_INVOKABLE void raise() override;
280
281 ////
282@@ -130,8 +128,6 @@
283 Q_INVOKABLE void setWidthIncrement(int);
284 Q_INVOKABLE void setHeightIncrement(int);
285
286- Q_INVOKABLE void createPromptSurface();
287-
288 /////
289 // internal mock stuff
290
291@@ -199,7 +195,6 @@
292 QSize m_pendingResize;
293
294 Mir::ShellChrome m_shellChrome;
295- MirSurfaceListModel m_promptSurfaceList;
296
297 struct View {
298 bool visible;
299
300=== modified file 'tests/mocks/Unity/Application/MirSurfaceListModel.cpp'
301--- tests/mocks/Unity/Application/MirSurfaceListModel.cpp 2016-04-04 13:37:49 +0000
302+++ tests/mocks/Unity/Application/MirSurfaceListModel.cpp 2016-05-17 20:00:40 +0000
303@@ -67,6 +67,9 @@
304 connectSurface(surface);
305 endInsertRows();
306 Q_EMIT countChanged();
307+ if (m_surfaceList.count() == 1) {
308+ Q_EMIT firstChanged();
309+ }
310 }
311
312 void MirSurfaceListModel::connectSurface(MirSurface *surface)
313@@ -83,6 +86,9 @@
314 m_surfaceList.removeAt(i);
315 endRemoveRows();
316 Q_EMIT countChanged();
317+ if (m_surfaceList.count() == 0 || i == 0) {
318+ Q_EMIT firstChanged();
319+ }
320 }
321 }
322
323@@ -100,6 +106,10 @@
324 m_surfaceList.move(from, to);
325 endMoveRows();
326 }
327+
328+ if ((from == 0 || to == 0) && m_surfaceList.count() > 1) {
329+ Q_EMIT firstChanged();
330+ }
331 }
332
333 MirSurfaceInterface *MirSurfaceListModel::get(int index)
334@@ -119,3 +129,21 @@
335 return nullptr;
336 }
337 }
338+
339+MirSurfaceInterface *MirSurfaceListModel::createSurface()
340+{
341+ QStringList screenshotIds = {"gallery", "map", "facebook", "camera", "browser", "music", "twitter"};
342+ int i = rand() % screenshotIds.count();
343+
344+ QUrl screenshotUrl = QString("qrc:///Unity/Application/screenshots/%1@12.png")
345+ .arg(screenshotIds[i]);
346+
347+ auto surface = new MirSurface(QString("prompt foo"),
348+ Mir::NormalType,
349+ Mir::RestoredState,
350+ screenshotUrl);
351+
352+ appendSurface(surface);
353+
354+ return surface;
355+}
356
357=== modified file 'tests/mocks/Unity/Application/MirSurfaceListModel.h'
358--- tests/mocks/Unity/Application/MirSurfaceListModel.h 2016-04-04 13:37:49 +0000
359+++ tests/mocks/Unity/Application/MirSurfaceListModel.h 2016-05-17 20:00:40 +0000
360@@ -43,6 +43,11 @@
361
362 bool contains(MirSurface *surface) const { return m_surfaceList.contains(surface); }
363
364+ ////
365+ // API for tests
366+
367+ Q_INVOKABLE unity::shell::application::MirSurfaceInterface *createSurface();
368+
369 private:
370 void raise(MirSurface *surface);
371 void moveSurface(int from, int to);
372
373=== modified file 'tests/plugins/Unity/Launcher/launchermodeltest.cpp'
374--- tests/plugins/Unity/Launcher/launchermodeltest.cpp 2016-04-27 15:01:10 +0000
375+++ tests/plugins/Unity/Launcher/launchermodeltest.cpp 2016-05-17 20:00:40 +0000
376@@ -67,6 +67,7 @@
377 QSize initialSurfaceSize() const override { return QSize(); }
378 void setInitialSurfaceSize(const QSize &) override {}
379 MirSurfaceListInterface* surfaceList() override { return nullptr; }
380+ MirSurfaceListInterface* promptSurfaceList() override { return nullptr; }
381
382 // Methods used for mocking (not in the interface)
383 void setFocused(bool focused) { m_focused = focused; Q_EMIT focusedChanged(focused); }
384
385=== modified file 'tests/qmltests/Stages/ApplicationCheckBox.qml'
386--- tests/qmltests/Stages/ApplicationCheckBox.qml 2016-04-26 10:29:25 +0000
387+++ tests/qmltests/Stages/ApplicationCheckBox.qml 2016-05-17 20:00:40 +0000
388@@ -44,6 +44,7 @@
389 d.bindGuard = false;
390 }
391
392+ // Application checkbox row
393 RowLayout {
394
395 QtObject {
396@@ -128,17 +129,47 @@
397 visible: enabled
398 Label {
399 text: "âž•"
400- color: "white"
401 anchors.centerIn: parent
402 }
403 }
404 }
405+
406+ // Prompts controls row
407+ RowLayout {
408+ anchors.left: root.left
409+ anchors.leftMargin: units.gu(2)
410+ visible: root.checked === true && d.application !== null && root.enabled
411+ spacing: units.gu(1)
412+ Label {
413+ property int promptCount: d.application ? d.application.promptSurfaceList.count : 0
414+ id: promptsLabel
415+ text: promptCount + " prompts"
416+ }
417+ MouseArea {
418+ width: height
419+ height: promptsLabel.height * 0.7
420+ anchors.verticalCenter: parent.verticalCenter
421+ onClicked: d.application.promptSurfaceList.createSurface()
422+ Label { text: "âž•"; anchors.centerIn: parent }
423+ }
424+ MouseArea {
425+ width: height
426+ height: promptsLabel.height * 0.7
427+ anchors.verticalCenter: parent.verticalCenter
428+ onClicked: d.application.promptSurfaceList.get(d.application.promptSurfaceList.count - 1).close()
429+ enabled: d.application && d.application.promptSurfaceList.count > 0
430+ Label { text: "âž–"; anchors.centerIn: parent; enabled: parent.enabled }
431+ }
432+ }
433+
434+ // Rows of application surfaces
435 Repeater {
436 model: d.application ? d.application.surfaceList : null
437 RowLayout {
438+ anchors.left: root.left
439+ anchors.leftMargin: units.gu(2)
440 spacing: units.gu(1)
441 Label {
442- color: "white"
443 text: "- " + model.surface.name
444 }
445 MouseArea {
446@@ -150,7 +181,6 @@
447 onClicked: model.surface.setLive(false);
448 Label {
449 text: "â›’"
450- color: "white"
451 anchors.centerIn: parent
452 }
453 }
454
455=== removed file 'tests/qmltests/Stages/RecursingChildSessionControl.qml'
456--- tests/qmltests/Stages/RecursingChildSessionControl.qml 2016-04-04 13:37:49 +0000
457+++ tests/qmltests/Stages/RecursingChildSessionControl.qml 1970-01-01 00:00:00 +0000
458@@ -1,94 +0,0 @@
459-/*
460- * Copyright 2014,2016 Canonical Ltd.
461- *
462- * This program is free software; you can redistribute it and/or modify
463- * it under the terms of the GNU General Public License as published by
464- * the Free Software Foundation; version 3.
465- *
466- * This program is distributed in the hope that it will be useful,
467- * but WITHOUT ANY WARRANTY; without even the implied warranty of
468- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
469- * GNU General Public License for more details.
470- *
471- * You should have received a copy of the GNU General Public License
472- * along with this program. If not, see <http://www.gnu.org/licenses/>.
473- */
474-
475-import QtQuick 2.4
476-import QtQuick.Layouts 1.1
477-import Ubuntu.Components 1.3
478-import Unity.Application 0.1
479-
480-ColumnLayout {
481- id: root
482-
483- property var surface
484-
485- Column {
486- id: column
487- Layout.fillWidth: true
488- visible: repeater.count
489- spacing: units.gu(1)
490-
491- Repeater {
492- id: repeater
493- model: root.surface ? root.surface.promptSurfaceList : null
494- delegate: Rectangle {
495- border {
496- color: "black"
497- width: 1
498- }
499- anchors {
500- left: column.left
501- right: column.right
502- leftMargin: units.gu(1)
503- rightMargin: units.gu(1)
504- }
505- height: loader.height
506-
507- Rectangle {
508- anchors.fill: parent
509- color: Qt.rgba(Math.random(), Math.random(), Math.random(), 0.4 )
510- }
511-
512- Loader {
513- id: loader
514- visible: status == Loader.Ready
515- source: Qt.resolvedUrl("RecursingChildSessionControl.qml")
516-
517- anchors {
518- left: parent.left
519- right: parent.right
520- }
521-
522- onLoaded: {
523- item.surface = model.surface;
524- }
525- }
526- }
527- }
528- }
529-
530- ColumnLayout {
531- Layout.fillWidth: true
532- spacing: units.gu(1)
533-
534- RowLayout {
535- id: buttonLayout
536-
537- Button {
538- enabled: root.surface
539- activeFocusOnPress: false
540- text: "Remove"
541- onClicked: { root.surface.close(); }
542- }
543-
544- Button {
545- enabled: root.surface !== null
546- activeFocusOnPress: false
547- text: "Add Prompt Surface"
548- onClicked: { root.surface.createPromptSurface(); }
549- }
550- }
551- }
552-}
553
554=== modified file 'tests/qmltests/Stages/tst_ApplicationWindow.qml'
555--- tests/qmltests/Stages/tst_ApplicationWindow.qml 2016-04-04 13:37:49 +0000
556+++ tests/qmltests/Stages/tst_ApplicationWindow.qml 2016-05-17 20:00:40 +0000
557@@ -33,7 +33,6 @@
558 Component.onCompleted: {
559 root.fakeApplication = ApplicationManager.add("gallery-app");
560 root.fakeApplication.manualSurfaceCreation = true;
561- root.fakeApplication.setState(ApplicationInfoInterface.Starting);
562 applicationWindowLoader.item.application = root.fakeApplication;
563 }
564 property QtObject fakeApplication: null
565@@ -78,7 +77,7 @@
566 Layout.fillWidth: true
567
568 CheckBox {
569- id: surfaceCheckbox;
570+ id: surfaceCheckbox
571 checked: false;
572 activeFocusOnPress: false
573 onCheckedChanged: {
574@@ -86,10 +85,8 @@
575 return;
576
577 if (checked) {
578- applicationWindowLoader.item.surface = SurfaceManager.createSurface("foo",
579- Mir.NormalType, Mir.MaximizedState, root.fakeApplication);
580-
581- root.fakeApplication.setState(ApplicationInfoInterface.Running);
582+ root.fakeApplication.createSurface();
583+ applicationWindowLoader.item.surface = root.fakeApplication.surfaceList.get(0);
584 } else {
585 if (applicationWindowLoader.item.surface) {
586 applicationWindowLoader.item.surface.setLive(false);
587@@ -103,22 +100,20 @@
588 }
589 }
590
591- Rectangle {
592- border {
593- color: "black"
594- width: 1
595- }
596- anchors {
597- left: parent.left
598- right: parent.right
599- }
600- Layout.preferredHeight: sessionControl.height
601-
602- RecursingChildSessionControl {
603- id: sessionControl
604- anchors { left: parent.left; right: parent.right; }
605-
606- surface: applicationWindowLoader.item ? applicationWindowLoader.item.surface : null
607+ RowLayout {
608+ property var promptSurfaceList: root.fakeApplication ? root.fakeApplication.promptSurfaceList : null
609+ Button {
610+ enabled: parent.promptSurfaceList !== null && parent.promptSurfaceList.count > 0
611+ activeFocusOnPress: false
612+ text: "Remove"
613+ onClicked: { parent.promptSurfaceList.get(parent.promptSurfaceList.count - 1).close(); }
614+ }
615+
616+ Button {
617+ enabled: parent.promptSurfaceList !== null
618+ activeFocusOnPress: false
619+ text: "Add Prompt Surface"
620+ onClicked: { parent.promptSurfaceList.createSurface(); }
621 }
622 }
623
624@@ -244,19 +239,29 @@
625 // deleted, so you end up with two instances in memory.
626 tryCompare(applicationWindowLoader, "itemDestroyed", true);
627
628- setApplicationState(appStarting);
629 surfaceCheckbox.checked = false;
630
631- ApplicationManager.stopApplication("gallery-app");
632+ console.log("killApps() start");
633+ killApps();
634+ console.log("killApps() end");
635+
636 root.fakeApplication = ApplicationManager.add("gallery-app");
637 root.fakeApplication.manualSurfaceCreation = true;
638- root.fakeApplication.setState(ApplicationInfoInterface.Starting);
639
640 applicationWindowLoader.active = true;
641
642 applicationWindowLoader.item.application = root.fakeApplication;
643 }
644
645+ function waitUntilSurfaceContainerStopsAnimating(container) {
646+ var animationsLoader = findChild(container, "animationsLoader");
647+ verify(animationsLoader);
648+ tryCompare(animationsLoader, "status", Loader.Ready)
649+
650+ var animation = animationsLoader.item;
651+ waitUntilTransitionsEnd(animation);
652+ }
653+
654 function test_showSplashUntilAppFullyInit_data() {
655 return [
656 {tag: "state=Running then create surface", swapInitOrder: false},
657@@ -432,5 +437,66 @@
658 applicationWindow.interactive = true;
659 compare(applicationWindow.surface.activeFocus, true);
660 }
661+
662+ function test_promptSurfaceDestructionReturnsFocusToPreviousSurface() {
663+ surfaceCheckbox.checked = true;
664+ var promptSurfaces = testCase.findChild(applicationWindow, "promptSurfacesRepeater");
665+ var promptSurfaceList = root.fakeApplication.promptSurfaceList;
666+ compare(promptSurfaces.count, 0);
667+
668+ var i;
669+ // 3 surfaces should cover all edge cases
670+ for (i = 0; i < 3; i++) {
671+ promptSurfaceList.createSurface();
672+ compare(promptSurfaces.count, i+1);
673+ waitUntilSurfaceContainerStopsAnimating(promptSurfaces.itemAt(promptSurfaces.count - 1));
674+ }
675+
676+ for (i = 2; i >= 0; --i) {
677+ var promptSurface = promptSurfaceList.get(i);
678+ compare(promptSurface.activeFocus, true);
679+
680+ promptSurface.close();
681+ tryCompareFunction(function() { return promptSurfaces.count; }, i);
682+
683+ if (i > 0) {
684+ // active focus should have gone to the yongest remaining sibling
685+ var previousPromptSurface = promptSurfaceList.get(i-1);
686+ tryCompare(previousPromptSurface, "activeFocus", true);
687+ } else {
688+ // active focus should have gone to the application surface
689+ tryCompare(applicationWindow.surface, "activeFocus", true);
690+ }
691+ }
692+ }
693+
694+ function test_promptSurfaceAdjustsForParentSize() {
695+ var promptSurfaceList = root.fakeApplication.promptSurfaceList;
696+
697+ promptSurfaceList.createSurface();
698+
699+ var promptSurfaces = testCase.findChild(applicationWindow, "promptSurfacesRepeater");
700+
701+ var delegate = promptSurfaces.itemAt(0);
702+ waitUntilSurfaceContainerStopsAnimating(delegate);
703+
704+ var promptSurfaceContainer = findChild(delegate, "surfaceContainer");
705+
706+ tryCompareFunction(function() { return promptSurfaceContainer.height === applicationWindow.height; }, true);
707+ tryCompareFunction(function() { return promptSurfaceContainer.width === applicationWindow.width; }, true);
708+ tryCompareFunction(function() { return promptSurfaceContainer.x === 0; }, true);
709+ tryCompareFunction(function() { return promptSurfaceContainer.y === 0; }, true);
710+
711+ applicationWindow.anchors.margins = units.gu(2);
712+
713+ tryCompareFunction(function() { return promptSurfaceContainer.height === applicationWindow.height; }, true);
714+ tryCompareFunction(function() { return promptSurfaceContainer.width === applicationWindow.width; }, true);
715+ tryCompareFunction(function() { return promptSurfaceContainer.x === 0; }, true);
716+ tryCompareFunction(function() { return promptSurfaceContainer.y === 0; }, true);
717+
718+ // clean up
719+ delegate.surface.close();
720+ tryCompare(promptSurfaces, "count", 0);
721+ }
722 }
723 }
724
725=== modified file 'tests/qmltests/Stages/tst_SurfaceContainer.qml'
726--- tests/qmltests/Stages/tst_SurfaceContainer.qml 2016-04-07 13:54:29 +0000
727+++ tests/qmltests/Stages/tst_SurfaceContainer.qml 2016-05-17 20:00:40 +0000
728@@ -42,6 +42,7 @@
729 anchors.fill: parent
730 focus: true
731 interactive: interactiveCheckbox.checked
732+ isPromptSurface: promptCheckbox.checked
733 Component.onDestruction: {
734 surfaceContainerLoader.itemDestroyed = true;
735 }
736@@ -75,17 +76,19 @@
737 anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
738 spacing: units.gu(1)
739
740- RowLayout {
741- Layout.fillWidth: true
742
743- Row {
744- CheckBox {id: fullscreenCheckbox; checked: true; activeFocusOnPress: false }
745- Label { text: "fullscreen" }
746- }
747- Row {
748- CheckBox {id: interactiveCheckbox; checked: true; activeFocusOnPress: false }
749- Label { text: "interactive" }
750- }
751+ Row {
752+ CheckBox {id: fullscreenCheckbox; checked: true; activeFocusOnPress: false }
753+ Label { text: "fullscreen" }
754+ }
755+ Row {
756+ CheckBox {id: interactiveCheckbox; checked: true; activeFocusOnPress: false }
757+ Label { text: "interactive" }
758+ }
759+ Row {
760+ CheckBox {id: promptCheckbox; checked: false; activeFocusOnPress: false
761+ enabled: surfaceContainerLoader.item.surface === null }
762+ Label { text: "isPromptSurface" }
763 }
764
765 RowLayout {
766@@ -102,10 +105,9 @@
767 if (checked) {
768 var application = ApplicationManager.add("music-app");
769 application.manualSurfaceCreation = true;
770- application.setState(ApplicationInfoInterface.Starting);
771
772- surfaceContainerLoader.item.surface = SurfaceManager.createSurface("foo",
773- Mir.NormalType, Mir.MaximizedState, application.screenshot);
774+ application.createSurface();
775+ surfaceContainerLoader.item.surface = application.surfaceList.get(0);
776
777 application.setState(ApplicationInfoInterface.Running);
778 } else {
779@@ -123,22 +125,11 @@
780 }
781 }
782
783- Rectangle {
784- border {
785- color: "black"
786- width: 1
787- }
788- anchors {
789- left: parent.left
790- right: parent.right
791- }
792- Layout.preferredHeight: surfaceChildrenControl.height
793-
794- RecursingChildSessionControl {
795- id: surfaceChildrenControl
796- anchors { left: parent.left; right: parent.right; }
797-
798- surface: surfaceContainerLoader.item ? surfaceContainerLoader.item.surface : null
799+ Button {
800+ text: "Reload"
801+ enabled: !surfaceCheckbox.checked
802+ onClicked: {
803+ testCase.cleanup();
804 }
805 }
806 }
807@@ -164,6 +155,7 @@
808
809 surfaceCheckbox.checked = false;
810 interactiveCheckbox.checked = true;
811+ promptCheckbox.checked = false;
812
813 surfaceContainerLoader.active = true;
814 tryCompare(surfaceContainerLoader, "status", Loader.Ready);
815@@ -171,121 +163,6 @@
816
817 when: windowShown
818
819- function test_addChildSession_data() {
820- return [ { tag: "count=1", count: 1 },
821- { tag: "count=4", count: 4 } ];
822- }
823-
824- function test_addChildSession(data) {
825- surfaceCheckbox.checked = true;
826- var childSurfaces = testCase.findChild(surfaceContainer, "childSurfacesRepeater");
827- compare(childSurfaces.count, 0);
828-
829- var i;
830- for (i = 0; i < data.count; i++) {
831- surfaceContainer.surface.createPromptSurface();
832- compare(childSurfaces.count, i+1);
833- }
834-
835- for (i = data.count-1; i >= 0; i--) {
836- {
837- var childPromptSurface = surfaceContainer.surface.promptSurfaceList.get(i);
838- childPromptSurface.close();
839- }
840- tryCompareFunction(function() { return childSurfaces.count; }, i);
841- }
842- }
843-
844- function test_childSessionDestructionReturnsFocusToSiblingOrParent() {
845- surfaceCheckbox.checked = true;
846- var childSurfaces = testCase.findChild(surfaceContainer, "childSurfacesRepeater");
847- compare(childSurfaces.count, 0);
848-
849- var i;
850- // 3 surfaces should cover all edge cases
851- for (i = 0; i < 3; i++) {
852- surfaceContainer.surface.createPromptSurface();
853- compare(childSurfaces.count, i+1);
854- }
855-
856- for (i = 2; i >= 0; --i) {
857- var childPromptSurface = surfaceContainer.surface.promptSurfaceList.get(i);
858- compare(childPromptSurface.activeFocus, true);
859-
860- childPromptSurface.close();
861- tryCompareFunction(function() { return childSurfaces.count; }, i);
862-
863- if (i > 0) {
864- // active focus should have gone to the yongest remaining sibling
865- var previousSiblingSurface = surfaceContainer.surface.promptSurfaceList.get(i-1);
866- tryCompare(previousSiblingSurface, "activeFocus", true);
867- } else {
868- // active focus should have gone to the parent surface
869- tryCompare(surfaceContainer.surface, "activeFocus", true);
870- }
871- }
872- }
873-
874- function test_nestedChildSessions_data() {
875- return [ { tag: "depth=2", depth: 2 },
876- { tag: "depth=8", depth: 8 }
877- ];
878- }
879- function test_nestedChildSessions(data) {
880- surfaceCheckbox.checked = true;
881-
882- var i;
883- var container = surfaceContainer;
884- var surface = container.surface;
885- var surfaces = [surface];
886- var parent_childSurfaces = [null];
887- for (i = 0; i < data.depth; i++) {
888- surface.createPromptSurface();
889- var childSurfaces = testCase.findChild(container, "childSurfacesRepeater");
890- compare(childSurfaces.count, 1);
891-
892- var childDelegate = childSurfaces.itemAt(0);
893- container = findChild(childDelegate, "surfaceContainer");
894- {
895- var animationsLoader = findChild(container, "animationsLoader");
896- tryCompare(animationsLoader, "status", Loader.Ready);
897- waitUntilTransitionsEnd(animationsLoader.item);
898- }
899- surface = container.surface;
900-
901- surfaces.push(surface);
902- parent_childSurfaces.push(childSurfaces);
903- }
904-
905- for (i = surfaces.length-1; i >= 0; i--) {
906- surfaces[i].close();
907- if (parent_childSurfaces[i]) {
908- tryCompareFunction(function() { return parent_childSurfaces[i].count; }, 0);
909- }
910- }
911- }
912-
913- function test_childrenAdjustForParentSize() {
914- surfaceCheckbox.checked = true;
915-
916- surfaceContainer.surface.createPromptSurface();
917-
918- var delegate = findChild(surfaceContainer, "childDelegate0");
919- var childContainer = findChild(delegate, "surfaceContainer");
920-
921- tryCompareFunction(function() { return childContainer.height === surfaceContainer.height; }, true);
922- tryCompareFunction(function() { return childContainer.width === surfaceContainer.width; }, true);
923- tryCompareFunction(function() { return childContainer.x === 0; }, true);
924- tryCompareFunction(function() { return childContainer.y === 0; }, true);
925-
926- surfaceContainer.anchors.margins = units.gu(2);
927-
928- tryCompareFunction(function() { return childContainer.height === surfaceContainer.height; }, true);
929- tryCompareFunction(function() { return childContainer.width === surfaceContainer.width; }, true);
930- tryCompareFunction(function() { return childContainer.x === 0; }, true);
931- tryCompareFunction(function() { return childContainer.y === 0; }, true);
932- }
933-
934 function isContainerAnimating(container) {
935 var animationsLoader = findChild(container, "animationsLoader");
936 if (!animationsLoader || animationsLoader.status != Loader.Ready) {
937@@ -303,25 +180,21 @@
938 return false;
939 }
940
941- function test_childrenAnimate() {
942+ function test_promptSurfaceAnimates() {
943+ promptCheckbox.checked = true;
944 surfaceCheckbox.checked = true;
945
946- surfaceContainer.surface.createPromptSurface();
947-
948- var delegate = findChild(surfaceContainer, "childDelegate0");
949- var childContainer = findChild(delegate, "surfaceContainer");
950-
951- // wait for animation to begin
952- tryCompareFunction(function() { return isContainerAnimating(childContainer); }, true);
953- // wait for animation to end
954- tryCompareFunction(function() { return isContainerAnimating(childContainer); }, false);
955-
956- surfaceContainer.surface.promptSurfaceList.get(0).close();
957-
958- // wait for animation to begin
959- tryCompareFunction(function() { return isContainerAnimating(childContainer); }, true);
960- // wait for animation to end
961- tryCompareFunction(function() { return isContainerAnimating(childContainer); }, false);
962+ // wait for animation to begin
963+ tryCompareFunction(function() { return isContainerAnimating(surfaceContainer); }, true);
964+ // wait for animation to end
965+ tryCompareFunction(function() { return isContainerAnimating(surfaceContainer); }, false);
966+
967+ surfaceContainer.surface.close();
968+
969+ // wait for animation to begin
970+ tryCompareFunction(function() { return isContainerAnimating(surfaceContainer); }, true);
971+ // wait for animation to end
972+ tryCompareFunction(function() { return isContainerAnimating(surfaceContainer); }, false);
973 }
974
975 function test_surfaceItemGetsNoTouchesWhenContainerNotInteractive() {

Subscribers

People subscribed via source and target branches