@@ -1,1250 +0,0 @@
1−/*
2− * Copyright (C) 2013-2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include <QtTest/QtTest>
18−#include <QtCore/QObject>
19−#include <QtQuick/QQuickView>
20−#include <QtQml/QQmlEngine>
21−#include <QPointer>
22−#include <private/qquickmousearea_p.h>
23−
24−
25−#include <DirectionalDragArea.h>
26−#include <DirectionalDragArea_p.h>
27−#include <TouchRegistry.h>
28−
29−#include "GestureTest.h"
30−
31−using namespace UbuntuGestures;
32−
33−// Because QSignalSpy(directionalDragArea, SIGNAL(DirectionalDragArea::Status)) simply
34−// doesn't work
35−class StatusSpy : public QObject {
36− Q_OBJECT
37−public:
38− StatusSpy(DirectionalDragArea *edgeDragArea) {
39− m_recognized = false;
40− connect(edgeDragArea->d, &DirectionalDragAreaPrivate::statusChanged,
41− this, &StatusSpy::onStatusChanged);
42− }
43− bool recognized() {
44− return m_recognized;
45− }
46−
47−private Q_SLOTS:
48− void onStatusChanged(DirectionalDragAreaPrivate::Status status) {
49− m_recognized |= status == DirectionalDragAreaPrivate::Recognized;
50− }
51−
52−private:
53− bool m_recognized;
54−};
55−
56−/*
57− QQuickMouseArea::canceled() signal is not registered in the meta object system.
58− So using a QSignalSpy to track it won't work. Thus the only way to connect to it
59− is using its method address directly.
60− */
61−class MouseAreaSpy : public QObject
62−{
63− Q_OBJECT
64−public:
65− MouseAreaSpy(QQuickMouseArea *mouseArea)
66− : canceledCount(0)
67− {
68− connect(mouseArea, &QQuickMouseArea::canceled,
69− this, &MouseAreaSpy::onMouseAreaCanceled);
70− }
71−
72− int canceledCount;
73−
74−private Q_SLOTS:
75− void onMouseAreaCanceled() {
76− ++canceledCount;
77− }
78−};
79−
80−class tst_DirectionalDragArea: public GestureTest
81−{
82− Q_OBJECT
83−public:
84− tst_DirectionalDragArea();
85−private Q_SLOTS:
86− void init() override; // called right before each and every test function is executed
87−
88− void dragWithShortDirectionChange();
89− void recognitionTimerUsage();
90− void sceneXAndX();
91− void sceneYAndY();
92− void twoFingerTap();
93− void movingDDA();
94− void ignoreOldFinger();
95− void rotated();
96− void sceneDistance();
97− void sceneDistance_data();
98− void disabledWhileDragging();
99− void oneFingerDownFollowedByLateSecondFingerDown();
100− void givesUpWhenLosesTouch();
101− void threeFingerDrag();
102− void immediateRecognitionWhenConstraintsDisabled();
103− void withdrawTouchOwnershipCandidacyIfDisabledDuringRecognition();
104− void withdrawTouchOwnershipCandidacyIfDisabledDuringRecognition_data();
105− void gettingTouchOwnershipMakesMouseAreaBehindGetCanceled();
106− void interleavedTouches();
107− void makoRightEdgeDrag();
108− void makoRightEdgeDrag_verticalDownwards();
109− void makoLeftEdgeDrag_slowStart();
110− void makoLeftEdgeDrag_movesSlightlyBackwardsOnStart();
111−};
112−
113−tst_DirectionalDragArea::tst_DirectionalDragArea()
114− : GestureTest(QStringLiteral("tst_DirectionalDragArea.qml"))
115−{
116−}
117−
118−void tst_DirectionalDragArea::init()
119−{
120− GestureTest::init();
121−
122− // We shouldn't need the three lines below, but a compiz/unity7
123− // regression means we don't pass the test without them because
124− // the window doesn't have the proper size. Can be removed in the
125− // future if the regression is fixed and tests pass again
126− m_view->resize(m_view->rootObject()->width(), m_view->rootObject()->height());
127− QTRY_COMPARE(m_view->width(), (int)m_view->rootObject()->width());
128− QTRY_COMPARE(m_view->height(), (int)m_view->rootObject()->height());
129−}
130−
131−namespace {
132−QPointF calculateInitialTouchPos(DirectionalDragArea *edgeDragArea)
133−{
134− QPointF localCenter(edgeDragArea->width() / 2., edgeDragArea->height() / 2.);
135− return edgeDragArea->mapToScene(localCenter);
136−}
137−}
138−
139−/*
140− A directional drag should still be recognized if there is a momentaneous, small,
141− change in the direction of a drag. That should be accounted as input noise and
142− therefore ignored.
143− */
144−void tst_DirectionalDragArea::dragWithShortDirectionChange()
145−{
146− DirectionalDragArea *edgeDragArea =
147− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
148− QVERIFY(edgeDragArea != 0);
149− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
150− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
151−
152− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
153− QPointF touchPoint = initialTouchPos;
154−
155− qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0;
156− QPointF dragDirectionVector(1.0, 0.0);
157− qreal touchStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
158− // make sure we are above maximum time
159− int touchStepTimeMs = edgeDragArea->d->maxTime / 20. ;
160− QPointF touchMovement = dragDirectionVector * touchStepDistance;
161−
162− QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
163−
164− // Move a bit in the proper direction
165− for (int i=0; i < 3; ++i) {
166− touchPoint += touchMovement;
167− passTime(touchStepTimeMs);
168− QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
169− }
170−
171− // Then a sudden and small movement to the opposite direction
172− touchPoint -= touchMovement*0.2;
173− passTime(touchStepTimeMs*0.2);
174− QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
175−
176− // And then resume movment in the correct direction until it crosses the distance and time
177− // thresholds.
178− do {
179− touchPoint += touchMovement;
180− passTime(touchStepTimeMs);
181− QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
182− } while ((touchPoint - initialTouchPos).manhattanLength() < desiredDragDistance
183− || m_fakeTimerFactory->timeSource()->msecsSinceReference() < (edgeDragArea->d->compositionTime * 1.5f));
184−
185− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
186−
187− QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
188−}
189−
190−/*
191− Checks that the recognition timer is started and stopped appropriately.
192− I.e., check that it's running only while gesture recognition is taking place
193− (status == Undecided)
194− */
195−void tst_DirectionalDragArea::recognitionTimerUsage()
196−{
197− DirectionalDragArea *edgeDragArea =
198− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
199− QVERIFY(edgeDragArea != 0);
200− AbstractTimer *fakeTimer = m_fakeTimerFactory->createTimer();
201− edgeDragArea->d->setRecognitionTimer(fakeTimer);
202− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
203−
204− int timeStepMs = 5; // some arbitrary small value.
205−
206− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
207− QPointF touchPoint = initialTouchPos;
208−
209− QPointF dragDirectionVector(1.0, 0.0);
210− QPointF touchMovement = dragDirectionVector * (edgeDragArea->d->distanceThreshold * 0.2f);
211−
212− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
213− QVERIFY(!fakeTimer->isRunning());
214−
215− QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
216−
217− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
218− QVERIFY(fakeTimer->isRunning());
219−
220− // Move beyond distance threshold and composition time to ensure recognition
221− while (m_fakeTimerFactory->timeSource()->msecsSinceReference() <= edgeDragArea->d->compositionTime ||
222− (touchPoint - initialTouchPos).manhattanLength() <= edgeDragArea->d->distanceThreshold) {
223−
224− QCOMPARE(edgeDragArea->d->status == DirectionalDragAreaPrivate::Undecided, fakeTimer->isRunning());
225−
226− touchPoint += touchMovement;
227− passTime(timeStepMs);
228− QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
229− }
230−
231− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
232− QVERIFY(!fakeTimer->isRunning());
233−}
234−
235−/*
236− Checks that it informs the X coordinate of the touch point in local and scene coordinates
237− correctly.
238− */
239−void tst_DirectionalDragArea::sceneXAndX()
240−{
241− DirectionalDragArea *edgeDragArea =
242− m_view->rootObject()->findChild<DirectionalDragArea*>("hnDragArea");
243− QVERIFY(edgeDragArea != 0);
244− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
245− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
246− edgeDragArea->setImmediateRecognition(true);
247−
248− QPointF touchScenePos(m_view->width() - (edgeDragArea->width()/2.0f), m_view->height()/2.0f);
249−
250− sendTouchPress(0 /* timestamp */, 0 /* id */, touchScenePos);
251−
252− QSignalSpy touchXSpy(edgeDragArea, &DirectionalDragArea::touchXChanged);
253− QSignalSpy touchSceneXSpy(edgeDragArea, &DirectionalDragArea::touchSceneXChanged);
254−
255− touchScenePos.rx() = m_view->width() / 2;
256− sendTouchUpdate(50 /* timestamp */, 0 /* id */, touchScenePos);
257−
258− QCOMPARE(touchXSpy.count(), 1);
259− QCOMPARE(touchSceneXSpy.count(), 1);
260− QCOMPARE(edgeDragArea->touchX(), touchScenePos.x() - edgeDragArea->x());
261− QCOMPARE(edgeDragArea->touchSceneX(), touchScenePos.x());
262−}
263−
264−/*
265− Checks that it informs the Y coordinate of the touch point in local and scene coordinates
266− correctly.
267− */
268−void tst_DirectionalDragArea::sceneYAndY()
269−{
270− DirectionalDragArea *edgeDragArea =
271− m_view->rootObject()->findChild<DirectionalDragArea*>("vnDragArea");
272− QVERIFY(edgeDragArea != 0);
273− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
274− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
275− edgeDragArea->setImmediateRecognition(true);
276−
277− QPointF touchScenePos(m_view->width()/2.0f, m_view->height() - (edgeDragArea->height()/2.0f));
278−
279− sendTouchPress(0 /* timestamp */, 0 /* id */, touchScenePos);
280−
281− QSignalSpy touchYSpy(edgeDragArea, &DirectionalDragArea::touchYChanged);
282− QSignalSpy touchSceneYSpy(edgeDragArea, &DirectionalDragArea::touchSceneYChanged);
283−
284− touchScenePos.ry() = m_view->height() / 2;
285− sendTouchUpdate(50 /* timestamp */, 0 /* id */, touchScenePos);
286−
287− QCOMPARE(touchYSpy.count(), 1);
288− QCOMPARE(touchSceneYSpy.count(), 1);
289− QCOMPARE(edgeDragArea->touchY(), touchScenePos.y() - edgeDragArea->y());
290− QCOMPARE(edgeDragArea->touchSceneY(), touchScenePos.y());
291−}
292−
293−/*
294− Regression test for https://bugs.launchpad.net/bugs/1228336
295−
296− Perform a quick two-finger double-tap and check that DirectionalDragArea properly
297− rejects those touch points. In the bug above it got confused and crashed.
298− */
299−void tst_DirectionalDragArea::twoFingerTap()
300−{
301− DirectionalDragArea *edgeDragArea =
302− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
303− QVERIFY(edgeDragArea != 0);
304− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
305− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
306−
307− // Make touches evenly spaced along the edgeDragArea
308− QPoint touchAPos(edgeDragArea->width()/2.0f, m_view->height()*0.33f);
309− QPoint touchBPos(edgeDragArea->width()/2.0f, m_view->height()*0.66f);
310−
311− qint64 timeStepMsecs = 5; // some arbitrary, small value
312−
313− // Perform the first two-finger tap
314− // NB: using move() instead of stationary() becasue in the latter you cannot provide
315− // the touch position and therefore it's left with some garbage numbers.
316− QTest::touchEvent(m_view, m_device)
317− .press(0, touchAPos);
318−
319− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
320−
321− passTime(timeStepMsecs);
322− QTest::touchEvent(m_view, m_device)
323− .move(0, touchAPos)
324− .press(1, touchBPos);
325−
326− // A second touch point appeared during recognition, reject immediately as this
327− // can't be a single-touch gesture anymore.
328− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
329−
330− passTime(timeStepMsecs);
331− QTest::touchEvent(m_view, m_device)
332− .release(0, touchAPos)
333− .move(1, touchBPos);
334−
335− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
336−
337− passTime(timeStepMsecs);
338− QTest::touchEvent(m_view, m_device)
339− .release(1, touchBPos);
340−
341− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
342−
343− // Perform the second two-finger tap
344−
345− passTime(timeStepMsecs);
346− QTest::touchEvent(m_view, m_device)
347− .press(0, touchAPos);
348−
349− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
350−
351− passTime(timeStepMsecs);
352− QTest::touchEvent(m_view, m_device)
353− .move(0, touchAPos)
354− .press(1, touchBPos);
355−
356− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
357−
358− passTime(timeStepMsecs);
359− QTest::touchEvent(m_view, m_device)
360− .release(0, touchAPos)
361− .move(1, touchBPos);
362−
363− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
364−
365− passTime(timeStepMsecs);
366− QTest::touchEvent(m_view, m_device)
367− .release(1, touchBPos);
368−
369− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
370−}
371−
372−/*
373− Tests that gesture recognition works normally even if the DirectionalDragArea moves
374− during recognition.
375− This effectively means that we have to do gesture recognition with scene coordinates
376− instead of local item coordinates.
377− */
378−void tst_DirectionalDragArea::movingDDA()
379−{
380− QQuickItem *rightwardsLauncher = m_view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
381− Q_ASSERT(rightwardsLauncher != 0);
382−
383− DirectionalDragArea *edgeDragArea =
384− rightwardsLauncher->findChild<DirectionalDragArea*>("hpDragArea");
385− Q_ASSERT(edgeDragArea != 0);
386− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
387− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
388−
389− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
390− QPointF touchPoint = initialTouchPos;
391−
392− qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
393− QPointF dragDirectionVector(1.0f, 0.0f);
394−
395− qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
396− QPointF touchMovement = dragDirectionVector * movementStepDistance;
397− int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
398− int movementTimeStepMs = (edgeDragArea->d->compositionTime * 1.5f) / totalMovementSteps;
399−
400− QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
401−
402− // Move it far ahead along the direction of the gesture
403− // rightwardsLauncher is a parent of our DirectionalDragArea. So moving it will move our DDA
404− rightwardsLauncher->setX(rightwardsLauncher->x() + edgeDragArea->d->distanceThreshold * 5.0f);
405−
406− for (int i = 0; i < totalMovementSteps; ++i) {
407− touchPoint += touchMovement;
408− passTime(movementTimeStepMs);
409− QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
410− }
411−
412− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
413−
414− QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
415−}
416−
417−/*
418− The presence of and old, rejected, touch point lying on the DirectionalDragArea
419− shouldn't impede the recognition of a gesture from a new touch point.
420− */
421−void tst_DirectionalDragArea::ignoreOldFinger()
422−{
423− DirectionalDragArea *edgeDragArea =
424− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
425− Q_ASSERT(edgeDragArea != 0);
426− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
427− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
428−
429− // Make touches evenly spaced along the edgeDragArea
430− QPoint touch0Pos(edgeDragArea->width()/2.0f, m_view->height()*0.33f);
431− QPoint touch1Pos(edgeDragArea->width()/2.0f, m_view->height()*0.66f);
432−
433− QTest::touchEvent(m_view, m_device).press(0, touch0Pos);
434−
435− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
436−
437− // leave it lying around for some time
438− passTime(edgeDragArea->d->maxTime * 10);
439−
440− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
441−
442− qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
443− QPointF dragDirectionVector(1.0f, 0.0f);
444−
445− qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
446− QPointF touchMovement = dragDirectionVector * movementStepDistance;
447− int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
448− int movementTimeStepMs = (edgeDragArea->d->compositionTime * 1.5f) / totalMovementSteps;
449−
450− QTest::touchEvent(m_view, m_device)
451− .move(0, touch0Pos)
452− .press(1, touch1Pos);
453−
454− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
455−
456− for (int i = 0; i < totalMovementSteps; ++i) {
457− touch1Pos += touchMovement.toPoint();
458− passTime(movementTimeStepMs);
459− QTest::touchEvent(m_view, m_device)
460− .move(0, touch0Pos)
461− .move(1, touch1Pos);
462− }
463−
464− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
465−
466− QTest::touchEvent(m_view, m_device)
467− .move(0, touch0Pos)
468− .release(1, touch1Pos);
469−
470− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
471−}
472−
473−/*
474− A Rightwards DDA that is rotated 90 degrees clockwise should recognize gestures
475− that are done downwards in scene coordinates. I.e. the gesture recognition direction
476− should be in local coordinates, not scene coordinates.
477− */
478−void tst_DirectionalDragArea::rotated()
479−{
480− QQuickItem *baseItem = m_view->rootObject()->findChild<QQuickItem*>("baseItem");
481− baseItem->setRotation(90.);
482−
483− QQuickItem *rightwardsLauncher = m_view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
484− Q_ASSERT(rightwardsLauncher != 0);
485−
486− DirectionalDragArea *edgeDragArea =
487− rightwardsLauncher->findChild<DirectionalDragArea*>("hpDragArea");
488− Q_ASSERT(edgeDragArea != 0);
489− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
490− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
491−
492− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
493− QPointF touchPoint = initialTouchPos;
494−
495− qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
496− QPointF dragDirectionVector(0.0f, 1.0f);
497−
498− qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
499− QPointF touchMovement = dragDirectionVector * movementStepDistance;
500− int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
501− int movementTimeStepMs = (edgeDragArea->d->compositionTime * 1.5f) / totalMovementSteps;
502−
503− QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
504−
505− for (int i = 0; i < totalMovementSteps; ++i) {
506− touchPoint += touchMovement;
507− passTime(movementTimeStepMs);
508− QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
509− }
510−
511− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
512−
513− QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
514−}
515−
516−void tst_DirectionalDragArea::sceneDistance()
517−{
518− QQuickItem *baseItem = m_view->rootObject()->findChild<QQuickItem*>("baseItem");
519− QFETCH(qreal, rotation);
520− QFETCH(QPointF, dragDirectionVector);
521− baseItem->setRotation(rotation);
522−
523− QQuickItem *rightwardsLauncher = m_view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
524− Q_ASSERT(rightwardsLauncher != 0);
525−
526− DirectionalDragArea *edgeDragArea =
527− rightwardsLauncher->findChild<DirectionalDragArea*>("hpDragArea");
528− Q_ASSERT(edgeDragArea != 0);
529− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
530− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
531−
532− // to disable the position smoothing so that we can more easily check sceneDistance values
533− edgeDragArea->setImmediateRecognition(true);
534−
535− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
536− QPointF touchPoint = initialTouchPos;
537−
538− qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
539−
540− qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
541− QPointF touchMovement = dragDirectionVector * movementStepDistance;
542− int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
543− int movementTimeStepMs = (edgeDragArea->d->compositionTime * 1.5f) / totalMovementSteps;
544−
545− qint64 timestamp = 0;
546−
547− sendTouchPress(timestamp, 0, touchPoint);
548−
549− for (int i = 0; i < totalMovementSteps; ++i) {
550− touchPoint += touchMovement;
551− timestamp += movementTimeStepMs;
552− sendTouchUpdate(timestamp, 0, touchPoint);
553− }
554−
555− qreal actualDragDistance = ((qreal)totalMovementSteps) * movementStepDistance;
556−
557− // DirectionalDragArea::sceneDistance() must match the actual drag distance as the
558− // drag was aligned with the gesture direction
559− // NB: qFuzzyCompare(), used internally by QCOMPARE(), is broken.
560− QVERIFY(qAbs(edgeDragArea->sceneDistance() - actualDragDistance) < 0.001);
561−
562− timestamp += movementTimeStepMs;
563− sendTouchRelease(timestamp, 0, touchPoint);
564−}
565−
566−void tst_DirectionalDragArea::sceneDistance_data()
567−{
568− QTest::addColumn<qreal>("rotation");
569− QTest::addColumn<QPointF>("dragDirectionVector");
570−
571− QTest::newRow("not rotated") << 0. << QPointF(1., 0.);
572− QTest::newRow("rotated by 90 degrees") << 90. << QPointF(0., 1.);
573−}
574−
575−/*
576− Regression test for https://bugs.launchpad.net/unity8/+bug/1276122
577−
578− The bug:
579− If setting "enabled: false" while the DirectionalDragArea's (DDA) dragging
580− property is true, the DDA stays in that state and doesn't recover any more.
581−*/
582−void tst_DirectionalDragArea::disabledWhileDragging()
583−{
584− DirectionalDragArea *edgeDragArea =
585− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
586− Q_ASSERT(edgeDragArea != 0);
587− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
588− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
589−
590− QPointF touchPoint = calculateInitialTouchPos(edgeDragArea);
591−
592− qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2.0f;
593− QPointF dragDirectionVector(1., 0.); // horizontal positive
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− QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
601−
602− for (int i = 0; i < totalMovementSteps; ++i) {
603− touchPoint += touchMovement;
604− passTime(movementTimeStepMs);
605− QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
606− }
607−
608− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
609− QCOMPARE(edgeDragArea->dragging(), true);
610−
611− // disable the dragArea while it's being dragged.
612− edgeDragArea->setEnabled(false);
613−
614− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
615− QCOMPARE(edgeDragArea->dragging(), false);
616−
617− QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
618−}
619−
620−void tst_DirectionalDragArea::oneFingerDownFollowedByLateSecondFingerDown()
621−{
622− DirectionalDragArea *edgeDragArea =
623− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
624− Q_ASSERT(edgeDragArea != 0);
625− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
626− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
627−
628− // Disable some constraints we're not interested in
629− edgeDragArea->d->setMaxTime(60 * 1000);
630−
631− // And ensure others have the values we want
632− edgeDragArea->d->compositionTime = 60;
633−
634− // Put an item right behind edgeDragArea to receive the touches ignored by it
635− DummyItem *dummyItem = new DummyItem;
636− dummyItem->setParentItem(edgeDragArea->parentItem());
637− dummyItem->setX(edgeDragArea->x());
638− dummyItem->setY(edgeDragArea->y());
639− dummyItem->setZ(edgeDragArea->z() - 1.0);
640− dummyItem->setWidth(edgeDragArea->width());
641− dummyItem->setHeight(edgeDragArea->height());
642−
643− // Make touches evenly spaced along the edgeDragArea
644− QPoint touch0Pos(edgeDragArea->width()/2.0f, m_view->height()*0.33f);
645− QPoint touch1Pos(edgeDragArea->width()/2.0f, m_view->height()*0.66f);
646−
647− QTest::touchEvent(m_view, m_device).press(0, touch0Pos);
648−
649− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
650−
651− // We are now going to be way beyond compositionTime
652− passTime(edgeDragArea->d->compositionTime*3);
653−
654− QTest::touchEvent(m_view, m_device)
655− .move(0, touch0Pos)
656− .press(1, touch1Pos);
657−
658− // A new touch has come, but as it can't be composed with touch 0, it should be
659− // ignored/rejected by the DirectionalDragArea
660− // Therefore the last event received by dummyItem must have both touch points (0 and 1)
661− {
662− TouchMemento &touchMemento = dummyItem->touchEvents.last();
663− QCOMPARE(touchMemento.touchPoints.count(), 2);
664− QVERIFY(touchMemento.containsTouchWithId(0));
665− QVERIFY(touchMemento.containsTouchWithId(1));
666− }
667−
668− passTime(30);
669−
670− QTest::touchEvent(m_view, m_device)
671− .move(0, touch0Pos)
672− .move(1, touch1Pos);
673−
674− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
675−
676− passTime(5);
677−
678− QTest::touchEvent(m_view, m_device)
679− .release(0, touch0Pos)
680− .move(1, touch1Pos);
681−
682− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
683−
684− passTime(5);
685−
686− QTest::touchEvent(m_view, m_device)
687− .release(1, touch1Pos);
688−
689− // Shouldn't be keepping info about touches that no longer exist or interest us
690− QVERIFY(edgeDragArea->d->activeTouches.isEmpty());
691−
692− delete dummyItem;
693−}
694−
695−void tst_DirectionalDragArea::givesUpWhenLosesTouch()
696−{
697− DirectionalDragArea *edgeDragArea =
698− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
699− Q_ASSERT(edgeDragArea != 0);
700− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
701− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
702−
703− // Disable some constraints we're not interested in
704− edgeDragArea->d->setMaxTime(60 * 1000);
705−
706− // Put an item right in front of edgeDragArea
707− DummyItem *dummyItem = new DummyItem(edgeDragArea->parentItem());
708− dummyItem->setX(edgeDragArea->x());
709− dummyItem->setY(edgeDragArea->y());
710− dummyItem->setZ(edgeDragArea->z() + 1.0);
711− dummyItem->setWidth(edgeDragArea->width());
712− dummyItem->setHeight(edgeDragArea->height());
713−
714− QPoint touchPos(edgeDragArea->width()/2.0f, m_view->height()/2.0f);
715−
716− dummyItem->touchEventHandler = [&](QTouchEvent *event) {
717− m_touchRegistry->addCandidateOwnerForTouch(0, dummyItem);
718− event->ignore();
719− };
720−
721− QTest::touchEvent(m_view, m_device).press(0, touchPos);
722−
723− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
724−
725− m_touchRegistry->requestTouchOwnership(0, dummyItem);
726−
727− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
728−
729− dummyItem->grabTouchPoints({0});
730− dummyItem->touchEventHandler = [&](QTouchEvent *event) { event->accept(); };
731−
732− passTime(5);
733− QTest::touchEvent(m_view, m_device).release(0, touchPos);
734−
735− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
736−
737− QVERIFY(edgeDragArea->d->activeTouches.isEmpty());
738−}
739−
740−void tst_DirectionalDragArea::threeFingerDrag()
741−{
742− DirectionalDragArea *edgeDragArea =
743− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
744− Q_ASSERT(edgeDragArea != 0);
745− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
746− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
747−
748− // Disable some constraints we're not interested in
749− edgeDragArea->d->setMaxTime(60 * 1000);
750−
751− // And ensure others have the values we want
752− edgeDragArea->d->compositionTime = 60;
753−
754− // Make touches evenly spaced along the edgeDragArea
755− QPoint touch0Pos(edgeDragArea->width()/2.0f, m_view->height()*0.25f);
756− QPoint touch1Pos(edgeDragArea->width()/2.0f, m_view->height()*0.50f);
757− QPoint touch2Pos(edgeDragArea->width()/2.0f, m_view->height()*0.75f);
758−
759− QTest::touchEvent(m_view, m_device)
760− .press(0, touch0Pos);
761−
762− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
763−
764− passTime(5);
765− QTest::touchEvent(m_view, m_device)
766− .move(0, touch0Pos)
767− .press(1, touch1Pos);
768−
769− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
770−
771− passTime(5);
772− QTest::touchEvent(m_view, m_device)
773− .move(0, touch0Pos)
774− .move(1, touch1Pos)
775− .press(2, touch2Pos);
776−
777− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
778−
779− passTime(10);
780− QTest::touchEvent(m_view, m_device)
781− .move(0, touch0Pos)
782− .move(1, touch1Pos)
783− .move(2, touch2Pos);
784−
785− passTime(200);
786− QTest::touchEvent(m_view, m_device)
787− .move(0, touch0Pos)
788− .release(1, touch1Pos)
789− .move(2, touch2Pos);
790−
791− passTime(10);
792− QTest::touchEvent(m_view, m_device)
793− .move(0, touch0Pos)
794− .release(2, touch2Pos);
795−
796− passTime(5);
797− QTest::touchEvent(m_view, m_device)
798− .release(0, touch0Pos);
799−
800− // Shouldn't be keepping info about touches that no longer exist or interest us
801− QVERIFY(edgeDragArea->d->activeTouches.isEmpty());
802−}
803−
804−/*
805− If all the relevant gesture recognition constraints/parameters have been disabled,
806− it means that the gesture recognition itself has been disabled and DirectionalDragArea
807− will therefore work like a simple touch area, merely reporting touch movement.
808− */
809−void tst_DirectionalDragArea::immediateRecognitionWhenConstraintsDisabled()
810−{
811− DirectionalDragArea *edgeDragArea =
812− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
813− Q_ASSERT(edgeDragArea != 0);
814− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
815− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
816−
817− // Disable the minimum amount of constraints to ensure immediate recognition
818− edgeDragArea->d->setDistanceThreshold(0);
819− edgeDragArea->d->compositionTime = 0;
820−
821− // Put an item right behind edgeDragArea to receive the touches ignored by it
822− DummyItem *dummyItem = new DummyItem;
823− dummyItem->setParentItem(edgeDragArea->parentItem());
824− dummyItem->setX(edgeDragArea->x());
825− dummyItem->setY(edgeDragArea->y());
826− dummyItem->setZ(edgeDragArea->z() - 1.0);
827− dummyItem->setWidth(edgeDragArea->width());
828− dummyItem->setHeight(edgeDragArea->height());
829−
830− QPoint touch0Pos(edgeDragArea->width()/2.0f, m_view->height()/2.0f);
831−
832− QTest::touchEvent(m_view, m_device).press(0, touch0Pos);
833−
834− // check for immediate recognition
835− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
836−
837− // and therefore it should have immediately grabbed the touch point,
838− // not letting it leak to items behind him.
839− QCOMPARE(dummyItem->touchEvents.count(), 0);
840−}
841−
842−void tst_DirectionalDragArea::withdrawTouchOwnershipCandidacyIfDisabledDuringRecognition()
843−{
844− DirectionalDragArea *edgeDragArea =
845− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
846− Q_ASSERT(edgeDragArea != 0);
847− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
848− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
849−
850− QPointF touchPoint = calculateInitialTouchPos(edgeDragArea);
851−
852− // Move less than the minimum needed for the drag gesture recognition
853− qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 0.5f;
854− QPointF dragDirectionVector(1., 0.); // horizontal positive
855−
856− qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
857− QPointF touchMovement = dragDirectionVector * movementStepDistance;
858− int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
859− int movementTimeStepMs = (edgeDragArea->d->compositionTime * 0.8f) / totalMovementSteps;
860−
861− QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
862−
863− for (int i = 0; i < totalMovementSteps; ++i) {
864− touchPoint += touchMovement;
865− passTime(movementTimeStepMs);
866− QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
867− }
868−
869− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
870−
871− // edgeDragArea should be an undecided candidate
872− {
873− auto touchInfo = m_touchRegistry->findTouchInfo(0);
874− QCOMPARE(touchInfo->candidates.size(), 1);
875− QCOMPARE(touchInfo->candidates.at(0).item.data(), edgeDragArea);
876− QCOMPARE(touchInfo->candidates.at(0).state, TouchRegistry::CandidateInfo::Undecided);
877− }
878−
879− // disable the dragArea while it's still recognizing a possible drag gesture.
880− QFETCH(bool, disable);
881− if (disable) {
882− edgeDragArea->setEnabled(false);
883− } else {
884− edgeDragArea->setVisible(false);
885− }
886−
887− // edgeDragArea should no longer be a candidate
888− {
889− auto touchInfo = m_touchRegistry->findTouchInfo(0);
890− QCOMPARE(touchInfo->candidates.size(), 0);
891− }
892−
893− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
894−
895− QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
896−}
897−
898−void tst_DirectionalDragArea::withdrawTouchOwnershipCandidacyIfDisabledDuringRecognition_data()
899−{
900− QTest::addColumn<bool>("disable");
901−
902− QTest::newRow("disabled") << true;
903− QTest::newRow("invisible") << false;
904−}
905−
906−void tst_DirectionalDragArea::gettingTouchOwnershipMakesMouseAreaBehindGetCanceled()
907−{
908− DirectionalDragArea *edgeDragArea =
909− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
910− QVERIFY(edgeDragArea != nullptr);
911− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
912− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
913−
914− QQuickMouseArea *mouseArea =
915− m_view->rootObject()->findChild<QQuickMouseArea*>("mouseArea");
916− QVERIFY(mouseArea != nullptr);
917−
918− MouseAreaSpy mouseAreaSpy(mouseArea);
919−
920− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
921− QPointF touchPoint = initialTouchPos;
922−
923− qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2;
924− QPointF dragDirectionVector(1.0f, 0.0f); // rightwards
925− qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
926− QPointF touchMovement = dragDirectionVector * movementStepDistance;
927− int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
928− int movementTimeStepMs = (edgeDragArea->d->compositionTime * 1.5f) / totalMovementSteps;
929−
930− QCOMPARE(mouseArea->pressed(), false);
931−
932− QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
933−
934− // The TouchBegin passes through the DirectionalDragArea and reaches the MouseArea behind it,
935− // where it's converted to a MouseEvent by QQuickWindow and sent to the MouseArea which then
936− // accepts it. Making it get pressed.
937− QCOMPARE(mouseArea->pressed(), true);
938− QCOMPARE(mouseAreaSpy.canceledCount, 0);
939−
940− for (int i = 0; i < totalMovementSteps; ++i) {
941− touchPoint += touchMovement;
942− passTime(movementTimeStepMs);
943− QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
944− }
945−
946− // As the DirectionalDragArea recognizes the gesture, it grabs the touch from the MouseArea,
947− // which should make the MouseArea get a cancelation event, which will then cause it to
948− // reset its state (going back to "unpressed"/"released").
949− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
950− QCOMPARE(mouseArea->pressed(), false);
951− QCOMPARE(mouseAreaSpy.canceledCount, 1);
952−
953− QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
954−}
955−
956−void tst_DirectionalDragArea::interleavedTouches()
957−{
958− DirectionalDragArea *edgeDragArea =
959− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
960− QVERIFY(edgeDragArea != 0);
961− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
962− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
963−
964− QPointF touch0 = edgeDragArea->mapToScene(
965− QPointF(edgeDragArea->width()*0.5, edgeDragArea->height()*0.3));
966−
967− qreal desiredDragDistance = edgeDragArea->d->distanceThreshold * 2;
968− QPointF dragDirectionVector(1.0f, 0.0f); // rightwards
969− qreal movementStepDistance = edgeDragArea->d->distanceThreshold * 0.1f;
970− QPointF touchMovement = dragDirectionVector * movementStepDistance;
971− int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
972− int movementTimeStepMs = (edgeDragArea->d->maxTime * 0.4f) / totalMovementSteps;
973−
974− QTest::touchEvent(m_view, m_device).press(0, touch0.toPoint());
975− for (int i = 0; i < totalMovementSteps; ++i) {
976− touch0 += touchMovement;
977− passTime(movementTimeStepMs);
978− QTest::touchEvent(m_view, m_device).move(0, touch0.toPoint());
979− }
980− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
981−
982− QPointF touch1 = edgeDragArea->mapToScene(
983− QPointF(edgeDragArea->width()*0.5, edgeDragArea->height()*0.6));
984−
985− QTest::touchEvent(m_view, m_device)
986− .move(0, touch0.toPoint())
987− .press(1, touch1.toPoint());
988−
989− touch1 += touchMovement;
990− passTime(movementTimeStepMs);
991− QTest::touchEvent(m_view, m_device)
992− .move(0, touch0.toPoint())
993− .move(1, touch1.toPoint());
994−
995− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Recognized);
996−
997− QTest::touchEvent(m_view, m_device)
998− .release(0, touch0.toPoint())
999− .move(1, touch1.toPoint());
1000−
1001− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
1002−
1003− touch1 += touchMovement;
1004− passTime(movementTimeStepMs);
1005− QTest::touchEvent(m_view, m_device)
1006− .move(1, touch1.toPoint());
1007−
1008− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
1009−
1010− QPointF touch2 = edgeDragArea->mapToScene(
1011− QPointF(edgeDragArea->width()*0.5, edgeDragArea->height()*0.9));
1012−
1013− passTime(edgeDragArea->d->compositionTime + movementTimeStepMs);
1014− QTest::touchEvent(m_view, m_device)
1015− .move(1, touch1.toPoint())
1016− .press(2, touch2.toPoint());
1017−
1018− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::Undecided);
1019− QCOMPARE(edgeDragArea->d->touchId, 2);
1020−
1021− touch2 += touchMovement;
1022− passTime(movementTimeStepMs);
1023− QTest::touchEvent(m_view, m_device)
1024− .move(1, touch1.toPoint())
1025− .move(2, touch2.toPoint());
1026−
1027− touch1 += touchMovement;
1028− passTime(movementTimeStepMs);
1029− QTest::touchEvent(m_view, m_device)
1030− .move(1, touch1.toPoint())
1031− .move(2, touch2.toPoint());
1032−
1033− passTime(movementTimeStepMs);
1034− QTest::touchEvent(m_view, m_device)
1035− .release(1, touch1.toPoint())
1036− .move(2, touch2.toPoint());
1037−
1038− passTime(movementTimeStepMs);
1039− QTest::touchEvent(m_view, m_device)
1040− .release(2, touch2.toPoint());
1041−
1042− QCOMPARE((int)edgeDragArea->d->status, (int)DirectionalDragAreaPrivate::WaitingForTouch);
1043−}
1044−
1045−/*
1046− A valid right-edge drag performed on mako
1047− */
1048−void tst_DirectionalDragArea::makoRightEdgeDrag()
1049−{
1050− m_view->resize(768, 1280);
1051− QTest::qWait(300);
1052−
1053− DirectionalDragArea *edgeDragArea =
1054− m_view->rootObject()->findChild<DirectionalDragArea*>("hnDragArea");
1055− QVERIFY(edgeDragArea != nullptr);
1056− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
1057− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
1058−
1059− StatusSpy *statusSpy = new StatusSpy(edgeDragArea);
1060−
1061− edgeDragArea->d->setPixelsPerMm(320.0 /*mako ppi*/ * 0.03937 /* inches per mm*/);
1062−
1063− sendTouchPress(319744, 0, QPointF(767.001, 719.719));
1064− sendTouchUpdate(319765, 0, QPointF(765.744,729.973));
1065− sendTouchUpdate(319784, 0, QPointF(740.879,752.182));
1066− sendTouchUpdate(319803, 0, QPointF(689.698,795.795));
1067− sendTouchUpdate(319826, 0, QPointF(616.978,856.212));
1068− sendTouchUpdate(319845, 0, QPointF(558.769,906.157));
1069− sendTouchUpdate(319859, 0, QPointF(513.219,945.266));
1070− sendTouchUpdate(319878, 0, QPointF(481.31,975.496));
1071− sendTouchUpdate(319902, 0, QPointF(460.016,997.439));
1072− sendTouchUpdate(319920, 0, QPointF(449.761,1008.6));
1073− sendTouchUpdate(319929, 0, QPointF(445.891,1012.42));
1074− sendTouchUpdate(319947, 0, QPointF(444.884,1013.93));
1075− sendTouchUpdate(319965, 0, QPointF(444.461,1014.35));
1076− sendTouchUpdate(320057, 0, QPointF(444.71,1013.56));
1077− sendTouchUpdate(320138, 0, QPointF(445.434,1013.6));
1078− sendTouchUpdate(320154, 0, QPointF(446.338,1012.98));
1079− sendTouchUpdate(320171, 0, QPointF(447.232,1012.08));
1080− sendTouchRelease(320171, 0, QPointF(447.232,1012.08));
1081−
1082− QCOMPARE(statusSpy->recognized(), true);
1083−
1084− delete statusSpy;
1085−}
1086−
1087−/*
1088− A vertical, downwards swipe performed on mako near its right edge.
1089−
1090− The DirectionalDragArea on the right edge must not recognize this
1091− gesture.
1092− */
1093−void tst_DirectionalDragArea::makoRightEdgeDrag_verticalDownwards()
1094−{
1095− m_view->resize(768, 1280);
1096− QTest::qWait(300);
1097−
1098− DirectionalDragArea *edgeDragArea =
1099− m_view->rootObject()->findChild<DirectionalDragArea*>("hnDragArea");
1100− QVERIFY(edgeDragArea != nullptr);
1101− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
1102− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
1103−
1104− edgeDragArea->d->setPixelsPerMm(320.0 /*mako ppi*/ * 0.03937 /* inches per mm*/);
1105−
1106− StatusSpy *statusSpy = new StatusSpy(edgeDragArea);
1107−
1108− sendTouchPress(12012445, 26, QPointF(767.001,461.82));
1109− sendTouchUpdate(12012472, 26, QPointF(767.001,462.569));
1110− sendTouchUpdate(12012528, 26, QPointF(767.001,463.334));
1111− sendTouchUpdate(12012546, 26, QPointF(767.001,466.856));
1112− sendTouchUpdate(12012571, 26, QPointF(767.001,473.291));
1113− sendTouchUpdate(12012587, 26, QPointF(767.001,487.31));
1114− sendTouchUpdate(12012604, 26, QPointF(765.364,507.521));
1115− sendTouchUpdate(12012618, 26, QPointF(765.364,507.521));
1116− sendTouchUpdate(12012627, 26, QPointF(762.642,534.317));
1117− sendTouchUpdate(12012655, 26, QPointF(760.846,573.406));
1118− sendTouchUpdate(12012667, 26, QPointF(759.838,625.295));
1119− sendTouchUpdate(12012675, 26, QPointF(758.875,703.207));
1120− sendTouchUpdate(12012696, 26, QPointF(761.52,777.015));
1121− sendTouchUpdate(12012713, 26, QPointF(765.659,835.591));
1122− sendTouchUpdate(12012731, 26, QPointF(766.778,883.206));
1123− sendTouchUpdate(12012748, 26, QPointF(767.001,922.937));
1124− sendTouchUpdate(12012779, 26, QPointF(767.001,967.558));
1125− sendTouchUpdate(12012798, 26, QPointF(767.001,1006.12));
1126− sendTouchUpdate(12012809, 26, QPointF(767.001,1033.1));
1127− sendTouchRelease(12012810, 26, QPointF(767.001,1033.1));
1128−
1129− QCOMPARE(statusSpy->recognized(), false);
1130−
1131− delete statusSpy;
1132−}
1133−
1134−/*
1135− A valid left-edge drag performed on mako. This one starts a bit slow than speeds up
1136− */
1137−void tst_DirectionalDragArea::makoLeftEdgeDrag_slowStart()
1138−{
1139− m_view->resize(768, 1280);
1140− QTest::qWait(300);
1141−
1142− DirectionalDragArea *edgeDragArea =
1143− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
1144− QVERIFY(edgeDragArea != nullptr);
1145− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
1146− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
1147−
1148− edgeDragArea->d->setPixelsPerMm(320.0 /*mako ppi*/ * 0.03937 /* inches per mm*/);
1149−
1150− StatusSpy *statusSpy = new StatusSpy(edgeDragArea);
1151−
1152− sendTouchPress(4002267, 77, QPointF(0,885.154));
1153− sendTouchUpdate(4002275, 77, QPointF(0,886.214));
1154− sendTouchUpdate(4002311, 77, QPointF(1.09568,887.75));
1155− sendTouchUpdate(4002329, 77, QPointF(3.53647,890.191));
1156− sendTouchUpdate(4002347, 77, QPointF(7.87434,892.879));
1157− sendTouchUpdate(4002366, 77, QPointF(12.3036,895.075));
1158− sendTouchUpdate(4002384, 77, QPointF(15.8885,896.849));
1159− sendTouchUpdate(4002406, 77, QPointF(18.4504,897.88));
1160− sendTouchUpdate(4002420, 77, QPointF(20.2429,898.149));
1161− sendTouchUpdate(4002439, 77, QPointF(20.9945,898.149));
1162− sendTouchUpdate(4002457, 77, QPointF(21.8819,898.149));
1163− sendTouchUpdate(4002480, 77, QPointF(22.7454,897.389));
1164− sendTouchUpdate(4002493, 77, QPointF(23.5456,896.589));
1165− sendTouchUpdate(4002511, 77, QPointF(24.5435,895.031));
1166− sendTouchUpdate(4002529, 77, QPointF(25.4271,892.32));
1167− sendTouchUpdate(4002548, 77, QPointF(26.3145,889.658));
1168− sendTouchUpdate(4002566, 77, QPointF(27.2004,886.999));
1169− sendTouchUpdate(4002584, 77, QPointF(28.035,885.048));
1170− sendTouchUpdate(4002603, 77, QPointF(29.9684,883.167));
1171− sendTouchUpdate(4002620, 77, QPointF(33.3591,881.403));
1172− sendTouchUpdate(4002639, 77, QPointF(44.1017,879.642));
1173− sendTouchUpdate(4002657, 77, QPointF(64.828,878.502));
1174− sendTouchUpdate(4002675, 77, QPointF(87.9486,878.157));
1175− sendTouchUpdate(4002693, 77, QPointF(112.96,877.742));
1176− sendTouchUpdate(4002711, 77, QPointF(138.903,877.157));
1177− sendTouchUpdate(4002729, 77, QPointF(163.204,877.157));
1178− sendTouchUpdate(4002747, 77, QPointF(182.127,877.157));
1179− sendTouchUpdate(4002765, 77, QPointF(194.478,877.657));
1180− sendTouchUpdate(4002785, 77, QPointF(201.474,878.508));
1181− sendTouchUpdate(4002803, 77, QPointF(204.855,879.401));
1182− sendTouchUpdate(4002822, 77, QPointF(206.616,880.281));
1183− sendTouchUpdate(4002839, 77, QPointF(207.115,880.906));
1184− sendTouchUpdate(4002894, 77, QPointF(206.865,881.184));
1185− sendTouchUpdate(4002912, 77, QPointF(206.865,882.143));
1186− sendTouchUpdate(4002930, 77, QPointF(206.865,883.106));
1187− sendTouchUpdate(4002949, 77, QPointF(206.526,883.994));
1188− sendTouchUpdate(4002967, 77, QPointF(205.866,884.88));
1189− sendTouchUpdate(4002985, 77, QPointF(205.866,885.766));
1190− sendTouchUpdate(4003005, 77, QPointF(205.866,886.654));
1191− sendTouchUpdate(4003021, 77, QPointF(205.366,887.537));
1192− sendTouchUpdate(4003039, 77, QPointF(204.592,888.428));
1193− sendTouchUpdate(4003050, 77, QPointF(204.367,888.653));
1194− sendTouchRelease(4003050, 77, QPointF(204.367,888.653));
1195−
1196− QCOMPARE(statusSpy->recognized(), true);
1197−
1198− delete statusSpy;
1199−}
1200−
1201−void tst_DirectionalDragArea::makoLeftEdgeDrag_movesSlightlyBackwardsOnStart()
1202−{
1203− m_view->resize(768, 1280);
1204− QTest::qWait(300);
1205−
1206− DirectionalDragArea *edgeDragArea =
1207− m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
1208− QVERIFY(edgeDragArea != nullptr);
1209− edgeDragArea->d->setRecognitionTimer(m_fakeTimerFactory->createTimer(edgeDragArea));
1210− edgeDragArea->d->setTimeSource(m_fakeTimerFactory->timeSource());
1211−
1212− edgeDragArea->d->setPixelsPerMm(320.0 /*mako ppi*/ * 0.03937 /* inches per mm*/);
1213−
1214− StatusSpy *statusSpy = new StatusSpy(edgeDragArea);
1215−
1216− sendTouchPress(41097, 24, QPointF(13.9909,827.177));
1217− sendTouchUpdate(41120, 24, QPointF(19.2375,825.677));
1218− sendTouchUpdate(41138, 24, QPointF(18.4057,826.177));
1219− sendTouchUpdate(41161, 24, QPointF(20.1067,825.867));
1220− sendTouchUpdate(41177, 24, QPointF(21.8869,824.977));
1221− sendTouchUpdate(41193, 24, QPointF(24.7603,823.494));
1222− sendTouchUpdate(41211, 24, QPointF(28.3889,821.725));
1223− sendTouchUpdate(41229, 24, QPointF(32.2909,819.955));
1224− sendTouchUpdate(41247, 24, QPointF(38.2251,817.431));
1225− sendTouchUpdate(41266, 24, QPointF(52.4182,814.223));
1226− sendTouchUpdate(41284, 24, QPointF(85.8465,809.483));
1227− sendTouchUpdate(41302, 24, QPointF(126.091,802.741));
1228− sendTouchUpdate(41320, 24, QPointF(153.171,797.977));
1229− sendTouchUpdate(41338, 24, QPointF(170.565,795.077));
1230− sendTouchUpdate(41356, 24, QPointF(178.685,794.101));
1231− sendTouchUpdate(41375, 24, QPointF(183.706,793.225));
1232− sendTouchUpdate(41393, 24, QPointF(186.112,793.19));
1233− sendTouchUpdate(41411, 24, QPointF(187.634,793.19));
1234− sendTouchUpdate(41429, 24, QPointF(188.505,793.19));
1235− sendTouchUpdate(41532, 24, QPointF(187.816,793.19));
1236− sendTouchUpdate(41538, 24, QPointF(186.902,793.19));
1237− sendTouchUpdate(41557, 24, QPointF(186.01,793.19));
1238− sendTouchUpdate(41575, 24, QPointF(185.125,793.444));
1239− sendTouchUpdate(41593, 24, QPointF(184.229,793.69));
1240− sendTouchUpdate(41605, 24, QPointF(183.88,793.69));
1241− sendTouchRelease(41607, 24, QPointF(183.88,793.69));
1242−
1243− QCOMPARE(statusSpy->recognized(), true);
1244−
1245− delete statusSpy;
1246−}
1247−
1248−QTEST_MAIN(tst_DirectionalDragArea)
1249−
1250−#include "tst_DirectionalDragArea.moc"