on xenial help sign in
composition of ApplicationWindow & SessionContainer
4979650Nick Dedekind
qml/Stages/ApplicationWindow.qml+44−31
@@ -18,15 +18,15 @@ import QtQuick 2.0
18import Ubuntu.Components 1.1
18import Ubuntu.Components 1.1
19import Unity.Application 0.1
19import Unity.Application 0.1
20
20
21−SessionContainer {
21+Item {
22 id: root
22 id: root
23
23
24 // to be read from outside
24 // to be read from outside
25 readonly property bool fullscreen: application ? application.fullscreen : false
25 readonly property bool fullscreen: application ? application.fullscreen : false
26+ property alias interactive: sessionContainer.interactive
26
27
27 // to be set from outside
28 // to be set from outside
28 property QtObject application
29 property QtObject application
29− session: application ? application.session : null
30
30
31 QtObject {
31 QtObject {
32 id: d
32 id: d
@@ -41,7 +41,7 @@ SessionContainer {
41 property bool hadSurface: false
41 property bool hadSurface: false
42
42
43 property bool needToTakeScreenshot:
43 property bool needToTakeScreenshot:
44− root.surface && d.surfaceInitialized && screenshotImage.status === Image.Null
44+ sessionContainer.surface && d.surfaceInitialized && screenshotImage.status === Image.Null
45 && d.applicationState === ApplicationInfoInterface.Stopped
45 && d.applicationState === ApplicationInfoInterface.Stopped
46 onNeedToTakeScreenshotChanged: {
46 onNeedToTakeScreenshotChanged: {
47 if (needToTakeScreenshot) {
47 if (needToTakeScreenshot) {
@@ -54,31 +54,23 @@ SessionContainer {
54 // Remove this when possible
54 // Remove this when possible
55 property bool surfaceInitialized: false
55 property bool surfaceInitialized: false
56 }
56 }
57− onSurfaceChanged: {
58− if (root.surface) {
59− surfaceInitTimer.start();
60− } else {
61− d.hadSurface = true;
62− d.surfaceInitialized = false;
63− }
64− }
65
57
66 Timer {
58 Timer {
67 id: surfaceInitTimer
59 id: surfaceInitTimer
68 interval: 100
60 interval: 100
69− onTriggered: { if (root.surface) {d.surfaceInitialized = true;} }
61+ onTriggered: { if (sessionContainer.surface) {d.surfaceInitialized = true;} }
70 }
62 }
71
63
72 Connections {
64 Connections {
73− target: root.surface
65+ target: sessionContainer.surface
74 // FIXME: I would rather not need to do this, but currently it doesn't get
66 // FIXME: I would rather not need to do this, but currently it doesn't get
75 // active focus without it and I don't know why.
67 // active focus without it and I don't know why.
76 onFocusChanged: forceSurfaceActiveFocusIfReady();
68 onFocusChanged: forceSurfaceActiveFocusIfReady();
77 onParentChanged: forceSurfaceActiveFocusIfReady();
69 onParentChanged: forceSurfaceActiveFocusIfReady();
78 onEnabledChanged: forceSurfaceActiveFocusIfReady();
70 onEnabledChanged: forceSurfaceActiveFocusIfReady();
79 function forceSurfaceActiveFocusIfReady() {
71 function forceSurfaceActiveFocusIfReady() {
80− if (root.surface.focus && root.surface.parent === surfaceContainer && root.surface.enabled) {
72+ if (sessionContainer.surface.focus && sessionContainer.surface.parent === sessionContainer.surfaceContainer && sessionContainer.surface.enabled) {
81− root.surface.forceActiveFocus();
73+ sessionContainer.surface.forceActiveFocus();
82 }
74 }
83 }
75 }
84 }
76 }
@@ -111,27 +103,42 @@ SessionContainer {
111 }
103 }
112 }
104 }
113
105
106+ SessionContainer {
107+ id: sessionContainer
108+ session: application ? application.session : null
109+ anchors.fill: parent
110+
111+ onSurfaceChanged: {
112+ if (sessionContainer.surface) {
113+ surfaceInitTimer.start();
114+ } else {
115+ d.hadSurface = true;
116+ d.surfaceInitialized = false;
117+ }
118+ }
119+ }
120+
114 StateGroup {
121 StateGroup {
115 objectName: "applicationWindowStateGroup"
122 objectName: "applicationWindowStateGroup"
116 states: [
123 states: [
117 State {
124 State {
118 name: "void"
125 name: "void"
119 when:
126 when:
120− d.hadSurface && (!root.surface || !d.surfaceInitialized)
127+ d.hadSurface && (!sessionContainer.surface || !d.surfaceInitialized)
121 &&
128 &&
122 screenshotImage.status !== Image.Ready
129 screenshotImage.status !== Image.Ready
123 },
130 },
124 State {
131 State {
125 name: "splashScreen"
132 name: "splashScreen"
126 when:
133 when:
127− !d.hadSurface && (!root.surface || !d.surfaceInitialized)
134+ !d.hadSurface && (!sessionContainer.surface || !d.surfaceInitialized)
128 &&
135 &&
129 screenshotImage.status !== Image.Ready
136 screenshotImage.status !== Image.Ready
130 },
137 },
131 State {
138 State {
132 name: "surface"
139 name: "surface"
133 when:
140 when:
134− (root.surface && d.surfaceInitialized)
141+ (sessionContainer.surface && d.surfaceInitialized)
135 &&
142 &&
136 (d.applicationState !== ApplicationInfoInterface.Stopped
143 (d.applicationState !== ApplicationInfoInterface.Stopped
137 || screenshotImage.status !== Image.Ready)
144 || screenshotImage.status !== Image.Ready)
@@ -142,7 +149,7 @@ SessionContainer {
142 screenshotImage.status === Image.Ready
149 screenshotImage.status === Image.Ready
143 &&
150 &&
144 (d.applicationState === ApplicationInfoInterface.Stopped
151 (d.applicationState === ApplicationInfoInterface.Stopped
145− || !root.surface || !d.surfaceInitialized)
152+ || !sessionContainer.surface || !d.surfaceInitialized)
146 }
153 }
147 ]
154 ]
148
155
@@ -150,14 +157,18 @@ SessionContainer {
150 Transition {
157 Transition {
151 from: ""; to: "splashScreen"
158 from: ""; to: "splashScreen"
152 PropertyAction { target: splashLoader; property: "active"; value: true }
159 PropertyAction { target: splashLoader; property: "active"; value: true }
160+ PropertyAction { target: sessionContainer.surfaceContainer
161+ property: "visible"; value: false }
153 },
162 },
154 Transition {
163 Transition {
155 from: "splashScreen"; to: "surface"
164 from: "splashScreen"; to: "surface"
156 SequentialAnimation {
165 SequentialAnimation {
157− PropertyAction { target: surfaceContainer
166+ PropertyAction { target: sessionContainer.surfaceContainer
167+ property: "opacity"; value: 0.0 }
168+ PropertyAction { target: sessionContainer.surfaceContainer
158 property: "visible"; value: true }
169 property: "visible"; value: true }
159− UbuntuNumberAnimation { target: splashLoader; property: "opacity";
170+ UbuntuNumberAnimation { target: sessionContainer.surfaceContainer; property: "opacity";
160− from: 1.0; to: 0.0
171+ from: 0.0; to: 1.0
161 duration: UbuntuAnimation.BriskDuration }
172 duration: UbuntuAnimation.BriskDuration }
162 PropertyAction { target: splashLoader; property: "active"; value: false }
173 PropertyAction { target: splashLoader; property: "active"; value: false }
163 }
174 }
@@ -166,11 +177,13 @@ SessionContainer {
166 from: "surface"; to: "splashScreen"
177 from: "surface"; to: "splashScreen"
167 SequentialAnimation {
178 SequentialAnimation {
168 PropertyAction { target: splashLoader; property: "active"; value: true }
179 PropertyAction { target: splashLoader; property: "active"; value: true }
169− PropertyAction { target: surfaceContainer
180+ PropertyAction { target: sessionContainer.surfaceContainer
170 property: "visible"; value: true }
181 property: "visible"; value: true }
171 UbuntuNumberAnimation { target: splashLoader; property: "opacity";
182 UbuntuNumberAnimation { target: splashLoader; property: "opacity";
172 from: 0.0; to: 1.0
183 from: 0.0; to: 1.0
173 duration: UbuntuAnimation.BriskDuration }
184 duration: UbuntuAnimation.BriskDuration }
185+ PropertyAction { target: sessionContainer.surfaceContainer
186+ property: "visible"; value: false }
174 }
187 }
175 },
188 },
176 Transition {
189 Transition {
@@ -181,15 +194,15 @@ SessionContainer {
181 UbuntuNumberAnimation { target: screenshotImage; property: "opacity";
194 UbuntuNumberAnimation { target: screenshotImage; property: "opacity";
182 from: 0.0; to: 1.0
195 from: 0.0; to: 1.0
183 duration: UbuntuAnimation.BriskDuration }
196 duration: UbuntuAnimation.BriskDuration }
184− PropertyAction { target: surfaceContainer
197+ PropertyAction { target: sessionContainer.surfaceContainer
185 property: "visible"; value: false }
198 property: "visible"; value: false }
186− ScriptAction { script: { if (root.session) { root.session.release(); } } }
199+ ScriptAction { script: { if (sessionContainer.session) { sessionContainer.session.release(); } } }
187 }
200 }
188 },
201 },
189 Transition {
202 Transition {
190 from: "screenshot"; to: "surface"
203 from: "screenshot"; to: "surface"
191 SequentialAnimation {
204 SequentialAnimation {
192− PropertyAction { target: surfaceContainer
205+ PropertyAction { target: sessionContainer.surfaceContainer
193 property: "visible"; value: true }
206 property: "visible"; value: true }
194 UbuntuNumberAnimation { target: screenshotImage; property: "opacity";
207 UbuntuNumberAnimation { target: screenshotImage; property: "opacity";
195 from: 1.0; to: 0.0
208 from: 1.0; to: 0.0
@@ -201,16 +214,16 @@ SessionContainer {
201 Transition {
214 Transition {
202 from: "surface"; to: "void"
215 from: "surface"; to: "void"
203 SequentialAnimation {
216 SequentialAnimation {
204− PropertyAction { target: surfaceContainer; property: "visible"; value: false }
217+ PropertyAction { target: sessionContainer.surfaceContainer; property: "visible"; value: false }
205− ScriptAction { script: { if (root.session) { d.session.release(); } } }
218+ ScriptAction { script: { if (sessionContainer.session) { sessionContainer.session.release(); } } }
206 }
219 }
207 },
220 },
208 Transition {
221 Transition {
209 from: "void"; to: "surface"
222 from: "void"; to: "surface"
210 SequentialAnimation {
223 SequentialAnimation {
211− PropertyAction { target: surfaceContainer; property: "opacity"; value: 0.0 }
224+ PropertyAction { target: sessionContainer.surfaceContainer; property: "opacity"; value: 0.0 }
212− PropertyAction { target: surfaceContainer; property: "visible"; value: true }
225+ PropertyAction { target: sessionContainer.surfaceContainer; property: "visible"; value: true }
213− UbuntuNumberAnimation { target: surfaceContainer; property: "opacity";
226+ UbuntuNumberAnimation { target: sessionContainer.surfaceContainer; property: "opacity";
214 from: 0.0; to: 1.0
227 from: 0.0; to: 1.0
215 duration: UbuntuAnimation.BriskDuration }
228 duration: UbuntuAnimation.BriskDuration }
216 }
229 }
qml/Stages/SessionContainer.qml−2
@@ -30,7 +30,6 @@ Item {
30 SurfaceContainer {
30 SurfaceContainer {
31 id: _surfaceContainer
31 id: _surfaceContainer
32 anchors.fill: parent
32 anchors.fill: parent
33− z: 2
34 surface: session ? session.surface : null
33 surface: session ? session.surface : null
35 }
34 }
36
35
@@ -53,7 +52,6 @@ Item {
53 delegate: Loader {
52 delegate: Loader {
54 objectName: "childDelegate" + index
53 objectName: "childDelegate" + index
55 anchors.fill: surfaceContainer
54 anchors.fill: surfaceContainer
56− z: 4
57
55
58 // Only way to do recursive qml items.
56 // Only way to do recursive qml items.
59 source: Qt.resolvedUrl("SessionContainer.qml")
57 source: Qt.resolvedUrl("SessionContainer.qml")
tests/mocks/Unity/Application/SessionManager.cpp−1
@@ -51,4 +51,3 @@ void SessionManager::registerSession(Session *session)
51 Q_EMIT sessionStopping(session);
51 Q_EMIT sessionStopping(session);
52 });
52 });
53}
53}
54−
tests/qmltests/Stages/RecursingChildSessionControl.qml+4−3
@@ -25,6 +25,7 @@ ColumnLayout {
25 property var session
25 property var session
26 property var childSessions: session ? session.childSessions : 0
26 property var childSessions: session ? session.childSessions : 0
27 property bool removable: false
27 property bool removable: false
28+ property alias surfaceCheckbox: _surfaceCheckbox
28
29
29 property var screenshotIds: [ "gallery", "map", "facebook", "camera", "browser", "music", "twitter"]
30 property var screenshotIds: [ "gallery", "map", "facebook", "camera", "browser", "music", "twitter"]
30
31
@@ -86,10 +87,10 @@ ColumnLayout {
86 Layout.fillWidth: true
87 Layout.fillWidth: true
87
88
88 CheckBox {
89 CheckBox {
89− id: surfaceCheckbox;
90+ id: _surfaceCheckbox;
90 checked: false;
91 checked: false;
91 enabled: root.session
92 enabled: root.session
92− onClicked: {
93+ onCheckedChanged: {
93 if (checked) {
94 if (checked) {
94 root.session.createSurface();
95 root.session.createSurface();
95 } else if (root.session.surface) {
96 } else if (root.session.surface) {
@@ -106,7 +107,7 @@ ColumnLayout {
106 }
107 }
107
108
108 Label {
109 Label {
109− text: "surface"
110+ text: "Surface"
110 anchors.verticalCenter: parent.verticalCenter
111 anchors.verticalCenter: parent.verticalCenter
111 }
112 }
112 }
113 }
tests/qmltests/Stages/tst_ApplicationWindow.qml+51−20
@@ -14,7 +14,8 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
15 */
16
16
17−import QtQuick 2.0
17+import QtQuick 2.1
18+import QtQuick.Layouts 1.1
18import QtTest 1.0
19import QtTest 1.0
19import Unity.Test 0.1 as UT
20import Unity.Test 0.1 as UT
20import ".."
21import ".."
@@ -40,7 +41,7 @@ Rectangle {
40 Connections {
41 Connections {
41 target: fakeApplication
42 target: fakeApplication
42 onSessionChanged: {
43 onSessionChanged: {
43− surfaceCheckbox.checked = fakeApplication.session !== null
44+ sessionCheckbox.checked = fakeApplication.session !== null
44 }
45 }
45 }
46 }
46
47
@@ -71,30 +72,51 @@ Rectangle {
71 right: parent.right
72 right: parent.right
72 }
73 }
73
74
74− Column {
75+ ColumnLayout {
75 anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
76 anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
76 spacing: units.gu(1)
77 spacing: units.gu(1)
77− Row {
78+
78− anchors { left: parent.left; right: parent.right }
79+ RowLayout {
80+ Layout.fillWidth: true
81+
79 CheckBox {
82 CheckBox {
80− id: surfaceCheckbox; checked: false
83+ id: sessionCheckbox; checked: false
81 onCheckedChanged: {
84 onCheckedChanged: {
82 if (applicationWindowLoader.status !== Loader.Ready)
85 if (applicationWindowLoader.status !== Loader.Ready)
83 return;
86 return;
84
87
85 if (checked && !fakeApplication.session) {
88 if (checked && !fakeApplication.session) {
86 fakeApplication.createSession();
89 fakeApplication.createSession();
87− fakeSession.createSurface();
88 } else if (!checked && fakeApplication.session) {
90 } else if (!checked && fakeApplication.session) {
89 fakeApplication.session.release();
91 fakeApplication.session.release();
90 }
92 }
91 }
93 }
92 }
94 }
93 Label {
95 Label {
94− text: "Surface"
96+ text: "Session"
95 anchors.verticalCenter: parent.verticalCenter
97 anchors.verticalCenter: parent.verticalCenter
96 }
98 }
97 }
99 }
100+
101+ Rectangle {
102+ border {
103+ color: "black"
104+ width: 1
105+ }
106+ anchors {
107+ left: parent.left
108+ right: parent.right
109+ }
110+ Layout.preferredHeight: sessionControl.height
111+
112+ RecursingChildSessionControl {
113+ id: sessionControl
114+ anchors { left: parent.left; right: parent.right; }
115+
116+ session: fakeSession
117+ }
118+ }
119+
98 ListItem.ItemSelector {
120 ListItem.ItemSelector {
99 id: appStateSelector
121 id: appStateSelector
100 anchors { left: parent.left; right: parent.right }
122 anchors { left: parent.left; right: parent.right }
@@ -119,6 +141,7 @@ Rectangle {
119 fakeApplication.setState(selectedApplicationState);
141 fakeApplication.setState(selectedApplicationState);
120 }
142 }
121 }
143 }
144+
122 }
145 }
123 }
146 }
124
147
@@ -175,6 +198,14 @@ Rectangle {
175 findInterestingApplicationWindowChildren();
198 findInterestingApplicationWindowChildren();
176 }
199 }
177
200
201+ function initSession() {
202+ sessionCheckbox.checked = true;
203+ sessionControl.surfaceCheckbox.checked = true;
204+ }
205+ function cleanupSession() {
206+ sessionCheckbox.checked = false;
207+ }
208+
178 function cleanup() {
209 function cleanup() {
179 forgetApplicationWindowChildren();
210 forgetApplicationWindowChildren();
180
211
@@ -182,7 +213,7 @@ Rectangle {
182 applicationWindowLoader.active = false;
213 applicationWindowLoader.active = false;
183
214
184 appStateSelector.selectedIndex = 0;
215 appStateSelector.selectedIndex = 0;
185− surfaceCheckbox.checked = false;
216+ cleanupSession();
186
217
187 if (fakeApplication.session)
218 if (fakeApplication.session)
188 fakeApplication.session.release();
219 fakeApplication.session.release();
@@ -202,7 +233,7 @@ Rectangle {
202 verify(stateGroup.state === "splashScreen");
233 verify(stateGroup.state === "splashScreen");
203
234
204 if (data.swapInitOrder) {
235 if (data.swapInitOrder) {
205− surfaceCheckbox.checked = true;
236+ initSession();
206 } else {
237 } else {
207 setApplicationState(appRunning);
238 setApplicationState(appRunning);
208 }
239 }
@@ -212,14 +243,14 @@ Rectangle {
212 if (data.swapInitOrder) {
243 if (data.swapInitOrder) {
213 setApplicationState(appRunning);
244 setApplicationState(appRunning);
214 } else {
245 } else {
215− surfaceCheckbox.checked = true;
246+ initSession();
216 }
247 }
217
248
218 tryCompare(stateGroup, "state", "surface");
249 tryCompare(stateGroup, "state", "surface");
219 }
250 }
220
251
221 function test_suspendedAppShowsSurface() {
252 function test_suspendedAppShowsSurface() {
222− surfaceCheckbox.checked = true;
253+ initSession();
223 setApplicationState(appRunning);
254 setApplicationState(appRunning);
224
255
225 tryCompare(stateGroup, "state", "surface");
256 tryCompare(stateGroup, "state", "surface");
@@ -233,7 +264,7 @@ Rectangle {
233 }
264 }
234
265
235 function test_killedAppShowsScreenshot() {
266 function test_killedAppShowsScreenshot() {
236− surfaceCheckbox.checked = true;
267+ initSession();
237 setApplicationState(appRunning);
268 setApplicationState(appRunning);
238 tryCompare(stateGroup, "state", "surface");
269 tryCompare(stateGroup, "state", "surface");
239
270
@@ -252,7 +283,7 @@ Rectangle {
252 function test_restartApp() {
283 function test_restartApp() {
253 var screenshotImage = findChild(applicationWindowLoader.item, "screenshotImage");
284 var screenshotImage = findChild(applicationWindowLoader.item, "screenshotImage");
254
285
255− surfaceCheckbox.checked = true;
286+ initSession();
256 setApplicationState(appRunning);
287 setApplicationState(appRunning);
257 tryCompare(stateGroup, "state", "surface");
288 tryCompare(stateGroup, "state", "surface");
258 waitUntilTransitionsEnd();
289 waitUntilTransitionsEnd();
@@ -278,14 +309,14 @@ Rectangle {
278 waitUntilTransitionsEnd();
309 waitUntilTransitionsEnd();
279 verify(stateGroup.state === "screenshot");
310 verify(stateGroup.state === "screenshot");
280
311
281− surfaceCheckbox.checked = true;
312+ initSession();
282
313
283 tryCompare(stateGroup, "state", "surface");
314 tryCompare(stateGroup, "state", "surface");
284 tryCompare(screenshotImage, "status", Image.Null);
315 tryCompare(screenshotImage, "status", Image.Null);
285 }
316 }
286
317
287 function test_appCrashed() {
318 function test_appCrashed() {
288− surfaceCheckbox.checked = true;
319+ initSession();
289 setApplicationState(appRunning);
320 setApplicationState(appRunning);
290 tryCompare(stateGroup, "state", "surface");
321 tryCompare(stateGroup, "state", "surface");
291 waitUntilTransitionsEnd();
322 waitUntilTransitionsEnd();
@@ -298,7 +329,7 @@ Rectangle {
298 }
329 }
299
330
300 function test_keepSurfaceWhileInvisible() {
331 function test_keepSurfaceWhileInvisible() {
301− surfaceCheckbox.checked = true;
332+ initSession();
302 setApplicationState(appRunning);
333 setApplicationState(appRunning);
303 tryCompare(stateGroup, "state", "surface");
334 tryCompare(stateGroup, "state", "surface");
304 waitUntilTransitionsEnd();
335 waitUntilTransitionsEnd();
@@ -319,7 +350,7 @@ Rectangle {
319
350
320 function test_touchesReachSurfaceWhenItsShown() {
351 function test_touchesReachSurfaceWhenItsShown() {
321 setApplicationState(appRunning);
352 setApplicationState(appRunning);
322− surfaceCheckbox.checked = true;
353+ initSession();
323
354
324 tryCompare(stateGroup, "state", "surface");
355 tryCompare(stateGroup, "state", "surface");
325
356
@@ -338,12 +369,12 @@ Rectangle {
338 }
369 }
339
370
340 function test_showNothingOnSuddenSurfaceLoss() {
371 function test_showNothingOnSuddenSurfaceLoss() {
341− surfaceCheckbox.checked = true;
372+ initSession();
342 setApplicationState(appRunning);
373 setApplicationState(appRunning);
343 tryCompare(stateGroup, "state", "surface");
374 tryCompare(stateGroup, "state", "surface");
344 waitUntilTransitionsEnd();
375 waitUntilTransitionsEnd();
345
376
346− surfaceCheckbox.checked = false;
377+ cleanupSession();
347
378
348 verify(stateGroup.state === "void");
379 verify(stateGroup.state === "void");
349 }
380 }
tests/qmltests/Stages/tst_SessionContainer.qml+1−1
@@ -103,7 +103,7 @@ Rectangle {
103 left: parent.left
103 left: parent.left
104 right: parent.right
104 right: parent.right
105 }
105 }
106− height: sessionChildrenControl.height
106+ Layout.preferredHeight: sessionChildrenControl.height
107
107
108 RecursingChildSessionControl {
108 RecursingChildSessionControl {
109 id: sessionChildrenControl
109 id: sessionChildrenControl