on xenial help sign in
Using InputInfo, determine if we need swipe or click to dismiss the notifications (e.g. incoming phone call)
555dfcaLukáš Tinkl
qml/Notifications/Notification.qml+11−7
@@ -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
@@ -17,11 +17,10 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import QtMultimedia 5.0
18import QtMultimedia 5.0
19import Powerd 0.1
19import Powerd 0.1
20−import Ubuntu.Components 1.1
20+import Ubuntu.Components 1.2
21import Unity.Notifications 1.0
21import Unity.Notifications 1.0
22import QMenuModel 0.1
22import QMenuModel 0.1
23import Utils 0.1
23import Utils 0.1
24−
25import Ubuntu.Components.ListItems 0.1 as ListItem
24import Ubuntu.Components.ListItems 0.1 as ListItem
26
25
27Item {
26Item {
@@ -49,6 +48,8 @@ Item {
49 readonly property color sdDarkGrey: "#dddddd"
48 readonly property color sdDarkGrey: "#dddddd"
50 readonly property color sdFontColor: "#5d5d5d"
49 readonly property color sdFontColor: "#5d5d5d"
51 readonly property real contentSpacing: units.gu(2)
50 readonly property real contentSpacing: units.gu(2)
51+ readonly property bool canBeClosed: type === Notification.Ephemeral
52+ property bool hasMouse
52
53
53 objectName: "background"
54 objectName: "background"
54 implicitHeight: type !== Notification.PlaceHolder ? (fullscreen ? maxHeight : outterColumn.height - shapedBack.anchors.topMargin + contentSpacing * 2) : 0
55 implicitHeight: type !== Notification.PlaceHolder ? (fullscreen ? maxHeight : outterColumn.height - shapedBack.anchors.topMargin + contentSpacing * 2) : 0
@@ -216,6 +217,8 @@ Item {
216 onClicked: {
217 onClicked: {
217 if (notification.type == Notification.Interactive) {
218 if (notification.type == Notification.Interactive) {
218 notification.notification.invokeAction(actionRepeater.itemAt(0).actionId)
219 notification.notification.invokeAction(actionRepeater.itemAt(0).actionId)
220+ } else if (hasMouse && canBeClosed) {
221+ notification.notification.close()
219 } else {
222 } else {
220 notificationList.currentIndex = index;
223 notificationList.currentIndex = index;
221 }
224 }
@@ -280,7 +283,7 @@ Item {
280 fontSize: "medium"
283 fontSize: "medium"
281 color: darkOnBright ? sdFontColor : Theme.palette.selected.backgroundText
284 color: darkOnBright ? sdFontColor : Theme.palette.selected.backgroundText
282 elide: Text.ElideRight
285 elide: Text.ElideRight
283− textFormat: Text.PlainText
286+ textFormat: Text.StyledText
284 }
287 }
285
288
286 Label {
289 Label {
@@ -297,7 +300,7 @@ Item {
297 wrapMode: Text.WordWrap
300 wrapMode: Text.WordWrap
298 maximumLineCount: type == Notification.SnapDecision ? 12 : 2
301 maximumLineCount: type == Notification.SnapDecision ? 12 : 2
299 elide: Text.ElideRight
302 elide: Text.ElideRight
300− textFormat: Text.PlainText
303+ textFormat: Text.StyledText
301 }
304 }
302 }
305 }
303
306
@@ -471,7 +474,7 @@ Item {
471 onClicked: notification.notification.invokeAction(oneOverTwoLoaderBottom.actionId)
474 onClicked: notification.notification.invokeAction(oneOverTwoLoaderBottom.actionId)
472 }
475 }
473 }
476 }
474− sourceComponent: (index == 1 || index == 2) ? oneOverTwoButtonBottom : undefined
477+ sourceComponent: (index == 1 || index == 2) ? oneOverTwoButtonBottom : undefined
475 }
478 }
476 }
479 }
477 }
480 }
@@ -487,7 +490,7 @@ Item {
487 margins: contentSpacing
490 margins: contentSpacing
488 }
491 }
489 visible: notification.type === Notification.SnapDecision && actionRepeater.count > 0 && !oneOverTwoCase.visible
492 visible: notification.type === Notification.SnapDecision && actionRepeater.count > 0 && !oneOverTwoCase.visible
490− spacing: units.gu(2)
493+ spacing: contentSpacing
491 layoutDirection: Qt.RightToLeft
494 layoutDirection: Qt.RightToLeft
492
495
493 Loader {
496 Loader {
@@ -499,6 +502,7 @@ Item {
499 width: buttonRow.width
502 width: buttonRow.width
500 leftIconName: "call-end"
503 leftIconName: "call-end"
501 rightIconName: "call-start"
504 rightIconName: "call-start"
505+ clickToAct: notification.hasMouse
502 onRightTriggered: {
506 onRightTriggered: {
503 notification.notification.invokeAction(notification.actions.data(0, ActionModel.RoleActionId))
507 notification.notification.invokeAction(notification.actions.data(0, ActionModel.RoleActionId))
504 }
508 }
qml/Notifications/Notifications.qml+3−1
@@ -28,6 +28,7 @@ ListView {
28
28
29 property real margin
29 property real margin
30 property bool useModal: snapDecisionProxyModel.count > 0
30 property bool useModal: snapDecisionProxyModel.count > 0
31+ property bool hasMouse
31
32
32 UnitySortFilterProxyModel {
33 UnitySortFilterProxyModel {
33 id: snapDecisionProxyModel
34 id: snapDecisionProxyModel
@@ -52,12 +53,13 @@ ListView {
52 secondaryIconSource: model.secondaryIcon
53 secondaryIconSource: model.secondaryIcon
53 summary: model.summary
54 summary: model.summary
54 body: model.body
55 body: model.body
55− value: model.value
56+ value: model.value ? model.value : -1
56 actions: model.actions
57 actions: model.actions
57 notificationId: model.id
58 notificationId: model.id
58 notification: notificationList.model.getRaw(notificationId)
59 notification: notificationList.model.getRaw(notificationId)
59 maxHeight: notificationList.height
60 maxHeight: notificationList.height
60 margins: notificationList.margin
61 margins: notificationList.margin
62+ hasMouse: notificationList.hasMouse
61
63
62 // make sure there's no opacity-difference between the several
64 // make sure there's no opacity-difference between the several
63 // elements in a notification
65 // elements in a notification
qml/Notifications/SwipeToAct.qml+38−3
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 20014-2015 Canonical, Ltd.
2+ * Copyright (C) 2014-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
@@ -15,12 +15,12 @@
15 */
15 */
16
16
17import QtQuick 2.3
17import QtQuick 2.3
18−import Ubuntu.Components 1.1
18+import Ubuntu.Components 1.2
19
19
20Item {
20Item {
21 id: swipeToAct
21 id: swipeToAct
22
22
23− height: childrenRect.height
23+ height: clickToAct ? leftButton.height : childrenRect.height
24
24
25 signal leftTriggered()
25 signal leftTriggered()
26 signal rightTriggered()
26 signal rightTriggered()
@@ -28,6 +28,8 @@ Item {
28 property string leftIconName
28 property string leftIconName
29 property string rightIconName
29 property string rightIconName
30
30
31+ property bool clickToAct
32+
31 QtObject {
33 QtObject {
32 id: priv
34 id: priv
33
35
@@ -64,15 +66,45 @@ Item {
64 }
66 }
65 }
67 }
66
68
69+ Button {
70+ id: leftButton
71+ objectName: "leftButton"
72+ anchors.verticalCenter: parent.verticalCenter
73+ anchors.left: parent.left
74+ iconName: leftIconName
75+ visible: clickToAct
76+ width: (parent.width / 2) - priv.gap
77+ color: UbuntuColors.red
78+ onClicked: {
79+ leftTriggered()
80+ }
81+ }
82+
83+ Button {
84+ id: rightButton
85+ objectName: "rightButton"
86+ anchors.verticalCenter: parent.verticalCenter
87+ anchors.right: parent.right
88+ iconName: rightIconName
89+ visible: clickToAct
90+ width: (parent.width / 2) - priv.gap
91+ color: UbuntuColors.green
92+ onClicked: {
93+ rightTriggered()
94+ }
95+ }
96+
67 UbuntuShape {
97 UbuntuShape {
68 id: row
98 id: row
69 width: parent.width
99 width: parent.width
70 height: priv.sliderHeight
100 height: priv.sliderHeight
71 color: priv.sliderBGColor
101 color: priv.sliderBGColor
72 borderSource: "none"
102 borderSource: "none"
103+ visible: !clickToAct
73
104
74 UbuntuShape {
105 UbuntuShape {
75 id: leftShape
106 id: leftShape
107+ objectName: "leftArea"
76 anchors.top: parent.top
108 anchors.top: parent.top
77 anchors.left: parent.left
109 anchors.left: parent.left
78 anchors.margins: priv.gap
110 anchors.margins: priv.gap
@@ -167,6 +199,7 @@ Item {
167 color: "white"
199 color: "white"
168 }
200 }
169 }
201 }
202+
170 Row {
203 Row {
171 anchors.verticalCenter: parent.verticalCenter
204 anchors.verticalCenter: parent.verticalCenter
172 anchors.left: slider.right
205 anchors.left: slider.right
@@ -189,6 +222,7 @@ Item {
189
222
190 UbuntuShape {
223 UbuntuShape {
191 id: rightShape
224 id: rightShape
225+ objectName: "rightArea"
192 anchors.top: parent.top
226 anchors.top: parent.top
193 anchors.right: parent.right
227 anchors.right: parent.right
194 anchors.margins: priv.gap
228 anchors.margins: priv.gap
@@ -214,6 +248,7 @@ Item {
214 MouseArea {
248 MouseArea {
215 id: mouseArea
249 id: mouseArea
216 objectName: "swipeMouseArea"
250 objectName: "swipeMouseArea"
251+ enabled: !clickToAct
217
252
218 anchors.fill: row
253 anchors.fill: row
219 drag.target: slider
254 drag.target: slider
qml/OrientedShell.qml+1
@@ -155,6 +155,7 @@ Rectangle {
155 nativeWidth: root.width
155 nativeWidth: root.width
156 nativeHeight: root.height
156 nativeHeight: root.height
157 mode: applicationArguments.mode
157 mode: applicationArguments.mode
158+ hasMouse: UnityInputInfo.mice > deviceConfiguration.ignoredMice
158
159
159 // TODO: Factor in the connected input devices (eg: physical keyboard, mouse, touchscreen),
160 // TODO: Factor in the connected input devices (eg: physical keyboard, mouse, touchscreen),
160 // what's the output device (eg: big TV, desktop monitor, phone display), etc.
161 // what's the output device (eg: big TV, desktop monitor, phone display), etc.
qml/Shell.qml+2
@@ -63,6 +63,7 @@ Item {
63 function updateFocusedAppOrientationAnimated() {
63 function updateFocusedAppOrientationAnimated() {
64 applicationsDisplayLoader.item.updateFocusedAppOrientationAnimated();
64 applicationsDisplayLoader.item.updateFocusedAppOrientationAnimated();
65 }
65 }
66+ property bool hasMouse
66
67
67 // to be read from outside
68 // to be read from outside
68 readonly property int mainAppWindowOrientationAngle:
69 readonly property int mainAppWindowOrientationAngle:
@@ -636,6 +637,7 @@ Item {
636
637
637 model: NotificationBackend.Model
638 model: NotificationBackend.Model
638 margin: units.gu(1)
639 margin: units.gu(1)
640+ hasMouse: shell.hasMouse
639
641
640 y: topmostIsFullscreen ? 0 : panel.panelHeight
642 y: topmostIsFullscreen ? 0 : panel.panelHeight
641 height: parent.height - (topmostIsFullscreen ? 0 : panel.panelHeight)
643 height: parent.height - (topmostIsFullscreen ? 0 : panel.panelHeight)
tests/mocks/Unity/Notifications/MockActionModel.cpp+1−1
@@ -59,7 +59,7 @@ QHash<int, QByteArray> ActionModel::roleNames() const {
59 return roles;
59 return roles;
60}
60}
61
61
62−Q_INVOKABLE QVariant ActionModel::data(int row, int role) const
62+QVariant ActionModel::data(int row, int role) const
63{
63{
64 return data(index(row, 0), role);
64 return data(index(row, 0), role);
65}
65}
tests/mocks/Unity/Notifications/MockNotification.cpp+1
@@ -39,6 +39,7 @@ MockNotification::MockNotification(QObject *parent) : QObject(parent), p(new Moc
39}
39}
40
40
41MockNotification::~MockNotification() {
41MockNotification::~MockNotification() {
42+ delete p->actionsModel;
42}
43}
43
44
44QString MockNotification::getSummary() const {
45QString MockNotification::getSummary() const {
tests/mocks/Unity/Notifications/MockNotification.h+1−1
@@ -30,7 +30,7 @@ struct MockNotificationPrivate;
30
30
31class MockNotification : public QObject {
31class MockNotification : public QObject {
32 Q_OBJECT
32 Q_OBJECT
33− Q_ENUMS(Type)
33+ Q_ENUMS(Type Urgency)
34 Q_PROPERTY(QString summary READ getSummary WRITE setSummary NOTIFY summaryChanged)
34 Q_PROPERTY(QString summary READ getSummary WRITE setSummary NOTIFY summaryChanged)
35 Q_PROPERTY(QString body READ getBody WRITE setBody NOTIFY bodyChanged)
35 Q_PROPERTY(QString body READ getBody WRITE setBody NOTIFY bodyChanged)
36 Q_PROPERTY(int nid READ getID WRITE setID NOTIFY idChanged)
36 Q_PROPERTY(int nid READ getID WRITE setID NOTIFY idChanged)
tests/mocks/Unity/Notifications/MockNotificationModel.cpp+5−1
@@ -35,6 +35,10 @@ MockNotificationModel::MockNotificationModel(QObject *parent) : QAbstractListMod
35}
35}
36
36
37MockNotificationModel::~MockNotificationModel() {
37MockNotificationModel::~MockNotificationModel() {
38+ Q_FOREACH(MockNotification *n, m_queue) {
39+ n->deleteLater();
40+ }
41+ m_queue.clear();
38}
42}
39
43
40int MockNotificationModel::rowCount(const QModelIndex &) const {
44int MockNotificationModel::rowCount(const QModelIndex &) const {
@@ -47,7 +51,7 @@ int MockNotificationModel::getCount() const {
47
51
48QVariant MockNotificationModel::data(const QModelIndex &index, int role) const {
52QVariant MockNotificationModel::data(const QModelIndex &index, int role) const {
49 if (!index.isValid())
53 if (!index.isValid())
50− return QVariant();
54+ return QVariant();
51
55
52 switch(role) {
56 switch(role) {
53 case ModelInterface::RoleType:
57 case ModelInterface::RoleType:
tests/qmltests/Notifications/tst_Notifications.qml+61−8
@@ -12,16 +12,15 @@
12 *
12 *
13 * You should have received a copy of the GNU Lesser General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors:
17− * Mirco Mueller <mirco.mueller@canonical.com>
18 */
15 */
19
16
20−import QtQuick 2.0
17+import QtQuick 2.4
18+import QtQuick.Layouts 1.1
21import QtTest 1.0
19import QtTest 1.0
22import ".."
20import ".."
23import "../../../qml/Notifications"
21import "../../../qml/Notifications"
22+import "../../../qml/Components/UnityInputInfo"
24−import Ubuntu.Components 0.1
23+import Ubuntu.Components 1.2
25import Unity.Test 0.1
24import Unity.Test 0.1
26import Unity.Notifications 1.0
25import Unity.Notifications 1.0
27import QtMultimedia 5.0
26import QtMultimedia 5.0
@@ -77,7 +76,7 @@ Item {
77 "type": Notification.Ephemeral,
76 "type": Notification.Ephemeral,
78 "hints": {},
77 "hints": {},
79 "summary": "Cole Raby",
78 "summary": "Cole Raby",
80− "body": "I did not expect it to be that late.",
79+ "body": "I did not expect it to be <b>that</b> late.",
81 "icon": "../graphics/avatars/amanda.png",
80 "icon": "../graphics/avatars/amanda.png",
82 "secondaryIcon": "../graphics/applicationIcons/facebook.png",
81 "secondaryIcon": "../graphics/applicationIcons/facebook.png",
83 "rawActions": ["reply_id", "Dummy"]})
82 "rawActions": ["reply_id", "Dummy"]})
@@ -91,7 +90,7 @@ Item {
91 "type": Notification.Ephemeral,
90 "type": Notification.Ephemeral,
92 "hints": {"x-canonical-non-shaped-icon": "true"},
91 "hints": {"x-canonical-non-shaped-icon": "true"},
93 "summary": "Contacts",
92 "summary": "Contacts",
94− "body": "Synchronised contacts-database with cloud-storage.",
93+ "body": "Synchronised contacts-database &amp; cloud-storage.",
95 "icon": "../graphics/applicationIcons/contacts-app.png",
94 "icon": "../graphics/applicationIcons/contacts-app.png",
96 "secondaryIcon": "",
95 "secondaryIcon": "",
97 "rawActions": ["reply_id", "Dummy"]})
96 "rawActions": ["reply_id", "Dummy"]})
@@ -189,6 +188,7 @@ Item {
189
188
190 anchors.fill: parent
189 anchors.fill: parent
191 model: mockModel
190 model: mockModel
191+ hasMouse: UnityInputInfo.mice > 0 // for testing, we add/remove only a mock mouse
192 }
192 }
193 }
193 }
194
194
@@ -218,7 +218,7 @@ Item {
218
218
219 Button {
219 Button {
220 width: parent.width
220 width: parent.width
221− text: "add an non-shaped-icon-summary-body"
221+ text: "add a non-shaped-icon-summary-body"
222 onClicked: rootRow.addEphemeralNonShapedIconNotification()
222 onClicked: rootRow.addEphemeralNonShapedIconNotification()
223 }
223 }
224
224
@@ -257,6 +257,24 @@ Item {
257 text: "clear model"
257 text: "clear model"
258 onClicked: rootRow.clearNotifications()
258 onClicked: rootRow.clearNotifications()
259 }
259 }
260+
261+ RowLayout {
262+ Layout.fillWidth: true
263+ CheckBox {
264+ id: fakeMouseCB
265+ onClicked: {
266+ if (checked) {
267+ UnityInputInfo.inputInfo.addMockMouse();
268+ } else {
269+ UnityInputInfo.inputInfo.removeMockMouse();
270+ }
271+ }
272+ }
273+ Label {
274+ text: "With fake mouse"
275+ anchors.verticalCenter: parent.verticalCenter
276+ }
277+ }
260 }
278 }
261 }
279 }
262
280
@@ -675,6 +693,41 @@ Item {
675 tryCompare(mockModel, "count", before - 1)
693 tryCompare(mockModel, "count", before - 1)
676 }
694 }
677 }
695 }
696+
697+ function test_clickToClose_data() { // reuse the data
698+ UnityInputInfo.inputInfo.addMockMouse();
699+ return test_NotificationRenderer_data();
700+ }
701+
702+ function test_clickToClose(data) {
703+ // populate model with some mock notifications
704+ mockModel.append(data.n)
705+
706+ // make sure the view is properly updated before going on
707+ notifications.forceLayout();
708+ waitForRendering(notifications);
709+
710+ var notification = findChild(notifications, "notification" + (mockModel.count - 1))
711+ verify(!!notification, "notification wasn't found");
712+
713+ // click-to-dismiss check
714+ waitForRendering(notification);
715+ var before = mockModel.count;
716+ var canBeClosed = notification.canBeClosed;
717+ mouseClick(notification);
718+
719+ if (canBeClosed) {
720+ // closing the notification, the model count should be one less
721+ tryCompare(mockModel, "count", before - 1)
722+ } else {
723+ // not closing, model stays the same
724+ tryCompare(mockModel, "count", before)
725+ }
726+ }
727+
728+ function cleanupTestCase() {
729+ UnityInputInfo.inputInfo.removeMockMouse();
730+ }
678 }
731 }
679 }
732 }
680}
733}
tests/qmltests/Notifications/tst_SwipeToAct.qml+58−14
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2014, 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
@@ -14,10 +14,12 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
15 */
16
16
17−import QtQuick 2.0
17+import QtQuick 2.4
18+import QtQuick.Layouts 1.1
18import QtTest 1.0
19import QtTest 1.0
19import ".."
20import ".."
20import "../../../qml/Notifications"
21import "../../../qml/Notifications"
22+import "../../../qml/Components/UnityInputInfo"
21import Ubuntu.Components 0.1
23import Ubuntu.Components 0.1
22import Unity.Test 0.1
24import Unity.Test 0.1
23import Unity.Notifications 1.0
25import Unity.Notifications 1.0
@@ -74,7 +76,10 @@ Item {
74 icon: "../graphics/avatars/amanda.png",
76 icon: "../graphics/avatars/amanda.png",
75 secondaryIcon: "incoming-call",
77 secondaryIcon: "incoming-call",
76 actions: [{ id: "ok_id", label: "Ok"},
78 actions: [{ id: "ok_id", label: "Ok"},
77− { id: "cancel_id", label: "Cancel"}]
79+ { id: "cancel_id", label: "Cancel"},
80+ { id: "foo_id", label: "Foo"},
81+ { id: "bar_id", label: "Bar"}
82+ ]
78 }
83 }
79
84
80 mockModel.append(n)
85 mockModel.append(n)
@@ -97,7 +102,6 @@ Item {
97
102
98 MouseArea{
103 MouseArea{
99 id: clickThroughCatcher
104 id: clickThroughCatcher
100−
101 anchors.fill: parent
105 anchors.fill: parent
102 }
106 }
103
107
@@ -108,6 +112,7 @@ Item {
108
112
109 anchors.fill: parent
113 anchors.fill: parent
110 model: mockModel
114 model: mockModel
115+ hasMouse: UnityInputInfo.mice > 0 // for testing, we add/remove only a mock mouse
111 }
116 }
112 }
117 }
113
118
@@ -140,6 +145,24 @@ Item {
140 text: "clear model"
145 text: "clear model"
141 onClicked: rootRow.clearNotifications()
146 onClicked: rootRow.clearNotifications()
142 }
147 }
148+
149+ RowLayout {
150+ Layout.fillWidth: true
151+ CheckBox {
152+ id: fakeMouseCB
153+ onClicked: {
154+ if (checked) {
155+ UnityInputInfo.inputInfo.addMockMouse();
156+ } else {
157+ UnityInputInfo.inputInfo.removeMockMouse();
158+ }
159+ }
160+ }
161+ Label {
162+ text: "With fake mouse"
163+ anchors.verticalCenter: parent.verticalCenter
164+ }
165+ }
143 }
166 }
144 }
167 }
145
168
@@ -258,21 +281,42 @@ Item {
258
281
259 if(data.buttonRowVisible) {
282 if(data.buttonRowVisible) {
260 var swipeButton = findChild(buttonRow, "notify_swipe_button")
283 var swipeButton = findChild(buttonRow, "notify_swipe_button")
284+
285+ if (!swipeButton.clickToAct) { // don't run if there's a real mouse
261− var slider = findChild(swipeButton, "slider")
286+ var slider = findChild(swipeButton, "slider")
262− var swipeMouseArea = findChild(swipeButton, "swipeMouseArea")
287+ var swipeMouseArea = findChild(swipeButton, "swipeMouseArea")
263− var x = swipeMouseArea.width / 2
288+ var x = swipeMouseArea.width / 2
264− var y = swipeMouseArea.height / 2
289+ var y = swipeMouseArea.height / 2
290+
291+ if(data.checkSwipeToActAccept) {
292+ tryCompareFunction(function() { mouseDrag(slider, x, y, (swipeMouseArea.width / 2) - slider.width, 0); return actionSpy.signalArguments.length > 0; }, true);
293+ compare(actionSpy.signalArguments[0][0], data.actions.data(0, ActionModel.RoleActionId), "got wrong id for positive action");
294+ actionSpy.clear();
295+ }
296+ if(data.checkSwipeToActReject) {
297+ tryCompareFunction(function() { mouseDrag(slider, x, y, -(swipeMouseArea.width / 2), 0); return actionSpy.signalArguments.length > 0; }, true);
298+ compare(actionSpy.signalArguments[0][0], data.actions.data(1, ActionModel.RoleActionId), "got wrong id for negative action");
299+ actionSpy.clear();
300+ }
301+ }
302+
303+ // add a mock mouse, test clicking the left/right buttons
304+ UnityInputInfo.inputInfo.addMockMouse();
305+ var leftButton = findChild(swipeButton, "leftButton");
306+ var rightButton = findChild(swipeButton, "rightButton");
265
307
266 if(data.checkSwipeToActAccept) {
308 if(data.checkSwipeToActAccept) {
267− tryCompareFunction(function() { mouseDrag(slider, x, y, (swipeMouseArea.width / 2) - slider.width, 0); return actionSpy.signalArguments.length > 0; }, true);
309+ mouseClick(rightButton);
268− compare(actionSpy.signalArguments[0][0], data.actions.data(0, ActionModel.RoleActionId), "got wrong id for positive action")
310+ compare(actionSpy.signalArguments[0][0], data.actions.data(0, ActionModel.RoleActionId), "got wrong id for positive action");
269− actionSpy.clear()
311+ actionSpy.clear();
270 }
312 }
313+
271 if(data.checkSwipeToActReject) {
314 if(data.checkSwipeToActReject) {
272− tryCompareFunction(function() { mouseDrag(slider, x, y, -(swipeMouseArea.width / 2), 0); return actionSpy.signalArguments.length > 0; }, true);
315+ mouseClick(leftButton);
273− compare(actionSpy.signalArguments[0][0], data.actions.data(1, ActionModel.RoleActionId), "got wrong id for negative action")
316+ compare(actionSpy.signalArguments[0][0], data.actions.data(1, ActionModel.RoleActionId), "got wrong id for negative action");
274− actionSpy.clear()
317+ actionSpy.clear();
275 }
318 }
319+ UnityInputInfo.inputInfo.removeMockMouse();
276 }
320 }
277 }
321 }
278 }
322 }