2 * Copyright (C) 2013-2016 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/>.
19import AccountsService 0.1
21import LightDMController 0.1
22import LightDM.FullLightDM 0.1 as LightDM
23import SessionBroadcast 0.1
24import Ubuntu.Components 1.3
25import Ubuntu.Components.ListItems 1.3 as ListItem
26import Ubuntu.Telephony 0.1 as Telephony
27import Unity.Application 0.1
28import Unity.ApplicationMenu 0.1
29import Unity.Connectivity 0.1
30import Unity.Indicators 0.1
31import Unity.Notifications 1.0
32import Unity.Launcher 0.1
35import Wizard 0.1 as Wizard
37import Unity.Indicators 0.1 as Indicators
40import "../../qml/Components"
41import "../../qml/Components/PanelState"
47 width: units.gu(100) + controls.width
50 Component.onCompleted: {
51 // must set the mock mode before loading the Shell
52 LightDMController.userMode = "single";
53 shellLoader.active = true;
56 ApplicationMenuDataLoader {
60 property var shell: shellLoader.item ? shellLoader.item : null
63 topLevelSurfaceList = testCase.findInvisibleChild(shell, "topLevelSurfaceList");
64 appMenuData.surfaceManager = testCase.findInvisibleChild(shell, "surfaceManager");
66 topLevelSurfaceList = null;
67 appMenuData.surfaceManager = null;
71 property var topLevelSurfaceList: null
75 anchors.left: root.left
76 anchors.right: controls.left
78 anchors.bottom: root.bottom
83 anchors.centerIn: parent
85 property int shellOrientation: Qt.PortraitOrientation
86 property int nativeOrientation: Qt.PortraitOrientation
87 property int primaryOrientation: Qt.PortraitOrientation
88 property string mode: "full-greeter"
106 shellOrientation: Qt.LandscapeOrientation
107 nativeOrientation: Qt.LandscapeOrientation
108 primaryOrientation: Qt.LandscapeOrientation
115 width: shellContainer.width
116 height: shellContainer.height
119 target: mouseEmulation
126 property bool itemDestroyed: false
127 sourceComponent: Component {
131 usageScenario: usageScenarioSelector.model[usageScenarioSelector.selectedIndex]
134 orientation: shellLoader.shellOrientation
135 orientations: Orientations {
136 native_: shellLoader.nativeOrientation
137 primary: shellLoader.primaryOrientation
139 mode: shellLoader.mode
141 Component.onDestruction: {
142 shellLoader.itemDestroyed = true;
151 contentHeight: controlRect.height
153 anchors.top: root.top
154 anchors.bottom: root.bottom
155 anchors.right: root.right
160 anchors { left: parent.left; right: parent.right }
162 height: childrenRect.height + units.gu(2)
165 anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
170 anchors { left: parent.left; right: parent.right }
174 activeFocusOnPress: false
176 if (shellLoader.status !== Loader.Ready)
179 var greeter = testCase.findChild(shellLoader.item, "greeter");
180 if (!greeter.shown) {
181 LightDM.Greeter.showGreeter();
187 activeFocusOnPress: false
189 if (shellLoader.status !== Loader.Ready)
192 var greeter = testCase.findChild(shellLoader.item, "greeter");
199 text: callManager.foregroundCall ? "Hide Call" : "Show Call"
200 activeFocusOnPress: false
202 if (shellLoader.status !== Loader.Ready)
205 callManager.foregroundCall = callManager.foregroundCall ? null : phoneCall;
209 text: "Show Launcher"
210 activeFocusOnPress: false
212 if (shellLoader.status !== Loader.Ready)
215 var launcher = testCase.findChild(shellLoader.item, "launcher");
216 launcher.state = "visible";
220 text: "Print focused"
221 activeFocusOnPress: false
223 var childs = new Array(0);
224 childs.push(shellLoader.item)
225 while (childs.length > 0) {
226 if (childs[0].activeFocus && childs[0].focus && childs[0].objectName != "shell") {
227 console.log("Active focus is on item:", childs[0]);
230 for (var i in childs[0].children) {
231 childs.push(childs[0].children[i])
235 console.log("No active focused item found within shell.")
240 text: "LightDM mock mode"
243 ListItem.ItemSelector {
244 anchors { left: parent.left; right: parent.right }
245 activeFocusOnPress: false
246 model: ["single", "single-passphrase", "single-pin", "full"]
247 onSelectedIndexChanged: {
249 LightDMController.userMode = model[selectedIndex];
250 shellLoader.active = true;
257 ListItem.ItemSelector {
259 anchors { left: parent.left; right: parent.right }
260 activeFocusOnPress: false
261 model: ["phone", "tablet", "desktop"]
262 onSelectedIndexChanged: {
263 shellLoader.state = model[selectedIndex];
267 text: "Usage scenario"
270 ListItem.ItemSelector {
271 id: usageScenarioSelector
272 anchors { left: parent.left; right: parent.right }
273 activeFocusOnPress: false
274 model: ["phone", "tablet", "desktop"]
276 MouseTouchEmulationCheckbox {
284 ListItem.ItemSelector {
286 anchors { left: parent.left; right: parent.right }
287 activeFocusOnPress: false
288 model: ["Ctrl", "Alt", "Super"]
289 onSelectedIndexChanged: {
290 var keyMapper = testCase.findChild(shellContainer, "physicalKeysMapper");
291 keyMapper.controlInsteadOfAlt = selectedIndex == 1;
292 keyMapper.controlInsteadOfSuper = selectedIndex == 2;
297 anchors { left: parent.left; right: parent.right }
299 id: autohideLauncherCheckbox
301 GSettingsController.setAutohideLauncher(checked)
305 text: "Autohide launcher"
309 Label { text: "Applications"; font.bold: true }
312 text: "Start all apps"
314 activeFocusOnPress: false
316 for (var i = 0; i < ApplicationManager.availableApplications.length; i++) {
317 var appId = ApplicationManager.availableApplications[i];
318 ApplicationManager.startApplication(appId)
324 id: appCheckBoxRepeater
325 model: ApplicationManager.availableApplications
326 ApplicationCheckBox {
331 Label { text: "Focused Application"; font.bold: true }
335 id: fullscreenAppCheck
336 activeFocusOnPress: false
337 activeFocusOnTab: false
340 if (!topLevelSurfaceList.focusedWindow) return;
341 if (topLevelSurfaceList.focusedWindow.state == Mir.FullscreenState) {
342 topLevelSurfaceList.focusedWindow.requestState(Mir.RestoredState);
344 topLevelSurfaceList.focusedWindow.requestState(Mir.FullscreenState);
349 target: fullscreenAppCheck
350 when: topLevelSurfaceList && topLevelSurfaceList.focusedWindow
352 value: topLevelSurfaceList.focusedWindow.state === Mir.FullscreenState
363 activeFocusOnPress: false
364 activeFocusOnTab: false
367 if (!topLevelSurfaceList.focusedWindow || !topLevelSurfaceList.focusedWindow.surface) return;
368 var surface = topLevelSurfaceList.focusedWindow.surface;
369 if (surface.shellChrome == Mir.LowChrome) {
370 surface.setShellChrome(Mir.NormalChrome);
372 surface.setShellChrome(Mir.LowChrome);
377 target: chromeAppCheck
378 when: topLevelSurfaceList && topLevelSurfaceList.focusedWindow !== null && topLevelSurfaceList.focusedWindow.surface !== null
380 value: topLevelSurfaceList.focusedWindow.surface &&
381 topLevelSurfaceList.focusedWindow.surface.shellChrome === Mir.LowChrome
390 text: "Toggle input method"
392 activeFocusOnPress: false
394 testCase.ensureInputMethodSurface();
395 var inputMethod = root.topLevelSurfaceList.inputMethodSurface;
396 if (inputMethod.visible) {
397 inputMethod.requestState(Mir.HiddenState);
399 inputMethod.requestState(Mir.RestoredState);
407 ListItem.ItemSelector {
408 id: shellModeSelector
409 anchors { left: parent.left; right: parent.right }
410 activeFocusOnPress: false
411 model: ["full-greeter", "greeter", "shell"]
412 property bool guard: false
413 onSelectedIndexChanged: {
417 shellLoader.mode = model[selectedIndex];
418 shellLoader.active = true;
424 if (shellModeSelector.guard) {
427 shellModeSelector.guard = true;
428 for (var i = 0; i < 3; i++) {
429 if (shellModeSelector.model[i] === shellLoader.mode) {
430 shellModeSelector.selectedIndex = i;
434 shellModeSelector.guard = false;
447 var biometryd = testCase.findInvisibleChild(shellContainer, "biometryd");
449 for (var i = 0; i < LightDM.Users.count; i++) {
450 if (LightDM.Users.data(i, LightDM.UserRoles.NameRole) == AccountsService.user) {
451 uid = LightDM.Users.data(i, LightDM.UserRoles.UidRole);
455 biometryd.operation.mockSuccess(uid);
462 var biometryd = testCase.findInvisibleChild(shellContainer, "biometryd");
463 biometryd.operation.mockFailure("error");
475 function invokeAction(actionId) {
476 mockNotificationsModel.actionInvoked(actionId)
481 id: mockNotificationsModel
483 signal actionInvoked(string actionId)
485 function getRaw(id) {
486 return mockNotification.createObject(mockNotificationsModel)
490 if(actionId == "ok_id") {
491 mockNotificationsModel.clear()
497 id: launcherShowDashHomeSpy
498 signalName: "showDashHome"
503 signalName: "sessionStarted"
507 id: dashCommunicatorSpy
508 signalName: "setCurrentScopeCalled"
513 target: SessionBroadcast
514 signalName: "startUrl"
519 target: SessionBroadcast
520 signalName: "showHome"
524 id: unlockAllModemsSpy
526 signalName: "unlockingAllModems"
530 id: notificationActionSpy
531 target: mockNotificationsModel
532 signalName: "actionInvoked"
535 Telephony.CallEntry {
537 phoneNumber: "+447812221111"
542 property bool running: false
559 property Item shell: shellLoader.status === Loader.Ready ? shellLoader.item : null
562 if (shellLoader.active) {
563 // happens for the very first test function as shell
564 // is loaded by default
570 waitForRendering(shell);
571 mouseEmulation.checked = true;
572 tryCompare(shell, "waitingOnGreeter", false); // make sure greeter didn't leave us in disabled state
574 WindowStateStorage.clear();
577 function loadShell(formFactor) {
578 shellLoader.state = formFactor;
579 shellLoader.active = true;
580 tryCompare(shellLoader, "status", Loader.Ready);
581 removeTimeConstraintsFromSwipeAreas(shellLoader.item);
582 tryCompare(shell, "waitingOnGreeter", false); // reset by greeter when ready
584 sessionSpy.target = findChild(shell, "greeter")
585 dashCommunicatorSpy.target = findInvisibleChild(shell, "dashCommunicator");
587 var launcher = findChild(shell, "launcher");
588 launcherShowDashHomeSpy.target = launcher;
590 var panel = findChild(launcher, "launcherPanel");
593 panel.dismissTimer = fakeDismissTimer;
595 waitForGreeterToStabilize();
597 // from StageTestCase
598 topLevelSurfaceList = findInvisibleChild(shell, "topLevelSurfaceList");
599 verify(topLevelSurfaceList);
600 stage = findChild(shell, "stage");
603 function loadDesktopShellWithApps() {
604 loadShell("desktop");
605 waitForRendering(shell)
606 shell.usageScenario = "desktop"
607 waitForRendering(shell)
608 var app0 = ApplicationManager.startApplication("unity8-dash")
609 var app1 = ApplicationManager.startApplication("dialer-app")
610 var app2 = ApplicationManager.startApplication("webbrowser-app")
611 var app3 = ApplicationManager.startApplication("camera-app")
612 var app4 = ApplicationManager.startApplication("facebook-webapp")
613 var app5 = ApplicationManager.startApplication("camera-app")
614 var app6 = ApplicationManager.startApplication("gallery-app")
615 var app7 = ApplicationManager.startApplication("calendar-app")
616 for (var i = 0; i < topLevelSurfaceList.count; ++i) {
617 waitUntilAppWindowIsFullyLoaded(topLevelSurfaceList.idAt(i));
621 function waitForGreeterToStabilize() {
622 var greeter = findChild(shell, "greeter");
625 var loginList = findChild(greeter, "loginList", 0 /* timeout */);
626 // Only present in WideView
628 var userList = findChild(loginList, "userList");
630 tryCompare(userList, "movingInternally", false);
634 function tearDown() {
635 launcherShowDashHomeSpy.target = null;
637 shellLoader.itemDestroyed = false;
639 shellLoader.active = false;
641 tryCompare(shellLoader, "status", Loader.Null);
642 tryCompare(shellLoader, "item", null);
643 // Loader.status might be Loader.Null and Loader.item might be null but the Loader
644 // item might still be alive. So if we set Loader.active back to true
645 // again right now we will get the very same Shell instance back. So no reload
646 // actually took place. Likely because Loader waits until the next event loop
647 // iteration to do its work. So to ensure the reload, we will wait until the
648 // Shell instance gets destroyed.
649 tryCompare(shellLoader, "itemDestroyed", true);
651 LightDMController.reset();
652 setLightDMMockMode("single"); // these tests default to "single"
654 AccountsService.demoEdges = false;
655 AccountsService.demoEdgesCompleted = [];
656 AccountsService.backgroundFile = "";
657 Wizard.System.wizardEnabled = false;
658 shellLoader.mode = "full-greeter";
660 // kill all (fake) running apps
663 unlockAllModemsSpy.clear()
664 LightDM.Greeter.authenticate(""); // reset greeter
667 broadcastUrlSpy.clear();
668 broadcastHomeSpy.clear();
670 GSettingsController.setLifecycleExemptAppids([]);
671 GSettingsController.setPictureUri("");
674 function ensureInputMethodSurface() {
675 var surfaceManager = findInvisibleChild(shell, "surfaceManager");
676 verify(surfaceManager);
677 surfaceManager.createInputMethodSurface();
679 tryCompareFunction(function() { return root.topLevelSurfaceList.inputMethodSurface !== null }, true);
682 function test_snapDecisionDismissalReturnsFocus() {
685 var notifications = findChild(shell, "notificationList");
686 var appDelegate = startApplication("camera-app");
688 var appSurface = appDelegate.surface;
691 tryCompare(appSurface, "activeFocus", true);
693 notifications.model = mockNotificationsModel;
695 // FIXME: Hack: UnitySortFilterProxyModelQML doesn't work with QML ListModels which we use
696 // for mocking here (RoleType can't be found in the QML model). As we only need to show
697 // one SnapDecision lets just disable the filtering and make appear any notification as a
699 var snapDecisionProxyModel = findInvisibleChild(shell, "snapDecisionProxyModel");
700 snapDecisionProxyModel.filterRegExp = RegExp("");
702 // Pop-up a notification
703 addSnapDecisionNotification();
704 waitForRendering(shell);
706 // Make sure the notification really opened
707 var notification = findChild(notifications, "notification" + (mockNotificationsModel.count - 1));
708 verify(notification !== undefined && notification != null, "notification wasn't found");
709 tryCompare(notification, "height", notification.implicitHeight)
710 waitForRendering(notification);
712 // Make sure activeFocus went away from the app window
713 tryCompare(appSurface, "activeFocus", false);
714 tryCompare(stage, "interactive", false);
716 // Clicking the button should dismiss the notification and return focus
717 var buttonAccept = findChild(notification, "notify_button0");
718 mouseClick(buttonAccept);
720 // Make sure we're back to normal
721 tryCompare(appSurface, "activeFocus", true);
722 compare(stage.interactive, true, "Stages not interactive again after modal notification has closed");
725 function addSnapDecisionNotification() {
727 type: Notification.SnapDecision,
728 hints: {"x-canonical-private-affirmative-tint": "true"},
730 body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
731 icon: Qt.resolvedUrl("../graphics/avatars/funky.png"),
732 secondaryIcon: Qt.resolvedUrl("../graphics/applicationIcons/facebook.png"),
733 actions: [{ id: "ok_id", label: "Ok"},
734 { id: "cancel_id", label: "Cancel"},
735 { id: "notreally_id", label: "Not really"},
736 { id: "noway_id", label: "messages:No way"},
737 { id: "nada_id", label: "messages:Nada"}]
740 mockNotificationsModel.append(n)
743 function test_suspend() {
746 var greeter = findChild(shell, "greeter");
748 // Launch an app from the launcher
749 dragLauncherIntoView();
750 var appSurfaceId = topLevelSurfaceList.nextId;
751 tapOnAppIconInLauncher();
752 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
754 var mainAppId = ApplicationManager.focusedApplicationId;
755 verify(mainAppId != "");
756 var mainApp = ApplicationManager.findApplication(mainAppId);
758 tryCompare(mainApp, "requestedState", ApplicationInfoInterface.RequestedRunning);
760 // Display off while call is active...
761 callManager.foregroundCall = phoneCall;
762 Powerd.setStatus(Powerd.Off, Powerd.Unknown);
763 tryCompare(greeter, "shown", false);
765 // Now try again after ending call
766 callManager.foregroundCall = null;
767 Powerd.setStatus(Powerd.On, Powerd.Unknown);
768 Powerd.setStatus(Powerd.Off, Powerd.Unknown);
769 tryCompare(greeter, "fullyShown", true);
771 compare(mainApp.requestedState, ApplicationInfoInterface.RequestedSuspended);
774 Powerd.setStatus(Powerd.On, Powerd.Unknown);
775 tryCompare(greeter, "fullyShown", true);
777 // Swipe away greeter to focus app
779 // greeter unloads its internal components when hidden
780 // and reloads them when shown. Thus we have to do this
781 // again before interacting with it otherwise any
782 // SwipeAreas in there won't be easily fooled by
784 removeTimeConstraintsFromSwipeAreas(greeter);
787 compare(mainApp.requestedState, ApplicationInfoInterface.RequestedRunning);
788 tryCompare(ApplicationManager, "focusedApplicationId", mainAppId);
791 function test_greeterStartsCorrectSession() {
792 loadShell("desktop");
793 setLightDMMockMode("full");
795 LightDMController.sessionMode = "full"
796 LightDMController.numSessions = LightDMController.numAvailableSessions;
797 var greeter = findChild(shell, "greeter");
798 var view = findChild(greeter, "WideView");
799 verify(view, "This test requires WideView to be loaded");
801 var loginList = findChild(view, "loginList");
803 compare(view.sessionToStart, greeter.sessionToStart());
805 // Ensure another session can actually be selected
806 compare(LightDMController.numSessions > 1, true);
807 loginList.currentSession = LightDM.Sessions.data(1, LightDM.SessionRoles.KeyRole);
809 compare(view.sessionToStart, greeter.sessionToStart());
814 function swipeAwayGreeter() {
815 var greeter = findChild(shell, "greeter");
817 if (!greeter.shown) {
818 console.log("Greeter not shown. Not swiping.");
822 tryCompare(greeter, "fullyShown", true);
823 waitForGreeterToStabilize();
824 removeTimeConstraintsFromSwipeAreas(greeter);
826 var touchX = shell.width - (shell.edgeSize / 2);
827 var touchY = shell.height / 2;
828 touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY);
830 // wait until the animation has finished
831 tryCompare(greeter, "shown", false);
832 waitForRendering(greeter);
835 function selectUserAtIndex(i) {
836 // We could be anywhere in list; find target index to know which direction
837 var greeter = findChild(shell, "greeter")
838 var userlist = findChild(greeter, "userList")
839 if (userlist.currentIndex == i)
840 keyClick(Qt.Key_Escape) // Reset state if we're not moving
841 while (userlist.currentIndex != i) {
842 var next = userlist.currentIndex + 1
843 var key = Qt.Key_Down;
844 if (userlist.currentIndex > i) {
845 next = userlist.currentIndex - 1
849 tryCompare(userlist, "currentIndex", next)
851 tryCompare(userlist, "movingInternally", false);
852 tryCompare(shell, "waitingOnGreeter", false); // wait for PAM to settle
855 function selectUser(name) {
856 // Find index of user with the right name
857 for (var i = 0; i < LightDM.Users.count; i++) {
858 if (LightDM.Users.data(i, LightDM.UserRoles.NameRole) == name) {
862 if (i == LightDM.Users.count) {
863 fail("Didn't find name")
870 function clickPasswordInput(isButton) {
871 var greeter = findChild(shell, "greeter")
872 tryCompare(greeter, "fullyShown", true);
874 var promptButton = findChild(greeter, "promptButton");
875 tryCompare(promptButton, "visible", isButton);
877 var promptField = findChild(greeter, "promptField");
878 tryCompare(promptField, "visible", !isButton);
880 mouseClick(promptButton);
883 function confirmLoggedIn(loggedIn) {
884 var greeter = findChild(shell, "greeter");
885 tryCompare(greeter, "shown", loggedIn ? false : true);
886 verify(loggedIn ? sessionSpy.count > 0 : sessionSpy.count === 0);
889 function setLightDMMockMode(mode) {
890 LightDMController.userMode = mode;
893 function test_showInputMethod() {
896 ensureInputMethodSurface();
898 var item = findChild(shell, "inputMethod");
899 var surface = topLevelSurfaceList.inputMethodSurface;
901 surface.requestState(Mir.MinimizedState);
902 tryCompare(item, "visible", false);
904 surface.requestState(Mir.RestoredState);
905 tryCompare(item, "visible", true);
907 surface.requestState(Mir.MinimizedState);
908 tryCompare(item, "visible", false);
910 surface.requestState(Mir.MaximizedState);
911 tryCompare(item, "visible", true);
913 surface.requestState(Mir.MinimizedState);
914 tryCompare(item, "visible", false);
917 function test_surfaceLosesActiveFocusWhilePanelIsOpen() {
920 var appDelegate = startApplication("dialer-app");
921 var appSurface = appDelegate.surface;
924 tryCompare(appSurface, "activeFocus", true);
926 // Drag the indicators panel half-open
927 var touchX = shell.width / 2;
928 var indicators = findChild(shell, "indicators");
929 touchFlick(indicators,
930 touchX /* fromX */, indicators.minimizedPanelHeight * 0.5 /* fromY */,
931 touchX /* toX */, shell.height * 0.5 /* toY */,
932 true /* beginTouch */, false /* endTouch */);
933 verify(indicators.partiallyOpened);
935 tryCompare(appSurface, "activeFocus", false);
937 // And finish getting it open
938 touchFlick(indicators,
939 touchX /* fromX */, shell.height * 0.5 /* fromY */,
940 touchX /* toX */, shell.height * 0.9 /* toY */,
941 false /* beginTouch */, true /* endTouch */);
942 tryCompare(indicators, "fullyOpened", true);
944 tryCompare(appSurface, "activeFocus", false);
946 dragToCloseIndicatorsPanel();
948 tryCompare(appSurface, "activeFocus", true);
951 function test_launchedAppHasActiveFocus_data() {
953 {tag: "phone", formFactor: "phone", usageScenario: "phone"},
954 {tag: "tablet", formFactor: "tablet", usageScenario: "tablet"},
955 {tag: "desktop", formFactor: "tablet", usageScenario: "desktop"}
959 function test_launchedAppHasActiveFocus(data) {
960 loadShell(data.formFactor);
961 shell.usageScenario = data.usageScenario;
964 var appDelegate = startApplication("webbrowser-app");
966 tryCompare(appDelegate.surface, "activeFocus", true);
969 function test_launchedAppKeepsActiveFocusOnUsageModeChange() {
973 var webAppSurfaceId = topLevelSurfaceList.nextId;
974 var webApp = ApplicationManager.startApplication("webbrowser-app");
976 waitUntilAppWindowIsFullyLoaded(webAppSurfaceId);
978 var webAppSurface = webApp.surfaceList.get(topLevelSurfaceList.indexForId(webAppSurfaceId));
979 verify(webAppSurface);
981 tryCompare(webAppSurface, "activeFocus", true);
983 shell.usageScenario = "desktop";
985 // check that the desktop stage and window have been loaded
986 waitUntilAppWindowIsFullyLoaded(webAppSurfaceId);
988 tryCompare(webAppSurface, "activeFocus", true);
990 shell.usageScenario = "tablet";
992 // check that the tablet stage and app surface delegate have been loaded
993 waitUntilAppWindowIsFullyLoaded(webAppSurfaceId);
995 tryCompare(webAppSurface, "activeFocus", true);
998 function dragToCloseIndicatorsPanel() {
999 var indicators = findChild(shell, "indicators");
1001 var touchStartX = shell.width / 2;
1002 var touchStartY = shell.height - (indicators.minimizedPanelHeight * 0.5);
1004 touchStartX, touchStartY,
1005 touchStartX, shell.height * 0.1);
1007 tryCompare(indicators, "fullyClosed", true);
1010 function dragLauncherIntoView() {
1011 var launcher = findChild(shell, "launcher");
1012 var launcherPanel = findChild(launcher, "launcherPanel");
1013 waitForRendering(launcher);
1014 verify(launcherPanel.x = - launcherPanel.width);
1016 var touchStartX = 2;
1017 var touchStartY = shell.height / 2;
1018 touchFlick(shell, touchStartX, touchStartY, launcherPanel.width + units.gu(1), touchStartY);
1020 tryCompare(launcherPanel, "x", 0);
1021 tryCompare(launcher, "state", "visible");
1024 function tapOnAppIconInLauncher() {
1025 var launcherPanel = findChild(shell, "launcherPanel");
1027 // pick the first icon, the one at the top.
1028 var appIcon = findChild(launcherPanel, "launcherDelegate0")
1029 tap(appIcon, appIcon.width / 2, appIcon.height / 2);
1032 function showIndicators() {
1033 var indicators = findChild(shell, "indicators");
1035 tryCompare(indicators, "fullyOpened", true);
1038 function hideIndicators() {
1039 var indicators = findChild(shell, "indicators");
1040 if (indicators.fullyOpened) {
1045 function waitUntilDashIsFocused() {
1046 tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
1049 function swipeFromLeftEdge(swipeLength) {
1050 var touchStartX = 2;
1051 var touchStartY = shell.height / 2;
1053 touchStartX , touchStartY,
1054 touchStartX + swipeLength, touchStartY);
1057 function itemIsOnScreen(item) {
1058 var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
1060 return itemRectInShell.x >= 0
1061 && itemRectInShell.y >= 0
1062 && itemRectInShell.x + itemRectInShell.width <= shell.width
1063 && itemRectInShell.y + itemRectInShell.height <= shell.height;
1066 function showGreeter() {
1067 var greeter = findChild(shell, "greeter");
1068 LightDM.Greeter.showGreeter();
1069 waitForRendering(greeter);
1070 tryCompare(greeter, "fullyShown", true);
1072 // greeter unloads its internal components when hidden
1073 // and reloads them when shown. Thus we have to do this
1074 // again before interacting with it otherwise any
1075 // SwipeAreas in there won't be easily fooled by
1077 removeTimeConstraintsFromSwipeAreas(greeter);
1080 function revealLauncherByEdgePushWithMouse() {
1081 var launcher = findChild(shell, "launcher");
1084 // Place the mouse against the window/screen edge and push beyond the barrier threshold
1085 mouseMove(shell, 0, shell.height / 2);
1086 launcher.pushEdge(EdgeBarrierSettings.pushThreshold * .8);
1088 var panel = findChild(launcher, "launcherPanel");
1091 // wait until it gets fully extended
1092 tryCompare(panel, "x", 0);
1093 tryCompare(launcher, "state", "visibleTemporary");
1096 function test_focusRequestedHidesGreeter() {
1099 var greeter = findChild(shell, "greeter");
1101 var appSurfaceId = topLevelSurfaceList.nextId;
1102 var app = ApplicationManager.startApplication("dialer-app");
1103 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
1105 // Minimize the application we just launched
1106 swipeFromLeftEdge(units.gu(15));
1110 // The main point of this test
1111 ApplicationManager.requestFocusApplication("dialer-app");
1112 tryCompare(greeter, "shown", false);
1113 waitForRendering(greeter);
1116 function test_focusRequestedHidesIndicators() {
1119 var indicators = findChild(shell, "indicators");
1123 var oldCount = ApplicationManager.count;
1124 ApplicationManager.startApplication("camera-app");
1125 tryCompare(ApplicationManager, "count", oldCount + 1);
1127 tryCompare(indicators, "fullyClosed", true);
1130 function test_greeterShownAgainHidesIndicators() {
1131 // Regression test for https://launchpad.net/bugs/1595569
1137 var indicators = findChild(shell, "indicators");
1138 tryCompare(indicators, "fullyClosed", true);
1141 function test_showAndHideGreeterDBusCalls() {
1144 var greeter = findChild(shell, "greeter")
1145 tryCompare(greeter, "shown", false)
1146 waitForRendering(greeter);
1147 LightDM.Greeter.showGreeter()
1148 waitForRendering(greeter)
1149 tryCompare(greeter, "fullyShown", true)
1150 LightDM.Greeter.hideGreeter()
1151 tryCompare(greeter, "shown", false)
1154 function test_greeterLoginsAutomaticallyWhenNoPasswordSet() {
1157 var greeter = findChild(shell, "greeter");
1158 verify(!greeter.locked);
1159 compare(sessionSpy.count, 0);
1162 compare(sessionSpy.count, 1);
1165 function test_fullscreen() {
1168 var panel = findChild(shell, "panel");
1169 compare(panel.fullscreenMode, false);
1170 var cameraSurfaceId = topLevelSurfaceList.nextId;
1171 var cameraApp = ApplicationManager.startApplication("camera-app");
1172 waitUntilAppWindowIsFullyLoaded(cameraSurfaceId);
1173 tryCompare(panel, "fullscreenMode", true);
1174 var dialerSurfaceId = topLevelSurfaceList.nextId;
1175 var dialerApp = ApplicationManager.startApplication("dialer-app");
1176 waitUntilAppWindowIsFullyLoaded(dialerSurfaceId);
1177 tryCompare(panel, "fullscreenMode", false);
1178 ApplicationManager.requestFocusApplication(cameraApp.appId);
1179 tryCompare(panel, "fullscreenMode", true);
1180 ApplicationManager.requestFocusApplication(dialerApp.appId);
1181 tryCompare(panel, "fullscreenMode", false);
1184 function test_leftEdgeDragFullscreen() {
1187 var panel = findChild(shell, "panel");
1188 tryCompare(panel, "fullscreenMode", false)
1190 ApplicationManager.startApplication("camera-app");
1191 tryCompare(panel, "fullscreenMode", true)
1193 var touchStartX = 2;
1194 var touchStartY = shell.height / 2;
1196 touchFlick(shell, touchStartX, touchStartY, units.gu(2), touchStartY, true, false);
1198 compare(panel.fullscreenMode, true);
1200 touchFlick(shell, units.gu(2), touchStartY, shell.width * 0.5, touchStartY, false, false);
1202 tryCompare(panel, "fullscreenMode", false);
1204 touchRelease(shell);
1207 function test_unlockedProperties() {
1210 // Confirm that various properties have the correct values when unlocked
1211 var greeter = findChild(shell, "greeter");
1212 tryCompare(greeter, "locked", false);
1214 var launcher = findChild(shell, "launcher")
1215 tryCompare(launcher, "available", true)
1217 var indicators = findChild(shell, "indicators")
1218 tryCompare(indicators, "available", true)
1221 function test_unlockAllModemsOnBoot() {
1224 tryCompare(unlockAllModemsSpy, "count", 1)
1227 function test_unlockAllModemsAfterWizard() {
1228 Wizard.System.wizardEnabled = true;
1231 var wizard = findChild(shell, "wizard");
1232 compare(wizard.active, true);
1233 compare(Wizard.System.wizardEnabled, true);
1234 compare(unlockAllModemsSpy.count, 0);
1237 tryCompare(wizard, "active", false);
1238 compare(Wizard.System.wizardEnabled, false);
1239 compare(unlockAllModemsSpy.count, 1);
1242 function test_wizardEarlyExit() {
1243 Wizard.System.wizardEnabled = true;
1246 var wizard = findChild(shell, "wizard");
1247 tryCompare(wizard, "active", true);
1249 tryCompare(topLevelSurfaceList, "count", 0);
1250 compare(wizard.shown, true);
1252 // And make sure we stop when some surface shows app
1253 var gallerySurfaceId = topLevelSurfaceList.nextId;
1254 var galleryApp = ApplicationManager.startApplication("gallery-app");
1255 waitUntilAppWindowIsFullyLoaded(gallerySurfaceId);
1256 tryCompareFunction(function() { return topLevelSurfaceList.applicationAt(0).appId; }, "gallery-app");
1257 compare(wizard.shown, false);
1258 tryCompare(Wizard.System, "wizardEnabled", false);
1261 function test_tutorialPausedDuringGreeter() {
1264 var tutorial = findChild(shell, "tutorial");
1266 AccountsService.demoEdges = true;
1267 tryCompare(tutorial, "paused", true);
1270 tryCompare(tutorial, "paused", false);
1273 function test_customBackground() {
1274 loadShell("desktop");
1275 shell.usageScenario = "desktop";
1276 waitForRendering(shell);
1278 var wallpaperResolver = findInvisibleChild(shell, "wallpaperResolver");
1279 var greeter = findChild(shell, "greeter");
1280 verify(!greeter.hasCustomBackground);
1281 compare(wallpaperResolver.background, wallpaperResolver.defaultBackground);
1283 AccountsService.backgroundFile = Qt.resolvedUrl("../graphics/applicationIcons/dash.png");
1284 tryCompare(greeter, "hasCustomBackground", true);
1285 compare(wallpaperResolver.background, AccountsService.backgroundFile);
1288 function test_cachedBackground() {
1289 loadShell("desktop");
1290 shell.usageScenario = "desktop";
1291 waitForRendering(shell);
1293 var greeter = findChild(shell, "greeter");
1294 verify(!greeter.hasCustomBackground);
1295 compare(greeter.background.toString().indexOf("image://unity8imagecache/file:///"), 0);
1296 verify(greeter.background.toString().indexOf("?name=wallpaper") > 0);
1299 function test_tapOnRightEdgeReachesApplicationSurface() {
1303 var appSurfaceId = topLevelSurfaceList.nextId;
1304 var app = ApplicationManager.startApplication("unity8-dash")
1305 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
1307 var topmostSpreadDelegate = findChild(shell, "appDelegate_" + topLevelSurfaceList.idAt(0));
1308 verify(topmostSpreadDelegate);
1310 waitUntilFocusedApplicationIsShowingItsSurface();
1312 var topmostSurfaceItem = findChild(topmostSpreadDelegate, "surfaceItem");
1313 verify(topmostSurfaceItem);
1315 var rightEdgeDragArea = findChild(shell, "rightEdgeDragArea");
1316 topmostSurfaceItem.touchPressCount = 0;
1317 topmostSurfaceItem.touchReleaseCount = 0;
1319 var tapPoint = rightEdgeDragArea.mapToItem(shell, rightEdgeDragArea.width / 2,
1320 rightEdgeDragArea.height / 2);
1322 tap(shell, tapPoint.x, tapPoint.y);
1324 tryCompare(topmostSurfaceItem, "touchPressCount", 1);
1325 tryCompare(topmostSurfaceItem, "touchReleaseCount", 1);
1329 Perform a right edge drag over an application surface and check
1330 that no touch event was sent to it (ie, they were all consumed
1331 by the right-edge drag area)
1333 function test_rightEdgeDragDoesNotReachApplicationSurface() {
1337 var appSurfaceId = topLevelSurfaceList.nextId;
1338 var app = ApplicationManager.startApplication("unity8-dash")
1339 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
1341 var topmostSpreadDelegate = findChild(shell, "appDelegate_" + topLevelSurfaceList.idAt(0));
1342 var topmostSurfaceItem = findChild(topmostSpreadDelegate, "surfaceItem");
1343 var rightEdgeDragArea = findChild(shell, "rightEdgeDragArea");
1345 topmostSurfaceItem.touchPressCount = 0;
1346 topmostSurfaceItem.touchReleaseCount = 0;
1348 var gestureStartPoint = rightEdgeDragArea.mapToItem(shell, rightEdgeDragArea.width / 2,
1349 rightEdgeDragArea.height / 2);
1352 gestureStartPoint.x /* fromX */, gestureStartPoint.y /* fromY */,
1353 units.gu(1) /* toX */, gestureStartPoint.y /* toY */);
1355 tryCompare(topmostSurfaceItem, "touchPressCount", 0);
1356 tryCompare(topmostSurfaceItem, "touchReleaseCount", 0);
1359 function waitUntilFocusedApplicationIsShowingItsSurface()
1361 var spreadDelegate = findChild(shell, "appDelegate_" + topLevelSurfaceList.idAt(0));
1362 var appState = findInvisibleChild(spreadDelegate, "applicationWindowStateGroup");
1363 tryCompare(appState, "state", "surface");
1364 var transitions = appState.transitions;
1365 for (var i = 0; i < transitions.length; ++i) {
1366 var transition = transitions[i];
1367 tryCompare(transition, "running", false, 2000);
1371 function swipeFromRightEdgeToShowAppSpread()
1373 // perform a right-edge drag to show the spread
1374 var touchStartX = shell.width - (shell.edgeSize / 2)
1375 var touchStartY = shell.height / 2;
1376 touchFlick(shell, touchStartX, touchStartY, units.gu(1) /* endX */, touchStartY /* endY */);
1378 // check if it's indeed showing the spread
1379 var stage = findChild(shell, "stage");
1380 tryCompare(stage, "state", "spread");
1383 function test_physicalHomeKeyPressDoesNothingWithActiveGreeter() {
1386 var windowInputMonitor = findInvisibleChild(shell, "windowInputMonitor");
1387 var coverPage = findChild(shell, "coverPage");
1389 windowInputMonitor.homeKeyActivated();
1390 verify(coverPage.shown);
1393 function test_physicalHomeKeyPressOpensDrawer() {
1397 var windowInputMonitor = findInvisibleChild(shell, "windowInputMonitor");
1398 windowInputMonitor.homeKeyActivated();
1400 var launcher = findChild(shell, "launcher");
1401 tryCompare(launcher, "drawerShown", true);
1404 function test_tabletLogin_data() {
1406 {tag: "auth error", user: "auth-error", loggedIn: false, password: ""},
1407 {tag: "with password", user: "has-password", loggedIn: true, password: "password"},
1408 {tag: "without password", user: "no-password", loggedIn: true, password: ""},
1412 function test_tabletLogin(data) {
1413 setLightDMMockMode("full");
1414 loadShell("tablet");
1416 selectUser(data.user);
1418 clickPasswordInput(data.password === "" /* isButton */);
1420 if (data.password !== "") {
1421 typeString(data.password);
1422 keyClick(Qt.Key_Enter);
1425 confirmLoggedIn(data.loggedIn);
1428 function test_appLaunchDuringGreeter_data() {
1430 {tag: "auth error", user: "auth-error", loggedIn: false, passwordFocus: false},
1431 {tag: "without password", user: "no-password", loggedIn: true, passwordFocus: false},
1432 {tag: "with password", user: "has-password", loggedIn: false, passwordFocus: true},
1436 function test_appLaunchDuringGreeter(data) {
1437 setLightDMMockMode("full");
1438 loadShell("tablet");
1440 selectUser(data.user)
1442 var greeter = findChild(shell, "greeter")
1443 var app = ApplicationManager.startApplication("dialer-app")
1445 confirmLoggedIn(data.loggedIn)
1447 if (data.passwordFocus) {
1448 var passwordInput = findChild(greeter, "promptField");
1449 tryCompare(passwordInput, "focus", true)
1453 function test_manualLoginFlow() {
1454 LightDMController.showManualLoginHint = true;
1455 setLightDMMockMode("full");
1456 loadShell("desktop");
1458 var i = selectUser("*other");
1459 var greeter = findChild(shell, "greeter");
1460 var username = findChild(greeter, "username" + i);
1461 var promptField = findChild(greeter, "promptField");
1462 var promptHint = findChild(greeter, "promptHint");
1464 compare(username.text, "Login");
1465 compare(promptHint.text, "Username");
1467 tryCompare(promptField, "activeFocus", true);
1468 typeString("has-password");
1469 keyClick(Qt.Key_Enter);
1471 promptHint = findChild(greeter, "promptHint");
1472 tryCompare(username, "text", "has-password");
1473 tryCompare(promptHint, "text", "Passphrase");
1475 typeString("password");
1476 keyClick(Qt.Key_Enter);
1478 confirmLoggedIn(true);
1481 function test_terminalShortcut() {
1482 loadShell("desktop");
1483 shell.usageScenario = "desktop";
1484 waitForRendering(shell);
1487 // not running, should start
1488 keyClick(Qt.Key_T, Qt.ControlModifier|Qt.AltModifier);
1489 tryCompare(ApplicationManager, "focusedApplicationId", "ubuntu-terminal-app");
1491 // start something else
1492 ApplicationManager.startApplication("dialer-app");
1493 tryCompare(ApplicationManager, "focusedApplicationId", "dialer-app");
1495 // terminal running in background, should get focused
1496 keyClick(Qt.Key_T, Qt.ControlModifier|Qt.AltModifier);
1497 tryCompare(ApplicationManager, "focusedApplicationId", "ubuntu-terminal-app");
1500 function test_launcherInverted_data() {
1502 {tag: "phone", formFactor: "phone", usageScenario: "phone", launcherInverted: true},
1503 {tag: "tablet", formFactor: "tablet", usageScenario: "tablet", launcherInverted: true},
1504 {tag: "desktop", formFactor: "tablet", usageScenario: "desktop", launcherInverted: false}
1508 function test_launcherInverted(data) {
1509 loadShell(data.formFactor);
1510 shell.usageScenario = data.usageScenario;
1512 var launcher = findChild(shell, "launcher");
1513 compare(launcher.inverted, data.launcherInverted);
1516 function test_unfocusedAppsGetSuspendedAfterEnteringStagedMode() {
1517 loadShell("tablet");
1518 shell.usageScenario = "desktop";
1520 var appSurfaceId = topLevelSurfaceList.nextId;
1521 var app = ApplicationManager.startApplication("unity8-dash")
1522 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
1524 var webBrowserSurfaceId = topLevelSurfaceList.nextId;
1525 var webBrowserApp = ApplicationManager.startApplication("webbrowser-app");
1526 waitUntilAppWindowIsFullyLoaded(webBrowserSurfaceId);
1528 var gallerySurfaceId = topLevelSurfaceList.nextId;
1529 var galleryApp = ApplicationManager.startApplication("gallery-app");
1530 waitUntilAppWindowIsFullyLoaded(gallerySurfaceId);
1532 ApplicationManager.requestFocusApplication("unity8-dash");
1533 tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
1535 compare(webBrowserApp.requestedState, ApplicationInfoInterface.RequestedRunning);
1536 compare(galleryApp.requestedState, ApplicationInfoInterface.RequestedRunning);
1538 shell.usageScenario = "tablet";
1540 tryCompare(webBrowserApp, "requestedState", ApplicationInfoInterface.RequestedSuspended);
1541 tryCompare(galleryApp, "requestedState", ApplicationInfoInterface.RequestedSuspended);
1544 function test_unfocusedAppsAreResumedWhenEnteringWindowedMode() {
1545 loadShell("tablet");
1546 shell.usageScenario = "tablet";
1548 var appSurfaceId = topLevelSurfaceList.nextId;
1549 var app = ApplicationManager.startApplication("unity8-dash")
1550 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
1552 var webBrowserSurfaceId = topLevelSurfaceList.nextId;
1553 var webBrowserApp = ApplicationManager.startApplication("webbrowser-app");
1554 waitUntilAppWindowIsFullyLoaded(webBrowserSurfaceId);
1556 var gallerySurfaceId = topLevelSurfaceList.nextId;
1557 var galleryApp = ApplicationManager.startApplication("gallery-app");
1558 waitUntilAppWindowIsFullyLoaded(gallerySurfaceId);
1560 ApplicationManager.requestFocusApplication("unity8-dash");
1561 tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
1563 compare(webBrowserApp.requestedState, ApplicationInfoInterface.RequestedSuspended);
1564 compare(galleryApp.requestedState, ApplicationInfoInterface.RequestedSuspended);
1566 shell.usageScenario = "desktop";
1568 tryCompare(webBrowserApp, "requestedState", ApplicationInfoInterface.RequestedRunning);
1569 tryCompare(galleryApp, "requestedState", ApplicationInfoInterface.RequestedRunning);
1572 function test_altTabSwitchesFocus_data() {
1574 { tag: "windowed", shellType: "desktop" },
1575 { tag: "staged", shellType: "phone" },
1576 { tag: "sidestaged", shellType: "tablet" }
1580 function test_altTabSwitchesFocus(data) {
1581 loadShell(data.shellType);
1582 shell.usageScenario = data.shellType;
1583 waitForRendering(root)
1585 var desktopStage = findChild(shell, "stage");
1586 verify(desktopStage != null)
1588 var app1SurfaceId = topLevelSurfaceList.nextId;
1589 var app1 = ApplicationManager.startApplication("dialer-app")
1590 waitUntilAppWindowIsFullyLoaded(app1SurfaceId);
1592 var app2SurfaceId = topLevelSurfaceList.nextId;
1593 var app2 = ApplicationManager.startApplication("webbrowser-app")
1594 waitUntilAppWindowIsFullyLoaded(app2SurfaceId);
1595 var app2Surface = app2.surfaceList.get(0);
1596 verify(app2Surface);
1598 var app3SurfaceId = topLevelSurfaceList.nextId;
1599 var app3 = ApplicationManager.startApplication("camera-app")
1600 waitUntilAppWindowIsFullyLoaded(app3SurfaceId);
1601 var app3Surface = app3.surfaceList.get(0);
1602 verify(app3Surface);
1604 // Do a quick alt-tab and see if focus changes
1605 tryCompare(app3Surface, "activeFocus", true)
1606 keyClick(Qt.Key_Tab, Qt.AltModifier)
1607 tryCompare(app2Surface, "activeFocus", true)
1610 keyPress(Qt.Key_Alt);
1611 keyClick(Qt.Key_Tab);
1612 keyRelease(Qt.Key_Alt)
1614 // Focus should have switched back now
1615 tryCompare(app3Surface, "activeFocus", true)
1618 function test_altTabWrapAround() {
1619 loadDesktopShellWithApps();
1621 var stage = findChild(shell, "stage");
1622 verify(stage !== null)
1624 var spread = findChild(shell, "spreadItem");
1625 verify(spread !== null)
1627 // remember the focused appId
1628 var focused = ApplicationManager.get(ApplicationManager.findApplication(ApplicationManager.focusedApplicationId));
1630 tryCompare(stage, "state", "windowed")
1632 // Just press Alt, make sure the spread comes up
1633 keyPress(Qt.Key_Alt);
1634 keyClick(Qt.Key_Tab);
1635 tryCompare(stage, "state", "spread")
1636 tryCompare(spread, "highlightedIndex", 1)
1637 waitForRendering(shell)
1639 // Now press and hold Tab, make sure the highlight moves all the way but stops at the last one
1640 // We can't simulate a pressed key with keyPress() currently, so let's inject the events
1641 // at API level. Jump for 10 times, verify that it's still at the last one and didn't wrap around.
1642 for (var i = 0; i < 10; i++) {
1643 spread.selectNext(true); // true == isAutoRepeat
1644 wait(0); // Trigger the event loop to make sure all the things happen
1646 tryCompare(spread, "highlightedIndex", 6)
1648 // Now release it once, and verify that it does wrap around with an additional Tab press
1649 keyRelease(Qt.Key_Tab);
1650 keyClick(Qt.Key_Tab);
1651 tryCompare(spread, "highlightedIndex", 0)
1653 // Release control, check if spread disappears
1654 keyRelease(Qt.Key_Alt)
1655 tryCompare(stage, "state", "windowed")
1657 // Make sure that after wrapping around once, we have the same one focused as at the beginning
1658 var focusedAppSurface = focused.surfaceList.get(0);
1659 verify(focusedAppSurface);
1660 tryCompare(focusedAppSurface, "activeFocus", true)
1663 function test_altBackTabNavigation() {
1664 loadDesktopShellWithApps();
1666 var spreadItem = findChild(shell, "spreadItem");
1667 verify(spreadItem !== null);
1669 keyPress(Qt.Key_Alt)
1670 keyClick(Qt.Key_Tab);
1671 tryCompare(spreadItem, "highlightedIndex", 1);
1673 keyClick(Qt.Key_Tab);
1674 tryCompare(spreadItem, "highlightedIndex", 2);
1676 keyClick(Qt.Key_Tab);
1677 tryCompare(spreadItem, "highlightedIndex", 3);
1679 keyClick(Qt.Key_Tab);
1680 tryCompare(spreadItem, "highlightedIndex", 4);
1682 keyClick(Qt.Key_Backtab);
1683 tryCompare(spreadItem, "highlightedIndex", 3);
1685 keyClick(Qt.Key_Backtab);
1686 tryCompare(spreadItem, "highlightedIndex", 2);
1688 keyClick(Qt.Key_Backtab);
1689 tryCompare(spreadItem, "highlightedIndex", 1);
1691 keyRelease(Qt.Key_Alt);
1694 function otest_highlightFollowsMouse() {
1695 loadDesktopShellWithApps()
1697 var spreadRepeater = findInvisibleChild(shell, "spreadRepeater");
1698 verify(spreadRepeater !== null);
1700 keyPress(Qt.Key_Alt)
1701 keyClick(Qt.Key_Tab);
1703 tryCompare(spreadRepeater, "highlightedIndex", 1);
1706 var y = shell.height * .75;
1707 mouseMove(shell, x, y)
1709 for (var i = 0; i < 7; i++) {
1710 while (spreadRepeater.highlightedIndex != i && x <= 4000) {
1712 mouseMove(shell, x, y)
1713 wait(0); // spin the loop so bindings get evaluated
1719 keyRelease(Qt.Key_Alt);
1722 function test_closeFromSpread() {
1723 loadDesktopShellWithApps()
1725 var appRepeater = findInvisibleChild(shell, "appRepeater");
1726 verify(appRepeater !== null);
1728 var spreadItem = findChild(shell, "spreadItem");
1729 verify(spreadItem !== null);
1731 keyPress(Qt.Key_Alt)
1732 keyClick(Qt.Key_Tab);
1734 var surfaceId = topLevelSurfaceList.idAt(2);
1735 var spreadDelegate2 = appRepeater.itemAt(2);
1736 var closeMouseArea = findChild(spreadDelegate2, "closeMouseArea");
1738 // Move the mosue over tile 2 and verify the close button becomes visible
1740 var y = shell.height * .5;
1741 mouseMove(shell, x, y)
1742 while (spreadItem.highlightedIndex !== 2 && x <= 4000) {
1744 mouseMove(shell, x, y)
1745 wait(0); // spin the loop so bindings get evaluated
1747 tryCompare(closeMouseArea, "enabled", true)
1749 var countBeforeClickingCloseButton = topLevelSurfaceList.count;
1750 verify(topLevelSurfaceList.indexForId(surfaceId) === 2);
1752 // Close the app using the close button
1753 mouseClick(closeMouseArea, closeMouseArea.width / 2, closeMouseArea.height / 2)
1755 tryCompare(topLevelSurfaceList, "count", countBeforeClickingCloseButton - 1);
1756 verify(topLevelSurfaceList.indexForId(surfaceId) === -1);
1758 keyRelease(Qt.Key_Alt);
1761 function test_selectFromSpreadWithMouse_data() {
1763 {tag: "click on tileInfo", tileInfo: true },
1764 {tag: "click on surface", tileInfo: false },
1768 function test_selectFromSpreadWithMouse(data) {
1769 loadDesktopShellWithApps()
1771 var stage = findChild(shell, "stage");
1772 var spreadItem = findChild(stage, "spreadItem");
1773// waitForRendering(spread)
1775 var appRepeater = findInvisibleChild(shell, "appRepeater");
1776 verify(appRepeater !== null);
1778 keyPress(Qt.Key_Alt)
1779 keyClick(Qt.Key_Tab);
1781 var surface = topLevelSurfaceList.surfaceAt(2);
1782 var spreadDelegate2 = appRepeater.itemAt(2);
1783 var decoratedWindow = findChild(spreadDelegate2, "decoratedWindow");
1785 tryCompare(stage, "state", "spread");
1787 // Move the mouse over tile 2 and verify the highlight becomes visible
1789 var y = shell.height * (data.tileInfo ? .9 : 0.5)
1790 mouseMove(shell, x, y)
1791 while (spreadItem.highlightedIndex !== 2 && x <= 4000) {
1793 mouseMove(shell, x, y)
1794 wait(0); // spin the loop so bindings get evaluated
1796 tryCompare(decoratedWindow, "showHighlight", true);
1799 mouseClick(decoratedWindow, units.gu(2), decoratedWindow.height / 2)
1801 // Verify that we left the spread and app2 is the focused one now
1802 tryCompare(stage, "state", "windowed");
1803 tryCompare(surface, "focused", true);
1805 keyRelease(Qt.Key_Alt);
1808 function test_progressiveAutoScrolling() {
1809 loadDesktopShellWithApps()
1811 var appRepeater = findInvisibleChild(shell, "appRepeater");
1812 verify(appRepeater !== null);
1814 keyPress(Qt.Key_Alt)
1815 keyClick(Qt.Key_Tab);
1817 var spreadFlickable = findChild(shell, "spreadFlickable")
1819 compare(spreadFlickable.contentX, 0);
1821 // Move the mouse to the right and make sure it scrolls the Flickable
1823 var y = shell.height * .5
1824 mouseMove(shell, x, y)
1825 while (x <= shell.width) {
1827 mouseMove(shell, x, y)
1828 wait(0); // spin the loop so bindings get evaluated
1830 tryCompare(spreadFlickable, "contentX", spreadFlickable.contentWidth - spreadFlickable.width);
1835 mouseMove(shell, x, y)
1836 wait(0); // spin the loop so bindings get evaluated
1838 tryCompare(spreadFlickable, "contentX", 0);
1840 keyRelease(Qt.Key_Alt);
1843 // This makes sure the hoverMouseArea is set to invisible AND disabled
1844 // when not needed. Otherwise it'll eat mouse hover events for the rest of the shell/apps
1845 function test_hoverMouseAreaDisabledAndInvisible() {
1846 loadDesktopShellWithApps()
1848 var hoverMouseArea = findChild(shell, "hoverMouseArea");
1849 tryCompare(hoverMouseArea, "enabled", false)
1850 tryCompare(hoverMouseArea, "visible", false)
1852 keyPress(Qt.Key_Alt)
1853 keyClick(Qt.Key_Tab);
1855 tryCompare(hoverMouseArea, "enabled", true)
1856 tryCompare(hoverMouseArea, "visible", true)
1858 keyRelease(Qt.Key_Alt)
1860 tryCompare(hoverMouseArea, "enabled", false)
1861 tryCompare(hoverMouseArea, "visible", false)
1864 function test_focusAppFromLauncherExitsSpread_data() {
1866 {tag: "autohide launcher", launcherLocked: false },
1867 {tag: "locked launcher", launcherLocked: true }
1871 function test_focusAppFromLauncherExitsSpread(data) {
1872 loadDesktopShellWithApps()
1873 var launcher = findChild(shell, "launcher");
1874 var stage = findChild(shell, "stage");
1875 var app1 = findChild(launcher, "launcherDelegate0");
1877 GSettingsController.setAutohideLauncher(!data.launcherLocked);
1878 waitForRendering(shell);
1880 keyPress(Qt.Key_Alt)
1881 keyClick(Qt.Key_Tab);
1883 tryCompare(stage, "state", "spread")
1885 if (!data.launcherLocked) {
1886 revealLauncherByEdgePushWithMouse();
1887 tryCompare(launcher, "x", 0);
1888 mouseMove(app1, app1.width / 2, app1.height / 2)
1889 waitForRendering(shell)
1892 mouseClick(app1, app1.width / 2, app1.height / 2)
1893 if (!data.launcherLocked) {
1894 tryCompare(launcher, "state", "")
1896 tryCompare(stage, "state", "windowed")
1898 tryCompare(ApplicationManager, "focusedApplicationId", "dialer-app")
1900 keyRelease(Qt.Key_Alt);
1903 // regression test for http://pad.lv/1443319
1904 function test_closeMaximizedAndRestart() {
1905 loadDesktopShellWithApps();
1907 var appRepeater = findChild(shell, "appRepeater")
1908 var application = topLevelSurfaceList.applicationAt(0);
1909 var surfaceId = topLevelSurfaceList.idAt(0);
1910 var appDelegate = appRepeater.itemAt(0);
1911 var maximizeButton = findChild(appDelegate, "maximizeWindowButton");
1913 tryCompare(appDelegate, "state", "normal");
1914 tryCompare(PanelState, "decorationsVisible", false)
1916 mouseClick(maximizeButton, maximizeButton.width / 2, maximizeButton.height / 2);
1917 tryCompare(appDelegate, "state", "maximized");
1918 tryCompare(PanelState, "decorationsVisible", true)
1920 ApplicationManager.stopApplication(application.appId);
1921 tryCompare(PanelState, "decorationsVisible", false)
1923 // wait until all zombie surfaces are gone. As MirSurfaceItems hold references over them.
1924 // They won't be gone until those surface items are destroyed.
1925 tryCompareFunction(function() { return application.surfaceList.count }, 0);
1927 ApplicationManager.startApplication(application.appId);
1928 tryCompare(PanelState, "decorationsVisible", true)
1931 function test_newAppHasValidGeometry() {
1932 loadDesktopShellWithApps();
1933 var appRepeater = findChild(shell, "appRepeater");
1934 var appDelegate = appRepeater.itemAt(0);
1936 // Make sure windows are at 0,0 or greater and they have a size that's > 0
1937 compare(appDelegate.normalX >= 0, true)
1938 compare(appDelegate.normalY >= 0, true)
1939 compare(appDelegate.normalWidth > 0, true)
1940 compare(appDelegate.normalHeight > 0, true)
1943 // bug http://pad.lv/1431566
1944 function test_switchToStagedHidesPanelButtons() {
1945 loadDesktopShellWithApps();
1946 var appRepeater = findChild(shell, "appRepeater")
1947 var appDelegate = appRepeater.itemAt(0);
1948 var panelButtons = findChild(shell, "panelWindowControlButtons")
1949 verify(panelButtons)
1951 tryCompare(appDelegate, "state", "normal");
1952 tryCompare(panelButtons, "visible", false);
1954 appDelegate.maximize(false);
1956 shell.usageScenario = "phone";
1957 waitForRendering(shell);
1958 tryCompare(panelButtons, "visible", false);
1961 function test_lockingGreeterHidesPanelButtons() {
1962 loadDesktopShellWithApps();
1963 var appRepeater = findChild(shell, "appRepeater")
1964 var appDelegate = appRepeater.itemAt(0);
1965 var panelButtons = findChild(shell, "panelWindowControlButtons")
1967 tryCompare(appDelegate, "state", "normal");
1968 tryCompare(panelButtons, "visible", false);
1970 appDelegate.maximize(false);
1972 LightDM.Greeter.showGreeter();
1973 waitForRendering(shell);
1974 tryCompare(panelButtons, "visible", false);
1977 function test_cantMoveWindowUnderPanel() {
1978 loadDesktopShellWithApps();
1979 var appRepeater = findChild(shell, "appRepeater")
1980 var appDelegate = appRepeater.itemAt(0);
1982 mousePress(appDelegate, appDelegate.width / 2, units.gu(1))
1983 mouseMove(appDelegate, appDelegate.width / 2, -units.gu(100))
1985 compare(appDelegate.y >= PanelState.panelHeight, true);
1988 function test_cantResizeWindowUnderPanel() {
1989 loadShell("desktop");
1990 shell.usageScenario = "desktop";
1991 waitForRendering(shell);
1993 var appSurfaceId = topLevelSurfaceList.nextId;
1994 var app = ApplicationManager.startApplication("dialer-app")
1995 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
1997 var appContainer = findChild(shell, "appContainer");
1998 verify(appContainer);
1999 var appDelegate = findChild(appContainer, "appDelegate_" + appSurfaceId);
2000 verify(appDelegate);
2001 var decoration = findChild(appDelegate, "appWindowDecoration");
2004 // move it away from launcher and panel
2005 appDelegate.x = units.gu(10)
2006 appDelegate.y = units.gu(10)
2008 // drag-resize the area up
2009 mousePress(decoration, decoration.width/2, -units.gu(1));
2010 mouseMove(decoration, decoration.width/2, -units.gu(100));
2012 // verify we don't go past the panel
2013 compare(appDelegate.y >= PanelState.panelHeight, true);
2016 function test_restoreWindowStateFixesIfUnderPanel() {
2017 loadDesktopShellWithApps();
2018 var appRepeater = findChild(shell, "appRepeater")
2019 var application = topLevelSurfaceList.applicationAt(0);
2020 var appDelegate = appRepeater.itemAt(0);
2022 // Move it under the panel programmatically (might happen later with an alt+drag)
2023 appDelegate.y = -units.gu(10)
2025 ApplicationManager.stopApplication(application.appId);
2026 // wait until all zombie surfaces are gone. As MirSurfaceItems hold references over them.
2027 // They won't be gone until those surface items are destroyed.
2028 tryCompareFunction(function() { return application.surfaceList.count }, 0);
2030 ApplicationManager.startApplication(application.appId);
2031 waitForRendering(shell)
2033 // Make sure the newly started one is at index 0 again
2034 tryCompareFunction(function () { return topLevelSurfaceList.applicationAt(0).appId; }, application.appId);
2036 appDelegate = appRepeater.itemAt(0);
2037 compare(appDelegate.y >= PanelState.panelHeight, true);
2040 function test_lifecyclePolicyForNonTouchApp_data() {
2042 {tag: "phone", formFactor: "phone", usageScenario: "phone"},
2043 {tag: "tablet", formFactor: "tablet", usageScenario: "tablet"}
2047 function test_lifecyclePolicyForNonTouchApp(data) {
2048 loadShell(data.formFactor);
2049 shell.usageScenario = data.usageScenario;
2051 // Add two main stage apps, the second in order to suspend the first.
2052 // LibreOffice has isTouchApp set to false by our mocks.
2053 var app1SurfaceId = topLevelSurfaceList.nextId;
2054 var app1 = ApplicationManager.startApplication("libreoffice");
2055 waitUntilAppWindowIsFullyLoaded(app1SurfaceId);
2056 var app2SurfaceId = topLevelSurfaceList.nextId;
2057 var app2 = ApplicationManager.startApplication("gallery-app");
2058 waitUntilAppWindowIsFullyLoaded(app2SurfaceId);
2061 if (data.usageScenario === "tablet") {
2062 var app1Delegate = findChild(shell, "appDelegate_" + app1SurfaceId);
2063 compare(app1Delegate.stage, ApplicationInfoInterface.MainStage);
2065 var app2Delegate = findChild(shell, "appDelegate_" + app2SurfaceId);
2066 compare(app2Delegate.stage, ApplicationInfoInterface.MainStage);
2068 verify(!app1.isTouchApp);
2070 var app1Surface = app1.surfaceList.get(0);
2071 verify(app1Surface);
2073 verify(!app1Surface.activeFocus);
2075 // Make sure app1 is exempt with a requested suspend
2076 verify(app1.exemptFromLifecycle);
2077 compare(app1.requestedState, ApplicationInfoInterface.RequestedSuspended);
2080 function test_lifecyclePolicyExemption_data() {
2082 {tag: "phone", formFactor: "phone", usageScenario: "phone"},
2083 {tag: "tablet", formFactor: "tablet", usageScenario: "tablet"}
2087 function test_lifecyclePolicyExemption(data) {
2088 loadShell(data.formFactor);
2089 shell.usageScenario = data.usageScenario;
2091 GSettingsController.setLifecycleExemptAppids(["webbrowser-app"]);
2093 // Add two main stage apps, the second in order to suspend the first
2094 var app1SurfaceId = topLevelSurfaceList.nextId;
2095 var app1 = ApplicationManager.startApplication("webbrowser-app");
2096 waitUntilAppWindowIsFullyLoaded(app1SurfaceId);
2097 var app2SurfaceId = topLevelSurfaceList.nextId;
2098 var app2 = ApplicationManager.startApplication("gallery-app");
2099 waitUntilAppWindowIsFullyLoaded(app2SurfaceId);
2102 if (data.usageScenario === "tablet") {
2103 var app1Delegate = findChild(shell, "appDelegate_" + app1SurfaceId);
2104 compare(app1Delegate.stage, ApplicationInfoInterface.MainStage);
2106 var app2Delegate = findChild(shell, "appDelegate_" + app2SurfaceId);
2107 compare(app2Delegate.stage, ApplicationInfoInterface.MainStage);
2110 var app1Surface = app1.surfaceList.get(0);
2111 verify(app1Surface);
2113 verify(!app1Surface.activeFocus);
2115 // Make sure app1 is exempt with a requested suspend
2116 verify(app1.exemptFromLifecycle);
2117 compare(app1.requestedState, ApplicationInfoInterface.RequestedSuspended);
2120 function test_switchToStagedForcesLegacyAppClosing_data() {
2122 {tag: "forceClose", replug: false, tabletMode: false, screenSize: Qt.size(units.gu(20), units.gu(40)) },
2123 {tag: "replug", replug: true, tabletMode: false, screenSize: Qt.size(units.gu(20), units.gu(40)) },
2124 {tag: "forceClose+tablet", replug: false, tabletMode: true, screenSize: Qt.size(units.gu(90), units.gu(65)) },
2125 {tag: "replug+tablet", replug: true, tabletMode: true, screenSize: Qt.size(units.gu(90), units.gu(65)) }
2129 function test_switchToStagedForcesLegacyAppClosing(data) {
2130 loadShell("desktop")
2131 shell.usageScenario = "desktop"
2132 waitForRendering(shell);
2134 // setup some screen size
2135 var dialogs = findChild(root, "dialogs");
2137 dialogs.screenSize = data.screenSize;
2139 ApplicationManager.startApplication("camera-app")
2141 shell.usageScenario = "phone"
2142 waitForRendering(shell);
2144 // No legacy app running yet... Popup must *not* show.
2145 var popup = findChild(root, "modeSwitchWarningDialog");
2146 compare(popup, null);
2148 shell.usageScenario = "desktop"
2149 waitForRendering(shell);
2151 // Now start a legacy app
2152 ApplicationManager.startApplication("libreoffice")
2154 shell.usageScenario = "phone"
2155 waitForRendering(shell);
2157 // The popup must appear now, unless in "tablet" mode
2158 popup = findChild(root, "modeSwitchWarningDialog");
2159 compare(popup !== null, !data.tabletMode);
2161 if (data.replug || data.tabletMode) {
2162 shell.usageScenario = "desktop"
2163 waitForRendering(shell);
2165 var forceCloseButton = findChild(popup, "forceCloseButton");
2166 mouseClick(forceCloseButton, forceCloseButton.width / 2, forceCloseButton.height / 2);
2167 waitForRendering(root);
2170 // Popup must be gone now
2171 popup = findChild(root, "modeSwitchWarningDialog");
2172 tryCompareFunction(function() { return popup === null}, true);
2174 if (data.replug || data.tabletMode) {
2175 // Libreoffice must still be running
2176 compare(ApplicationManager.findApplication("libreoffice") !== null, true);
2178 // Libreoffice must be gone now (or soon at least)
2179 tryCompareFunction(function() { return ApplicationManager.findApplication("libreoffice") === null}, true);
2183 function test_superTabToCycleLauncher_data() {
2185 {tag: "autohide launcher", launcherLocked: false},
2186 {tag: "locked launcher", launcherLocked: true}
2190 function test_superTabToCycleLauncher(data) {
2191 loadShell("desktop");
2192 shell.usageScenario = "desktop";
2193 waitForRendering(shell);
2194 GSettingsController.setAutohideLauncher(!data.launcherLocked);
2195 waitForRendering(shell);
2197 var stage = findChild(shell, "stage");
2198 var launcher = findChild(shell, "launcher");
2199 var launcherPanel = findChild(launcher, "launcherPanel");
2200 var firstAppInLauncher = LauncherModel.get(0).appId;
2201 compare(launcher.state, data.launcherLocked ? "visible": "");
2202 compare(launcherPanel.highlightIndex, -2);
2204 // Use Super + Tab Tab to cycle to the first entry in the launcher
2205 keyPress(Qt.Key_Super_L, Qt.MetaModifier);
2206 keyClick(Qt.Key_Tab);
2207 tryCompare(launcher, "state", "visible");
2208 tryCompare(launcherPanel, "highlightIndex", -1);
2209 keyClick(Qt.Key_Tab);
2210 tryCompare(launcherPanel, "highlightIndex", 0);
2211 keyRelease(Qt.Key_Super_L, Qt.MetaModifier);
2212 tryCompare(launcher, "state", data.launcherLocked ? "visible" : "");
2213 tryCompare(launcherPanel, "highlightIndex", -2);
2214 tryCompare(ApplicationManager, "focusedApplicationId", firstAppInLauncher);
2216 // Now go back to the dash
2217 keyPress(Qt.Key_Super_L, Qt.MetaModifier);
2218 keyClick(Qt.Key_Tab);
2219 tryCompare(launcher, "state", "visible");
2220 tryCompare(launcherPanel, "highlightIndex", -1);
2221 keyRelease(Qt.Key_Super_L, Qt.MetaModifier);
2222 tryCompare(launcher, "state", "drawer");
2223 tryCompare(launcherPanel, "highlightIndex", -2);
2226 function test_longpressSuperOpensLauncherAndShortcutsOverlay() {
2227 loadShell("desktop");
2228 var launcher = findChild(shell, "launcher");
2229 var shortcutHint = findChild(findChild(launcher, "launcherDelegate0"), "shortcutHint")
2230 var shortcutsOverlay = findChild(shell, "shortcutsOverlay");
2232 compare(launcher.state, "");
2233 keyPress(Qt.Key_Super_L, Qt.MetaModifier);
2234 waitForRendering(shortcutsOverlay);
2235 tryCompare(launcher, "state", "visible");
2236 tryCompare(shortcutHint, "visible", true);
2237 if (shortcutsOverlay.enabled) {
2238 tryCompare(shortcutsOverlay, "visible", true, 10000);
2241 keyRelease(Qt.Key_Super_L, Qt.MetaModifier);
2242 tryCompare(launcher, "state", "");
2243 tryCompare(shortcutHint, "visible", false);
2244 if (shortcutsOverlay.enabled) {
2245 tryCompare(shortcutsOverlay, "visible", false);
2249 function test_metaNumberLaunchesFromLauncher_data() {
2251 {tag: "Meta+1", key: Qt.Key_1, index: 0},
2252 {tag: "Meta+2", key: Qt.Key_2, index: 1},
2253 {tag: "Meta+4", key: Qt.Key_5, index: 4},
2254 {tag: "Meta+0", key: Qt.Key_0, index: 9},
2258 function test_metaNumberLaunchesFromLauncher(data) {
2259 loadShell("desktop");
2260 var launcher = findChild(shell, "launcher");
2261 var appId = LauncherModel.get(data.index).appId;
2262 waitForRendering(shell);
2264 keyClick(data.key, Qt.MetaModifier);
2265 tryCompare(ApplicationManager, "focusedApplicationId", appId);
2268 function test_altF1OpensLauncherForKeyboardNavigation() {
2269 loadShell("desktop");
2270 waitForRendering(shell);
2271 var launcher = findChild(shell, "launcher");
2273 keyClick(Qt.Key_F1, Qt.AltModifier);
2274 tryCompare(launcher, "state", "visible");
2275 tryCompare(launcher, "focus", true)
2278 function test_lockedOutLauncherAddsMarginsToMaximized() {
2279 loadShell("desktop");
2280 shell.usageScenario = "desktop";
2281 waitForRendering(shell);
2282 var appContainer = findChild(shell, "appContainer");
2283 var launcher = findChild(shell, "launcher");
2284 var launcherPanel = findChild(launcher, "launcherPanel");
2286 var appSurfaceId = topLevelSurfaceList.nextId;
2287 var app = ApplicationManager.startApplication("music-app");
2288 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
2289 var appDelegate = findChild(appContainer, "appDelegate_" + appSurfaceId);
2290 appDelegate.maximize();
2291 tryCompare(appDelegate, "visuallyMaximized", true);
2292 waitForRendering(shell);
2294 GSettingsController.setAutohideLauncher(true);
2295 tryCompare(launcherPanel, "x", -launcher.panelWidth)
2296 waitForRendering(shell)
2297 var hiddenSize = appDelegate.width;
2299 GSettingsController.setAutohideLauncher(false);
2300 tryCompare(launcherPanel, "x", 0)
2301 waitForRendering(shell)
2302 var shownSize = appDelegate.width;
2304 compare(shownSize + launcher.panelWidth, hiddenSize);
2307 function test_fullscreenAppHidesLockedOutLauncher() {
2308 loadShell("desktop");
2309 shell.usageScenario = "desktop";
2311 var launcher = findChild(shell, "launcher");
2312 var launcherPanel = findChild(launcher, "launcherPanel");
2314 GSettingsController.setAutohideLauncher(false);
2315 waitForRendering(shell)
2317 tryCompare(launcher, "lockedVisible", true);
2319 var surfaceId = topLevelSurfaceList.nextId;
2320 var app = ApplicationManager.startApplication("gmail-webapp");
2322 waitUntilAppWindowIsFullyLoaded(surfaceId);
2324 // Sanity check: ensure the fake app we chose creates a surface the way
2326 compare(app.surfaceList.get(0).shellChrome, Mir.NormalChrome);
2328 compare(launcher.lockedVisible, true);
2330 app.surfaceList.get(0).requestState(Mir.FullscreenState);
2332 tryCompare(launcher, "lockedVisible", false);
2336 function test_inputEventsOnEdgesEndUpInAppSurface_data() {
2343 function test_inputEventsOnEdgesEndUpInAppSurface(data) {
2344 loadShell(data.tag);
2345 shell.usageScenario = data.tag;
2346 waitForRendering(shell);
2349 // Let's open a fullscreen app
2350 var appSurfaceId = topLevelSurfaceList.nextId;
2351 var app = ApplicationManager.startApplication("camera-app");
2352 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
2354 var appRepeater = findChild(shell, "appRepeater");
2355 var topmostAppDelegate = appRepeater.itemAt(0);
2356 verify(topmostAppDelegate);
2358 var topmostSurfaceItem = findChild(topmostAppDelegate, "surfaceItem");
2359 verify(topmostSurfaceItem);
2361 mouseClick(shell, 1, shell.height / 2);
2362 compare(topmostSurfaceItem.mousePressCount, 1);
2363 compare(topmostSurfaceItem.mouseReleaseCount, 1);
2365 mouseClick(shell, shell.width - 1, shell.height / 2);
2366 compare(topmostSurfaceItem.mousePressCount, 2);
2367 compare(topmostSurfaceItem.mouseReleaseCount, 2);
2369 tap(shell, 1, shell.height / 2);
2370 compare(topmostSurfaceItem.touchPressCount, 1);
2371 compare(topmostSurfaceItem.touchReleaseCount, 1);
2373 tap(shell, shell.width - 1, shell.height / 2);
2374 compare(topmostSurfaceItem.touchPressCount, 2);
2375 compare(topmostSurfaceItem.touchReleaseCount, 2);
2378 function test_background_data() {
2381 accounts: Qt.resolvedUrl("data:image/svg+xml,<svg><rect width='100%' height='100%' fill='#dd4814'/></svg>"),
2383 output: Qt.resolvedUrl("data:image/svg+xml,<svg><rect width='100%' height='100%' fill='#dd4814'/></svg>")},
2385 {tag: "empty", accounts: "", gsettings: "", output: "defaultBackground"},
2387 {tag: "as-specified",
2388 accounts: Qt.resolvedUrl("../data/unity/backgrounds/blue.png"),
2390 output: Qt.resolvedUrl("../data/unity/backgrounds/blue.png")},
2392 {tag: "gs-specified",
2394 gsettings: Qt.resolvedUrl("../data/unity/backgrounds/red.png"),
2395 output: Qt.resolvedUrl("../data/unity/backgrounds/red.png")},
2397 {tag: "both-specified",
2398 accounts: Qt.resolvedUrl("../data/unity/backgrounds/blue.png"),
2399 gsettings: Qt.resolvedUrl("../data/unity/backgrounds/red.png"),
2400 output: Qt.resolvedUrl("../data/unity/backgrounds/blue.png")},
2403 accounts: Qt.resolvedUrl("../data/unity/backgrounds/nope.png"),
2404 gsettings: Qt.resolvedUrl("../data/unity/backgrounds/red.png"),
2405 output: Qt.resolvedUrl("../data/unity/backgrounds/red.png")},
2407 {tag: "invalid-both",
2408 accounts: Qt.resolvedUrl("../data/unity/backgrounds/nope.png"),
2409 gsettings: Qt.resolvedUrl("../data/unity/backgrounds/stillnope.png"),
2410 output: "defaultBackground"},
2413 function test_background(data) {
2415 shell.usageScenario = "phone";
2416 waitForRendering(shell);
2418 AccountsService.backgroundFile = data.accounts;
2419 GSettingsController.setPictureUri(data.gsettings);
2421 var wallpaperResolver = findChild(shell, "wallpaperResolver");
2422 if (data.output === "defaultBackground") {
2423 tryCompare(wallpaperResolver, "background", wallpaperResolver.defaultBackground);
2424 verify(!wallpaperResolver.hasCustomBackground);
2426 tryCompare(wallpaperResolver, "background", data.output);
2427 verify(wallpaperResolver.hasCustomBackground);
2431 function test_greeterModeBroadcastsApp() {
2432 setLightDMMockMode("single-pin");
2433 shellLoader.mode = "greeter";
2435 shell.usageScenario = "phone";
2436 waitForRendering(shell);
2438 dragLauncherIntoView();
2439 var appIcon = findChild(shell, "launcherDelegate0")
2442 tryCompare(broadcastUrlSpy, "count", 1);
2443 compare(broadcastUrlSpy.signalArguments[0][0], "application:///" + appIcon.appId + ".desktop");
2444 compare(ApplicationManager.count, 0); // confirm no app is open, we didn't start new app
2446 var coverPage = findChild(shell, "coverPage");
2447 tryCompare(coverPage, "showProgress", 0);
2450 function test_greeterModeBroadcastsHome() {
2451 setLightDMMockMode("single-pin");
2452 shellLoader.mode = "greeter";
2454 shell.usageScenario = "phone";
2455 waitForRendering(shell);
2457 var gallerySurfaceId = topLevelSurfaceList.nextId;
2458 var galleryApp = ApplicationManager.startApplication("gallery-app");
2459 waitUntilAppWindowIsFullyLoaded(gallerySurfaceId);
2460 compare(topLevelSurfaceList.applicationAt(0).appId, "gallery-app");
2462 dragLauncherIntoView();
2463 tap(findChild(shell, "buttonShowDashHome"));
2465 tryCompare(broadcastHomeSpy, "count", 1);
2466 compare(topLevelSurfaceList.applicationAt(0).appId, "gallery-app"); // confirm we didn't raise dash
2468 var coverPage = findChild(shell, "coverPage");
2469 tryCompare(coverPage, "showProgress", 0);
2472 function test_greeterModeDispatchesURL() {
2473 setLightDMMockMode("single-pin");
2474 shellLoader.mode = "greeter";
2476 shell.usageScenario = "phone";
2477 waitForRendering(shell);
2479 var urlDispatcher = findInvisibleChild(shell, "urlDispatcher");
2480 verify(urlDispatcher.active);
2481 urlDispatcher.urlRequested("test:"); // force signal emission
2483 tryCompare(broadcastUrlSpy, "count", 1);
2484 compare(broadcastUrlSpy.signalArguments[0][0], "test:");
2485 compare(ApplicationManager.count, 0); // confirm no app is open, we didn't start new app
2487 var coverPage = findChild(shell, "coverPage");
2488 tryCompare(coverPage, "showProgress", 0);
2491 function test_switchKeymap() {
2492 // start with phone shell
2494 shell.usageScenario = "phone";
2495 waitForRendering(shell);
2498 // configure keymaps
2499 AccountsService.keymaps = ["sk", "cz+qwerty", "fr"] // "configure" the keymaps for user
2502 var appSurfaceId = topLevelSurfaceList.nextId;
2503 var app = ApplicationManager.startApplication("dialer-app");
2504 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
2505 var appSurface = app.surfaceList.get(0);
2507 // verify the initial keymap of the newly started app is the first one from the list
2508 tryCompare(appSurface, "keymap", "sk");
2510 // try to create a prompt surface, verify it also has the same keymap
2511 app.createPromptSurface();
2512 var promptSurface = app.promptSurfaceList.get(0);
2513 verify(promptSurface);
2514 tryCompare(appSurface, "keymap", promptSurface.keymap);
2515 // ... and that the controller's surface keymap is also the same
2516 tryCompare(topLevelSurfaceList.focusedWindow.surface, "keymap", "sk");
2517 app.promptSurfaceList.get(0).close();
2519 // switch to next keymap, should go to "cz+qwerty"
2520 keyClick(Qt.Key_Space, Qt.MetaModifier);
2521 tryCompare(appSurface, "keymap", "cz+qwerty");
2523 // switch to next keymap, should go to "fr"
2524 keyClick(Qt.Key_Space, Qt.MetaModifier);
2525 tryCompare(appSurface, "keymap", "fr");
2527 // go to e.g. desktop stage
2528 shellLoader.state = "desktop";
2529 shell.usageScenario = "desktop";
2530 waitForRendering(shell);
2532 // start a second app, should get the last configured keyboard, "fr"
2533 var app2SurfaceId = topLevelSurfaceList.nextId;
2534 var app2 = ApplicationManager.startApplication("calendar-app");
2535 waitUntilAppWindowIsFullyLoaded(app2SurfaceId);
2536 var app2Surface = app2.surfaceList.get(0);
2537 tryCompare(app2Surface, "keymap", "fr");
2539 // focus our first app, make sure it also has the "fr" keymap
2540 ApplicationManager.requestFocusApplication("dialer-app");
2541 tryCompare(appSurface, "keymap", "fr");
2543 // switch to previous keymap, should be "cz+qwerty"
2544 keyClick(Qt.Key_Space, Qt.MetaModifier|Qt.ShiftModifier);
2545 tryCompare(appSurface, "keymap", "cz+qwerty");
2547 // go next twice to "sk", past the end
2548 keyClick(Qt.Key_Space, Qt.MetaModifier);
2549 keyClick(Qt.Key_Space, Qt.MetaModifier);
2550 tryCompare(appSurface, "keymap", "sk");
2552 // go back once to past the beginning, to "fr"
2553 keyClick(Qt.Key_Space, Qt.MetaModifier|Qt.ShiftModifier);
2554 tryCompare(appSurface, "keymap", "fr");
2556 // switch to app2, should also get "fr"
2557 ApplicationManager.requestFocusApplication("calendar-app");
2558 tryCompare(app2Surface, "keymap", "fr");
2561 function test_dragPanelToRestoreMaximizedWindow_data() {
2563 { tag: "with mouse", mouse: true },
2564 { tag: "with touch", mouse: false }
2568 function test_dragPanelToRestoreMaximizedWindow(data) {
2569 loadShell("desktop");
2570 shell.usageScenario = "desktop";
2571 waitForRendering(shell);
2572 var panel = findChild(shell, "windowControlArea");
2575 // start dialer, maximize it
2576 var appDelegate = startApplication("dialer-app");
2577 verify(appDelegate);
2579 var maximizeButton = findChild(appDelegate, "maximizeWindowButton");
2581 mouseClick(maximizeButton);
2583 tap(maximizeButton);
2586 waitUntilTransitionsEnd(appDelegate);
2587 tryCompare(appDelegate, "state", "maximized");
2590 mouseMove(panel, panel.width/2, panel.panelHeight/2); // to reveal the menus
2591 var menuBarLoader = findInvisibleChild(panel, "menuBarLoader");
2592 verify(menuBarLoader);
2593 tryCompare(menuBarLoader.item, "visible", true);
2594 mouseDrag(panel, panel.width/2, panel.height/2, 0, shell.height/3, Qt.LeftButton, Qt.NoModifier, 500);
2596 touchFlick(panel, panel.width/2, panel.panelHeight/2, panel.width/2, shell.height/3);
2599 tryCompare(appDelegate, "state", "restored");
2602 function test_fullShellModeHasNoInitialGreeter() {
2603 setLightDMMockMode("single-pin");
2604 shellLoader.mode = "full-shell";
2606 shell.usageScenario = "phone";
2607 waitForRendering(shell);
2609 var greeter = findChild(shell, "greeter");
2610 verify(!greeter.shown);
2611 verify(!greeter.locked);
2615 verify(greeter.shown);
2616 verify(greeter.locked);
2619 function test_closeFocusedDelegate_data() {
2627 function test_closeFocusedDelegate(data) {
2628 loadShell(data.tag);
2629 shell.usageScenario = data.tag;
2630 waitForRendering(shell);
2633 var app2SurfaceId = topLevelSurfaceList.nextId;
2634 var app2 = ApplicationManager.startApplication("calendar-app");
2635 waitUntilAppWindowIsFullyLoaded(app2SurfaceId);
2637 var app1SurfaceId = topLevelSurfaceList.nextId;
2638 var app1 = ApplicationManager.startApplication("dialer-app")
2639 waitUntilAppWindowIsFullyLoaded(app1SurfaceId);
2641 var countBeforeClose = topLevelSurfaceList.count;
2643 keyClick(Qt.Key_F4, Qt.AltModifier);
2645 tryCompare(topLevelSurfaceList, "count", countBeforeClose - 1);
2646 tryCompareFunction(function() { return ApplicationManager.focusedApplicationId; }, "calendar-app");
2649 function test_rightEdgePushWithOpenIndicators() {
2650 loadShell("desktop");
2651 shell.usageScenario = "desktop";
2652 waitForRendering(shell);
2655 var stage = findChild(shell, "stage");
2656 var cursor = findChild(shell, "cursor");
2657 var indicators = findChild(shell, "indicators");
2660 var touchX = shell.width - units.gu(5);
2662 touchX /* fromX */, indicators.minimizedPanelHeight * 0.5 /* fromY */,
2663 touchX /* toX */, shell.height * 0.9 /* toY */,
2664 true /* beginTouch */, true /* endTouch */);
2665 tryCompare(indicators, "fullyOpened", true);
2667 // push the right edge
2668 mouseMove(shell, shell.width - 1, units.gu(10));
2669 for (var i = 0; i < units.gu(10); i++) {
2670 cursor.pushedRightBoundary(1, 0);
2672 tryCompare(stage, "rightEdgePushProgress", 1);
2673 tryCompare(stage, "state", "spread");
2674 tryCompare(indicators, "fullyOpened", false);
2676 mouseMove(shell, shell.width - units.gu(5), units.gu(10));
2678 tryCompare(stage, "rightEdgePushProgress", 0);
2681 function test_rightEdgePushOnGreeter() {
2682 loadShell("desktop");
2683 shell.usageScenario = "desktop";
2684 waitForRendering(shell);
2686 var stage = findChild(shell, "stage");
2687 var cursor = findChild(shell, "cursor");
2689 // push the right edge, but verify it doesn't emit any progress
2690 mouseMove(shell, shell.width - 1, units.gu(10));
2691 for (var i = 0; i < units.gu(10); i++) {
2692 cursor.pushedRightBoundary(1, 0);
2693 compare(stage.rightEdgePushProgress, 0);
2695 compare(stage.rightEdgePushProgress, 0);
2698 function test_oskDisplacesWindow_data() {
2700 {tag: "no need to displace", windowHeight: units.gu(10), windowY: units.gu(5), targetDisplacement: units.gu(5), oskEnabled: true},
2701 {tag: "displace to top", windowHeight: units.gu(50), windowY: units.gu(10), targetDisplacement: PanelState.panelHeight, oskEnabled: true},
2702 {tag: "osk not on this screen", windowHeight: units.gu(40), windowY: units.gu(10), targetDisplacement: units.gu(10), oskEnabled: false},
2706 function test_oskDisplacesWindow(data) {
2707 loadShell("desktop");
2708 shell.usageScenario = "desktop";
2709 waitForRendering(shell);
2711 ensureInputMethodSurface();
2712 shell.oskEnabled = data.oskEnabled;
2714 var appSurfaceId = topLevelSurfaceList.nextId;
2715 var app = ApplicationManager.startApplication("unity8-dash")
2716 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
2718 var oldOSKState = topLevelSurfaceList.inputMethodSurface.state;
2719 topLevelSurfaceList.inputMethodSurface.requestState(Mir.RestoredState);
2720 var appRepeater = findChild(shell, "appRepeater");
2721 var dashAppDelegate = appRepeater.itemAt(0);
2722 verify(dashAppDelegate);
2724 dashAppDelegate.windowedHeight = data.windowHeight;
2725 dashAppDelegate.windowedY = data.windowY;
2726 topLevelSurfaceList.inputMethodSurface.setInputBounds(Qt.rect(0, 0, 0, 0));
2727 var initialY = dashAppDelegate.y;
2728 print("intial", initialY, "panel", PanelState.panelHeight);
2729 verify(initialY > PanelState.panelHeight);
2731 topLevelSurfaceList.inputMethodSurface.setInputBounds(Qt.rect(0, root.height / 2, root.width, root.height / 2));
2732 tryCompare(dashAppDelegate, "y", data.targetDisplacement);
2734 topLevelSurfaceList.inputMethodSurface.setInputBounds(Qt.rect(0, 0, 0, 0));
2735 tryCompare(dashAppDelegate, "y", initialY);
2736 topLevelSurfaceList.inputMethodSurface.requestState(oldOSKState);
2739 function test_cursorHidingWithFullscreenApp() {
2741 shell.usageScenario = "phone";
2742 waitForRendering(shell);
2745 // load some fullscreen app
2746 var cameraSurfaceId = topLevelSurfaceList.nextId;
2747 var cameraApp = ApplicationManager.startApplication("camera-app");
2748 waitUntilAppWindowIsFullyLoaded(cameraSurfaceId);
2750 var cursor = findChild(shell, "cursor");
2752 tryCompare(cursor, "opacity", 1);
2754 // let the timer kick in and verify the cursor got hidden
2756 tryCompare(cursor, "opacity", 0);
2758 // simulate moving the mouse, check the cursor is visible again
2759 cursor.mouseMoved();
2760 tryCompare(cursor, "opacity", 1);
2762 // let the timer kick in again and verify the cursor got hidden
2764 tryCompare(cursor, "opacity", 0);
2767 function test_launcherEnabledSetting_data() {
2769 {tag: "launcher enabled", enabled: true},
2770 {tag: "launcher disabled", enabled: false}
2774 function test_launcherEnabledSetting(data) {
2777 GSettingsController.setEnableLauncher(data.enabled);
2779 var launcher = findChild(shell, "launcher");
2780 compare(launcher.available, data.enabled);
2782 GSettingsController.setEnableLauncher(true);
2785 function test_indicatorMenuEnabledSetting_data() {
2787 {tag: "indicator menu enabled", enabled: true},
2788 {tag: "indicator menu disabled", enabled: false}
2792 function test_indicatorMenuEnabledSetting(data) {
2795 GSettingsController.setEnableIndicatorMenu(data.enabled);
2797 var panel = findChild(shell, "panel");
2798 compare(panel.indicators.available, data.enabled);
2800 GSettingsController.setEnableIndicatorMenu(true);
2803 function test_spreadDisabled_WithSwipe_data() {
2805 { tag: "enabled", spreadEnabled: true },
2806 { tag: "disabled", spreadEnabled: false }
2810 function test_spreadDisabled_WithSwipe(data) {
2813 var stage = findChild(shell, "stage");
2814 stage.spreadEnabled = data.spreadEnabled;
2817 touchFlick(shell, shell.width - 2, shell.height / 2, units.gu(1), shell.height / 2);
2818 tryCompare(stage, "state", data.spreadEnabled ? "spread" : "staged");
2821 function test_spreadDisabled_WithEdgePush_data() {
2823 { tag: "enabled", spreadEnabled: true },
2824 { tag: "disabled", spreadEnabled: false }
2828 function test_spreadDisabled_WithEdgePush(data) {
2831 var stage = findChild(shell, "stage");
2832 stage.spreadEnabled = data.spreadEnabled;
2835 var cursor = findChild(shell, "cursor");
2836 mouseMove(stage, stage.width - 1, units.gu(10));
2837 for (var i = 0; i < units.gu(10); i++) {
2838 cursor.pushedRightBoundary(1, 0);
2840 mouseMove(stage, stage.width - units.gu(5), units.gu(10));
2841 tryCompare(stage, "state", data.spreadEnabled ? "spread" : "staged");
2844 function test_spreadDisabled_WithAltTab_data() {
2846 { tag: "enabled", spreadEnabled: true },
2847 { tag: "disabled", spreadEnabled: false }
2851 function test_spreadDisabled_WithAltTab(data) {
2854 var stage = findChild(shell, "stage");
2855 stage.spreadEnabled = data.spreadEnabled;
2858 keyPress(Qt.Key_Alt);
2859 keyClick(Qt.Key_Tab);
2860 tryCompare(stage, "state", data.spreadEnabled ? "spread" : "staged");
2861 keyRelease(Qt.Key_Alt);
2864 function test_spreadDisabled_WithSuperW_data() {
2866 { tag: "enabled", spreadEnabled: true },
2867 { tag: "disabled", spreadEnabled: false }
2871 function test_spreadDisabled_WithSuperW(data) {
2874 var stage = findChild(shell, "stage");
2875 stage.spreadEnabled = data.spreadEnabled;
2878 keyPress(Qt.Key_W, Qt.MetaModifier, 200);
2879 tryCompare(stage, "state", data.spreadEnabled ? "spread" : "staged");
2880 keyRelease(Qt.Key_W, Qt.MetaModifier)
2883 function test_launcherWindowResizeInteraction()
2885 loadShell("desktop");
2886 waitForRendering(shell)
2887 shell.usageScenario = "desktop"
2888 waitForRendering(shell)
2891 var app1SurfaceId = topLevelSurfaceList.nextId;
2892 var app1 = ApplicationManager.startApplication("dialer-app")
2893 waitUntilAppWindowIsFullyLoaded(app1SurfaceId);
2895 var launcherDelegate1 = findChild(shell, "launcherDelegate1");
2896 mouseClick(launcherDelegate1, launcherDelegate1.width / 2, launcherDelegate1.height / 2, Qt.RightButton);
2898 var appDelegate = findChild(shell, "appDelegate_" + app1SurfaceId);
2899 mouseMove(shell, appDelegate.mapToItem(shell, 0, 0).x, launcherDelegate1.mapToItem(shell, 0, 0).y);
2901 expectFail("", "Cursor should not change while launcher menu is open");
2902 tryCompare(Mir, "cursorName", "left_side");
2905 function test_panelTitleShowsWhenGreeterNotShown_data() {
2913 function test_panelTitleShowsWhenGreeterNotShown(data) {
2914 loadShell(data.tag);
2916 var panel = findChild(shell, "panel"); verify(panel);
2917 var panelTitle = findChild(panel, "panelTitle"); verify(panelTitle);
2918 compare(panelTitle.visible, false, "Panel title should not be visible when greeter is shown");
2922 tryCompare(panelTitle, "visible", true, undefined, "Panel title should be visible when greeter not shown");
2925 function test_fourFingerTapOpensDrawer_data() {
2927 { tag: "1 finger", touchIds: [0], shown: false },
2928 { tag: "2 finger", touchIds: [0, 1], shown: false },
2929 { tag: "3 finger", touchIds: [0, 1, 2], shown: false },
2930 { tag: "4 finger", touchIds: [0, 1, 2, 3], shown: true }
2934 function test_fourFingerTapOpensDrawer(data) {
2935 loadShell("desktop");
2936 shell.usageScenario = "desktop";
2937 waitForRendering(shell);
2940 var stage = findChild(shell, "stage");
2941 var drawer = findChild(shell, "drawer")
2942 verify(stage && drawer);
2944 multiTouchTap(data.touchIds, stage);
2946 if (data.shown) { // if shown, try to also hide it by clicking outside
2947 tryCompareFunction(function() { return drawer.visible; }, true);
2948 mouseClick(stage, stage.width-10, stage.height/2, undefined, undefined, 100);
2950 tryCompareFunction(function() { return drawer.visible; }, false);
2953 function test_restoreFromFullscreen() {
2954 loadShell("desktop");
2955 shell.usageScenario = "desktop";
2956 waitForRendering(shell);
2959 var appSurfaceId = topLevelSurfaceList.nextId;
2960 var app = ApplicationManager.startApplication("dialer-app")
2961 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
2964 var appContainer = findChild(shell, "appContainer");
2965 var appDelegate = findChild(appContainer, "appDelegate_" + appSurfaceId);
2966 verify(appDelegate);
2967 tryCompare(appDelegate, "state", "normal");
2969 // now maximize to right
2970 appDelegate.requestMaximizeRight();
2971 tryCompare(appDelegate, "state", "maximizedRight");
2973 // switch to fullscreen
2974 app.surfaceList.get(0).requestState(Mir.FullscreenState);
2975 tryCompare(appDelegate, "state", "fullscreen");
2977 // restore, should go back to maximizedRight, not restored
2978 appDelegate.requestRestore();
2979 tryCompare(appDelegate, "state", "maximizedRight");
2983 function test_closeAppsInSpreadWithQ() {
2984 loadShell("desktop");
2985 shell.usageScenario = "desktop";
2986 waitForRendering(shell);
2989 var appSurfaceId = topLevelSurfaceList.nextId;
2990 var app = ApplicationManager.startApplication("unity8-dash")
2991 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
2993 appSurfaceId = topLevelSurfaceList.nextId;
2994 app = ApplicationManager.startApplication("dialer-app")
2995 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
2997 appSurfaceId = topLevelSurfaceList.nextId;
2998 app = ApplicationManager.startApplication("calendar-app")
2999 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
3001 keyPress(Qt.Key_Alt);
3002 keyClick(Qt.Key_Tab);
3004 var stage = findChild(shell, "stage");
3005 var spread = findChild(stage, "spreadItem");
3006 var appRepeater = findChild(stage, "appRepeater");
3008 tryCompare(stage, "state", "spread");
3010 tryCompare(ApplicationManager, "count", 3);
3011 tryCompareFunction(function() {return appRepeater.itemAt(spread.highlightedIndex).appId == "dialer-app"}, true);
3013 // Close one app with Q while in spread
3016 tryCompare(ApplicationManager, "count", 2);
3018 // Now the dash should be highlighted
3019 tryCompareFunction(function() {return appRepeater.itemAt(spread.highlightedIndex).appId == "unity8-dash"}, true);
3021 keyClick(Qt.Key_Tab);
3022 tryCompareFunction(function() {return appRepeater.itemAt(spread.highlightedIndex).appId == "calendar-app"}, true);
3026 tryCompare(ApplicationManager, "count", 1);
3028 keyRelease(Qt.Key_Alt);
3030 // Now start the apps again
3031 appSurfaceId = topLevelSurfaceList.nextId;
3032 app = ApplicationManager.startApplication("dialer-app");
3033 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
3035 appSurfaceId = topLevelSurfaceList.nextId;
3036 app = ApplicationManager.startApplication("calendar-app");
3037 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
3039 // First focus the dash so it'll be the leftmost in the spread
3040 ApplicationManager.requestFocusApplication("unity8-dash");
3042 keyPress(Qt.Key_Alt);
3043 keyClick(Qt.Key_Tab);
3044 tryCompare(stage, "state", "spread");
3046 // Move to the last one
3047 keyClick(Qt.Key_Tab);
3049 // Close the last one, make sure the highlight fixes itself to stick within the list
3050 tryCompare(spread, "highlightedIndex", ApplicationManager.count - 1);
3051 var oldHighlighted = spread.highlightedIndex;
3054 tryCompare(spread, "highlightedIndex", oldHighlighted - 1);
3056 keyRelease(Qt.Key_Alt);
3060 function test_altTabToMinimizedApp() {
3061 loadShell("desktop");
3062 shell.usageScenario = "desktop";
3063 waitForRendering(shell);
3066 var appSurfaceId = topLevelSurfaceList.nextId;
3067 var app = ApplicationManager.startApplication("dialer-app")
3068 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
3071 var appContainer = findChild(shell, "appContainer");
3072 var appDelegate = findChild(appContainer, "appDelegate_" + appSurfaceId);
3073 verify(appDelegate);
3074 tryCompare(appDelegate, "state", "normal");
3077 appDelegate.requestMinimize();
3078 tryCompare(appDelegate, "state", "minimized");
3080 // try to bring dialer back from minimized by doing alt-tab
3081 keyClick(Qt.Key_Tab, Qt.AltModifier);
3082 tryCompare(appDelegate, "visible", true);
3083 tryCompare(appDelegate, "focus", true);
3084 tryCompare(topLevelSurfaceList.focusedWindow, "surface", appDelegate.surface);
3085 tryCompare(topLevelSurfaceList.applicationAt(0), "appId", "dialer-app");
3088 function test_touchMenuPosition_data() {
3090 { tag: "launcher locked", lockLauncher: true },
3091 { tag: "launcher not locked", lockLauncher: false }
3095 function test_touchMenuPosition(data) {
3096 loadShell("desktop");
3097 shell.usageScenario = "desktop";
3098 waitForRendering(shell);
3101 var panel = findChild(shell, "panel");
3102 var launcher = testCase.findChild(shell, "launcher");
3103 launcher.lockedVisible = data.lockLauncher;
3104 if (data.lockLauncher) {
3105 compare(panel.applicationMenus.x, launcher.panelWidth);
3107 compare(panel.applicationMenus.x, 0);
3111 function test_touchMenuHidesOnLauncherAppDrawer_data() {
3113 { tag: "launcher locked", lockLauncher: true },
3114 { tag: "launcher not locked", lockLauncher: false }
3118 function test_touchMenuHidesOnLauncherAppDrawer(data) {
3119 loadShell("desktop");
3120 shell.usageScenario = "desktop";
3121 waitForRendering(shell);
3124 var panel = findChild(shell, "panel");
3125 var launcher = testCase.findChild(shell, "launcher");
3126 launcher.lockedVisible = data.lockLauncher;
3128 waitForRendering(panel.applicationMenus);
3130 if (data.lockLauncher) {
3131 panel.applicationMenus.show();
3132 tryCompare(panel.applicationMenus, "fullyOpened", true);
3133 launcher.openDrawer();
3135 tryCompare(launcher, "shown", false);
3136 panel.applicationMenus.show();
3137 tryCompare(panel.applicationMenus, "fullyOpened", true);
3138 launcher.switchToNextState("visible");
3140 tryCompare(panel.applicationMenus, "fullyClosed", true);
3143 function test_doubleClickPanelRestoresWindow() {
3144 loadShell("desktop");
3145 shell.usageScenario = "desktop";
3146 waitForRendering(shell);
3150 var appDelegate = startApplication("dialer-app")
3151 verify(appDelegate);
3152 tryCompare(appDelegate, "state", "normal");
3155 var decoration = findChild(appDelegate, "appWindowDecoration");
3157 mouseDoubleClickSequence(decoration);
3158 tryCompare(appDelegate, "state", "maximized");
3160 // double click the panel
3161 var panel = findChild(shell, "panel");
3163 mouseDoubleClickSequence(panel, panel.width/2, PanelState.panelHeight/2, Qt.LeftButton, Qt.NoModifier, 300);
3164 tryCompare(appDelegate, "state", "restored");
3167 function test_noMenusWithActiveCall() {
3168 loadShell("desktop");
3169 shell.usageScenario = "desktop";
3170 waitForRendering(shell);
3173 // start music-app, maximize it
3174 var appDelegate = startApplication("music-app")
3175 verify(appDelegate);
3176 appDelegate.requestMaximize();
3178 // move the mouse over panel to reveal the menus
3179 var panel = findChild(shell, "panel");
3181 mouseMove(panel, panel.width/2, panel.panelHeight/2); // to reveal the menus
3182 var menuBarLoader = findInvisibleChild(panel, "menuBarLoader");
3183 verify(menuBarLoader);
3184 tryCompare(menuBarLoader.item, "visible", true);
3186 // place a phone call
3187 callManager.foregroundCall = phoneCall;
3189 // menu bar should be hidden
3190 tryCompare(menuBarLoader, "active", false);
3191 tryCompare(menuBarLoader, "item", null);
3194 callManager.foregroundCall = null;
3196 // menu bar should be revealed
3197 tryCompare(menuBarLoader, "active", true);
3198 tryCompare(menuBarLoader.item, "visible", true);
3201 function test_enforceFocusOnStageOnAltTab() {
3202 loadShell("desktop");
3203 shell.usageScenario = "desktop";
3204 waitForRendering(shell);
3207 var appSurfaceId = topLevelSurfaceList.nextId;
3208 var app = ApplicationManager.startApplication("unity8-dash")
3209 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
3211 var appDelegate = startApplication("music-app")
3212 verify(appDelegate);
3213 waitForRendering(shell);
3215 var launcher = findChild(shell, "launcher");
3216 launcher.focus = true;
3218 var stage = findChild(shell, "stage");
3220 var spreadItem = findChild(shell, "spreadItem");
3222 compare(spreadItem.highlightedIndex, -1);
3224 keyPress(Qt.Key_Alt);
3225 keyClick(Qt.Key_Tab);
3227 tryCompare(spreadItem, "highlightedIndex", 1);
3228 tryCompare(stage, "focus", true);
3230 keyClick(Qt.Key_Tab);
3232 tryCompare(spreadItem, "highlightedIndex", 0);
3234 keyRelease(Qt.Key_Alt);
3237 function test_maximizedWindowMenuThenAltTab_data() {
3239 { tag: "show spread", showSpread: true },
3240 { tag: "do not show spread", showSpread: false },
3244 function test_maximizedWindowMenuThenAltTab(data) {
3245 loadShell("desktop");
3246 shell.usageScenario = "desktop";
3247 waitForRendering(shell);
3250 var appDelegate = startApplication("gmail-webapp");
3251 var appDelegate2 = startApplication("dialer-app");
3253 tryCompare(appDelegate2.surface, "activeFocus", true);
3255 var maximizeButton = findChild(appDelegate2, "maximizeWindowButton");
3256 mouseClick(maximizeButton);
3257 tryCompare(appDelegate2, "state", "maximized");
3259 var panel = findChild(shell, "panel");
3260 var panelMouse = findChild(panel, "windowControlArea");
3261 mouseMove(panelMouse);
3262 var panelMenu = findChild(panel, "menuBar");
3263 var menuBarLoader = findChild(panel, "menuBarLoader");
3264 mouseMove(panelMenu);
3265 var panelMenuItem = findChild(panelMenu, "menuBar-item0");
3266 tryCompare(panelMenuItem, "visible", true);
3267 Util.waitForBehaviors(shell);
3268 mouseClick(panelMenuItem);
3269 var panelMenuItemItem = findChild(panelMenu, "menuBar-item0-menu-item0-actionItem");
3270 mouseMove(panelMenuItemItem, panelMenuItemItem.width/2, panelMenuItemItem.height/2);
3271 verify(panelMenuItemItem.activeFocus);
3272 verify(panelMenuItem.__popup);
3274 keyPress(Qt.Key_Alt);
3275 keyClick(Qt.Key_Tab);
3276 if (data.showSpread) {
3277 tryCompare(stage, "spreadShown", true);
3279 tryCompareFunction(function() { return menuBarLoader.active === false; }, true);
3280 keyRelease(Qt.Key_Alt)
3282 tryCompare(appDelegate.surface, "activeFocus", true);
3284 keyPress(Qt.Key_Alt);
3285 keyClick(Qt.Key_Tab);
3286 keyRelease(Qt.Key_Alt)
3288 tryCompare(appDelegate2.surface, "activeFocus", true);
3291 function test_maximizedWindowAndMenuInPanel() {
3292 loadShell("desktop");
3293 shell.usageScenario = "desktop";
3294 waitForRendering(shell);
3297 // start music-app, maximize it
3298 var appDelegate = startApplication("music-app")
3299 verify(appDelegate);
3300 appDelegate.requestMaximize();
3301 tryCompare(appDelegate, "state", "maximized");
3303 // move the mouse over panel to reveal the menus
3304 var panel = findChild(shell, "panel");
3306 mouseMove(panel, panel.width/2, panel.panelHeight/2); // to reveal the menus
3307 var menuBar = findChild(panel, "menuBar");
3309 tryCompare(menuBar, "visible", true);
3311 // check that the menu popup appears
3312 var priv = findInvisibleChild(menuBar, "d");
3313 var menuItem0 = findChild(menuBar, "menuBar-item0");
3315 mouseMove(menuItem0, menuItem0.width/2, menuItem0.height/2, 200);
3316 tryCompare(menuItem0, "visible", true);
3317 mouseClick(menuItem0);
3318 tryCompare(priv, "currentItem", menuItem0);
3319 tryCompare(priv.currentItem, "popupVisible", true);
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list