2
* Copyright 2015 Canonical Ltd.
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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/>.
18
#include <QtTest/QtTest>
19
#include <QtCore/QObject>
20
#include <QtQuick/QQuickView>
21
#include <QtQml/QQmlEngine>
23
#include <private/qquickmousearea_p.h>
24
#include <private/qquickwindow_p.h>
26
#include "gestures/ucswipearea.h"
27
#include "gestures/ucswipearea_p.h"
28
#define protected public
29
#define private public
30
#include <UbuntuGestures/TouchRegistry>
34
#include "GestureTest.h"
35
#include "uctestcase.h"
37
using namespace UbuntuGestures;
39
// Because QSignalSpy(UCSwipeArea, SIGNAL(UCSwipeArea::Status)) simply
41
class StatusSpy : public QObject {
44
StatusSpy(UCSwipeArea *edgeDragArea) {
46
connect(edgeDragArea->d, &UCSwipeAreaPrivate::statusChanged,
47
this, &StatusSpy::onStatusChanged);
54
void onStatusChanged(UCSwipeAreaPrivate::Status status) {
55
m_recognized |= status == UCSwipeAreaPrivate::Recognized;
63
QQuickMouseArea::canceled() signal is not registered in the meta object system.
64
So using a QSignalSpy to track it won't work. Thus the only way to connect to it
65
is using its method address directly.
67
class MouseAreaSpy : public QObject
71
MouseAreaSpy(QQuickMouseArea *mouseArea)
74
connect(mouseArea, &QQuickMouseArea::canceled,
75
this, &MouseAreaSpy::onMouseAreaCanceled);
81
void onMouseAreaCanceled() {
86
class tst_UCSwipeArea: public GestureTest
92
void init() override; // called right before each and every test function is executed
94
void dragWithShortDirectionChange();
95
void recognitionTimerUsage();
100
void ignoreOldFinger();
103
void distance_data();
104
void disabledWhileDragging();
105
void oneFingerDownFollowedByLateSecondFingerDown();
106
void givesUpWhenLosesTouch();
107
void threeFingerDrag();
108
void immediateRecognitionWhenConstraintsDisabled();
109
void withdrawTouchOwnershipCandidacyIfDisabledDuringRecognition();
110
void withdrawTouchOwnershipCandidacyIfDisabledDuringRecognition_data();
111
void gettingTouchOwnershipMakesMouseAreaBehindGetCanceled();
112
void interleavedTouches();
113
void makoRightEdgeDrag();
114
void makoRightEdgeDrag_verticalDownwards();
115
void makoLeftEdgeDrag_slowStart();
116
void makoLeftEdgeDrag_movesSlightlyBackwardsOnStart();
119
// QTest::touchEvent takes QPoint instead of QPointF and I don't want to
120
// lose precision due to rounding.
121
// Besides, those helper functions lead to more compact code.
122
void sendTouchPress(qint64 timestamp, int id, QPointF pos);
123
void sendTouchUpdate(qint64 timestamp, int id, QPointF pos);
124
void sendTouchRelease(qint64 timestamp, int id, QPointF pos);
125
void sendTouch(qint64 timestamp, int id, QPointF pos,
126
Qt::TouchPointState pointState, QEvent::Type eventType);
128
void passTime(qint64 timeSpanMs);
131
tst_UCSwipeArea::tst_UCSwipeArea()
132
: GestureTest(QStringLiteral("tst_swipearea.qml"))
136
void tst_UCSwipeArea::init()
140
// We shouldn't need the three lines below, but a compiz/unity7
141
// regression means we don't pass the test without them because
142
// the window doesn't have the proper size. Can be removed in the
143
// future if the regression is fixed and tests pass again
144
m_view->resize(m_view->rootObject()->width(), m_view->rootObject()->height());
145
QTRY_COMPARE(m_view->width(), (int)m_view->rootObject()->width());
146
QTRY_COMPARE(m_view->height(), (int)m_view->rootObject()->height());
149
void tst_UCSwipeArea::sendTouchPress(qint64 timestamp, int id, QPointF pos)
151
sendTouch(timestamp, id, pos, Qt::TouchPointPressed, QEvent::TouchBegin);
154
void tst_UCSwipeArea::sendTouchUpdate(qint64 timestamp, int id, QPointF pos)
156
sendTouch(timestamp, id, pos, Qt::TouchPointMoved, QEvent::TouchUpdate);
159
void tst_UCSwipeArea::sendTouchRelease(qint64 timestamp, int id, QPointF pos)
161
sendTouch(timestamp, id, pos, Qt::TouchPointReleased, QEvent::TouchEnd);
164
void tst_UCSwipeArea::sendTouch(qint64 timestamp, int id, QPointF pos,
165
Qt::TouchPointState pointState, QEvent::Type eventType)
167
m_fakeTimerFactory->updateTime(timestamp);
169
QTouchEvent::TouchPoint point;
171
point.setState(pointState);
173
point.setScenePos(pos);
176
QList<QTouchEvent::TouchPoint> points;
179
QTouchEvent touchEvent(eventType, m_device, Qt::NoModifier, Qt::TouchPointPressed, points);
180
QCoreApplication::sendEvent(m_view, &touchEvent);
182
QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(m_view);
183
windowPrivate->flushDelayedTouchEvent();
186
void tst_UCSwipeArea::passTime(qint64 timeSpanMs)
188
qint64 finalTime = m_fakeTimerFactory->timeSource()->msecsSinceReference() + timeSpanMs;
189
m_fakeTimerFactory->updateTime(finalTime);
193
QPointF calculateInitialtouchPosition(UCSwipeArea *edgeDragArea)
195
QPointF localCenter(edgeDragArea->width() / 2., edgeDragArea->height() / 2.);
196
return edgeDragArea->mapToScene(localCenter);
201
A directional drag should still be recognized if there is a momentaneous, small,
202
change in the direction of a drag. That should be accounted as input noise and
205
void tst_UCSwipeArea::dragWithShortDirectionChange()
207
UCSwipeArea *edgeDragArea =
208
m_view->rootObject()->findChild<UCSwipeArea*>("hpDragArea");
209
QVERIFY(edgeDragArea != 0);
210
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
211
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
213
QPointF initialtouchPosition = calculateInitialtouchPosition(edgeDragArea);
214
QPointF touchPoint = initialtouchPosition;
216
qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0;
217
QPointF dragDirectionVector(1.0, 0.0);
218
qreal touchStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
219
// make sure we are above maximum time
220
int touchStepTimeMs = edgeDragArea->d->maxTime / 20. ;
221
QPointF touchMovement = dragDirectionVector * touchStepDistance;
223
QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
225
// Move a bit in the proper direction
226
for (int i=0; i < 3; ++i) {
227
touchPoint += touchMovement;
228
passTime(touchStepTimeMs);
229
QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
232
// Then a sudden and small movement to the opposite direction
233
touchPoint -= touchMovement*0.2;
234
passTime(touchStepTimeMs*0.2);
235
QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
237
// And then resume movment in the correct direction until it crosses the distance and time
240
touchPoint += touchMovement;
241
passTime(touchStepTimeMs);
242
QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
243
} while ((touchPoint - initialtouchPosition).manhattanLength() < desiredDragDistance
244
|| m_fakeTimerFactory->timeSource()->msecsSinceReference() < (edgeDragArea->d->compositionTime * 1.5f));
246
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Recognized);
248
QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
252
Checks that the recognition timer is started and stopped appropriately.
253
I.e., check that it's running only while gesture recognition is taking place
254
(status == Undecided)
256
void tst_UCSwipeArea::recognitionTimerUsage()
258
UCSwipeArea *edgeDragArea =
259
m_view->rootObject()->findChild<UCSwipeArea*>("hpDragArea");
260
QVERIFY(edgeDragArea != 0);
261
AbstractTimer *fakeTimer = m_fakeTimerFactory->createTimer();
262
edgeDragArea->d->setRecognitionTimer(fakeTimer);
263
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
265
int timeStepMs = 5; // some arbitrary small value.
267
QPointF initialtouchPosition = calculateInitialtouchPosition(edgeDragArea);
268
QPointF touchPoint = initialtouchPosition;
270
QPointF dragDirectionVector(1.0, 0.0);
271
QPointF touchMovement = dragDirectionVector * (edgeDragArea->d->distanceThreshold * 0.2f);
273
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
274
QVERIFY(!fakeTimer->isRunning());
276
QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
278
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
279
QVERIFY(fakeTimer->isRunning());
281
// Move beyond distance threshold and composition time to ensure recognition
282
while (m_fakeTimerFactory->timeSource()->msecsSinceReference() <= edgeDragArea->d->compositionTime ||
283
(touchPoint - initialtouchPosition).manhattanLength() <= edgeDragArea->d->distanceThreshold) {
285
QCOMPARE(edgeDragArea->d->status == UCSwipeAreaPrivate::Undecided, fakeTimer->isRunning());
287
touchPoint += touchMovement;
288
passTime(timeStepMs);
289
QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
292
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Recognized);
293
QVERIFY(!fakeTimer->isRunning());
297
Checks that it informs the X coordinate of the touch point in local and scene coordinates
300
void tst_UCSwipeArea::sceneXAndX()
302
UCSwipeArea *edgeDragArea =
303
m_view->rootObject()->findChild<UCSwipeArea*>("hnDragArea");
304
QVERIFY(edgeDragArea != 0);
305
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
306
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
307
edgeDragArea->setImmediateRecognition(true);
309
QPointF touchScenePosition(m_view->width() - (edgeDragArea->width()/2.0f), m_view->height()/2.0f);
311
sendTouchPress(0 /* timestamp */, 0 /* id */, touchScenePosition);
313
QSignalSpy touchSpy(edgeDragArea, &UCSwipeArea::touchPositionChanged);
315
touchScenePosition.rx() = m_view->width() / 2;
316
sendTouchUpdate(50 /* timestamp */, 0 /* id */, touchScenePosition);
318
QCOMPARE(touchSpy.count(), 1);
319
QCOMPARE(edgeDragArea->touchPosition().x(), touchScenePosition.x() - edgeDragArea->x());
323
Checks that it informs the Y coordinate of the touch point in local and scene coordinates
326
void tst_UCSwipeArea::sceneYAndY()
328
UCSwipeArea *edgeDragArea =
329
m_view->rootObject()->findChild<UCSwipeArea*>("vnDragArea");
330
QVERIFY(edgeDragArea != 0);
331
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
332
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
333
edgeDragArea->setImmediateRecognition(true);
335
QPointF touchScenePosition(m_view->width()/2.0f, m_view->height() - (edgeDragArea->height()/2.0f));
337
sendTouchPress(0 /* timestamp */, 0 /* id */, touchScenePosition);
339
QSignalSpy touchSpy(edgeDragArea, &UCSwipeArea::touchPositionChanged);
341
touchScenePosition.ry() = m_view->height() / 2;
342
sendTouchUpdate(50 /* timestamp */, 0 /* id */, touchScenePosition);
344
QCOMPARE(touchSpy.count(), 1);
345
QCOMPARE(edgeDragArea->touchPosition().y(), touchScenePosition.y() - edgeDragArea->y());
349
Regression test for https://bugs.launchpad.net/bugs/1228336
351
Perform a quick two-finger double-tap and check that UCSwipeArea properly
352
rejects those touch points. In the bug above it got confused and crashed.
354
void tst_UCSwipeArea::twoFingerTap()
356
UCSwipeArea *edgeDragArea =
357
m_view->rootObject()->findChild<UCSwipeArea*>("hpDragArea");
358
QVERIFY(edgeDragArea != 0);
359
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
360
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
362
// Make touches evenly spaced along the edgeDragArea
363
QPoint touchAPos(edgeDragArea->width()/2.0f, m_view->height()*0.33f);
364
QPoint touchBPos(edgeDragArea->width()/2.0f, m_view->height()*0.66f);
366
qint64 timeStepMsecs = 5; // some arbitrary, small value
368
// Perform the first two-finger tap
369
// NB: using move() instead of stationary() becasue in the latter you cannot provide
370
// the touch position and therefore it's left with some garbage numbers.
371
QTest::touchEvent(m_view, m_device)
372
.press(0, touchAPos);
374
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
376
passTime(timeStepMsecs);
377
QTest::touchEvent(m_view, m_device)
379
.press(1, touchBPos);
381
// A second touch point appeared during recognition, reject immediately as this
382
// can't be a single-touch gesture anymore.
383
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
385
passTime(timeStepMsecs);
386
QTest::touchEvent(m_view, m_device)
387
.release(0, touchAPos)
390
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
392
passTime(timeStepMsecs);
393
QTest::touchEvent(m_view, m_device)
394
.release(1, touchBPos);
396
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
398
// Perform the second two-finger tap
400
passTime(timeStepMsecs);
401
QTest::touchEvent(m_view, m_device)
402
.press(0, touchAPos);
404
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
406
passTime(timeStepMsecs);
407
QTest::touchEvent(m_view, m_device)
409
.press(1, touchBPos);
411
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
413
passTime(timeStepMsecs);
414
QTest::touchEvent(m_view, m_device)
415
.release(0, touchAPos)
418
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
420
passTime(timeStepMsecs);
421
QTest::touchEvent(m_view, m_device)
422
.release(1, touchBPos);
424
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
428
Tests that gesture recognition works normally even if the UCSwipeArea moves
430
This effectively means that we have to do gesture recognition with scene coordinates
431
instead of local item coordinates.
433
void tst_UCSwipeArea::movingDDA()
435
QQuickItem *rightwardsLauncher = m_view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
436
Q_ASSERT(rightwardsLauncher != 0);
438
UCSwipeArea *edgeDragArea =
439
rightwardsLauncher->findChild<UCSwipeArea*>("hpDragArea");
440
Q_ASSERT(edgeDragArea != 0);
441
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
442
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
444
QPointF initialtouchPosition = calculateInitialtouchPosition(edgeDragArea);
445
QPointF touchPoint = initialtouchPosition;
447
qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
448
QPointF dragDirectionVector(1.0f, 0.0f);
450
qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
451
QPointF touchMovement = dragDirectionVector * movementStepDistance;
452
int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
453
int movementTimeStepMs = (edgeDragArea->d->compositionTime * 1.5f) / totalMovementSteps;
455
QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
457
// Move it far ahead along the direction of the gesture
458
// rightwardsLauncher is a parent of our UCSwipeArea. So moving it will move our DDA
459
rightwardsLauncher->setX(rightwardsLauncher->x() + edgeDragArea->d->distanceThreshold * 5.0f);
461
for (int i = 0; i < totalMovementSteps; ++i) {
462
touchPoint += touchMovement;
463
passTime(movementTimeStepMs);
464
QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
467
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Recognized);
469
QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
473
The presence of and old, rejected, touch point lying on the UCSwipeArea
474
shouldn't impede the recognition of a gesture from a new touch point.
476
void tst_UCSwipeArea::ignoreOldFinger()
478
UCSwipeArea *edgeDragArea =
479
m_view->rootObject()->findChild<UCSwipeArea*>("hpDragArea");
480
Q_ASSERT(edgeDragArea != 0);
481
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
482
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
484
// Make touches evenly spaced along the edgeDragArea
485
QPoint touch0Pos(edgeDragArea->width()/2.0f, m_view->height()*0.33f);
486
QPoint touch1Pos(edgeDragArea->width()/2.0f, m_view->height()*0.66f);
488
QTest::touchEvent(m_view, m_device).press(0, touch0Pos);
490
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
492
// leave it lying around for some time
493
passTime(edgeDragArea->d->maxTime * 10);
495
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
497
qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
498
QPointF dragDirectionVector(1.0f, 0.0f);
500
qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
501
QPointF touchMovement = dragDirectionVector * movementStepDistance;
502
int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
503
int movementTimeStepMs = (edgeDragArea->d->compositionTime * 1.5f) / totalMovementSteps;
505
QTest::touchEvent(m_view, m_device)
507
.press(1, touch1Pos);
509
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
511
for (int i = 0; i < totalMovementSteps; ++i) {
512
touch1Pos += touchMovement.toPoint();
513
passTime(movementTimeStepMs);
514
QTest::touchEvent(m_view, m_device)
519
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Recognized);
521
QTest::touchEvent(m_view, m_device)
523
.release(1, touch1Pos);
525
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
529
A Rightwards DDA that is rotated 90 degrees clockwise should recognize gestures
530
that are done downwards in scene coordinates. I.e. the gesture recognition direction
531
should be in local coordinates, not scene coordinates.
533
void tst_UCSwipeArea::rotated()
535
QQuickItem *baseItem = m_view->rootObject()->findChild<QQuickItem*>("baseItem");
536
baseItem->setRotation(90.);
538
QQuickItem *rightwardsLauncher = m_view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
539
Q_ASSERT(rightwardsLauncher != 0);
541
UCSwipeArea *edgeDragArea =
542
rightwardsLauncher->findChild<UCSwipeArea*>("hpDragArea");
543
Q_ASSERT(edgeDragArea != 0);
544
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
545
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
547
QPointF initialtouchPosition = calculateInitialtouchPosition(edgeDragArea);
548
QPointF touchPoint = initialtouchPosition;
550
qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
551
QPointF dragDirectionVector(0.0f, 1.0f);
553
qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
554
QPointF touchMovement = dragDirectionVector * movementStepDistance;
555
int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
556
int movementTimeStepMs = (edgeDragArea->d->compositionTime * 1.5f) / totalMovementSteps;
558
QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
560
for (int i = 0; i < totalMovementSteps; ++i) {
561
touchPoint += touchMovement;
562
passTime(movementTimeStepMs);
563
QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
566
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Recognized);
568
QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
571
void tst_UCSwipeArea::distance()
573
QQuickItem *baseItem = m_view->rootObject()->findChild<QQuickItem*>("baseItem");
574
QFETCH(qreal, rotation);
575
QFETCH(QPointF, dragDirectionVector);
576
baseItem->setRotation(rotation);
578
QQuickItem *rightwardsLauncher = m_view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
579
Q_ASSERT(rightwardsLauncher != 0);
581
UCSwipeArea *edgeDragArea =
582
rightwardsLauncher->findChild<UCSwipeArea*>("hpDragArea");
583
Q_ASSERT(edgeDragArea != 0);
584
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
585
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
587
// to disable the position smoothing so that we can more easily check distance values
588
edgeDragArea->setImmediateRecognition(true);
590
QPointF initialtouchPosition = calculateInitialtouchPosition(edgeDragArea);
591
QPointF touchPoint = initialtouchPosition;
593
qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
595
qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
596
QPointF touchMovement = dragDirectionVector * movementStepDistance;
597
int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
598
int movementTimeStepMs = (edgeDragArea->d->compositionTime * 1.5f) / totalMovementSteps;
600
qint64 timestamp = 0;
602
sendTouchPress(timestamp, 0, touchPoint);
604
for (int i = 0; i < totalMovementSteps; ++i) {
605
touchPoint += touchMovement;
606
timestamp += movementTimeStepMs;
607
sendTouchUpdate(timestamp, 0, touchPoint);
610
qreal actualDragDistance = ((qreal)totalMovementSteps) * movementStepDistance;
612
// UCSwipeArea::distance() must match the actual drag distance as the
613
// drag was aligned with the gesture direction
614
// NB: qFuzzyCompare(), used internally by QCOMPARE(), is broken.
615
QVERIFY(qAbs(edgeDragArea->distance() - actualDragDistance) < 0.001);
617
timestamp += movementTimeStepMs;
618
sendTouchRelease(timestamp, 0, touchPoint);
621
void tst_UCSwipeArea::distance_data()
623
QTest::addColumn<qreal>("rotation");
624
QTest::addColumn<QPointF>("dragDirectionVector");
626
QTest::newRow("not rotated") << 0. << QPointF(1., 0.);
627
QTest::newRow("rotated by 90 degrees") << 90. << QPointF(0., 1.);
631
Regression test for https://bugs.launchpad.net/unity8/+bug/1276122
634
If setting "enabled: false" while the UCSwipeArea's (DDA) dragging
635
property is true, the DDA stays in that state and doesn't recover any more.
637
void tst_UCSwipeArea::disabledWhileDragging()
639
UCSwipeArea *edgeDragArea =
640
m_view->rootObject()->findChild<UCSwipeArea*>("hpDragArea");
641
Q_ASSERT(edgeDragArea != 0);
642
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
643
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
645
QPointF touchPoint = calculateInitialtouchPosition(edgeDragArea);
647
qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
648
QPointF dragDirectionVector(1., 0.); // horizontal positive
650
qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
651
QPointF touchMovement = dragDirectionVector * movementStepDistance;
652
int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
653
int movementTimeStepMs = (edgeDragArea->d->compositionTime * 1.5f) / totalMovementSteps;
655
QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
657
for (int i = 0; i < totalMovementSteps; ++i) {
658
touchPoint += touchMovement;
659
passTime(movementTimeStepMs);
660
QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
663
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Recognized);
664
QCOMPARE(edgeDragArea->dragging(), true);
666
// disable the swipeArea while it's being dragged.
667
edgeDragArea->setEnabled(false);
669
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
670
QCOMPARE(edgeDragArea->dragging(), false);
672
QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
675
void tst_UCSwipeArea::oneFingerDownFollowedByLateSecondFingerDown()
677
UCSwipeArea *edgeDragArea =
678
m_view->rootObject()->findChild<UCSwipeArea*>("hpDragArea");
679
Q_ASSERT(edgeDragArea != 0);
680
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
681
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
683
// Disable some constraints we're not interested in
684
edgeDragArea->d->setMaxTime(60 * 1000);
686
// And ensure others have the values we want
687
edgeDragArea->d->compositionTime = 60;
689
// Put an item right behind edgeDragArea to receive the touches ignored by it
690
DummyItem *dummyItem = new DummyItem;
691
dummyItem->setParentItem(edgeDragArea->parentItem());
692
dummyItem->setX(edgeDragArea->x());
693
dummyItem->setY(edgeDragArea->y());
694
dummyItem->setZ(edgeDragArea->z() - 1.0);
695
dummyItem->setWidth(edgeDragArea->width());
696
dummyItem->setHeight(edgeDragArea->height());
698
// Make touches evenly spaced along the edgeDragArea
699
QPoint touch0Pos(edgeDragArea->width()/2.0f, m_view->height()*0.33f);
700
QPoint touch1Pos(edgeDragArea->width()/2.0f, m_view->height()*0.66f);
702
QTest::touchEvent(m_view, m_device).press(0, touch0Pos);
704
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
706
// We are now going to be way beyond compositionTime
707
passTime(edgeDragArea->d->compositionTime*3);
709
QTest::touchEvent(m_view, m_device)
711
.press(1, touch1Pos);
713
// A new touch has come, but as it can't be composed with touch 0, it should be
714
// ignored/rejected by the UCSwipeArea
715
// Therefore the last event received by dummyItem must have both touch points (0 and 1)
717
TouchMemento &touchMemento = dummyItem->touchEvents.last();
718
QCOMPARE(touchMemento.touchPoints.count(), 2);
719
QVERIFY(touchMemento.containsTouchWithId(0));
720
QVERIFY(touchMemento.containsTouchWithId(1));
725
QTest::touchEvent(m_view, m_device)
729
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
733
QTest::touchEvent(m_view, m_device)
734
.release(0, touch0Pos)
737
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
741
QTest::touchEvent(m_view, m_device)
742
.release(1, touch1Pos);
744
// Shouldn't be keepping info about touches that no longer exist or interest us
745
QVERIFY(edgeDragArea->d->activeTouches.isEmpty());
750
void tst_UCSwipeArea::givesUpWhenLosesTouch()
752
UCSwipeArea *edgeDragArea =
753
m_view->rootObject()->findChild<UCSwipeArea*>("hpDragArea");
754
Q_ASSERT(edgeDragArea != 0);
755
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
756
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
758
// Disable some constraints we're not interested in
759
edgeDragArea->d->setMaxTime(60 * 1000);
761
// Put an item right in front of edgeDragArea
762
DummyItem *dummyItem = new DummyItem(edgeDragArea->parentItem());
763
dummyItem->setX(edgeDragArea->x());
764
dummyItem->setY(edgeDragArea->y());
765
dummyItem->setZ(edgeDragArea->z() + 1.0);
766
dummyItem->setWidth(edgeDragArea->width());
767
dummyItem->setHeight(edgeDragArea->height());
769
QPoint touchPosition(edgeDragArea->width()/2.0f, m_view->height()/2.0f);
771
dummyItem->touchEventHandler = [&](QTouchEvent *event) {
772
m_touchRegistry->addCandidateOwnerForTouch(0, dummyItem);
776
QTest::touchEvent(m_view, m_device).press(0, touchPosition);
778
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
780
m_touchRegistry->requestTouchOwnership(0, dummyItem);
782
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
784
dummyItem->grabTouchPoints({0});
785
dummyItem->touchEventHandler = [&](QTouchEvent *event) { event->accept(); };
788
QTest::touchEvent(m_view, m_device).release(0, touchPosition);
790
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
792
QVERIFY(edgeDragArea->d->activeTouches.isEmpty());
795
void tst_UCSwipeArea::threeFingerDrag()
797
UCSwipeArea *edgeDragArea =
798
m_view->rootObject()->findChild<UCSwipeArea*>("hpDragArea");
799
Q_ASSERT(edgeDragArea != 0);
800
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
801
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
803
// Disable some constraints we're not interested in
804
edgeDragArea->d->setMaxTime(60 * 1000);
806
// And ensure others have the values we want
807
edgeDragArea->d->compositionTime = 60;
809
// Make touches evenly spaced along the edgeDragArea
810
QPoint touch0Pos(edgeDragArea->width()/2.0f, m_view->height()*0.25f);
811
QPoint touch1Pos(edgeDragArea->width()/2.0f, m_view->height()*0.50f);
812
QPoint touch2Pos(edgeDragArea->width()/2.0f, m_view->height()*0.75f);
814
QTest::touchEvent(m_view, m_device)
815
.press(0, touch0Pos);
817
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
820
QTest::touchEvent(m_view, m_device)
822
.press(1, touch1Pos);
824
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
827
QTest::touchEvent(m_view, m_device)
830
.press(2, touch2Pos);
832
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
835
QTest::touchEvent(m_view, m_device)
841
QTest::touchEvent(m_view, m_device)
843
.release(1, touch1Pos)
847
QTest::touchEvent(m_view, m_device)
849
.release(2, touch2Pos);
852
QTest::touchEvent(m_view, m_device)
853
.release(0, touch0Pos);
855
// Shouldn't be keepping info about touches that no longer exist or interest us
856
QVERIFY(edgeDragArea->d->activeTouches.isEmpty());
860
If all the relevant gesture recognition constraints/parameters have been disabled,
861
it means that the gesture recognition itself has been disabled and UCSwipeArea
862
will therefore work like a simple touch area, merely reporting touch movement.
864
void tst_UCSwipeArea::immediateRecognitionWhenConstraintsDisabled()
866
UCSwipeArea *edgeDragArea =
867
m_view->rootObject()->findChild<UCSwipeArea*>("hpDragArea");
868
Q_ASSERT(edgeDragArea != 0);
869
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
870
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
872
// Disable the minimum amount of constraints to ensure immediate recognition
873
edgeDragArea->d->setDistanceThreshold(0);
874
edgeDragArea->d->compositionTime = 0;
876
// Put an item right behind edgeDragArea to receive the touches ignored by it
877
DummyItem *dummyItem = new DummyItem;
878
dummyItem->setParentItem(edgeDragArea->parentItem());
879
dummyItem->setX(edgeDragArea->x());
880
dummyItem->setY(edgeDragArea->y());
881
dummyItem->setZ(edgeDragArea->z() - 1.0);
882
dummyItem->setWidth(edgeDragArea->width());
883
dummyItem->setHeight(edgeDragArea->height());
885
QPoint touch0Pos(edgeDragArea->width()/2.0f, m_view->height()/2.0f);
887
QTest::touchEvent(m_view, m_device).press(0, touch0Pos);
889
// check for immediate recognition
890
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Recognized);
892
// and therefore it should have immediately grabbed the touch point,
893
// not letting it leak to items behind him.
894
QCOMPARE(dummyItem->touchEvents.count(), 0);
897
void tst_UCSwipeArea::withdrawTouchOwnershipCandidacyIfDisabledDuringRecognition()
899
UCSwipeArea *edgeDragArea =
900
m_view->rootObject()->findChild<UCSwipeArea*>("hpDragArea");
901
Q_ASSERT(edgeDragArea != 0);
902
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
903
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
905
QPointF touchPoint = calculateInitialtouchPosition(edgeDragArea);
907
// Move less than the minimum needed for the drag gesture recognition
908
qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 0.5f;
909
QPointF dragDirectionVector(1., 0.); // horizontal positive
911
qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
912
QPointF touchMovement = dragDirectionVector * movementStepDistance;
913
int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
914
int movementTimeStepMs = (edgeDragArea->d->compositionTime * 0.8f) / totalMovementSteps;
916
QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
918
for (int i = 0; i < totalMovementSteps; ++i) {
919
touchPoint += touchMovement;
920
passTime(movementTimeStepMs);
921
QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
924
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
926
// edgeDragArea should be an undecided candidate
928
auto touchInfo = m_touchRegistry->findTouchInfo(0);
929
QCOMPARE(touchInfo->candidates.size(), 1);
930
QCOMPARE(touchInfo->candidates.at(0).item.data(), edgeDragArea);
931
QCOMPARE(touchInfo->candidates.at(0).state, TouchRegistry::CandidateInfo::Undecided);
934
// disable the swipeArea while it's still recognizing a possible drag gesture.
935
QFETCH(bool, disable);
937
edgeDragArea->setEnabled(false);
939
edgeDragArea->setVisible(false);
942
// edgeDragArea should no longer be a candidate
944
auto touchInfo = m_touchRegistry->findTouchInfo(0);
945
QCOMPARE(touchInfo->candidates.size(), 0);
948
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
950
QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
953
void tst_UCSwipeArea::withdrawTouchOwnershipCandidacyIfDisabledDuringRecognition_data()
955
QTest::addColumn<bool>("disable");
957
QTest::newRow("disabled") << true;
958
QTest::newRow("invisible") << false;
961
void tst_UCSwipeArea::gettingTouchOwnershipMakesMouseAreaBehindGetCanceled()
963
UCSwipeArea *edgeDragArea =
964
m_view->rootObject()->findChild<UCSwipeArea*>("hpDragArea");
965
QVERIFY(edgeDragArea != nullptr);
966
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
967
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
969
QQuickMouseArea *mouseArea =
970
m_view->rootObject()->findChild<QQuickMouseArea*>("mouseArea");
971
QVERIFY(mouseArea != nullptr);
973
MouseAreaSpy mouseAreaSpy(mouseArea);
975
QPointF initialtouchPosition = calculateInitialtouchPosition(edgeDragArea);
976
QPointF touchPoint = initialtouchPosition;
978
qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2;
979
QPointF dragDirectionVector(1.0f, 0.0f); // rightwards
980
qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
981
QPointF touchMovement = dragDirectionVector * movementStepDistance;
982
int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
983
int movementTimeStepMs = (edgeDragArea->d->compositionTime * 1.5f) / totalMovementSteps;
985
QCOMPARE(mouseArea->pressed(), false);
987
QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
989
// The TouchBegin passes through the UCSwipeArea and reaches the MouseArea behind it,
990
// where it's converted to a MouseEvent by QQuickWindow and sent to the MouseArea which then
991
// accepts it. Making it get pressed.
992
QCOMPARE(mouseArea->pressed(), true);
993
QCOMPARE(mouseAreaSpy.canceledCount, 0);
995
for (int i = 0; i < totalMovementSteps; ++i) {
996
touchPoint += touchMovement;
997
passTime(movementTimeStepMs);
998
QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
1001
// As the UCSwipeArea recognizes the gesture, it grabs the touch from the MouseArea,
1002
// which should make the MouseArea get a cancelation event, which will then cause it to
1003
// reset its state (going back to "unpressed"/"released").
1004
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Recognized);
1005
QCOMPARE(mouseArea->pressed(), false);
1006
QCOMPARE(mouseAreaSpy.canceledCount, 1);
1008
QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
1011
void tst_UCSwipeArea::interleavedTouches()
1013
UCSwipeArea *edgeDragArea =
1014
m_view->rootObject()->findChild<UCSwipeArea*>("hpDragArea");
1015
QVERIFY(edgeDragArea != 0);
1016
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
1017
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
1019
QPointF touch0 = edgeDragArea->mapToScene(
1020
QPointF(edgeDragArea->width()*0.5, edgeDragArea->height()*0.3));
1022
qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2;
1023
QPointF dragDirectionVector(1.0f, 0.0f); // rightwards
1024
qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
1025
QPointF touchMovement = dragDirectionVector * movementStepDistance;
1026
int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
1027
int movementTimeStepMs = (edgeDragArea->d->maxTime * 0.4f) / totalMovementSteps;
1029
QTest::touchEvent(m_view, m_device).press(0, touch0.toPoint());
1030
for (int i = 0; i < totalMovementSteps; ++i) {
1031
touch0 += touchMovement;
1032
passTime(movementTimeStepMs);
1033
QTest::touchEvent(m_view, m_device).move(0, touch0.toPoint());
1035
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Recognized);
1037
QPointF touch1 = edgeDragArea->mapToScene(
1038
QPointF(edgeDragArea->width()*0.5, edgeDragArea->height()*0.6));
1040
QTest::touchEvent(m_view, m_device)
1041
.move(0, touch0.toPoint())
1042
.press(1, touch1.toPoint());
1044
touch1 += touchMovement;
1045
passTime(movementTimeStepMs);
1046
QTest::touchEvent(m_view, m_device)
1047
.move(0, touch0.toPoint())
1048
.move(1, touch1.toPoint());
1050
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Recognized);
1052
QTest::touchEvent(m_view, m_device)
1053
.release(0, touch0.toPoint())
1054
.move(1, touch1.toPoint());
1056
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
1058
touch1 += touchMovement;
1059
passTime(movementTimeStepMs);
1060
QTest::touchEvent(m_view, m_device)
1061
.move(1, touch1.toPoint());
1063
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
1065
QPointF touch2 = edgeDragArea->mapToScene(
1066
QPointF(edgeDragArea->width()*0.5, edgeDragArea->height()*0.9));
1068
passTime(edgeDragArea->d->compositionTime + movementTimeStepMs);
1069
QTest::touchEvent(m_view, m_device)
1070
.move(1, touch1.toPoint())
1071
.press(2, touch2.toPoint());
1073
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
1074
QCOMPARE(edgeDragArea->d->touchId, 2);
1076
touch2 += touchMovement;
1077
passTime(movementTimeStepMs);
1078
QTest::touchEvent(m_view, m_device)
1079
.move(1, touch1.toPoint())
1080
.move(2, touch2.toPoint());
1082
touch1 += touchMovement;
1083
passTime(movementTimeStepMs);
1084
QTest::touchEvent(m_view, m_device)
1085
.move(1, touch1.toPoint())
1086
.move(2, touch2.toPoint());
1088
passTime(movementTimeStepMs);
1089
QTest::touchEvent(m_view, m_device)
1090
.release(1, touch1.toPoint())
1091
.move(2, touch2.toPoint());
1093
passTime(movementTimeStepMs);
1094
QTest::touchEvent(m_view, m_device)
1095
.release(2, touch2.toPoint());
1097
QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
1101
A valid right-edge drag performed on mako
1103
void tst_UCSwipeArea::makoRightEdgeDrag()
1105
m_view->resize(768, 1280);
1108
UCSwipeArea *edgeDragArea =
1109
m_view->rootObject()->findChild<UCSwipeArea*>("hnDragArea");
1110
QVERIFY(edgeDragArea != nullptr);
1111
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
1112
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
1114
StatusSpy *statusSpy = new StatusSpy(edgeDragArea);
1116
edgeDragArea->d->setPixelsPerMm(320.0 /*mako ppi*/ * 0.03937 /* inches per mm*/);
1118
sendTouchPress(319744, 0, QPointF(767.001, 719.719));
1119
sendTouchUpdate(319765, 0, QPointF(765.744,729.973));
1120
sendTouchUpdate(319784, 0, QPointF(740.879,752.182));
1121
sendTouchUpdate(319803, 0, QPointF(689.698,795.795));
1122
sendTouchUpdate(319826, 0, QPointF(616.978,856.212));
1123
sendTouchUpdate(319845, 0, QPointF(558.769,906.157));
1124
sendTouchUpdate(319859, 0, QPointF(513.219,945.266));
1125
sendTouchUpdate(319878, 0, QPointF(481.31,975.496));
1126
sendTouchUpdate(319902, 0, QPointF(460.016,997.439));
1127
sendTouchUpdate(319920, 0, QPointF(449.761,1008.6));
1128
sendTouchUpdate(319929, 0, QPointF(445.891,1012.42));
1129
sendTouchUpdate(319947, 0, QPointF(444.884,1013.93));
1130
sendTouchUpdate(319965, 0, QPointF(444.461,1014.35));
1131
sendTouchUpdate(320057, 0, QPointF(444.71,1013.56));
1132
sendTouchUpdate(320138, 0, QPointF(445.434,1013.6));
1133
sendTouchUpdate(320154, 0, QPointF(446.338,1012.98));
1134
sendTouchUpdate(320171, 0, QPointF(447.232,1012.08));
1135
sendTouchRelease(320171, 0, QPointF(447.232,1012.08));
1137
QCOMPARE(statusSpy->recognized(), true);
1143
A vertical, downwards swipe performed on mako near its right edge.
1145
The UCSwipeArea on the right edge must not recognize this
1148
void tst_UCSwipeArea::makoRightEdgeDrag_verticalDownwards()
1150
m_view->resize(768, 1280);
1153
UCSwipeArea *edgeDragArea =
1154
m_view->rootObject()->findChild<UCSwipeArea*>("hnDragArea");
1155
QVERIFY(edgeDragArea != nullptr);
1156
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
1157
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
1159
edgeDragArea->d->setPixelsPerMm(320.0 /*mako ppi*/ * 0.03937 /* inches per mm*/);
1161
StatusSpy *statusSpy = new StatusSpy(edgeDragArea);
1163
sendTouchPress(12012445, 26, QPointF(767.001,461.82));
1164
sendTouchUpdate(12012472, 26, QPointF(767.001,462.569));
1165
sendTouchUpdate(12012528, 26, QPointF(767.001,463.334));
1166
sendTouchUpdate(12012546, 26, QPointF(767.001,466.856));
1167
sendTouchUpdate(12012571, 26, QPointF(767.001,473.291));
1168
sendTouchUpdate(12012587, 26, QPointF(767.001,487.31));
1169
sendTouchUpdate(12012604, 26, QPointF(765.364,507.521));
1170
sendTouchUpdate(12012618, 26, QPointF(765.364,507.521));
1171
sendTouchUpdate(12012627, 26, QPointF(762.642,534.317));
1172
sendTouchUpdate(12012655, 26, QPointF(760.846,573.406));
1173
sendTouchUpdate(12012667, 26, QPointF(759.838,625.295));
1174
sendTouchUpdate(12012675, 26, QPointF(758.875,703.207));
1175
sendTouchUpdate(12012696, 26, QPointF(761.52,777.015));
1176
sendTouchUpdate(12012713, 26, QPointF(765.659,835.591));
1177
sendTouchUpdate(12012731, 26, QPointF(766.778,883.206));
1178
sendTouchUpdate(12012748, 26, QPointF(767.001,922.937));
1179
sendTouchUpdate(12012779, 26, QPointF(767.001,967.558));
1180
sendTouchUpdate(12012798, 26, QPointF(767.001,1006.12));
1181
sendTouchUpdate(12012809, 26, QPointF(767.001,1033.1));
1182
sendTouchRelease(12012810, 26, QPointF(767.001,1033.1));
1184
QCOMPARE(statusSpy->recognized(), false);
1190
A valid left-edge drag performed on mako. This one starts a bit slow than speeds up
1192
void tst_UCSwipeArea::makoLeftEdgeDrag_slowStart()
1194
m_view->resize(768, 1280);
1197
UCSwipeArea *edgeDragArea =
1198
m_view->rootObject()->findChild<UCSwipeArea*>("hpDragArea");
1199
QVERIFY(edgeDragArea != nullptr);
1200
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
1201
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
1203
edgeDragArea->d->setPixelsPerMm(320.0 /*mako ppi*/ * 0.03937 /* inches per mm*/);
1205
StatusSpy *statusSpy = new StatusSpy(edgeDragArea);
1207
sendTouchPress(4002267, 77, QPointF(0,885.154));
1208
sendTouchUpdate(4002275, 77, QPointF(0,886.214));
1209
sendTouchUpdate(4002311, 77, QPointF(1.09568,887.75));
1210
sendTouchUpdate(4002329, 77, QPointF(3.53647,890.191));
1211
sendTouchUpdate(4002347, 77, QPointF(7.87434,892.879));
1212
sendTouchUpdate(4002366, 77, QPointF(12.3036,895.075));
1213
sendTouchUpdate(4002384, 77, QPointF(15.8885,896.849));
1214
sendTouchUpdate(4002406, 77, QPointF(18.4504,897.88));
1215
sendTouchUpdate(4002420, 77, QPointF(20.2429,898.149));
1216
sendTouchUpdate(4002439, 77, QPointF(20.9945,898.149));
1217
sendTouchUpdate(4002457, 77, QPointF(21.8819,898.149));
1218
sendTouchUpdate(4002480, 77, QPointF(22.7454,897.389));
1219
sendTouchUpdate(4002493, 77, QPointF(23.5456,896.589));
1220
sendTouchUpdate(4002511, 77, QPointF(24.5435,895.031));
1221
sendTouchUpdate(4002529, 77, QPointF(25.4271,892.32));
1222
sendTouchUpdate(4002548, 77, QPointF(26.3145,889.658));
1223
sendTouchUpdate(4002566, 77, QPointF(27.2004,886.999));
1224
sendTouchUpdate(4002584, 77, QPointF(28.035,885.048));
1225
sendTouchUpdate(4002603, 77, QPointF(29.9684,883.167));
1226
sendTouchUpdate(4002620, 77, QPointF(33.3591,881.403));
1227
sendTouchUpdate(4002639, 77, QPointF(44.1017,879.642));
1228
sendTouchUpdate(4002657, 77, QPointF(64.828,878.502));
1229
sendTouchUpdate(4002675, 77, QPointF(87.9486,878.157));
1230
sendTouchUpdate(4002693, 77, QPointF(112.96,877.742));
1231
sendTouchUpdate(4002711, 77, QPointF(138.903,877.157));
1232
sendTouchUpdate(4002729, 77, QPointF(163.204,877.157));
1233
sendTouchUpdate(4002747, 77, QPointF(182.127,877.157));
1234
sendTouchUpdate(4002765, 77, QPointF(194.478,877.657));
1235
sendTouchUpdate(4002785, 77, QPointF(201.474,878.508));
1236
sendTouchUpdate(4002803, 77, QPointF(204.855,879.401));
1237
sendTouchUpdate(4002822, 77, QPointF(206.616,880.281));
1238
sendTouchUpdate(4002839, 77, QPointF(207.115,880.906));
1239
sendTouchUpdate(4002894, 77, QPointF(206.865,881.184));
1240
sendTouchUpdate(4002912, 77, QPointF(206.865,882.143));
1241
sendTouchUpdate(4002930, 77, QPointF(206.865,883.106));
1242
sendTouchUpdate(4002949, 77, QPointF(206.526,883.994));
1243
sendTouchUpdate(4002967, 77, QPointF(205.866,884.88));
1244
sendTouchUpdate(4002985, 77, QPointF(205.866,885.766));
1245
sendTouchUpdate(4003005, 77, QPointF(205.866,886.654));
1246
sendTouchUpdate(4003021, 77, QPointF(205.366,887.537));
1247
sendTouchUpdate(4003039, 77, QPointF(204.592,888.428));
1248
sendTouchUpdate(4003050, 77, QPointF(204.367,888.653));
1249
sendTouchRelease(4003050, 77, QPointF(204.367,888.653));
1251
QCOMPARE(statusSpy->recognized(), true);
1256
void tst_UCSwipeArea::makoLeftEdgeDrag_movesSlightlyBackwardsOnStart()
1258
m_view->resize(768, 1280);
1261
UCSwipeArea *edgeDragArea =
1262
m_view->rootObject()->findChild<UCSwipeArea*>("hpDragArea");
1263
QVERIFY(edgeDragArea != nullptr);
1264
edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
1265
edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
1267
edgeDragArea->d->setPixelsPerMm(320.0 /*mako ppi*/ * 0.03937 /* inches per mm*/);
1269
StatusSpy *statusSpy = new StatusSpy(edgeDragArea);
1271
sendTouchPress(41097, 24, QPointF(13.9909,827.177));
1272
sendTouchUpdate(41120, 24, QPointF(19.2375,825.677));
1273
sendTouchUpdate(41138, 24, QPointF(18.4057,826.177));
1274
sendTouchUpdate(41161, 24, QPointF(20.1067,825.867));
1275
sendTouchUpdate(41177, 24, QPointF(21.8869,824.977));
1276
sendTouchUpdate(41193, 24, QPointF(24.7603,823.494));
1277
sendTouchUpdate(41211, 24, QPointF(28.3889,821.725));
1278
sendTouchUpdate(41229, 24, QPointF(32.2909,819.955));
1279
sendTouchUpdate(41247, 24, QPointF(38.2251,817.431));
1280
sendTouchUpdate(41266, 24, QPointF(52.4182,814.223));
1281
sendTouchUpdate(41284, 24, QPointF(85.8465,809.483));
1282
sendTouchUpdate(41302, 24, QPointF(126.091,802.741));
1283
sendTouchUpdate(41320, 24, QPointF(153.171,797.977));
1284
sendTouchUpdate(41338, 24, QPointF(170.565,795.077));
1285
sendTouchUpdate(41356, 24, QPointF(178.685,794.101));
1286
sendTouchUpdate(41375, 24, QPointF(183.706,793.225));
1287
sendTouchUpdate(41393, 24, QPointF(186.112,793.19));
1288
sendTouchUpdate(41411, 24, QPointF(187.634,793.19));
1289
sendTouchUpdate(41429, 24, QPointF(188.505,793.19));
1290
sendTouchUpdate(41532, 24, QPointF(187.816,793.19));
1291
sendTouchUpdate(41538, 24, QPointF(186.902,793.19));
1292
sendTouchUpdate(41557, 24, QPointF(186.01,793.19));
1293
sendTouchUpdate(41575, 24, QPointF(185.125,793.444));
1294
sendTouchUpdate(41593, 24, QPointF(184.229,793.69));
1295
sendTouchUpdate(41605, 24, QPointF(183.88,793.69));
1296
sendTouchRelease(41607, 24, QPointF(183.88,793.69));
1298
QCOMPARE(statusSpy->recognized(), true);
1303
QTEST_MAIN(tst_UCSwipeArea)
1305
#include "tst_swipearea.moc"