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