~faenil/ubuntu-ui-toolkit/flickableBasedScrollView

« back to all changes in this revision

Viewing changes to tests/unit_x11/tst_swipearea/tst_swipearea.cpp

  • Committer: Andrea Bernabei
  • Date: 2015-11-25 11:50:10 UTC
  • mfrom: (1681.2.44 staging)
  • Revision ID: andrea.bernabei@canonical.com-20151125115010-vpxkm2lze1hav9q9
mergeĀ upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 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 Lesser 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 Lesser General Public License for more details.
 
12
 *
 
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/>.
 
15
 *
 
16
 */
 
17
 
 
18
#include <QtTest/QtTest>
 
19
#include <QtCore/QObject>
 
20
#include <QtQuick/QQuickView>
 
21
#include <QtQml/QQmlEngine>
 
22
#include <QPointer>
 
23
#include <private/qquickmousearea_p.h>
 
24
#include <private/qquickwindow_p.h>
 
25
 
 
26
#include "gestures/ucswipearea.h"
 
27
#include "gestures/ucswipearea_p.h"
 
28
#define protected public
 
29
#define private public
 
30
#include <UbuntuGestures/TouchRegistry>
 
31
#undef protected
 
32
#undef private
 
33
 
 
34
#include "GestureTest.h"
 
35
#include "uctestcase.h"
 
36
 
 
37
using namespace UbuntuGestures;
 
38
 
 
39
// Because QSignalSpy(UCSwipeArea, SIGNAL(UCSwipeArea::Status)) simply
 
40
// doesn't work
 
41
class StatusSpy : public QObject {
 
42
    Q_OBJECT
 
43
public:
 
44
    StatusSpy(UCSwipeArea *edgeDragArea) {
 
45
        m_recognized = false;
 
46
        connect(edgeDragArea->d, &UCSwipeAreaPrivate::statusChanged,
 
47
                this, &StatusSpy::onStatusChanged);
 
48
    }
 
49
    bool recognized() {
 
50
        return m_recognized;
 
51
    }
 
52
 
 
53
private Q_SLOTS:
 
54
    void onStatusChanged(UCSwipeAreaPrivate::Status status) {
 
55
        m_recognized |= status == UCSwipeAreaPrivate::Recognized;
 
56
    }
 
57
 
 
58
private:
 
59
    bool m_recognized;
 
60
};
 
61
 
 
62
/*
 
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.
 
66
 */
 
67
class MouseAreaSpy : public QObject
 
68
{
 
69
    Q_OBJECT
 
70
public:
 
71
    MouseAreaSpy(QQuickMouseArea *mouseArea)
 
72
        : canceledCount(0)
 
73
    {
 
74
        connect(mouseArea, &QQuickMouseArea::canceled,
 
75
                this, &MouseAreaSpy::onMouseAreaCanceled);
 
76
    }
 
77
 
 
78
    int canceledCount;
 
79
 
 
80
private Q_SLOTS:
 
81
    void onMouseAreaCanceled() {
 
82
        ++canceledCount;
 
83
    }
 
84
};
 
85
 
 
86
class tst_UCSwipeArea: public GestureTest
 
87
{
 
88
    Q_OBJECT
 
89
public:
 
90
    tst_UCSwipeArea();
 
91
private Q_SLOTS:
 
92
    void init() override; // called right before each and every test function is executed
 
93
 
 
94
    void dragWithShortDirectionChange();
 
95
    void recognitionTimerUsage();
 
96
    void sceneXAndX();
 
97
    void sceneYAndY();
 
98
    void twoFingerTap();
 
99
    void movingDDA();
 
100
    void ignoreOldFinger();
 
101
    void rotated();
 
102
    void distance();
 
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();
 
117
 
 
118
private:
 
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);
 
127
 
 
128
    void passTime(qint64 timeSpanMs);
 
129
};
 
130
 
 
131
tst_UCSwipeArea::tst_UCSwipeArea()
 
132
    : GestureTest(QStringLiteral("tst_swipearea.qml"))
 
133
{
 
134
}
 
135
 
 
136
void tst_UCSwipeArea::init()
 
137
{
 
138
    GestureTest::init();
 
139
 
 
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());
 
147
}
 
148
 
 
149
void tst_UCSwipeArea::sendTouchPress(qint64 timestamp, int id, QPointF pos)
 
150
{
 
151
    sendTouch(timestamp, id, pos, Qt::TouchPointPressed, QEvent::TouchBegin);
 
152
}
 
153
 
 
154
void tst_UCSwipeArea::sendTouchUpdate(qint64 timestamp, int id, QPointF pos)
 
155
{
 
156
    sendTouch(timestamp, id, pos, Qt::TouchPointMoved, QEvent::TouchUpdate);
 
157
}
 
158
 
 
159
void tst_UCSwipeArea::sendTouchRelease(qint64 timestamp, int id, QPointF pos)
 
160
{
 
161
    sendTouch(timestamp, id, pos, Qt::TouchPointReleased, QEvent::TouchEnd);
 
162
}
 
163
 
 
164
void tst_UCSwipeArea::sendTouch(qint64 timestamp, int id, QPointF pos,
 
165
                                 Qt::TouchPointState pointState, QEvent::Type eventType)
 
166
{
 
167
    m_fakeTimerFactory->updateTime(timestamp);
 
168
 
 
169
    QTouchEvent::TouchPoint point;
 
170
 
 
171
    point.setState(pointState);
 
172
    point.setId(id);
 
173
    point.setScenePos(pos);
 
174
    point.setPos(pos);
 
175
 
 
176
    QList<QTouchEvent::TouchPoint> points;
 
177
    points << point;
 
178
 
 
179
    QTouchEvent touchEvent(eventType, m_device, Qt::NoModifier, Qt::TouchPointPressed, points);
 
180
    QCoreApplication::sendEvent(m_view, &touchEvent);
 
181
 
 
182
    QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(m_view);
 
183
    windowPrivate->flushDelayedTouchEvent();
 
184
}
 
185
 
 
186
void tst_UCSwipeArea::passTime(qint64 timeSpanMs)
 
187
{
 
188
    qint64 finalTime = m_fakeTimerFactory->timeSource()->msecsSinceReference() + timeSpanMs;
 
189
    m_fakeTimerFactory->updateTime(finalTime);
 
190
}
 
191
 
 
192
namespace {
 
193
QPointF calculateInitialtouchPosition(UCSwipeArea *edgeDragArea)
 
194
{
 
195
    QPointF localCenter(edgeDragArea->width() / 2., edgeDragArea->height() / 2.);
 
196
    return edgeDragArea->mapToScene(localCenter);
 
197
}
 
198
}
 
199
 
 
200
/*
 
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
 
203
  therefore ignored.
 
204
 */
 
205
void tst_UCSwipeArea::dragWithShortDirectionChange()
 
206
{
 
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());
 
212
 
 
213
    QPointF initialtouchPosition = calculateInitialtouchPosition(edgeDragArea);
 
214
    QPointF touchPoint = initialtouchPosition;
 
215
 
 
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;
 
222
 
 
223
    QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
 
224
 
 
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());
 
230
    }
 
231
 
 
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());
 
236
 
 
237
    // And then resume movment in the correct direction until it crosses the distance and time
 
238
    // thresholds.
 
239
    do {
 
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));
 
245
 
 
246
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Recognized);
 
247
 
 
248
    QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
 
249
}
 
250
 
 
251
/*
 
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)
 
255
 */
 
256
void tst_UCSwipeArea::recognitionTimerUsage()
 
257
{
 
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());
 
264
 
 
265
    int timeStepMs = 5; // some arbitrary small value.
 
266
 
 
267
    QPointF initialtouchPosition = calculateInitialtouchPosition(edgeDragArea);
 
268
    QPointF touchPoint = initialtouchPosition;
 
269
 
 
270
    QPointF dragDirectionVector(1.0, 0.0);
 
271
    QPointF touchMovement = dragDirectionVector * (edgeDragArea->d->distanceThreshold * 0.2f);
 
272
 
 
273
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
 
274
    QVERIFY(!fakeTimer->isRunning());
 
275
 
 
276
    QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
 
277
 
 
278
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
 
279
    QVERIFY(fakeTimer->isRunning());
 
280
 
 
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) {
 
284
 
 
285
        QCOMPARE(edgeDragArea->d->status == UCSwipeAreaPrivate::Undecided, fakeTimer->isRunning());
 
286
 
 
287
        touchPoint += touchMovement;
 
288
        passTime(timeStepMs);
 
289
        QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
 
290
    }
 
291
 
 
292
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Recognized);
 
293
    QVERIFY(!fakeTimer->isRunning());
 
294
}
 
295
 
 
296
/*
 
297
  Checks that it informs the X coordinate of the touch point in local and scene coordinates
 
298
  correctly.
 
299
 */
 
300
void tst_UCSwipeArea::sceneXAndX()
 
301
{
 
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);
 
308
 
 
309
    QPointF touchScenePosition(m_view->width() - (edgeDragArea->width()/2.0f), m_view->height()/2.0f);
 
310
 
 
311
    sendTouchPress(0 /* timestamp */, 0 /* id */, touchScenePosition);
 
312
 
 
313
    QSignalSpy touchSpy(edgeDragArea, &UCSwipeArea::touchPositionChanged);
 
314
 
 
315
    touchScenePosition.rx() = m_view->width() / 2;
 
316
    sendTouchUpdate(50 /* timestamp */, 0 /* id */, touchScenePosition);
 
317
 
 
318
    QCOMPARE(touchSpy.count(), 1);
 
319
    QCOMPARE(edgeDragArea->touchPosition().x(), touchScenePosition.x() - edgeDragArea->x());
 
320
}
 
321
 
 
322
/*
 
323
  Checks that it informs the Y coordinate of the touch point in local and scene coordinates
 
324
  correctly.
 
325
 */
 
326
void tst_UCSwipeArea::sceneYAndY()
 
327
{
 
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);
 
334
 
 
335
    QPointF touchScenePosition(m_view->width()/2.0f, m_view->height() - (edgeDragArea->height()/2.0f));
 
336
 
 
337
    sendTouchPress(0 /* timestamp */, 0 /* id */, touchScenePosition);
 
338
 
 
339
    QSignalSpy touchSpy(edgeDragArea, &UCSwipeArea::touchPositionChanged);
 
340
 
 
341
    touchScenePosition.ry() = m_view->height() / 2;
 
342
    sendTouchUpdate(50 /* timestamp */, 0 /* id */, touchScenePosition);
 
343
 
 
344
    QCOMPARE(touchSpy.count(), 1);
 
345
    QCOMPARE(edgeDragArea->touchPosition().y(), touchScenePosition.y() - edgeDragArea->y());
 
346
}
 
347
 
 
348
/*
 
349
  Regression test for https://bugs.launchpad.net/bugs/1228336
 
350
 
 
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.
 
353
 */
 
354
void tst_UCSwipeArea::twoFingerTap()
 
355
{
 
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());
 
361
 
 
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);
 
365
 
 
366
    qint64 timeStepMsecs = 5; // some arbitrary, small value
 
367
 
 
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);
 
373
 
 
374
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
 
375
 
 
376
    passTime(timeStepMsecs);
 
377
    QTest::touchEvent(m_view, m_device)
 
378
        .move(0, touchAPos)
 
379
        .press(1, touchBPos);
 
380
 
 
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);
 
384
 
 
385
    passTime(timeStepMsecs);
 
386
    QTest::touchEvent(m_view, m_device)
 
387
        .release(0, touchAPos)
 
388
        .move(1, touchBPos);
 
389
 
 
390
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
 
391
 
 
392
    passTime(timeStepMsecs);
 
393
    QTest::touchEvent(m_view, m_device)
 
394
        .release(1, touchBPos);
 
395
 
 
396
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
 
397
 
 
398
    // Perform the second two-finger tap
 
399
 
 
400
    passTime(timeStepMsecs);
 
401
    QTest::touchEvent(m_view, m_device)
 
402
        .press(0, touchAPos);
 
403
 
 
404
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
 
405
 
 
406
    passTime(timeStepMsecs);
 
407
    QTest::touchEvent(m_view, m_device)
 
408
        .move(0, touchAPos)
 
409
        .press(1, touchBPos);
 
410
 
 
411
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
 
412
 
 
413
    passTime(timeStepMsecs);
 
414
    QTest::touchEvent(m_view, m_device)
 
415
        .release(0, touchAPos)
 
416
        .move(1, touchBPos);
 
417
 
 
418
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
 
419
 
 
420
    passTime(timeStepMsecs);
 
421
    QTest::touchEvent(m_view, m_device)
 
422
        .release(1, touchBPos);
 
423
 
 
424
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
 
425
}
 
426
 
 
427
/*
 
428
   Tests that gesture recognition works normally even if the UCSwipeArea moves
 
429
   during recognition.
 
430
   This effectively means that we have to do gesture recognition with scene coordinates
 
431
   instead of local item coordinates.
 
432
 */
 
433
void tst_UCSwipeArea::movingDDA()
 
434
{
 
435
    QQuickItem *rightwardsLauncher =  m_view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
 
436
    Q_ASSERT(rightwardsLauncher != 0);
 
437
 
 
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());
 
443
 
 
444
    QPointF initialtouchPosition = calculateInitialtouchPosition(edgeDragArea);
 
445
    QPointF touchPoint = initialtouchPosition;
 
446
 
 
447
    qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
 
448
    QPointF dragDirectionVector(1.0f, 0.0f);
 
449
 
 
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;
 
454
 
 
455
    QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
 
456
 
 
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);
 
460
 
 
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());
 
465
    }
 
466
 
 
467
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Recognized);
 
468
 
 
469
    QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
 
470
}
 
471
 
 
472
/*
 
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.
 
475
 */
 
476
void tst_UCSwipeArea::ignoreOldFinger()
 
477
{
 
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());
 
483
 
 
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);
 
487
 
 
488
    QTest::touchEvent(m_view, m_device).press(0, touch0Pos);
 
489
 
 
490
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
 
491
 
 
492
    // leave it lying around for some time
 
493
    passTime(edgeDragArea->d->maxTime * 10);
 
494
 
 
495
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
 
496
 
 
497
    qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
 
498
    QPointF dragDirectionVector(1.0f, 0.0f);
 
499
 
 
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;
 
504
 
 
505
    QTest::touchEvent(m_view, m_device)
 
506
        .move(0, touch0Pos)
 
507
        .press(1, touch1Pos);
 
508
 
 
509
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
 
510
 
 
511
    for (int i = 0; i < totalMovementSteps; ++i) {
 
512
        touch1Pos += touchMovement.toPoint();
 
513
        passTime(movementTimeStepMs);
 
514
        QTest::touchEvent(m_view, m_device)
 
515
            .move(0, touch0Pos)
 
516
            .move(1, touch1Pos);
 
517
    }
 
518
 
 
519
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Recognized);
 
520
 
 
521
    QTest::touchEvent(m_view, m_device)
 
522
        .move(0, touch0Pos)
 
523
        .release(1, touch1Pos);
 
524
 
 
525
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
 
526
}
 
527
 
 
528
/*
 
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.
 
532
 */
 
533
void tst_UCSwipeArea::rotated()
 
534
{
 
535
    QQuickItem *baseItem =  m_view->rootObject()->findChild<QQuickItem*>("baseItem");
 
536
    baseItem->setRotation(90.);
 
537
 
 
538
    QQuickItem *rightwardsLauncher =  m_view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
 
539
    Q_ASSERT(rightwardsLauncher != 0);
 
540
 
 
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());
 
546
 
 
547
    QPointF initialtouchPosition = calculateInitialtouchPosition(edgeDragArea);
 
548
    QPointF touchPoint = initialtouchPosition;
 
549
 
 
550
    qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
 
551
    QPointF dragDirectionVector(0.0f, 1.0f);
 
552
 
 
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;
 
557
 
 
558
    QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
 
559
 
 
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());
 
564
    }
 
565
 
 
566
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Recognized);
 
567
 
 
568
    QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
 
569
}
 
570
 
 
571
void tst_UCSwipeArea::distance()
 
572
{
 
573
    QQuickItem *baseItem =  m_view->rootObject()->findChild<QQuickItem*>("baseItem");
 
574
    QFETCH(qreal, rotation);
 
575
    QFETCH(QPointF, dragDirectionVector);
 
576
    baseItem->setRotation(rotation);
 
577
 
 
578
    QQuickItem *rightwardsLauncher =  m_view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
 
579
    Q_ASSERT(rightwardsLauncher != 0);
 
580
 
 
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());
 
586
 
 
587
    // to disable the position smoothing so that we can more easily check distance values
 
588
    edgeDragArea->setImmediateRecognition(true);
 
589
 
 
590
    QPointF initialtouchPosition = calculateInitialtouchPosition(edgeDragArea);
 
591
    QPointF touchPoint = initialtouchPosition;
 
592
 
 
593
    qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
 
594
 
 
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;
 
599
 
 
600
    qint64 timestamp = 0;
 
601
 
 
602
    sendTouchPress(timestamp, 0, touchPoint);
 
603
 
 
604
    for (int i = 0; i < totalMovementSteps; ++i) {
 
605
        touchPoint += touchMovement;
 
606
        timestamp += movementTimeStepMs;
 
607
        sendTouchUpdate(timestamp, 0, touchPoint);
 
608
    }
 
609
 
 
610
    qreal actualDragDistance = ((qreal)totalMovementSteps) * movementStepDistance;
 
611
 
 
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);
 
616
 
 
617
    timestamp += movementTimeStepMs;
 
618
    sendTouchRelease(timestamp, 0, touchPoint);
 
619
}
 
620
 
 
621
void tst_UCSwipeArea::distance_data()
 
622
{
 
623
    QTest::addColumn<qreal>("rotation");
 
624
    QTest::addColumn<QPointF>("dragDirectionVector");
 
625
 
 
626
    QTest::newRow("not rotated")           << 0.  << QPointF(1., 0.);
 
627
    QTest::newRow("rotated by 90 degrees") << 90. << QPointF(0., 1.);
 
628
}
 
629
 
 
630
/*
 
631
    Regression test for https://bugs.launchpad.net/unity8/+bug/1276122
 
632
 
 
633
    The bug:
 
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.
 
636
*/
 
637
void tst_UCSwipeArea::disabledWhileDragging()
 
638
{
 
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());
 
644
 
 
645
    QPointF touchPoint = calculateInitialtouchPosition(edgeDragArea);
 
646
 
 
647
    qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
 
648
    QPointF dragDirectionVector(1., 0.); // horizontal positive
 
649
 
 
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;
 
654
 
 
655
    QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
 
656
 
 
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());
 
661
    }
 
662
 
 
663
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Recognized);
 
664
    QCOMPARE(edgeDragArea->dragging(), true);
 
665
 
 
666
    // disable the swipeArea while it's being dragged.
 
667
    edgeDragArea->setEnabled(false);
 
668
 
 
669
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
 
670
    QCOMPARE(edgeDragArea->dragging(), false);
 
671
 
 
672
    QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
 
673
}
 
674
 
 
675
void tst_UCSwipeArea::oneFingerDownFollowedByLateSecondFingerDown()
 
676
{
 
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());
 
682
 
 
683
    // Disable some constraints we're not interested in
 
684
    edgeDragArea->d->setMaxTime(60 * 1000);
 
685
 
 
686
    // And ensure others have the values we want
 
687
    edgeDragArea->d->compositionTime = 60;
 
688
 
 
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());
 
697
 
 
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);
 
701
 
 
702
    QTest::touchEvent(m_view, m_device).press(0, touch0Pos);
 
703
 
 
704
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
 
705
 
 
706
    // We are now going to be way beyond compositionTime
 
707
    passTime(edgeDragArea->d->compositionTime*3);
 
708
 
 
709
    QTest::touchEvent(m_view, m_device)
 
710
        .move(0, touch0Pos)
 
711
        .press(1, touch1Pos);
 
712
 
 
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)
 
716
    {
 
717
        TouchMemento &touchMemento = dummyItem->touchEvents.last();
 
718
        QCOMPARE(touchMemento.touchPoints.count(), 2);
 
719
        QVERIFY(touchMemento.containsTouchWithId(0));
 
720
        QVERIFY(touchMemento.containsTouchWithId(1));
 
721
    }
 
722
 
 
723
    passTime(30);
 
724
 
 
725
    QTest::touchEvent(m_view, m_device)
 
726
        .move(0, touch0Pos)
 
727
        .move(1, touch1Pos);
 
728
 
 
729
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
 
730
 
 
731
    passTime(5);
 
732
 
 
733
    QTest::touchEvent(m_view, m_device)
 
734
        .release(0, touch0Pos)
 
735
        .move(1, touch1Pos);
 
736
 
 
737
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
 
738
 
 
739
    passTime(5);
 
740
 
 
741
    QTest::touchEvent(m_view, m_device)
 
742
        .release(1, touch1Pos);
 
743
 
 
744
    // Shouldn't be keepping info about touches that no longer exist or interest us
 
745
    QVERIFY(edgeDragArea->d->activeTouches.isEmpty());
 
746
 
 
747
    delete dummyItem;
 
748
}
 
749
 
 
750
void tst_UCSwipeArea::givesUpWhenLosesTouch()
 
751
{
 
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());
 
757
 
 
758
    // Disable some constraints we're not interested in
 
759
    edgeDragArea->d->setMaxTime(60 * 1000);
 
760
 
 
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());
 
768
 
 
769
    QPoint touchPosition(edgeDragArea->width()/2.0f, m_view->height()/2.0f);
 
770
 
 
771
    dummyItem->touchEventHandler = [&](QTouchEvent *event) {
 
772
        m_touchRegistry->addCandidateOwnerForTouch(0, dummyItem);
 
773
        event->ignore();
 
774
    };
 
775
 
 
776
    QTest::touchEvent(m_view, m_device).press(0, touchPosition);
 
777
 
 
778
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
 
779
 
 
780
    m_touchRegistry->requestTouchOwnership(0, dummyItem);
 
781
 
 
782
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
 
783
 
 
784
    dummyItem->grabTouchPoints({0});
 
785
    dummyItem->touchEventHandler = [&](QTouchEvent *event) { event->accept(); };
 
786
 
 
787
    passTime(5);
 
788
    QTest::touchEvent(m_view, m_device).release(0, touchPosition);
 
789
 
 
790
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
 
791
 
 
792
    QVERIFY(edgeDragArea->d->activeTouches.isEmpty());
 
793
}
 
794
 
 
795
void tst_UCSwipeArea::threeFingerDrag()
 
796
{
 
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());
 
802
 
 
803
    // Disable some constraints we're not interested in
 
804
    edgeDragArea->d->setMaxTime(60 * 1000);
 
805
 
 
806
    // And ensure others have the values we want
 
807
    edgeDragArea->d->compositionTime = 60;
 
808
 
 
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);
 
813
 
 
814
    QTest::touchEvent(m_view, m_device)
 
815
        .press(0, touch0Pos);
 
816
 
 
817
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
 
818
 
 
819
    passTime(5);
 
820
    QTest::touchEvent(m_view, m_device)
 
821
        .move(0, touch0Pos)
 
822
        .press(1, touch1Pos);
 
823
 
 
824
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
 
825
 
 
826
    passTime(5);
 
827
    QTest::touchEvent(m_view, m_device)
 
828
        .move(0, touch0Pos)
 
829
        .move(1, touch1Pos)
 
830
        .press(2, touch2Pos);
 
831
 
 
832
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
 
833
 
 
834
    passTime(10);
 
835
    QTest::touchEvent(m_view, m_device)
 
836
        .move(0, touch0Pos)
 
837
        .move(1, touch1Pos)
 
838
        .move(2, touch2Pos);
 
839
 
 
840
    passTime(200);
 
841
    QTest::touchEvent(m_view, m_device)
 
842
        .move(0, touch0Pos)
 
843
        .release(1, touch1Pos)
 
844
        .move(2, touch2Pos);
 
845
 
 
846
    passTime(10);
 
847
    QTest::touchEvent(m_view, m_device)
 
848
        .move(0, touch0Pos)
 
849
        .release(2, touch2Pos);
 
850
 
 
851
    passTime(5);
 
852
    QTest::touchEvent(m_view, m_device)
 
853
        .release(0, touch0Pos);
 
854
 
 
855
    // Shouldn't be keepping info about touches that no longer exist or interest us
 
856
    QVERIFY(edgeDragArea->d->activeTouches.isEmpty());
 
857
}
 
858
 
 
859
/*
 
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.
 
863
 */
 
864
void tst_UCSwipeArea::immediateRecognitionWhenConstraintsDisabled()
 
865
{
 
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());
 
871
 
 
872
    // Disable the minimum amount of constraints to ensure immediate recognition
 
873
    edgeDragArea->d->setDistanceThreshold(0);
 
874
    edgeDragArea->d->compositionTime = 0;
 
875
 
 
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());
 
884
 
 
885
    QPoint touch0Pos(edgeDragArea->width()/2.0f, m_view->height()/2.0f);
 
886
 
 
887
    QTest::touchEvent(m_view, m_device).press(0, touch0Pos);
 
888
 
 
889
    // check for immediate recognition
 
890
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Recognized);
 
891
 
 
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);
 
895
}
 
896
 
 
897
void tst_UCSwipeArea::withdrawTouchOwnershipCandidacyIfDisabledDuringRecognition()
 
898
{
 
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());
 
904
 
 
905
    QPointF touchPoint = calculateInitialtouchPosition(edgeDragArea);
 
906
 
 
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
 
910
 
 
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;
 
915
 
 
916
    QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
 
917
 
 
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());
 
922
    }
 
923
 
 
924
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
 
925
 
 
926
    // edgeDragArea should be an undecided candidate
 
927
    {
 
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);
 
932
    }
 
933
 
 
934
    // disable the swipeArea while it's still recognizing a possible drag gesture.
 
935
    QFETCH(bool, disable);
 
936
    if (disable) {
 
937
        edgeDragArea->setEnabled(false);
 
938
    } else {
 
939
        edgeDragArea->setVisible(false);
 
940
    }
 
941
 
 
942
    // edgeDragArea should no longer be a candidate
 
943
    {
 
944
        auto touchInfo = m_touchRegistry->findTouchInfo(0);
 
945
        QCOMPARE(touchInfo->candidates.size(), 0);
 
946
    }
 
947
 
 
948
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
 
949
 
 
950
    QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
 
951
}
 
952
 
 
953
void tst_UCSwipeArea::withdrawTouchOwnershipCandidacyIfDisabledDuringRecognition_data()
 
954
{
 
955
    QTest::addColumn<bool>("disable");
 
956
 
 
957
    QTest::newRow("disabled") << true;
 
958
    QTest::newRow("invisible") << false;
 
959
}
 
960
 
 
961
void tst_UCSwipeArea::gettingTouchOwnershipMakesMouseAreaBehindGetCanceled()
 
962
{
 
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());
 
968
 
 
969
    QQuickMouseArea *mouseArea =
 
970
        m_view->rootObject()->findChild<QQuickMouseArea*>("mouseArea");
 
971
    QVERIFY(mouseArea != nullptr);
 
972
 
 
973
    MouseAreaSpy mouseAreaSpy(mouseArea);
 
974
 
 
975
    QPointF initialtouchPosition = calculateInitialtouchPosition(edgeDragArea);
 
976
    QPointF touchPoint = initialtouchPosition;
 
977
 
 
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;
 
984
 
 
985
    QCOMPARE(mouseArea->pressed(), false);
 
986
 
 
987
    QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
 
988
 
 
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);
 
994
 
 
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());
 
999
    }
 
1000
 
 
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);
 
1007
 
 
1008
    QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
 
1009
}
 
1010
 
 
1011
void tst_UCSwipeArea::interleavedTouches()
 
1012
{
 
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());
 
1018
 
 
1019
    QPointF touch0 = edgeDragArea->mapToScene(
 
1020
            QPointF(edgeDragArea->width()*0.5, edgeDragArea->height()*0.3));
 
1021
 
 
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;
 
1028
 
 
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());
 
1034
    }
 
1035
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Recognized);
 
1036
 
 
1037
    QPointF touch1 = edgeDragArea->mapToScene(
 
1038
            QPointF(edgeDragArea->width()*0.5, edgeDragArea->height()*0.6));
 
1039
 
 
1040
    QTest::touchEvent(m_view, m_device)
 
1041
        .move(0, touch0.toPoint())
 
1042
        .press(1, touch1.toPoint());
 
1043
 
 
1044
    touch1 += touchMovement;
 
1045
    passTime(movementTimeStepMs);
 
1046
    QTest::touchEvent(m_view, m_device)
 
1047
        .move(0, touch0.toPoint())
 
1048
        .move(1, touch1.toPoint());
 
1049
 
 
1050
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Recognized);
 
1051
 
 
1052
    QTest::touchEvent(m_view, m_device)
 
1053
        .release(0, touch0.toPoint())
 
1054
        .move(1, touch1.toPoint());
 
1055
 
 
1056
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
 
1057
 
 
1058
    touch1 += touchMovement;
 
1059
    passTime(movementTimeStepMs);
 
1060
    QTest::touchEvent(m_view, m_device)
 
1061
        .move(1, touch1.toPoint());
 
1062
 
 
1063
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
 
1064
 
 
1065
    QPointF touch2 = edgeDragArea->mapToScene(
 
1066
            QPointF(edgeDragArea->width()*0.5, edgeDragArea->height()*0.9));
 
1067
 
 
1068
    passTime(edgeDragArea->d->compositionTime + movementTimeStepMs);
 
1069
    QTest::touchEvent(m_view, m_device)
 
1070
        .move(1, touch1.toPoint())
 
1071
        .press(2, touch2.toPoint());
 
1072
 
 
1073
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::Undecided);
 
1074
    QCOMPARE(edgeDragArea->d->touchId, 2);
 
1075
 
 
1076
    touch2 += touchMovement;
 
1077
    passTime(movementTimeStepMs);
 
1078
    QTest::touchEvent(m_view, m_device)
 
1079
        .move(1, touch1.toPoint())
 
1080
        .move(2, touch2.toPoint());
 
1081
 
 
1082
    touch1 += touchMovement;
 
1083
    passTime(movementTimeStepMs);
 
1084
    QTest::touchEvent(m_view, m_device)
 
1085
        .move(1, touch1.toPoint())
 
1086
        .move(2, touch2.toPoint());
 
1087
 
 
1088
    passTime(movementTimeStepMs);
 
1089
    QTest::touchEvent(m_view, m_device)
 
1090
        .release(1, touch1.toPoint())
 
1091
        .move(2, touch2.toPoint());
 
1092
 
 
1093
    passTime(movementTimeStepMs);
 
1094
    QTest::touchEvent(m_view, m_device)
 
1095
        .release(2, touch2.toPoint());
 
1096
 
 
1097
    QCOMPARE((int)edgeDragArea->d->status, (int)UCSwipeAreaPrivate::WaitingForTouch);
 
1098
}
 
1099
 
 
1100
/*
 
1101
  A valid right-edge drag performed on mako
 
1102
 */
 
1103
void tst_UCSwipeArea::makoRightEdgeDrag()
 
1104
{
 
1105
    m_view->resize(768, 1280);
 
1106
    QTest::qWait(300);
 
1107
 
 
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());
 
1113
 
 
1114
    StatusSpy *statusSpy = new StatusSpy(edgeDragArea);
 
1115
 
 
1116
    edgeDragArea->d->setPixelsPerMm(320.0 /*mako ppi*/ * 0.03937 /* inches per mm*/);
 
1117
 
 
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));
 
1136
 
 
1137
    QCOMPARE(statusSpy->recognized(), true);
 
1138
 
 
1139
    delete statusSpy;
 
1140
}
 
1141
 
 
1142
/*
 
1143
   A vertical, downwards swipe performed on mako near its right edge.
 
1144
 
 
1145
   The UCSwipeArea on the right edge must not recognize this
 
1146
   gesture.
 
1147
 */
 
1148
void tst_UCSwipeArea::makoRightEdgeDrag_verticalDownwards()
 
1149
{
 
1150
    m_view->resize(768, 1280);
 
1151
    QTest::qWait(300);
 
1152
 
 
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());
 
1158
 
 
1159
    edgeDragArea->d->setPixelsPerMm(320.0 /*mako ppi*/ * 0.03937 /* inches per mm*/);
 
1160
 
 
1161
    StatusSpy *statusSpy = new StatusSpy(edgeDragArea);
 
1162
 
 
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));
 
1183
 
 
1184
    QCOMPARE(statusSpy->recognized(), false);
 
1185
 
 
1186
    delete statusSpy;
 
1187
}
 
1188
 
 
1189
/*
 
1190
   A valid left-edge drag performed on mako. This one starts a bit slow than speeds up
 
1191
 */
 
1192
void tst_UCSwipeArea::makoLeftEdgeDrag_slowStart()
 
1193
{
 
1194
    m_view->resize(768, 1280);
 
1195
    QTest::qWait(300);
 
1196
 
 
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());
 
1202
 
 
1203
    edgeDragArea->d->setPixelsPerMm(320.0 /*mako ppi*/ * 0.03937 /* inches per mm*/);
 
1204
 
 
1205
    StatusSpy *statusSpy = new StatusSpy(edgeDragArea);
 
1206
 
 
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));
 
1250
 
 
1251
    QCOMPARE(statusSpy->recognized(), true);
 
1252
 
 
1253
    delete statusSpy;
 
1254
}
 
1255
 
 
1256
void tst_UCSwipeArea::makoLeftEdgeDrag_movesSlightlyBackwardsOnStart()
 
1257
{
 
1258
    m_view->resize(768, 1280);
 
1259
    QTest::qWait(300);
 
1260
 
 
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());
 
1266
 
 
1267
    edgeDragArea->d->setPixelsPerMm(320.0 /*mako ppi*/ * 0.03937 /* inches per mm*/);
 
1268
 
 
1269
    StatusSpy *statusSpy = new StatusSpy(edgeDragArea);
 
1270
 
 
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));
 
1297
 
 
1298
    QCOMPARE(statusSpy->recognized(), true);
 
1299
 
 
1300
    delete statusSpy;
 
1301
}
 
1302
 
 
1303
QTEST_MAIN(tst_UCSwipeArea)
 
1304
 
 
1305
#include "tst_swipearea.moc"