on xenial help sign in
Only visible if in front of maximized application
ee81e8dNick Dedekind
qml/Stages/DesktopStage.qml+39−9
@@ -67,7 +67,7 @@ Rectangle {
67 }
67 }
68 onApplicationRemoved: {
68 onApplicationRemoved: {
69 if (priv.foregroundMaximizedAppId === appId) {
69 if (priv.foregroundMaximizedAppId === appId) {
70− priv.foregroundMaximizedAppId = "";
70+ priv.foregroundMaximizedAppIdIndex = -1;
71 }
71 }
72 }
72 }
73
73
@@ -91,7 +91,17 @@ Rectangle {
91 var index = indexOf(focusedAppId);
91 var index = indexOf(focusedAppId);
92 return index >= 0 && index < appRepeater.count ? appRepeater.itemAt(index) : null
92 return index >= 0 && index < appRepeater.count ? appRepeater.itemAt(index) : null
93 }
93 }
94− property string foregroundMaximizedAppId: ""
94+ readonly property string foregroundMaximizedAppId: {
95+ if (foregroundMaximizedAppIdIndex == -1) {
96+ return "";
97+ }
98+ var app = ApplicationManager.get(foregroundMaximizedAppIdIndex);
99+ if (app) {
100+ return app.appId;
101+ }
102+ return "";
103+ }
104+ property int foregroundMaximizedAppIdIndex: -1
95
105
96 function indexOf(appId) {
106 function indexOf(appId) {
97 for (var i = 0; i < ApplicationManager.count; i++) {
107 for (var i = 0; i < ApplicationManager.count; i++) {
@@ -138,6 +148,7 @@ Rectangle {
138
148
139 delegate: FocusScope {
149 delegate: FocusScope {
140 id: appDelegate
150 id: appDelegate
151+ objectName: "stageDelegate_" + model.appId
141 z: ApplicationManager.count - index
152 z: ApplicationManager.count - index
142 y: units.gu(3)
153 y: units.gu(3)
143 width: units.gu(60)
154 width: units.gu(60)
@@ -159,18 +170,37 @@ Rectangle {
159 }
170 }
160 }
171 }
161
172
173+ onZChanged: updateMaximized()
174+ onVisuallyMaximizedChanged: updateMaximized()
175+ Connections {
176+ target: priv
177+ onForegroundMaximizedAppIdIndexChanged: updateMaximized()
178+ }
179+
180+ property bool connectMaxEnabled: true
181+ function updateMaximized() {
182+ if (!connectMaxEnabled) return;
183+ connectMaxEnabled = false;
184+
185+ // work out if this is the top maximized app.
162− readonly property bool foregroundMaximized: visuallyMaximized && index == 0
186+ if (visuallyMaximized) {
163− onForegroundMaximizedChanged: {
164− if (foregroundMaximized) {
165− priv.foregroundMaximizedAppId = model.appId;
187+ if (priv.foregroundMaximizedAppId === model.appId) {
188+ priv.foregroundMaximizedAppIdIndex = index;
189+ }
190+ else if (priv.foregroundMaximizedAppIdIndex == -1 ||
191+ (index >= 0 && index <= priv.foregroundMaximizedAppIdIndex)) {
192+ priv.foregroundMaximizedAppIdIndex = index;
193+ }
166 } else if (priv.foregroundMaximizedAppId === model.appId) {
194 } else if (priv.foregroundMaximizedAppId === model.appId) {
167− priv.foregroundMaximizedAppId = "";
195+ priv.foregroundMaximizedAppIdIndex = -1;
168 }
196 }
197+
198+ connectMaxEnabled = true;
169 }
199 }
170
200
171 visible: !visuallyMinimized &&
201 visible: !visuallyMinimized &&
172− (priv.foregroundMaximizedAppId === "" || priv.foregroundMaximizedAppId === model.appId)
202+ (priv.foregroundMaximizedAppIdIndex === -1 || priv.foregroundMaximizedAppIdIndex >= index) ||
173− || (spread.focus && index === spread.highlightedIndex)
203+ (spread.focus && index === spread.highlightedIndex)
174
204
175 Binding {
205 Binding {
176 target: ApplicationManager.get(index)
206 target: ApplicationManager.get(index)
tests/mocks/Unity/Application/MirSurface.cpp+4−4
@@ -130,14 +130,14 @@ void MirSurface::setOrientationAngle(Mir::OrientationAngle angle)
130void MirSurface::registerView(qintptr viewId)
130void MirSurface::registerView(qintptr viewId)
131{
131{
132 m_views.insert(viewId, MirSurface::View{false});
132 m_views.insert(viewId, MirSurface::View{false});
133− qDebug().nospace() << "MirSurface[" << name() << "]::registerView(" << viewId << ")"
133+// qDebug().nospace() << "MirSurface[" << name() << "]::registerView(" << viewId << ")"
134− << " after=" << m_views.count();
134+// << " after=" << m_views.count();
135}
135}
136
136
137void MirSurface::unregisterView(qintptr viewId)
137void MirSurface::unregisterView(qintptr viewId)
138{
138{
139− qDebug().nospace() << "MirSurface[" << name() << "]::unregisterView(" << viewId << ")"
139+// qDebug().nospace() << "MirSurface[" << name() << "]::unregisterView(" << viewId << ")"
140− << " after=" << m_views.count() << " live=" << m_live;
140+// << " after=" << m_views.count() << " live=" << m_live;
141 m_views.remove(viewId);
141 m_views.remove(viewId);
142 if (!m_live && m_views.count() == 0) {
142 if (!m_live && m_views.count() == 0) {
143 deleteLater();
143 deleteLater();
tests/qmltests/Stages/tst_DesktopStage.qml+72−5
@@ -35,12 +35,15 @@ Item {
35 value: false
35 value: false
36 }
36 }
37
37
38− Component.onCompleted: {
38+ Component.onCompleted: resetGeometry()
39+
40+ function resetGeometry() {
39 // ensures apps which are tested decorations are in view.
41 // ensures apps which are tested decorations are in view.
40 WindowStateStorage.geometry = {
42 WindowStateStorage.geometry = {
41 'unity8-dash': Qt.rect(0, units.gu(3), units.gu(50), units.gu(40)),
43 'unity8-dash': Qt.rect(0, units.gu(3), units.gu(50), units.gu(40)),
42 'dialer-app': Qt.rect(units.gu(51), units.gu(3), units.gu(50), units.gu(40)),
44 'dialer-app': Qt.rect(units.gu(51), units.gu(3), units.gu(50), units.gu(40)),
43 'camera-app': Qt.rect(0, units.gu(44), units.gu(50), units.gu(40)),
45 'camera-app': Qt.rect(0, units.gu(44), units.gu(50), units.gu(40)),
46+ 'gallery-app': Qt.rect(units.gu(51), units.gu(44), units.gu(50), units.gu(40))
44 }
47 }
45 }
48 }
46
49
@@ -110,14 +113,14 @@ Item {
110
113
111 desktopStageLoader.active = true;
114 desktopStageLoader.active = true;
112 tryCompare(desktopStageLoader, "status", Loader.Ready);
115 tryCompare(desktopStageLoader, "status", Loader.Ready);
116+ root.resetGeometry();
113 }
117 }
114
118
115 function killAllRunningApps() {
119 function killAllRunningApps() {
116− while (ApplicationManager.count > 1) {
120+ while (ApplicationManager.count > 0) {
117− var appIndex = ApplicationManager.get(0).appId == "unity8-dash" ? 1 : 0
118− ApplicationManager.stopApplication(ApplicationManager.get(appIndex).appId);
121+ ApplicationManager.stopApplication(ApplicationManager.get(0).appId);
119 }
122 }
120− compare(ApplicationManager.count, 1)
123+ compare(ApplicationManager.count, 0)
121 }
124 }
122
125
123 function waitUntilAppSurfaceShowsUp(appId) {
126 function waitUntilAppSurfaceShowsUp(appId) {
@@ -210,5 +213,69 @@ Item {
210 tap(toAppDecoration);
213 tap(toAppDecoration);
211 tryCompare(ApplicationManager.findApplication(data.apps[data.focusTo]).session.surface, "activeFocus", true);
214 tryCompare(ApplicationManager.findApplication(data.apps[data.focusTo]).session.surface, "activeFocus", true);
212 }
215 }
216+
217+ function test_minimizeApplicationHidesSurface(data) {
218+ var dashApp = startApplication("unity8-dash");
219+
220+ var dashDelegate = findChild(desktopStage, "stageDelegate_unity8-dash");
221+ verify(dashDelegate);
222+
223+ dashDelegate.minimize();
224+ tryCompare(dashApp.session.surface, "visible", false);
225+ }
226+
227+ function test_maximizeApplicationHidesSurfacesBehindIt(data) {
228+ var dashApp = startApplication("unity8-dash");
229+ var dialerApp = startApplication("dialer-app");
230+ var cameraApp = startApplication("camera-app");
231+
232+ var dashDelegate = findChild(desktopStage, "stageDelegate_unity8-dash");
233+ verify(dashDelegate);
234+ var dialerDelegate = findChild(desktopStage, "stageDelegate_dialer-app");
235+ verify(dialerDelegate);
236+ var cameraDelegate = findChild(desktopStage, "stageDelegate_camera-app");
237+ verify(cameraDelegate);
238+
239+ dialerDelegate.maximize();
240+ tryCompare(dialerDelegate, "visuallyMaximized", true);
241+
242+ tryCompare(dashApp.session.surface, "visible", false);
243+ compare(cameraApp.session.surface.visible, true);
244+
245+ dialerDelegate.unmaximize();
246+ compare(dashApp.session.surface.visible, true);
247+ compare(cameraApp.session.surface.visible, true);
248+ }
249+
250+ function test_applicationsBecomeVisibleWhenOccludingAppRemoved(data) {
251+ var dashApp = startApplication("unity8-dash");
252+ var dialerApp = startApplication("dialer-app");
253+ var cameraApp = startApplication("camera-app");
254+ var galleryApp = startApplication("gallery-app");
255+
256+ var dashDelegate = findChild(desktopStage, "stageDelegate_unity8-dash");
257+ verify(dashDelegate);
258+ var dialerDelegate = findChild(desktopStage, "stageDelegate_dialer-app");
259+ verify(dialerDelegate);
260+ var cameraDelegate = findChild(desktopStage, "stageDelegate_camera-app");
261+ verify(cameraDelegate);
262+ var galleryDelegate = findChild(desktopStage, "stageDelegate_gallery-app");
263+ verify(galleryDelegate);
264+
265+ dialerDelegate.maximize();
266+ galleryDelegate.maximize();
267+ tryCompare(dialerDelegate, "visuallyMaximized", true);
268+ tryCompare(galleryDelegate, "visuallyMaximized", true);
269+
270+ tryCompare(dashApp.session.surface, "visible", false);
271+ tryCompare(dialerApp.session.surface, "visible", false);
272+ tryCompare(cameraApp.session.surface, "visible", false);
273+
274+ ApplicationManager.stopApplication("gallery-app");
275+
276+ compare(cameraApp.session.surface.visible, true);
277+ tryCompare(dialerApp.session.surface, "visible", true);
278+ tryCompare(dashApp.session.surface, "visible", false); // still occluded by maximised dialer
279+ }
213 }
280 }
214}
281}