on xenial help sign in
merge prereq
9e6b4daMichael Zanetti
src/Dash/main.cpp+2−2
@@ -98,8 +98,7 @@ int main(int argc, const char *argv[])
98 // Needed only when manually testing on a desktop.
98 // Needed only when manually testing on a desktop.
99 MouseTouchAdaptor *mouseTouchAdaptor = 0;
99 MouseTouchAdaptor *mouseTouchAdaptor = 0;
100 if (parser.isSet(mousetouchOption)) {
100 if (parser.isSet(mousetouchOption)) {
101− mouseTouchAdaptor = new MouseTouchAdaptor;
101+ mouseTouchAdaptor = MouseTouchAdaptor::instance();
102− application->installNativeEventFilter(mouseTouchAdaptor);
103 }
102 }
104
103
105 QUrl source(::qmlDirectory()+"Dash/DashApplication.qml");
104 QUrl source(::qmlDirectory()+"Dash/DashApplication.qml");
@@ -115,6 +114,7 @@ int main(int argc, const char *argv[])
115 int result = application->exec();
114 int result = application->exec();
116
115
117 delete view;
116 delete view;
117+ delete mouseTouchAdaptor;
118 delete application;
118 delete application;
119
119
120 return result;
120 return result;
src/MouseTouchAdaptor.cpp+40−4
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013,2015 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -20,12 +20,15 @@
20
20
21#include <qpa/qwindowsysteminterface.h>
21#include <qpa/qwindowsysteminterface.h>
22
22
23+#include <QCoreApplication>
23−#include <QtGui/QMouseEvent>
24+#include <QMouseEvent>
24−#include <QtTest/QTest>
25+#include <QTest>
25
26
26using QTest::QTouchEventSequence;
27using QTest::QTouchEventSequence;
27
28
28namespace {
29namespace {
30+MouseTouchAdaptor *g_instance = nullptr;
31+
29Qt::MouseButton translateMouseButton(xcb_button_t detail)
32Qt::MouseButton translateMouseButton(xcb_button_t detail)
30{
33{
31 switch (detail) {
34 switch (detail) {
@@ -39,16 +42,36 @@ Qt::MouseButton translateMouseButton(xcb_button_t detail)
39} // end of anonymous namespace
42} // end of anonymous namespace
40
43
41MouseTouchAdaptor::MouseTouchAdaptor()
44MouseTouchAdaptor::MouseTouchAdaptor()
42− : m_leftButtonIsPressed(false)
45+ : QObject(nullptr), m_leftButtonIsPressed(false), m_enabled(true)
43{
46{
47+ QCoreApplication::instance()->installNativeEventFilter(this);
48+
44 m_touchDevice = new QTouchDevice;
49 m_touchDevice = new QTouchDevice;
45 m_touchDevice->setType(QTouchDevice::TouchScreen);
50 m_touchDevice->setType(QTouchDevice::TouchScreen);
46 QWindowSystemInterface::registerTouchDevice(m_touchDevice);
51 QWindowSystemInterface::registerTouchDevice(m_touchDevice);
47}
52}
48
53
54+MouseTouchAdaptor::~MouseTouchAdaptor()
55+{
56+ g_instance = nullptr;
57+}
58+
59+MouseTouchAdaptor* MouseTouchAdaptor::instance()
60+{
61+ if (!g_instance) {
62+ g_instance = new MouseTouchAdaptor;
63+ }
64+
65+ return g_instance;
66+}
67+
49bool MouseTouchAdaptor::nativeEventFilter(const QByteArray & eventType,
68bool MouseTouchAdaptor::nativeEventFilter(const QByteArray & eventType,
50 void * message, long * /*result*/)
69 void * message, long * /*result*/)
51{
70{
71+ if (!m_enabled) {
72+ return false;
73+ }
74+
52 if (eventType != "xcb_generic_event_t") {
75 if (eventType != "xcb_generic_event_t") {
53 // wrong backend.
76 // wrong backend.
54 qWarning("MouseTouchAdaptor: XCB backend not in use. Adaptor inoperative!");
77 qWarning("MouseTouchAdaptor: XCB backend not in use. Adaptor inoperative!");
@@ -151,3 +174,16 @@ QWindow *MouseTouchAdaptor::findQWindowWithXWindowID(WId windowId)
151 Q_ASSERT(foundWindow);
174 Q_ASSERT(foundWindow);
152 return foundWindow;
175 return foundWindow;
153}
176}
177+
178+bool MouseTouchAdaptor::enabled() const
179+{
180+ return m_enabled;
181+}
182+
183+void MouseTouchAdaptor::setEnabled(bool value)
184+{
185+ if (value != m_enabled) {
186+ m_enabled = value;
187+ Q_EMIT enabledChanged(value);
188+ }
189+}
src/MouseTouchAdaptor.h+18−5
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013,2015 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -27,15 +27,26 @@ class QMouseEvent;
27class QTouchDevice;
27class QTouchDevice;
28
28
29// Transforms QMouseEvents into single-finger QTouchEvents.
29// Transforms QMouseEvents into single-finger QTouchEvents.
30−class MouseTouchAdaptor : public QAbstractNativeEventFilter {
30+class MouseTouchAdaptor : public QObject, public QAbstractNativeEventFilter {
31−
31+ Q_OBJECT
32public:
32public:
33− MouseTouchAdaptor();
33+ virtual ~MouseTouchAdaptor();
34+
35+ static MouseTouchAdaptor* instance();
34
36
35 // Filters mouse events and posts the equivalent QTouchEvents.
37 // Filters mouse events and posts the equivalent QTouchEvents.
36− virtual bool nativeEventFilter(const QByteArray & eventType, void *message, long *result);
38+ bool nativeEventFilter(const QByteArray & eventType, void *message, long *result) override;
39+
40+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
41+
42+ bool enabled() const;
43+ void setEnabled(bool value);
44+
45+Q_SIGNALS:
46+ void enabledChanged(bool value);
37
47
38private:
48private:
49+ MouseTouchAdaptor();
39
50
40 bool handleButtonPress(xcb_button_press_event_t *pressEvent);
51 bool handleButtonPress(xcb_button_press_event_t *pressEvent);
41 bool handleButtonRelease(xcb_button_release_event_t *releaseEvent);
52 bool handleButtonRelease(xcb_button_release_event_t *releaseEvent);
@@ -44,6 +55,8 @@ private:
44
55
45 QTouchDevice *m_touchDevice;
56 QTouchDevice *m_touchDevice;
46 bool m_leftButtonIsPressed;
57 bool m_leftButtonIsPressed;
58+
59+ bool m_enabled;
47};
60};
48
61
49#endif // MOUSE_TOUCH_ADAPTOR_H
62#endif // MOUSE_TOUCH_ADAPTOR_H
src/main.cpp+2−6
@@ -1,8 +1,5 @@
1/*
1/*
2− * Copyright (C) 2012-2014 Canonical, Ltd.
2+ * Copyright (C) 2012-2015 Canonical, Ltd.
3− *
4− * Authors:
5− * Gerry Boland <gerry.boland@canonical.com>
6 *
3 *
7 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -130,8 +127,7 @@ Load the testability driver");
130 // Needed only when manually testing on a desktop.
127 // Needed only when manually testing on a desktop.
131 MouseTouchAdaptor *mouseTouchAdaptor = 0;
128 MouseTouchAdaptor *mouseTouchAdaptor = 0;
132 if (parser.isSet(mousetouchOption)) {
129 if (parser.isSet(mousetouchOption)) {
133− mouseTouchAdaptor = new MouseTouchAdaptor;
130+ mouseTouchAdaptor = MouseTouchAdaptor::instance();
134− application->installNativeEventFilter(mouseTouchAdaptor);
135 }
131 }
136
132
137 QUrl source(::qmlDirectory()+"Shell.qml");
133 QUrl source(::qmlDirectory()+"Shell.qml");
tests/qmltests/CMakeLists.txt−1
@@ -21,7 +21,6 @@ set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/
21
21
22add_qml_test(. Shell)
22add_qml_test(. Shell)
23add_qml_test(. ShellWithPin)
23add_qml_test(. ShellWithPin)
24−add_qml_test(. TabletShell)
25add_qml_test(Components Background)
24add_qml_test(Components Background)
26add_qml_test(Components Carousel)
25add_qml_test(Components Carousel)
27add_qml_test(Components Dialogs)
26add_qml_test(Components Dialogs)
tests/qmltests/Panel/tst_Panel.qml+10−2
@@ -17,7 +17,7 @@
17import QtQuick 2.1
17import QtQuick 2.1
18import QtQuick.Layouts 1.1
18import QtQuick.Layouts 1.1
19import QtTest 1.0
19import QtTest 1.0
20−import Unity.Test 0.1 as UT
20+import Unity.Test 0.1
21import Ubuntu.Components 0.1
21import Ubuntu.Components 0.1
22import Unity.Indicators 0.1 as Indicators
22import Unity.Indicators 0.1 as Indicators
23import Ubuntu.Telephony 0.1 as Telephony
23import Ubuntu.Telephony 0.1 as Telephony
@@ -121,6 +121,14 @@ IndicatorTest {
121 }
121 }
122 }
122 }
123 }
123 }
124+
125+ Rectangle {
126+ Layout.preferredHeight: units.dp(1);
127+ Layout.fillWidth: true;
128+ color: "black"
129+ }
130+
131+ MouseTouchEmulationCheckbox {}
124 }
132 }
125 }
133 }
126
134
@@ -129,7 +137,7 @@ IndicatorTest {
129 phoneNumber: "+447812221111"
137 phoneNumber: "+447812221111"
130 }
138 }
131
139
132− UT.UnityTestCase {
140+ UnityTestCase {
133 name: "Panel"
141 name: "Panel"
134 when: windowShown
142 when: windowShown
135
143
tests/qmltests/tst_Shell.qml+336−76
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013-2014 Canonical, Ltd.
2+ * Copyright (C) 2013-2015 Canonical, Ltd.
3 *
3 *
4 * Authors:
4 * Authors:
5 * Daniel d'Andrada <daniel.dandrada@canonical.com>
5 * Daniel d'Andrada <daniel.dandrada@canonical.com>
@@ -29,14 +29,15 @@ import Unity.Application 0.1
29import Unity.Connectivity 0.1
29import Unity.Connectivity 0.1
30import Unity.Indicators 0.1
30import Unity.Indicators 0.1
31import Unity.Notifications 1.0
31import Unity.Notifications 1.0
32−import Unity.Test 0.1 as UT
32+import Unity.Test 0.1
33import Powerd 0.1
33import Powerd 0.1
34
34
35import "../../qml"
35import "../../qml"
36
36
37−Item {
37+Rectangle {
38 id: root
38 id: root
39+ color: "grey"
39− width: units.gu(60)
40+ width: units.gu(100) + controls.width
40 height: units.gu(71)
41 height: units.gu(71)
41
42
42 Component.onCompleted: {
43 Component.onCompleted: {
@@ -62,12 +63,37 @@ Item {
62 }
63 }
63 }
64 }
64
65
65− Row {
66+ Item {
66− anchors.fill: parent
67+ anchors.left: root.left
68+ anchors.right: controls.left
69+ anchors.top: root.top
70+ anchors.bottom: root.bottom
67 Loader {
71 Loader {
68 id: shellLoader
72 id: shellLoader
69 focus: true
73 focus: true
70
74
75+ anchors.centerIn: parent
76+
77+ state: "phone"
78+ states: [
79+ State {
80+ name: "phone"
81+ PropertyChanges {
82+ target: shellLoader
83+ width: units.gu(40)
84+ height: units.gu(71)
85+ }
86+ },
87+ State {
88+ name: "tablet"
89+ PropertyChanges {
90+ target: shellLoader
91+ width: units.gu(100)
92+ height: units.gu(71)
93+ }
94+ }
95+ ]
96+
71 active: false
97 active: false
72 property bool itemDestroyed: false
98 property bool itemDestroyed: false
73 sourceComponent: Component {
99 sourceComponent: Component {
@@ -80,43 +106,58 @@ Item {
80 }
106 }
81 }
107 }
82 }
108 }
109+ }
110+
111+ Rectangle {
112+ id: controls
113+ color: "darkgrey"
114+ width: units.gu(30)
115+ anchors.top: root.top
116+ anchors.bottom: root.bottom
117+ anchors.right: root.right
118+
119+ Column {
120+ anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
121+ spacing: units.gu(1)
122+ Row {
123+ anchors { left: parent.left; right: parent.right }
124+ Button {
125+ text: "Show Greeter"
126+ activeFocusOnPress: false
127+ onClicked: {
128+ if (shellLoader.status !== Loader.Ready)
129+ return;
83
130
84− Rectangle {
85− color: "darkgrey"
86− width: units.gu(30)
87− height: shellLoader.height
88−
89− Column {
90− anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
91− spacing: units.gu(1)
92− Row {
93− anchors { left: parent.left; right: parent.right }
94− Button {
95− text: "Show Greeter"
96− activeFocusOnPress: false
97− onClicked: {
98− if (shellLoader.status !== Loader.Ready)
99− return;
100−
101− var greeter = testCase.findChild(shellLoader.item, "greeter");
131+ var greeter = testCase.findChild(shellLoader.item, "greeter");
102− if (!greeter.shown) {
132+ if (!greeter.shown) {
103− LightDM.Greeter.showGreeter();
133+ LightDM.Greeter.showGreeter();
104− }
105 }
134 }
106 }
135 }
107 }
136 }
137+ }
108− ListItem.ItemSelector {
138+ ListItem.ItemSelector {
109− anchors { left: parent.left; right: parent.right }
139+ anchors { left: parent.left; right: parent.right }
110− activeFocusOnPress: false
140+ activeFocusOnPress: false
111− text: "LightDM mock mode"
141+ text: "LightDM mock mode"
112− model: ["single", "single-passphrase", "single-pin"]
142+ model: ["single", "single-passphrase", "single-pin", "full"]
113− onSelectedIndexChanged: {
143+ onSelectedIndexChanged: {
114− shellLoader.active = false;
144+ shellLoader.active = false;
115− LightDM.Greeter.mockMode = model[selectedIndex];
145+ LightDM.Greeter.mockMode = model[selectedIndex];
116− LightDM.Users.mockMode = model[selectedIndex];
146+ LightDM.Users.mockMode = model[selectedIndex];
117− shellLoader.active = true;
147+ shellLoader.active = true;
118− }
148+ }
149+ }
150+ ListItem.ItemSelector {
151+ anchors { left: parent.left; right: parent.right }
152+ activeFocusOnPress: false
153+ text: "Size"
154+ model: ["phone", "tablet"]
155+ onSelectedIndexChanged: {
156+ shellLoader.active = false;
157+ shellLoader.state = model[selectedIndex];
158+ shellLoader.active = true;
119 }
159 }
160+ MouseTouchEmulationCheckbox { color: "white" }
120 }
161 }
121 }
162 }
122 }
163 }
@@ -178,7 +219,7 @@ Item {
178 phoneNumber: "+447812221111"
219 phoneNumber: "+447812221111"
179 }
220 }
180
221
181− UT.UnityTestCase {
222+ UnityTestCase {
182 id: testCase
223 id: testCase
183 name: "Shell"
224 name: "Shell"
184 when: windowShown
225 when: windowShown
@@ -186,20 +227,49 @@ Item {
186 property Item shell: shellLoader.status === Loader.Ready ? shellLoader.item : null
227 property Item shell: shellLoader.status === Loader.Ready ? shellLoader.item : null
187
228
188 function init() {
229 function init() {
189− tryCompare(shell, "enabled", true); // enabled by greeter when ready
230+ if (shellLoader.active) {
190− shell.indicatorProfile = "phone";
231+ // happens for the very first test function as shell
232+ // is loaded by default
233+ tearDown();
234+ }
191
235
192− swipeAwayGreeter();
236+ }
237+
238+ function cleanup() {
239+ tryCompare(shell, "enabled", true); // make sure greeter didn't leave us in disabled state
240+ tearDown();
241+ }
242+
243+ function loadShell(formFactor) {
244+ shellLoader.state = formFactor;
245+ shellLoader.active = true;
246+ tryCompare(shellLoader, "status", Loader.Ready);
247+ removeTimeConstraintsFromDirectionalDragAreas(shellLoader.item);
248+ tryCompare(shell, "enabled", true); // enabled by greeter when ready
193
249
194 sessionSpy.target = findChild(shell, "greeter")
250 sessionSpy.target = findChild(shell, "greeter")
195 dashCommunicatorSpy.target = findInvisibleChild(shell, "dashCommunicator");
251 dashCommunicatorSpy.target = findInvisibleChild(shell, "dashCommunicator");
196
252
197 var launcher = findChild(shell, "launcher");
253 var launcher = findChild(shell, "launcher");
198 launcherShowDashHomeSpy.target = launcher;
254 launcherShowDashHomeSpy.target = launcher;
255+
256+ waitForGreeterToStabilize();
199 }
257 }
200
258
201− function cleanup() {
259+ function waitForGreeterToStabilize() {
202− tryCompare(shell, "enabled", true); // make sure greeter didn't leave us in disabled state
260+ var greeter = findChild(shell, "greeter");
261+ verify(greeter);
262+
263+ var loginList = findChild(greeter, "loginList");
264+ // Only present in WideView
265+ if (loginList) {
266+ var userList = findChild(loginList, "userList");
267+ verify(userList);
268+ tryCompare(userList, "movingInternally", false);
269+ }
270+ }
271+
272+ function tearDown() {
203 launcherShowDashHomeSpy.target = null;
273 launcherShowDashHomeSpy.target = null;
204
274
205 shellLoader.itemDestroyed = false;
275 shellLoader.itemDestroyed = false;
@@ -216,17 +286,17 @@ Item {
216 // Shell instance gets destroyed.
286 // Shell instance gets destroyed.
217 tryCompare(shellLoader, "itemDestroyed", true);
287 tryCompare(shellLoader, "itemDestroyed", true);
218
288
289+ setLightDMMockMode("single"); // back to the default value
290+
291+ AccountsService.demoEdges = false;
292+
219 // kill all (fake) running apps
293 // kill all (fake) running apps
220 killApps(ApplicationManager);
294 killApps(ApplicationManager);
221
295
222 unlockAllModemsSpy.clear()
296 unlockAllModemsSpy.clear()
223 LightDM.Greeter.authenticate(""); // reset greeter
297 LightDM.Greeter.authenticate(""); // reset greeter
224
298
225− // reload our test subject to get it in a fresh state once again
299+ sessionSpy.clear();
226− shellLoader.active = true;
227−
228− tryCompare(shellLoader, "status", Loader.Ready);
229− removeTimeConstraintsFromDirectionalDragAreas(shellLoader.item);
230 }
300 }
231
301
232 function killApps() {
302 function killApps() {
@@ -238,6 +308,8 @@ Item {
238 }
308 }
239
309
240 function test_snapDecisionDismissalReturnsFocus() {
310 function test_snapDecisionDismissalReturnsFocus() {
311+ loadShell("phone");
312+ swipeAwayGreeter();
241 var notifications = findChild(shell, "notificationList");
313 var notifications = findChild(shell, "notificationList");
242 var app = ApplicationManager.startApplication("camera-app");
314 var app = ApplicationManager.startApplication("camera-app");
243 var stage = findChild(shell, "stage")
315 var stage = findChild(shell, "stage")
@@ -296,19 +368,41 @@ Item {
296 mockNotificationsModel.append(n)
368 mockNotificationsModel.append(n)
297 }
369 }
298
370
299− function test_leftEdgeDrag_data() {
371+ function test_phoneLeftEdgeDrag_data() {
300 return [
372 return [
373+ {tag: "without launcher",
301− {tag: "without launcher", revealLauncher: false, swipeLength: units.gu(27), appHides: true, focusedApp: "dialer-app", launcherHides: true, greeterShown: false},
374+ revealLauncher: false, swipeLength: units.gu(27), appHides: true, focusedApp: "dialer-app",
375+ launcherHides: true, greeterShown: false},
376+
377+ {tag: "with launcher",
302− {tag: "with launcher", revealLauncher: true, swipeLength: units.gu(27), appHides: true, focusedApp: "dialer-app", launcherHides: true, greeterShown: false},
378+ revealLauncher: true, swipeLength: units.gu(27), appHides: true, focusedApp: "dialer-app",
379+ launcherHides: true, greeterShown: false},
380+
381+ {tag: "small swipe",
303− {tag: "small swipe", revealLauncher: false, swipeLength: units.gu(25), appHides: false, focusedApp: "dialer-app", launcherHides: false, greeterShown: false},
382+ revealLauncher: false, swipeLength: units.gu(25), appHides: false, focusedApp: "dialer-app",
383+ launcherHides: false, greeterShown: false},
384+
385+ {tag: "long swipe",
304− {tag: "long swipe", revealLauncher: false, swipeLength: units.gu(27), appHides: true, focusedApp: "dialer-app", launcherHides: true, greeterShown: false},
386+ revealLauncher: false, swipeLength: units.gu(27), appHides: true, focusedApp: "dialer-app",
387+ launcherHides: true, greeterShown: false},
388+
389+ {tag: "small swipe with greeter",
305− {tag: "small swipe with greeter", revealLauncher: false, swipeLength: units.gu(25), appHides: false, focusedApp: "dialer-app", launcherHides: false, greeterShown: true},
390+ revealLauncher: false, swipeLength: units.gu(25), appHides: false, focusedApp: "dialer-app",
391+ launcherHides: false, greeterShown: true},
392+
393+ {tag: "long swipe with greeter",
306− {tag: "long swipe with greeter", revealLauncher: false, swipeLength: units.gu(27), appHides: true, focusedApp: "dialer-app", launcherHides: true, greeterShown: true},
394+ revealLauncher: false, swipeLength: units.gu(27), appHides: true, focusedApp: "dialer-app",
395+ launcherHides: true, greeterShown: true},
396+
397+ {tag: "swipe over dash",
307− {tag: "swipe over dash", revealLauncher: false, swipeLength: units.gu(27), appHides: true, focusedApp: "unity8-dash", launcherHides: false, greeterShown: false},
398+ revealLauncher: false, swipeLength: units.gu(27), appHides: true, focusedApp: "unity8-dash",
399+ launcherHides: false, greeterShown: false},
308 ];
400 ];
309 }
401 }
310
402
311− function test_leftEdgeDrag(data) {
403+ function test_phoneLeftEdgeDrag(data) {
404+ loadShell("phone");
405+ swipeAwayGreeter();
312 dragLauncherIntoView();
406 dragLauncherIntoView();
313 tapOnAppIconInLauncher();
407 tapOnAppIconInLauncher();
314 waitUntilApplicationWindowIsFullyVisible();
408 waitUntilApplicationWindowIsFullyVisible();
@@ -341,7 +435,32 @@ Item {
341 compare(animateTimer.nextState, "visible");
435 compare(animateTimer.nextState, "visible");
342 }
436 }
343
437
438+ function test_tabletLeftEdgeDrag_data() {
439+ return [
440+ {tag: "without password", user: "no-password", loggedIn: true, demo: false},
441+ {tag: "with password", user: "has-password", loggedIn: false, demo: false},
442+ {tag: "with demo", user: "has-password", loggedIn: true, demo: true},
443+ ]
444+ }
445+
446+ function test_tabletLeftEdgeDrag(data) {
447+ setLightDMMockMode("full");
448+ loadShell("tablet");
449+
450+ selectUser(data.user)
451+
452+ AccountsService.demoEdges = data.demo
453+ var tutorial = findChild(shell, "tutorial");
454+ tryCompare(tutorial, "running", data.demo);
455+
456+ swipeFromLeftEdge(shell.width * 0.75)
457+ wait(500) // to give time to handle dash() signal from Launcher
458+ confirmLoggedIn(data.loggedIn)
459+ }
460+
344 function test_suspend() {
461 function test_suspend() {
462+ loadShell("phone");
463+ swipeAwayGreeter();
345 var greeter = findChild(shell, "greeter");
464 var greeter = findChild(shell, "greeter");
346
465
347 // Launch an app from the launcher
466 // Launch an app from the launcher
@@ -401,6 +520,60 @@ Item {
401 waitForRendering(greeter);
520 waitForRendering(greeter);
402 }
521 }
403
522
523+ function selectUserAtIndex(i) {
524+ // We could be anywhere in list; find target index to know which direction
525+ var greeter = findChild(shell, "greeter")
526+ var userlist = findChild(greeter, "userList")
527+ if (userlist.currentIndex == i)
528+ keyClick(Qt.Key_Escape) // Reset state if we're not moving
529+ while (userlist.currentIndex != i) {
530+ var next = userlist.currentIndex + 1
531+ if (userlist.currentIndex > i) {
532+ next = userlist.currentIndex - 1
533+ }
534+ tap(findChild(greeter, "username"+next));
535+ tryCompare(userlist, "currentIndex", next)
536+ tryCompare(userlist, "movingInternally", false)
537+ }
538+ }
539+
540+ function selectUser(name) {
541+ // Find index of user with the right name
542+ for (var i = 0; i < LightDM.Users.count; i++) {
543+ if (LightDM.Users.data(i, LightDM.UserRoles.NameRole) == name) {
544+ break
545+ }
546+ }
547+ if (i == LightDM.Users.count) {
548+ fail("Didn't find name")
549+ return -1
550+ }
551+ selectUserAtIndex(i)
552+ return i
553+ }
554+
555+ function clickPasswordInput(isButton) {
556+ var greeter = findChild(shell, "greeter")
557+ tryCompare(greeter, "fullyShown", true);
558+
559+ var passwordMouseArea = findChild(shell, "passwordMouseArea")
560+ tryCompare(passwordMouseArea, "enabled", isButton)
561+
562+ var passwordInput = findChild(shell, "passwordInput")
563+ mouseClick(passwordInput)
564+ }
565+
566+ function confirmLoggedIn(loggedIn) {
567+ var greeter = findChild(shell, "greeter");
568+ tryCompare(greeter, "shown", loggedIn ? false : true);
569+ verify(loggedIn ? sessionSpy.count > 0 : sessionSpy.count === 0);
570+ }
571+
572+ function setLightDMMockMode(mode) {
573+ LightDM.Greeter.mockMode = mode;
574+ LightDM.Users.mockMode = mode;
575+ }
576+
404 /*
577 /*
405 Regression test for bug https://bugs.launchpad.net/touch-preview-images/+bug/1193419
578 Regression test for bug https://bugs.launchpad.net/touch-preview-images/+bug/1193419
406
579
@@ -413,6 +586,8 @@ Item {
413 - verify the setCurrentScope() D-Bus call to the dash has been called for the correct scope id.
586 - verify the setCurrentScope() D-Bus call to the dash has been called for the correct scope id.
414 */
587 */
415 function test_minimizingAppTakesToDashApps() {
588 function test_minimizingAppTakesToDashApps() {
589+ loadShell("phone");
590+ swipeAwayGreeter();
416 dragLauncherIntoView();
591 dragLauncherIntoView();
417
592
418 // Launch an app from the launcher
593 // Launch an app from the launcher
@@ -433,6 +608,8 @@ Item {
433 }
608 }
434
609
435 function test_showInputMethod() {
610 function test_showInputMethod() {
611+ loadShell("phone");
612+ swipeAwayGreeter();
436 var item = findChild(shell, "inputMethod");
613 var item = findChild(shell, "inputMethod");
437 var surface = SurfaceManager.inputMethodSurface();
614 var surface = SurfaceManager.inputMethodSurface();
438
615
@@ -471,6 +648,8 @@ Item {
471 }
648 }
472
649
473 function test_surfaceLosesActiveFocusWhilePanelIsOpen() {
650 function test_surfaceLosesActiveFocusWhilePanelIsOpen() {
651+ loadShell("phone");
652+ swipeAwayGreeter();
474 var app = ApplicationManager.startApplication("dialer-app");
653 var app = ApplicationManager.startApplication("dialer-app");
475 waitUntilAppWindowIsFullyLoaded(app);
654 waitUntilAppWindowIsFullyLoaded(app);
476
655
@@ -501,28 +680,26 @@ Item {
501 tryCompare(app.session.surface, "activeFocus", true);
680 tryCompare(app.session.surface, "activeFocus", true);
502 }
681 }
503
682
683+ function test_launchedAppHasActiveFocus_data() {
684+ return [
685+ {tag:"phone", formFactor:"phone"},
686+ {tag:"tablet", formFactor:"tablet"},
687+ ];
688+ }
689+
504− function test_launchedAppHasActiveFocus() {
690+ function test_launchedAppHasActiveFocus(data) {
691+ loadShell(data.formFactor);
692+ swipeAwayGreeter();
693+
505− var dialerApp = ApplicationManager.startApplication("dialer-app");
694+ var dialerApp = ApplicationManager.startApplication("webbrowser-app");
506 verify(dialerApp);
695 verify(dialerApp);
507− waitUntilAppSurfaceShowsUp("dialer-app")
696+ waitUntilAppSurfaceShowsUp("webbrowser-app")
508
697
509 verify(dialerApp.session.surface);
698 verify(dialerApp.session.surface);
510
699
511 tryCompare(dialerApp.session.surface, "activeFocus", true);
700 tryCompare(dialerApp.session.surface, "activeFocus", true);
512 }
701 }
513
702
514− // Wait for the whole UI to settle down
515− function waitForUIToSettle() {
516− var launcher = findChild(shell, "launcherPanel")
517− tryCompareFunction(function() {return launcher.x === 0 || launcher.x === -launcher.width;}, true);
518− if (launcher.x === 0) {
519− mouseClick(shell)
520− }
521− tryCompare(launcher, "x", -launcher.width)
522−
523− waitForRendering(shell)
524− }
525−
526 function waitUntilAppSurfaceShowsUp(appId) {
703 function waitUntilAppSurfaceShowsUp(appId) {
527 var appWindow = findChild(shell, "appWindow_" + appId);
704 var appWindow = findChild(shell, "appWindow_" + appId);
528 verify(appWindow);
705 verify(appWindow);
@@ -615,6 +792,8 @@ Item {
615 }
792 }
616
793
617 function test_greeterDoesNotChangeIndicatorProfile() {
794 function test_greeterDoesNotChangeIndicatorProfile() {
795+ loadShell("phone");
796+ swipeAwayGreeter();
618 var panel = findChild(shell, "panel");
797 var panel = findChild(shell, "panel");
619 tryCompare(panel.indicators.indicatorsModel, "profile", shell.indicatorProfile);
798 tryCompare(panel.indicators.indicatorsModel, "profile", shell.indicatorProfile);
620
799
@@ -626,6 +805,8 @@ Item {
626 }
805 }
627
806
628 function test_shellProfileChangesReachIndicators() {
807 function test_shellProfileChangesReachIndicators() {
808+ loadShell("phone");
809+ swipeAwayGreeter();
629 var panel = findChild(shell, "panel");
810 var panel = findChild(shell, "panel");
630
811
631 shell.indicatorProfile = "test1";
812 shell.indicatorProfile = "test1";
@@ -642,6 +823,8 @@ Item {
642 }
823 }
643
824
644 function test_focusRequestedHidesGreeter() {
825 function test_focusRequestedHidesGreeter() {
826+ loadShell("phone");
827+ swipeAwayGreeter();
645 var greeter = findChild(shell, "greeter");
828 var greeter = findChild(shell, "greeter");
646
829
647 var app = ApplicationManager.startApplication("dialer-app");
830 var app = ApplicationManager.startApplication("dialer-app");
@@ -662,6 +845,8 @@ Item {
662 }
845 }
663
846
664 function test_focusRequestedHidesIndicators() {
847 function test_focusRequestedHidesIndicators() {
848+ loadShell("phone");
849+ swipeAwayGreeter();
665 var indicators = findChild(shell, "indicators");
850 var indicators = findChild(shell, "indicators");
666
851
667 showIndicators();
852 showIndicators();
@@ -674,6 +859,8 @@ Item {
674 }
859 }
675
860
676 function test_showAndHideGreeterDBusCalls() {
861 function test_showAndHideGreeterDBusCalls() {
862+ loadShell("phone");
863+ swipeAwayGreeter();
677 var greeter = findChild(shell, "greeter")
864 var greeter = findChild(shell, "greeter")
678 tryCompare(greeter, "shown", false)
865 tryCompare(greeter, "shown", false)
679 waitForRendering(greeter);
866 waitForRendering(greeter);
@@ -685,6 +872,9 @@ Item {
685 }
872 }
686
873
687 function test_greeterLoginsAutomaticallyWhenNoPasswordSet() {
874 function test_greeterLoginsAutomaticallyWhenNoPasswordSet() {
875+ loadShell("phone");
876+ swipeAwayGreeter();
877+
688 sessionSpy.clear();
878 sessionSpy.clear();
689 verify(sessionSpy.valid);
879 verify(sessionSpy.valid);
690
880
@@ -694,6 +884,8 @@ Item {
694 }
884 }
695
885
696 function test_fullscreen() {
886 function test_fullscreen() {
887+ loadShell("phone");
888+ swipeAwayGreeter();
697 var panel = findChild(shell, "panel");
889 var panel = findChild(shell, "panel");
698 compare(panel.fullscreenMode, false);
890 compare(panel.fullscreenMode, false);
699 ApplicationManager.startApplication("camera-app");
891 ApplicationManager.startApplication("camera-app");
@@ -707,6 +899,8 @@ Item {
707 }
899 }
708
900
709 function test_leftEdgeDragFullscreen() {
901 function test_leftEdgeDragFullscreen() {
902+ loadShell("phone");
903+ swipeAwayGreeter();
710 var panel = findChild(shell, "panel");
904 var panel = findChild(shell, "panel");
711 tryCompare(panel, "fullscreenMode", false)
905 tryCompare(panel, "fullscreenMode", false)
712
906
@@ -728,6 +922,8 @@ Item {
728 }
922 }
729
923
730 function test_unlockedProperties() {
924 function test_unlockedProperties() {
925+ loadShell("phone");
926+ swipeAwayGreeter();
731 // Confirm that various properties have the correct values when unlocked
927 // Confirm that various properties have the correct values when unlocked
732 var greeter = findChild(shell, "greeter");
928 var greeter = findChild(shell, "greeter");
733 tryCompare(greeter, "locked", false);
929 tryCompare(greeter, "locked", false);
@@ -740,10 +936,14 @@ Item {
740 }
936 }
741
937
742 function test_unlockAllModemsOnBoot() {
938 function test_unlockAllModemsOnBoot() {
939+ loadShell("phone");
940+ swipeAwayGreeter();
743 tryCompare(unlockAllModemsSpy, "count", 1)
941 tryCompare(unlockAllModemsSpy, "count", 1)
744 }
942 }
745
943
746 function test_tapOnRightEdgeReachesApplicationSurface() {
944 function test_tapOnRightEdgeReachesApplicationSurface() {
945+ loadShell("phone");
946+ swipeAwayGreeter();
747 var topmostSpreadDelegate = findChild(shell, "appDelegate0");
947 var topmostSpreadDelegate = findChild(shell, "appDelegate0");
748 var topmostSurface = findChild(topmostSpreadDelegate, "surfaceContainer").surface;
948 var topmostSurface = findChild(topmostSpreadDelegate, "surfaceContainer").surface;
749 var rightEdgeDragArea = findChild(shell, "spreadDragArea");
949 var rightEdgeDragArea = findChild(shell, "spreadDragArea");
@@ -766,6 +966,8 @@ Item {
766 by the right-edge drag area)
966 by the right-edge drag area)
767 */
967 */
768 function test_rightEdgeDragDoesNotReachApplicationSurface() {
968 function test_rightEdgeDragDoesNotReachApplicationSurface() {
969+ loadShell("phone");
970+ swipeAwayGreeter();
769 var topmostSpreadDelegate = findChild(shell, "appDelegate0");
971 var topmostSpreadDelegate = findChild(shell, "appDelegate0");
770 var topmostSurface = findChild(topmostSpreadDelegate, "surfaceContainer").surface;
972 var topmostSurface = findChild(topmostSpreadDelegate, "surfaceContainer").surface;
771 var rightEdgeDragArea = findChild(shell, "spreadDragArea");
973 var rightEdgeDragArea = findChild(shell, "spreadDragArea");
@@ -810,6 +1012,8 @@ Item {
810 }
1012 }
811
1013
812 function test_tapUbuntuIconInLauncherOverAppSpread() {
1014 function test_tapUbuntuIconInLauncherOverAppSpread() {
1015+ loadShell("phone");
1016+ swipeAwayGreeter();
813
1017
814 waitUntilFocusedApplicationIsShowingItsSurface();
1018 waitUntilFocusedApplicationIsShowingItsSurface();
815
1019
@@ -856,19 +1060,75 @@ Item {
856 function test_background_data() {
1060 function test_background_data() {
857 return [
1061 return [
858 {tag: "color", accounts: Qt.resolvedUrl("data:image/svg+xml,<svg><rect width='100%' height='100%' fill='#dd4814'/></svg>"), gsettings: "", output: Qt.resolvedUrl("data:image/svg+xml,<svg><rect width='100%' height='100%' fill='#dd4814'/></svg>")},
1062 {tag: "color", accounts: Qt.resolvedUrl("data:image/svg+xml,<svg><rect width='100%' height='100%' fill='#dd4814'/></svg>"), gsettings: "", output: Qt.resolvedUrl("data:image/svg+xml,<svg><rect width='100%' height='100%' fill='#dd4814'/></svg>")},
859− {tag: "empty", accounts: "", gsettings: "", output: shell.defaultBackground},
1063+ {tag: "empty", accounts: "", gsettings: "", output: "defaultBackground"},
860 {tag: "as-specified", accounts: Qt.resolvedUrl("../data/unity/backgrounds/blue.png"), gsettings: "", output: Qt.resolvedUrl("../data/unity/backgrounds/blue.png")},
1064 {tag: "as-specified", accounts: Qt.resolvedUrl("../data/unity/backgrounds/blue.png"), gsettings: "", output: Qt.resolvedUrl("../data/unity/backgrounds/blue.png")},
861 {tag: "gs-specified", accounts: "", gsettings: Qt.resolvedUrl("../data/unity/backgrounds/red.png"), output: Qt.resolvedUrl("../data/unity/backgrounds/red.png")},
1065 {tag: "gs-specified", accounts: "", gsettings: Qt.resolvedUrl("../data/unity/backgrounds/red.png"), output: Qt.resolvedUrl("../data/unity/backgrounds/red.png")},
862 {tag: "both-specified", accounts: Qt.resolvedUrl("../data/unity/backgrounds/blue.png"), gsettings: Qt.resolvedUrl("../data/unity/backgrounds/red.png"), output: Qt.resolvedUrl("../data/unity/backgrounds/blue.png")},
1066 {tag: "both-specified", accounts: Qt.resolvedUrl("../data/unity/backgrounds/blue.png"), gsettings: Qt.resolvedUrl("../data/unity/backgrounds/red.png"), output: Qt.resolvedUrl("../data/unity/backgrounds/blue.png")},
863 {tag: "invalid-as", accounts: Qt.resolvedUrl("../data/unity/backgrounds/nope.png"), gsettings: Qt.resolvedUrl("../data/unity/backgrounds/red.png"), output: Qt.resolvedUrl("../data/unity/backgrounds/red.png")},
1067 {tag: "invalid-as", accounts: Qt.resolvedUrl("../data/unity/backgrounds/nope.png"), gsettings: Qt.resolvedUrl("../data/unity/backgrounds/red.png"), output: Qt.resolvedUrl("../data/unity/backgrounds/red.png")},
864− {tag: "invalid-both", accounts: Qt.resolvedUrl("../data/unity/backgrounds/nope.png"), gsettings: Qt.resolvedUrl("../data/unity/backgrounds/stillnope.png"), output: shell.defaultBackground},
1068+ {tag: "invalid-both", accounts: Qt.resolvedUrl("../data/unity/backgrounds/nope.png"), gsettings: Qt.resolvedUrl("../data/unity/backgrounds/stillnope.png"), output: "defaultBackground"},
865 ]
1069 ]
866 }
1070 }
867 function test_background(data) {
1071 function test_background(data) {
1072+ loadShell("phone");
1073+ swipeAwayGreeter();
868 AccountsService.backgroundFile = data.accounts;
1074 AccountsService.backgroundFile = data.accounts;
869 var backgroundSettings = findInvisibleChild(shell, "backgroundSettings");
1075 var backgroundSettings = findInvisibleChild(shell, "backgroundSettings");
870 backgroundSettings.pictureUri = data.gsettings;
1076 backgroundSettings.pictureUri = data.gsettings;
1077+
1078+ if (data.output === "defaultBackground") {
1079+ tryCompare(shell, "background", shell.defaultBackground);
1080+ } else {
871− tryCompare(shell, "background", data.output);
1081+ tryCompare(shell, "background", data.output);
1082+ }
1083+ }
1084+
1085+ function test_tabletLogin_data() {
1086+ return [
1087+ {tag: "auth error", user: "auth-error", loggedIn: false, password: ""},
1088+ {tag: "with password", user: "has-password", loggedIn: true, password: "password"},
1089+ {tag: "without password", user: "no-password", loggedIn: true, password: ""},
1090+ ]
1091+ }
1092+
1093+ function test_tabletLogin(data) {
1094+ setLightDMMockMode("full");
1095+ loadShell("tablet");
1096+
1097+ selectUser(data.user);
1098+
1099+ clickPasswordInput(data.password === "" /* isButton */);
1100+
1101+ if (data.password !== "") {
1102+ typeString(data.password);
1103+ keyClick(Qt.Key_Enter);
1104+ }
1105+
1106+ confirmLoggedIn(data.loggedIn);
1107+ }
1108+
1109+ function test_appLaunchDuringGreeter_data() {
1110+ return [
1111+ {tag: "auth error", user: "auth-error", loggedIn: false, passwordFocus: false},
1112+ {tag: "without password", user: "no-password", loggedIn: true, passwordFocus: false},
1113+ {tag: "with password", user: "has-password", loggedIn: false, passwordFocus: true},
1114+ ]
1115+ }
1116+
1117+ function test_appLaunchDuringGreeter(data) {
1118+ setLightDMMockMode("full");
1119+ loadShell("tablet");
1120+
1121+ selectUser(data.user)
1122+
1123+ var greeter = findChild(shell, "greeter")
1124+ var app = ApplicationManager.startApplication("dialer-app")
1125+
1126+ confirmLoggedIn(data.loggedIn)
1127+
1128+ if (data.passwordFocus) {
1129+ var passwordInput = findChild(greeter, "passwordInput")
1130+ tryCompare(passwordInput, "focus", true)
1131+ }
872 }
1132 }
873 }
1133 }
874}
1134}
tests/qmltests/tst_TabletShell.qmldeleted−304
@@ -1,304 +0,0 @@
1−/*
2− * Copyright (C) 2013,2014 Canonical, Ltd.
3− *
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.
7− *
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.
12− *
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/>.
15− */
16−
17−import QtQuick 2.0
18−import QtTest 1.0
19−import AccountsService 0.1
20−import GSettings 1.0
21−import LightDM 0.1 as LightDM
22−import Ubuntu.Components 1.1
23−import Ubuntu.Telephony 0.1 as Telephony
24−import Unity.Application 0.1
25−import Unity.Connectivity 0.1
26−import Unity.Test 0.1 as UT
27−import Powerd 0.1
28−
29−import "../../qml"
30−
31−Item {
32− id: root
33− width: units.gu(120)
34− height: units.gu(80)
35−
36− Component.onCompleted: {
37− // must set the mock mode before loading the Shell
38− LightDM.Greeter.mockMode = "full";
39− LightDM.Users.mockMode = "full";
40− shellLoader.active = true;
41− }
42−
43− QtObject {
44− id: applicationArguments
45−
46− function hasGeometry() {
47− return false
48− }
49−
50− function width() {
51− return 0
52− }
53−
54− function height() {
55− return 0
56− }
57− }
58−
59− Row {
60− anchors.fill: parent
61− Loader {
62− id: shellLoader
63−
64− active: false
65− width: units.gu(100)
66− height: parent.height
67−
68− property bool itemDestroyed: false
69− sourceComponent: Component {
70− Shell {
71− property string indicatorProfile: "phone"
72−
73− Component.onDestruction: {
74− shellLoader.itemDestroyed = true
75− }
76− }
77− }
78− }
79−
80− Rectangle {
81− color: "white"
82− width: units.gu(20)
83− height: parent.height
84−
85− Column {
86− anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
87− spacing: units.gu(1)
88− Button {
89− text: "Show Greeter"
90− onClicked: {
91− if (shellLoader.status !== Loader.Ready)
92− return
93−
94− var greeter = testCase.findChild(shellLoader.item, "greeter")
95− if (!greeter.shown) {
96− greeter.show()
97− }
98− }
99− }
100− Button {
101− text: "Demo edges"
102− onClicked: {
103− AccountsService.demoEdges = true;
104− }
105− }
106− }
107− }
108− }
109−
110− SignalSpy {
111− id: sessionSpy
112− signalName: "sessionStarted"
113− }
114−
115− SignalSpy {
116− id: dashCommunicatorSpy
117− signalName: "setCurrentScopeCalled"
118− }
119−
120− SignalSpy {
121− id: unlockAllModemsSpy
122− target: Connectivity
123− signalName: "unlockingAllModems"
124− }
125−
126− Telephony.CallEntry {
127− id: phoneCall
128− phoneNumber: "+447812221111"
129− }
130−
131− UT.UnityTestCase {
132− id: testCase
133− name: "TabletShell"
134− when: windowShown
135−
136− property Item shell: shellLoader.status === Loader.Ready ? shellLoader.item : null
137−
138− function init() {
139− tryCompare(shell, "enabled", true); // will be enabled when greeter is all ready
140− var userList = findChild(shell, "userList");
141− tryCompare(userList, "movingInternally", false);
142− sessionSpy.clear()
143− sessionSpy.target = findChild(shell, "greeter")
144− dashCommunicatorSpy.target = findInvisibleChild(shell, "dashCommunicator")
145− }
146−
147− function cleanup() {
148− tryCompare(shell, "enabled", true); // make sure greeter didn't leave us in disabled state
149−
150− shellLoader.itemDestroyed = false
151−
152− shellLoader.active = false
153−
154− tryCompare(shellLoader, "status", Loader.Null)
155− tryCompare(shellLoader, "item", null)
156− // Loader.status might be Loader.Null and Loader.item might be null but the Loader
157− // item might still be alive. So if we set Loader.active back to true
158− // again right now we will get the very same Shell instance back. So no reload
159− // actually took place. Likely because Loader waits until the next event loop
160− // iteration to do its work. So to ensure the reload, we will wait until the
161− // Shell instance gets destroyed.
162− tryCompare(shellLoader, "itemDestroyed", true)
163−
164− // kill all (fake) running apps
165− killApps()
166−
167− unlockAllModemsSpy.clear()
168− AccountsService.demoEdges = false
169− LightDM.Greeter.authenticate(""); // reset greeter
170−
171− // reload our test subject to get it in a fresh state once again
172− shellLoader.active = true
173−
174− tryCompare(shellLoader, "status", Loader.Ready)
175− removeTimeConstraintsFromDirectionalDragAreas(shellLoader.item)
176− }
177−
178− function killApps() {
179− while (ApplicationManager.count > 1) {
180− var appIndex = ApplicationManager.get(0).appId == "unity8-dash" ? 1 : 0
181− ApplicationManager.stopApplication(ApplicationManager.get(appIndex).appId)
182− }
183− compare(ApplicationManager.count, 1)
184− }
185−
186− function selectIndex(i) {
187− // We could be anywhere in list; find target index to know which direction
188− var greeter = findChild(shell, "greeter")
189− var userlist = findChild(greeter, "userList")
190− if (userlist.currentIndex == i)
191− keyClick(Qt.Key_Escape) // Reset state if we're not moving
192− while (userlist.currentIndex != i) {
193− var next = userlist.currentIndex + 1
194− if (userlist.currentIndex > i) {
195− next = userlist.currentIndex - 1
196− }
197− tap(findChild(greeter, "username"+next));
198− tryCompare(userlist, "currentIndex", next)
199− tryCompare(userlist, "movingInternally", false)
200− }
201− }
202−
203− function selectUser(name) {
204− // Find index of user with the right name
205− for (var i = 0; i < LightDM.Users.count; i++) {
206− if (LightDM.Users.data(i, LightDM.UserRoles.NameRole) == name) {
207− break
208− }
209− }
210− if (i == LightDM.Users.count) {
211− fail("Didn't find name")
212− return -1
213− }
214− selectIndex(i)
215− return i
216− }
217−
218− function clickPasswordInput(isButton) {
219− var greeter = findChild(shell, "greeter")
220− tryCompare(greeter, "fullyShown", true);
221−
222− var passwordMouseArea = findChild(shell, "passwordMouseArea")
223− tryCompare(passwordMouseArea, "enabled", isButton)
224−
225− var passwordInput = findChild(shell, "passwordInput")
226− mouseClick(passwordInput)
227− }
228−
229− function confirmLoggedIn(loggedIn) {
230− var greeter = findChild(shell, "greeter");
231− tryCompare(greeter, "shown", loggedIn ? false : true);
232− verify(loggedIn ? sessionSpy.count > 0 : sessionSpy.count === 0);
233− }
234−
235− function swipeFromLeftEdge(swipeLength) {
236− var touchStartX = 2
237− var touchStartY = shell.height / 2
238− touchFlick(shell, touchStartX, touchStartY, swipeLength, touchStartY)
239− }
240−
241− function test_login_data() {
242− return [
243− {tag: "auth error", user: "auth-error", loggedIn: false, password: ""},
244− {tag: "with password", user: "has-password", loggedIn: true, password: "password"},
245− {tag: "without password", user: "no-password", loggedIn: true, password: ""},
246− ]
247− }
248−
249− function test_login(data) {
250− selectUser(data.user)
251−
252− clickPasswordInput(data.password === "")
253−
254− if (data.password !== "") {
255− typeString(data.password)
256− keyClick(Qt.Key_Enter)
257− }
258−
259− confirmLoggedIn(data.loggedIn)
260− }
261−
262− function test_appLaunchDuringGreeter_data() {
263− return [
264− {tag: "auth error", user: "auth-error", loggedIn: false, passwordFocus: false},
265− {tag: "without password", user: "no-password", loggedIn: true, passwordFocus: false},
266− {tag: "with password", user: "has-password", loggedIn: false, passwordFocus: true},
267− ]
268− }
269−
270− function test_appLaunchDuringGreeter(data) {
271− selectUser(data.user)
272−
273− var greeter = findChild(shell, "greeter")
274− var app = ApplicationManager.startApplication("dialer-app")
275−
276− confirmLoggedIn(data.loggedIn)
277−
278− if (data.passwordFocus) {
279− var passwordInput = findChild(greeter, "passwordInput")
280− tryCompare(passwordInput, "focus", true)
281− }
282− }
283−
284− function test_leftEdgeDrag_data() {
285− return [
286− {tag: "without password", user: "no-password", loggedIn: true, demo: false},
287− {tag: "with password", user: "has-password", loggedIn: false, demo: false},
288− {tag: "with demo", user: "has-password", loggedIn: true, demo: true},
289− ]
290− }
291−
292− function test_leftEdgeDrag(data) {
293− selectUser(data.user)
294−
295− AccountsService.demoEdges = data.demo
296− var tutorial = findChild(shell, "tutorial");
297− tryCompare(tutorial, "running", data.demo);
298−
299− swipeFromLeftEdge(shell.width * 0.75)
300− wait(500) // to give time to handle dash() signal from Launcher
301− confirmLoggedIn(data.loggedIn)
302− }
303− }
304−}
tests/uqmlscene/CMakeLists.txt−1
@@ -2,7 +2,6 @@ add_executable(uqmlscene
2 ${shellapplication_MOC_SRCS}
2 ${shellapplication_MOC_SRCS}
3 ActiveFocusLogger.cpp
3 ActiveFocusLogger.cpp
4 main.cpp
4 main.cpp
5− ${CMAKE_SOURCE_DIR}/src/MouseTouchAdaptor.cpp
6 )
5 )
7
6
8qt5_use_modules(uqmlscene Qml Quick Test)
7qt5_use_modules(uqmlscene Qml Quick Test)
tests/uqmlscene/main.cpp−4
@@ -63,8 +63,6 @@
63#include <QtCore/QTranslator>
63#include <QtCore/QTranslator>
64#include <QtCore/QLibraryInfo>
64#include <QtCore/QLibraryInfo>
65
65
66−#include <MouseTouchAdaptor.h>
67−
68// UbuntuGestures lib
66// UbuntuGestures lib
69#include <TouchRegistry.h>
67#include <TouchRegistry.h>
70
68
@@ -436,8 +434,6 @@ int main(int argc, char ** argv)
436 app.setOrganizationName("Qt Project");
434 app.setOrganizationName("Qt Project");
437 app.setOrganizationDomain("qt-project.org");
435 app.setOrganizationDomain("qt-project.org");
438
436
439− MouseTouchAdaptor mouseTouchAdaptor;
440− app.installNativeEventFilter(&mouseTouchAdaptor);
441 // Create it before loading the module, so that TestUtil
437 // Create it before loading the module, so that TestUtil
442 // doesn't create one with a fake timer factory.
438 // doesn't create one with a fake timer factory.
443 // When interacting manually with a test we want the real deal.
439 // When interacting manually with a test we want the real deal.
tests/utils/modules/Unity/Test/CMakeLists.txt+2
@@ -6,12 +6,14 @@ include_directories(
6 ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
6 ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
7 ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
7 ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
8 ${CMAKE_SOURCE_DIR}/libs/UbuntuGestures
8 ${CMAKE_SOURCE_DIR}/libs/UbuntuGestures
9+ ${CMAKE_SOURCE_DIR}/src
9)
10)
10
11
11set(UnityTestQML_SOURCES
12set(UnityTestQML_SOURCES
12 testutil.cpp
13 testutil.cpp
13 plugin.cpp
14 plugin.cpp
14 TouchEventSequenceWrapper.cpp
15 TouchEventSequenceWrapper.cpp
16+ ${CMAKE_SOURCE_DIR}/src/MouseTouchAdaptor.cpp
15)
17)
16
18
17add_library(UnityTestQml MODULE ${UnityTestQML_SOURCES})
19add_library(UnityTestQml MODULE ${UnityTestQML_SOURCES})
tests/utils/modules/Unity/Test/MouseTouchEmulationCheckbox.qmlnew file+43
@@ -0,0 +1,43 @@
1+/*
2+ * Copyright (C) 2015 Canonical, Ltd.
3+ *
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.
7+ *
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.
12+ *
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/>.
15+ */
16+
17+import QtQuick 2.0
18+import QtQuick.Layouts 1.1
19+import Ubuntu.Components 1.1
20+import Unity.Test 0.1
21+
22+RowLayout {
23+ id: root
24+ property alias color: label.color
25+
26+ Binding {
27+ target: MouseTouchAdaptor
28+ property: "enabled"
29+ value: checkbox.checked
30+ }
31+
32+ Layout.fillWidth: true
33+ CheckBox {
34+ id: checkbox
35+ checked: true
36+ activeFocusOnPress: false
37+ }
38+ Label {
39+ id: label
40+ text: "Mouse emulates touch"
41+ anchors.verticalCenter: parent.verticalCenter
42+ }
43+}
tests/utils/modules/Unity/Test/plugin.cpp+15−2
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2012, 2013 Canonical, Ltd.
2+ * Copyright (C) 2012, 2013, 2015 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -17,20 +17,33 @@
17
17
18#include "plugin.h"
18#include "plugin.h"
19#include "testutil.h"
19#include "testutil.h"
20+#include <MouseTouchAdaptor.h>
20#include "TouchEventSequenceWrapper.h"
21#include "TouchEventSequenceWrapper.h"
21
22
22#include <qqml.h>
23#include <qqml.h>
23
24
25+namespace {
24−static QObject *testutil_provider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
26+QObject *testutil_provider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
25{
27{
26 return new TestUtil();
28 return new TestUtil();
27}
29}
30+QObject *getMouseTouchAdaptorQMLSingleton(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
31+{
32+ return MouseTouchAdaptor::instance();
33+}
34+} // anonymous namespace
28
35
29void UnityTestPlugin::registerTypes(const char *uri)
36void UnityTestPlugin::registerTypes(const char *uri)
30{
37{
31 Q_ASSERT(QLatin1String(uri) == QLatin1String("Unity.Test"));
38 Q_ASSERT(QLatin1String(uri) == QLatin1String("Unity.Test"));
39+
40+ // Ensure the instance gets created
41+ MouseTouchAdaptor::instance();
42+
32 // @uri Unity.Test
43 // @uri Unity.Test
33 qmlRegisterSingletonType<TestUtil>(uri, 0, 1, "Util", testutil_provider);
44 qmlRegisterSingletonType<TestUtil>(uri, 0, 1, "Util", testutil_provider);
34 qmlRegisterUncreatableType<TouchEventSequenceWrapper>(uri, 0, 1, "TouchEventSequence",
45 qmlRegisterUncreatableType<TouchEventSequenceWrapper>(uri, 0, 1, "TouchEventSequence",
35 "You cannot directly create a TouchEventSequence object.");
46 "You cannot directly create a TouchEventSequence object.");
47+ qmlRegisterSingletonType<MouseTouchAdaptor>(uri, 0, 1, "MouseTouchAdaptor",
48+ getMouseTouchAdaptorQMLSingleton);
36}
49}
tests/utils/modules/Unity/Test/qmldir+1
@@ -3,3 +3,4 @@ plugin UnityTestQml
3typeinfo Test.qmltypes
3typeinfo Test.qmltypes
4
4
5UnityTestCase 0.1 UnityTestCase.qml
5UnityTestCase 0.1 UnityTestCase.qml
6+MouseTouchEmulationCheckbox 0.1 MouseTouchEmulationCheckbox.qml