@@ -0,0 +1,201 @@
2+ * Copyright 2014-2016 Canonical Ltd.
3+ * Copyright 2019 UBports Foundation
5+ * This program is free software; you can redistribute it and/or modify
6+ * it under the terms of the GNU General Public License as published by
7+ * the Free Software Foundation; version 3.
9+ * This program is distributed in the hope that it will be useful,
10+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+ * GNU General Public License for more details.
14+ * You should have received a copy of the GNU General Public License
15+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
20+import Unity.Test 0.1 as UT
22+import "../../../qml/Components"
23+import "../../../qml/Stage"
24+import Ubuntu.Components 1.3
25+import Unity.Application 0.1
26+import WindowManager 1.0
33+ property var greeter: { fullyShown: true }
35+ SurfaceManager { id: sMgr }
36+ ApplicationMenuDataLoader {
45+ sourceComponent: Stage {
47+ anchors { fill: parent; rightMargin: units.gu(30) }
49+ dragAreaWidth: units.gu(2)
50+ allowInteractivity: true
51+ shellOrientation: Qt.PortraitOrientation
52+ orientations: Orientations {}
53+ applicationManager: ApplicationManager
55+ topLevelSurfaceList: TopLevelWindowModel {
56+ id: topLevelWindowModel
57+ applicationManager: ApplicationManager
60+ availableDesktopArea: availableDesktopAreaItem
62+ id: availableDesktopAreaItem
69+ contentHeight: controlRect.height
71+ anchors.top: root.top
72+ anchors.bottom: root.bottom
73+ anchors.right: root.right
77+ anchors { left: parent.left; right: parent.right }
78+ height: childrenRect.height + units.gu(2)
81+ anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
84+ model: ApplicationManager.availableApplications
85+ ApplicationCheckBox { appId: modelData }
91+ property alias stage: loader.item
92+ property var tlwm: loader.item.topLevelSurfaceList
100+ loader.active = true;
101+ tryCompare(loader, "status", Loader.Ready);
104+ waitForRendering(stage);
107+ function cleanup() {
109+ loader.active = false;
112+ function findAppWindowForSurfaceId(surfaceId) {
113+ var delegateObjectName = "appDelegate_" + surfaceId;
114+ var spreadDelegate = findChild(stage, delegateObjectName);
115+ if (!spreadDelegate) {
116+ console.warn("Failed to find " + delegateObjectName + " in stage");
119+ var appWindow = findChild(spreadDelegate, "appWindow");
123+ // Waits until ApplicationWindow has moved from showing a splash screen to displaying
124+ // the application surface.
125+ function waitUntilAppSurfaceShowsUp(surfaceId) {
126+ var appWindow = findAppWindowForSurfaceId(surfaceId);
128+ var appWindowStates = findInvisibleChild(appWindow, "applicationWindowStateGroup");
129+ verify(appWindowStates);
130+ tryCompare(appWindowStates, "state", "surface");
133+ function addApps(count) {
134+ if (count == undefined) count = 1;
135+ for (var i = 0; i < count; i++) {
136+ var startingAppId = ApplicationManager.availableApplications[ApplicationManager.count];
137+ var appSurfaceId = tlwm.nextId;
138+ var app = ApplicationManager.startApplication(startingAppId)
139+ tryCompare(app, "state", ApplicationInfoInterface.Running)
140+ waitUntilAppSurfaceShowsUp(appSurfaceId);
141+ waitForRendering(stage)
142+ tryCompare(ApplicationManager, "focusedApplicationId", startingAppId)
147+ Ensure that closing a surface while rootFocus is off focuses the
148+ next available surface when rootFocus is given back.
150+ Regression test for https://github.com/ubports/unity8/issues/234
152+ This cannot be tested in tst_TopLevelWindowModel.cpp, the mocks for
153+ it are not advanced enough.
155+ function test_closeLastFocusedApp()
157+ var dialerApp = ApplicationManager.startApplication("dialer-app");
158+ var webbrowserSurfaceId = tlwm.nextId;
159+ var webbrowserApp = ApplicationManager.startApplication("morph-browser");
160+ waitUntilAppSurfaceShowsUp(webbrowserSurfaceId);
162+ tlwm.rootFocus = false;
164+ ApplicationManager.stopApplication(webbrowserApp.appId);
165+ // It should be gone soon
166+ tryCompareFunction(function() { return tlwm.indexForId(webbrowserSurfaceId); }, -1);
168+ tlwm.rootFocus = true;
169+ compare(dialerApp.focused, true);
173+ Ensure that we can handle issuing windows up to maxWindowId,
174+ including reusing IDs once we're exhausted.
176+ function test_issueAllTheIds()
178+ tlwm.maxWindowId = 5;
180+ // Start an app ourselves so we can close it
181+ var nextAppId = ApplicationManager.availableApplications[5];
182+ var app = ApplicationManager.startApplication(nextAppId);
183+ var appWindowId = tlwm.idAt(0);
185+ // Add four more apps to bring us to five
188+ ApplicationManager.stopApplication(app.appId);
189+ // It should be gone soon
190+ tryCompareFunction(function() { return tlwm.indexForId(appWindowId); }, -1);
192+ // And now we can start a new one
193+ var appAgain = ApplicationManager.startApplication(nextAppId);
196+ // The new app should have taken the ID of the closed app since
197+ // we're under contention.
198+ tryCompareFunction(function() { return tlwm.indexForId(appWindowId); }, 0);