2
* Copyright 2013 Canonical Ltd.
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; version 3.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
20
import "../../../Components"
21
import Ubuntu.Application 0.1
22
import Ubuntu.Components 0.1
23
import Unity.Test 0.1 as UT
28
height: stageRect.height
30
// Even though we replace the ApplicationScreenshot instances in Stage
31
// with our own fake ones, ApplicationScreenshot.qml still gives out a warning
32
// if shell.importUbuntuApplicationAvailable is missing.
33
// For we have this here for the sake of keeping a clean log output.
36
property bool importUbuntuApplicationAvailable: false
39
// A fake ApplicationManager implementation to be passed to Stage
42
property ListModel mainStageApplications: ListModel {}
43
property ListModel sideStageApplications: ListModel {}
44
property var mainStageFocusedApplication
46
property Component fakeAppWindowComponent: Component {
50
property alias text : txt.text
55
function activateApplication(desktopFile, argument) {
56
var appWindow = fakeAppWindowComponent.createObject(fakeWindowContainer)
59
'handle': desktopFile,
62
'desktopFile': desktopFile,
63
'stage': ApplicationInfo.MainStage,
68
appWindow.color = application.color
69
appWindow.text = desktopFile + " actual";
71
mainStageApplications.append(application)
72
updateZOrderOfWindows(mainStageApplications)
77
function focusApplication(application) {
78
mainStageFocusedApplication = application
81
function getApplicationFromDesktopFile(desktopFile, stageType) {
82
var sideStage = (stage == ApplicationInfo.SideStage);
83
var applications = sideStage ? sideStageApplications
84
: mainStageApplications;
86
for (var i = 0; i < applications.count; i++ ) {
87
var application = applications.get(i);
88
if (application.desktopFile === desktopFile) {
95
function moveRunningApplicationStackPosition(from, to, stage) {
96
var sideStage = (stage == ApplicationInfo.SideStage);
97
var applications = sideStage ? sideStageApplications
98
: mainStageApplications;
100
if (from !== to && applications.count > 0 && from >= 0 && to >= 0) {
101
applications.move(from, to, 1);
104
updateZOrderOfWindows(applications)
107
function updateZOrderOfWindows(applications) {
109
for (var i = 0; i < applications.count; i++ ) {
110
var application = applications.get(i);
111
application.window.z = nextZ--;
115
function deacticateApplication(desktopFile) {
116
for (var i = 0; i < mainStageApplications.count; i++ ) {
117
var application = mainStageApplications.get(i)
118
if (application.desktopFile === desktopFile) {
119
focusApplication(null)
120
application.window.destroy();
121
mainStageApplications.remove(i)
122
updateZOrderOfWindows(mainStageApplications)
133
width: childrenRect.width
134
height: childrenRect.height
138
// This is where the fake windows are held.
139
// They stay behind the stage, so that the stage's screenshots are shown
141
// On a real usage scenario, the current application's surface is composited behind
142
// the shell's surface (where Stage lives). fakeWindowContainer simulates this stacking
144
id: fakeWindowContainer
149
// A black rectangle behind the stage so that the window switch animations
150
// look good, just like in Stage's real usage.
154
visible: stage.usingScreenshots
160
shouldUseScreenshots: false
161
applicationManager: fakeAppManager
162
rightEdgeDraggingAreaWidth: units.gu(2)
164
newApplicationScreenshot: FakeApplicationScreenshot {
168
height: stage.height - stage.y}
169
oldApplicationScreenshot: FakeApplicationScreenshot {
173
height: stage.height - stage.y}
179
anchors.top: parent.top
180
anchors.bottom: parent.bottom
181
anchors.left: stageRect.right
182
anchors.right: parent.right
188
AppControl {id: redControl; desktopFile:"red"}
189
AppControl {id: greenControl; desktopFile:"green"}
190
AppControl {id: blueControl; desktopFile:"blue"}
198
/* If you press Stage's right edge it should show the hint that it's possible to
199
switch to the next running application. This means (graphically) sliding the
200
next application window from Stage's right edge for a small part of its width */
201
function test_pressingRightEdgeShowsHint() {
202
redControl.checked = true
204
tryCompare(stage, "usingScreenshots", true) // wait for the animation to start
205
tryCompare(stage, "usingScreenshots", false) // and then for it to end
206
compare(fakeAppManager.mainStageFocusedApplication.desktopFile, "red")
207
compare(fakeAppManager.mainStageApplications.get(0).desktopFile, "red")
209
greenControl.checked = true
211
tryCompare(stage, "usingScreenshots", true) // wait for the animation to start
212
tryCompare(stage, "usingScreenshots", false) // and then for it to end
213
compare(fakeAppManager.mainStageFocusedApplication.desktopFile, "green")
214
compare(fakeAppManager.mainStageApplications.get(0).desktopFile, "green")
216
var draggingAreaCenterX = stage.width - (stage.rightEdgeDraggingAreaWidth / 2)
217
var draggingAreaCenterY = stage.height / 2
218
touchPress(stage, draggingAreaCenterX, draggingAreaCenterY)
220
// wait for the animation to start
221
tryCompare(stage, "usingScreenshots", true)
223
// "red" should be the new/next application being shown
224
compare(newAppScreenshot.application.desktopFile, "red")
225
tryCompareFunction(isShowingABitOfNewApp, true);
227
// "green" should be the current application being shown
228
compare(oldAppScreenshot.application.desktopFile, "green")
229
tryCompareFunction(isCurrentAppFadingOut, true);
231
touchRelease(stage, draggingAreaCenterX, draggingAreaCenterY)
234
function isShowingABitOfNewApp() {
235
// it should come from the right and take less than half of the screen
236
// but at least 5% of it
237
return newAppScreenshot.x > stage.width/2
238
&& newAppScreenshot.x < stage.width*(95/100)
239
&& newAppScreenshot.y === 0
240
&& newAppScreenshot.visible
243
function isCurrentAppFadingOut() {
244
// it should get a bit translucent and smaller
245
return oldAppScreenshot.opacity < 0.99
246
&& oldAppScreenshot.opacity >= 0.1
247
&& oldAppScreenshot.scale < 0.99
248
&& oldAppScreenshot.scale >= 0.1
249
&& oldAppScreenshot.visible
253
redControl.checked = false;
254
greenControl.checked = false;
255
blueControl.checked = false;
256
// give some room for animations to start
258
// wait until animations end, if any
259
tryCompare(stage, "usingScreenshots", false)
262
/* If you flick from the right edge of the stage leftwards it should cause an
263
application switch. */
264
function test_dragFromRightEdgeToSwitchApplication() {
265
redControl.checked = true
267
tryCompare(stage, "usingScreenshots", true) // wait for the animation to start
268
tryCompare(stage, "usingScreenshots", false) // and then for it to end
269
compare(fakeAppManager.mainStageFocusedApplication.desktopFile, "red")
270
compare(fakeAppManager.mainStageApplications.get(0).desktopFile, "red")
272
greenControl.checked = true
274
tryCompare(stage, "usingScreenshots", true) // wait for the animation to start
275
tryCompare(stage, "usingScreenshots", false) // and then for it to end
276
compare(fakeAppManager.mainStageFocusedApplication.desktopFile, "green")
277
compare(fakeAppManager.mainStageApplications.get(0).desktopFile, "green")
279
var touchX = stage.width - (stage.rightEdgeDraggingAreaWidth / 2)
280
var touchY = stage.height / 2
281
touchFlick(stage, touchX, touchY,
282
touchX - units.gu(5), touchY)
284
// wait until animations end, if any
285
tryCompare(stage, "usingScreenshots", false)
287
// "red" should be the new topmost, focused, application
288
compare(fakeAppManager.mainStageFocusedApplication.desktopFile, "red")
289
compare(fakeAppManager.mainStageApplications.get(0).desktopFile, "red")
292
/* When an application is launched, it needs a background before it's drawn on screen
293
so that the user does not see the previous running app while the new one is launching.
294
When switching between applications, backgrounds are unnecessary, 'cause the
295
applications are in front of them. */
296
function test_background() {
297
redControl.checked = true
298
tryCompare(stage, "usingScreenshots", true) // wait for the animation to start
300
compare(newAppScreenshot.withBackground, true, "starting app screenshot does not have background enabled")
302
tryCompare(stage, "usingScreenshots", false) // wait for the animation to finish
304
greenControl.checked = true
305
tryCompare(stage, "usingScreenshots", true) // wait for the animation to start
306
tryCompare(stage, "usingScreenshots", false) // and finish
308
var draggingAreaCenterX = stage.width - (stage.rightEdgeDraggingAreaWidth / 2)
309
var draggingAreaCenterY = stage.height / 2
310
touchPress(stage, draggingAreaCenterX, draggingAreaCenterY)
312
// wait for the animation to start
313
tryCompare(stage, "usingScreenshots", true)
315
compare(newAppScreenshot.withBackground, false, "switched app does have background enabled")
317
tryCompareFunction(isShowingABitOfNewApp, true); // wait for the hint animation to finish
318
touchRelease(stage, draggingAreaCenterX, draggingAreaCenterY)