2 * Copyright (C) 2013 Canonical, Ltd.
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.
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.
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/>.
17#include <QtTest/QtTest>
18#include <QtCore/QObject>
19#include <qpa/qwindowsysteminterface.h>
20#include <QtQuick/QQuickView>
21#include <QtQml/QQmlEngine>
24#include <DirectionalDragArea.h>
26using namespace UbuntuGestures;
28class FakeTimer : public AbstractTimer
32 FakeTimer(const SharedTimeSource &timeSource, QObject *parent = 0)
33 : UbuntuGestures::AbstractTimer(parent),
34 m_timeSource(timeSource)
37 int interval() const override { return m_interval; }
38 void setInterval(int msecs) override { m_interval = msecs; }
39 void start() override {
40 AbstractTimer::start();
41 m_nextTimeoutTime = m_timeSource->msecsSinceReference() + (qint64)m_interval;
45 m_nextTimeoutTime += m_interval;
49 qint64 nextTimeoutTime() const { return m_nextTimeoutTime; }
52 SharedTimeSource m_timeSource;
53 qint64 m_nextTimeoutTime;
56class FakeTimeSource : public UbuntuGestures::TimeSource
59 FakeTimeSource() { m_msecsSinceReference = 0; }
60 virtual qint64 msecsSinceReference() {return m_msecsSinceReference;}
61 qint64 m_msecsSinceReference;
64class tst_DirectionalDragArea: public QObject
68 tst_DirectionalDragArea() : device(0) { }
70 void initTestCase(); // will be called before the first test function is executed
71 void cleanupTestCase(); // will be called after the last test function was executed.
73 void init(); // called right before each and every test function is executed
74 void cleanup(); // called right after each and every test function is executed
78 void dragWithShortDirectionChange();
81 void recognitionTimerUsage();
82 void maxSilenceTime();
87 void ignoreOldFinger();
90 QQuickView *createView();
91 void passTime(qint64 timeSpan);
95 QSharedPointer<FakeTimeSource> fakeTimeSource;
98void tst_DirectionalDragArea::initTestCase()
101 device = new QTouchDevice;
102 device->setType(QTouchDevice::TouchScreen);
103 QWindowSystemInterface::registerTouchDevice(device);
109void tst_DirectionalDragArea::cleanupTestCase()
113void tst_DirectionalDragArea::init()
116 view->setSource(QUrl::fromLocalFile("edgeDragExample.qml"));
118 QVERIFY(QTest::qWaitForWindowExposed(view));
119 QVERIFY(view->rootObject() != 0);
120 qApp->processEvents();
122 fakeTimeSource.reset(new FakeTimeSource);
123 fakeTimer = new FakeTimer(fakeTimeSource);
126void tst_DirectionalDragArea::cleanup()
134 fakeTimeSource.reset();
137QQuickView *tst_DirectionalDragArea::createView()
139 QQuickView *window = new QQuickView(0);
140 window->setResizeMode(QQuickView::SizeRootObjectToView);
141 window->resize(600, 600);
142 window->engine()->addImportPath(QLatin1String(UBUNTU_GESTURES_PLUGIN_DIR));
147void tst_DirectionalDragArea::passTime(qint64 timeSpan)
149 qint64 finalTime = fakeTimeSource->m_msecsSinceReference + timeSpan;
151 if (fakeTimer->isRunning() && finalTime >= fakeTimer->nextTimeoutTime()) {
152 fakeTimeSource->m_msecsSinceReference = fakeTimer->nextTimeoutTime();
153 fakeTimer->emitTimeout();
155 qint64 timeSpanRemainder = finalTime - fakeTimeSource->m_msecsSinceReference;
156 if (timeSpanRemainder > 0) {
157 passTime(timeSpanRemainder);
160 fakeTimeSource->m_msecsSinceReference = finalTime;
165QPointF calculateInitialTouchPos(DirectionalDragArea *edgeDragArea, QQuickView *view)
167 switch (edgeDragArea->direction()) {
168 case Direction::Upwards:
169 return QPointF(view->width()/2.0f, view->height() - (edgeDragArea->height()/2.0f));
170 case Direction::Downwards:
171 return QPointF(view->width()/2.0f, edgeDragArea->height()/2.0f);
172 case Direction::Leftwards:
173 return QPointF(view->width() - (edgeDragArea->width()/2.0f), view->height()/2.0f);
174 default: // Direction::Rightwards:
175 return QPointF(edgeDragArea->width()/2.0f, view->height()/2.0f);
179QPointF calculateDirectionVector(DirectionalDragArea *edgeDragArea,
180 qreal wideningAngleMultiplier)
182 qreal angleRadians = edgeDragArea->wideningAngle() * wideningAngleMultiplier
185 qreal angleCos = qCos(angleRadians);
186 qreal angleSin = qSin(angleRadians);
188 switch (edgeDragArea->direction()) {
189 case Direction::Upwards:
190 return QPointF(angleSin, -angleCos);
191 case Direction::Downwards:
192 return QPointF(angleSin, angleCos);
193 case Direction::Leftwards:
194 return QPointF(-angleCos, angleSin);
195 default: // Direction::Rightwards:
196 return QPointF(angleCos, angleSin);
200QPointF createTouchDeviation(DirectionalDragArea *edgeDragArea)
202 qreal deviation = edgeDragArea->maxDeviation() * 0.8;
204 if (Direction::isHorizontal(edgeDragArea->direction())) {
205 return QPointF(0, deviation);
207 return QPointF(deviation, 0);
212void tst_DirectionalDragArea::edgeDrag()
214 QFETCH(QString, dragAreaObjectName);
215 QFETCH(qreal, wideningAngleMultiplier);
216 QFETCH(qreal, dragDistanceFactor);
217 QFETCH(bool, expectGestureRecognition);
219 DirectionalDragArea *edgeDragArea =
220 view->rootObject()->findChild<DirectionalDragArea*>(dragAreaObjectName);
221 QVERIFY(edgeDragArea != 0);
222 edgeDragArea->setRecognitionTimer(fakeTimer);
223 edgeDragArea->setTimeSource(fakeTimeSource);
225 QSignalSpy draggingSpy(edgeDragArea, SIGNAL(draggingChanged(bool)));
227 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
228 QPointF touchPoint = initialTouchPos;
230 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*dragDistanceFactor;
231 QPointF dragDirectionVector = calculateDirectionVector(edgeDragArea,
232 wideningAngleMultiplier);
233 qreal movementStepDistance = edgeDragArea->distanceThreshold() * 0.1f;
234 QPointF touchMovement = dragDirectionVector * movementStepDistance;
235 int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
236 int movementTimeStepMs = (edgeDragArea->compositionTime() * 1.5f) / totalMovementSteps;
238 QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
240 QCOMPARE(draggingSpy.count(), 1);
241 QCOMPARE(edgeDragArea->dragging(), true);
243 if (wideningAngleMultiplier > 0) {
244 // go close to the border of the valid area for this touch point
245 // in order to make it easier to leave it by dragging at an angle
246 // slightly bigger than the widening angle
247 touchPoint += createTouchDeviation(edgeDragArea);
248 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
251 for (int i = 0; i < totalMovementSteps; ++i) {
252 touchPoint += touchMovement;
253 passTime(movementTimeStepMs);
254 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
257 if (expectGestureRecognition)
258 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
260 if (edgeDragArea->status() == DirectionalDragArea::WaitingForTouch) {
261 QCOMPARE(edgeDragArea->dragging(), false);
262 QCOMPARE(draggingSpy.count(), 2);
265 QTest::touchEvent(view, device).release(0, touchPoint.toPoint());
267 QCOMPARE(draggingSpy.count(), 2);
268 QCOMPARE(edgeDragArea->dragging(), false);
271void tst_DirectionalDragArea::edgeDrag_data()
273 QTest::addColumn<QString>("dragAreaObjectName");
274 QTest::addColumn<qreal>("wideningAngleMultiplier");
275 QTest::addColumn<qreal>("dragDistanceFactor");
276 QTest::addColumn<bool>("expectGestureRecognition");
278 QTest::newRow("rightwards, tiny drag")
279 << "hpDragArea" << 0.0 << 0.2 << false;
281 QTest::newRow("rightwards, straight drag")
282 << "hpDragArea" << 0.0 << 3.0 << true;
284 QTest::newRow("rightwards, diagonal drag")
285 << "hpDragArea" << 0.9 << 3.0 << true;
287 QTest::newRow("rightwards, overly diagonal drag")
288 << "hpDragArea" << 2.0 << 3.0 << false;
290 QTest::newRow("leftwards, tiny drag")
291 << "hnDragArea" << 0.0 << 0.2 << false;
293 QTest::newRow("leftwards, straight drag")
294 << "hnDragArea" << 0.0 << 3.0 << true;
296 QTest::newRow("leftwards, diagonal drag")
297 << "hnDragArea" << 0.9 << 3.0 << true;
299 QTest::newRow("downwards, tiny drag")
300 << "vpDragArea" << 0.0 << 0.2 << false;
302 QTest::newRow("downwards, straight drag")
303 << "vpDragArea" << 0.0 << 3.0 << true;
305 QTest::newRow("downwards, diagonal drag")
306 << "vpDragArea" << 0.9 << 3.0 << true;
308 QTest::newRow("upwards, tiny drag")
309 << "vnDragArea" << 0.0 << 0.2 << false;
311 QTest::newRow("upwards, straight drag")
312 << "vnDragArea" << 0.0 << 3.0 << true;
314 QTest::newRow("upwards, diagonal drag")
315 << "vnDragArea" << 0.9 << 3.0 << true;
317 QTest::newRow("upwards, overly diagonal drag")
318 << "vnDragArea" << 2.0 << 3.0 << false;
322 A directional drag should still be recognized if there is a momentaneous, small,
323 change in the direction of a drag. That should be accounted as input noise and
326void tst_DirectionalDragArea::dragWithShortDirectionChange()
328 DirectionalDragArea *edgeDragArea =
329 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
330 QVERIFY(edgeDragArea != 0);
331 edgeDragArea->setRecognitionTimer(fakeTimer);
332 edgeDragArea->setTimeSource(fakeTimeSource);
334 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
335 QPointF touchPoint = initialTouchPos;
337 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0;
338 QPointF dragDirectionVector(1.0, 0.0);
339 qreal touchStepDistance = edgeDragArea->distanceThreshold() * 0.1f;
340 // make sure we are above minimum speed
341 int touchStepTimeMs = (touchStepDistance / (edgeDragArea->minSpeed() * 5.0f)) * 1000.0f;
342 QPointF touchMovement = dragDirectionVector * touchStepDistance;
344 QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
346 // Move a bit in the proper direction
347 for (int i=0; i < 3; ++i) {
348 touchPoint += touchMovement;
349 passTime(touchStepTimeMs);
350 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
353 // Then a sudden and small movement to the opposite direction
354 touchPoint -= touchMovement*0.2;
355 passTime(touchStepTimeMs*0.2);
356 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
358 // And then resume movment in the correct direction until it crosses the distance and time
361 touchPoint += touchMovement;
362 passTime(touchStepTimeMs);
363 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
364 } while ((touchPoint - initialTouchPos).manhattanLength() < desiredDragDistance
365 || fakeTimeSource->m_msecsSinceReference < (edgeDragArea->compositionTime() * 1.5f));
367 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
369 QTest::touchEvent(view, device).release(0, touchPoint.toPoint());
373 Checks that a gesture will be rejected if it's slower than minSpeed while
376void tst_DirectionalDragArea::minSpeed()
378 QFETCH(qreal, minSpeed);
379 QFETCH(qreal, speed);
380 QFETCH(int, expectedStatusAfterSpeedCheck);
382 DirectionalDragArea *edgeDragArea =
383 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
384 QVERIFY(edgeDragArea != 0);
385 edgeDragArea->setRecognitionTimer(fakeTimer);
386 edgeDragArea->setTimeSource(fakeTimeSource);
388 // A really long, unattainable, number. We don't want it getting recognized before
389 // the speed checks we want have been performed
390 edgeDragArea->setDistanceThreshold(500000);
392 edgeDragArea->setMinSpeed(minSpeed);
394 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
395 QPointF touchPoint = initialTouchPos;
397 QPointF dragDirectionVector(1.0, 0.0);
398 qint64 timeStepMsecs = 10;
399 qreal distanceStep = (speed / 1000.0f) * timeStepMsecs;
400 QPointF touchMovement = dragDirectionVector * distanceStep;
402 QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
404 // Move for a while to ensure our speed check is performed a couple of times
405 for (int i=0; i < 20; ++i) {
406 touchPoint += touchMovement;
407 passTime(timeStepMsecs);
408 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
411 QCOMPARE((int)edgeDragArea->status(), expectedStatusAfterSpeedCheck);
414void tst_DirectionalDragArea::minSpeed_data()
416 QTest::addColumn<qreal>("minSpeed");
417 QTest::addColumn<qreal>("speed");
418 QTest::addColumn<int>("expectedStatusAfterSpeedCheck");
420 QTest::newRow("slower than minSpeed") << 100.0 << 50.0 << (int)DirectionalDragArea::WaitingForTouch;
421 QTest::newRow("faster than minSpeed") << 100.0 << 150.0 << (int)DirectionalDragArea::Undecided;
425 Checks that the recognition timer is started and stopped appropriately.
426 I.e., check that it's running only while gesture recognition is taking place
427 (status == Undecided)
429void tst_DirectionalDragArea::recognitionTimerUsage()
431 DirectionalDragArea *edgeDragArea =
432 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
433 QVERIFY(edgeDragArea != 0);
434 edgeDragArea->setRecognitionTimer(fakeTimer);
435 edgeDragArea->setTimeSource(fakeTimeSource);
437 // don't let it interfere with our test
438 edgeDragArea->setMinSpeed(0.0);
440 int timeStepMs = 5; // some arbitrary small value.
442 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
443 QPointF touchPoint = initialTouchPos;
445 QPointF dragDirectionVector(1.0, 0.0);
446 QPointF touchMovement = dragDirectionVector * (edgeDragArea->distanceThreshold() * 0.2f);
448 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
449 QVERIFY(!fakeTimer->isRunning());
451 QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
453 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
454 QVERIFY(fakeTimer->isRunning());
456 // Move beyond distance threshold and composition time to ensure recognition
457 while (fakeTimeSource->m_msecsSinceReference <= edgeDragArea->compositionTime() ||
458 (touchPoint - initialTouchPos).manhattanLength() <= edgeDragArea->distanceThreshold()) {
460 QCOMPARE(edgeDragArea->status() == DirectionalDragArea::Undecided, fakeTimer->isRunning());
462 touchPoint += touchMovement;
463 passTime(timeStepMs);
464 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
467 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
468 QVERIFY(!fakeTimer->isRunning());
472 A gesture should be rejected if too much time has passed without any new input
475void tst_DirectionalDragArea::maxSilenceTime()
477 DirectionalDragArea *edgeDragArea =
478 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
479 QVERIFY(edgeDragArea != 0);
480 edgeDragArea->setRecognitionTimer(fakeTimer);
481 edgeDragArea->setTimeSource(fakeTimeSource);
483 // Make sure this property is not disabled
484 edgeDragArea->setMaxSilenceTime(100);
486 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
487 QPointF touchPoint = initialTouchPos;
489 QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
491 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
492 QVERIFY(fakeTimer->isRunning());
494 // Force timer to timeout until after maxSilenceTime has been reached
495 while (fakeTimeSource->m_msecsSinceReference < edgeDragArea->maxSilenceTime()) {
496 passTime(fakeTimer->interval());
499 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
503 Checks that it informs the X coordinate of the touch point in local and scene coordinates
506void tst_DirectionalDragArea::sceneXAndX()
508 DirectionalDragArea *edgeDragArea =
509 view->rootObject()->findChild<DirectionalDragArea*>("hnDragArea");
510 QVERIFY(edgeDragArea != 0);
511 edgeDragArea->setRecognitionTimer(fakeTimer);
512 edgeDragArea->setTimeSource(fakeTimeSource);
514 QPointF touchScenePos(view->width() - (edgeDragArea->width()/2.0f), view->height()/2.0f);
516 QTest::touchEvent(view, device).press(0, touchScenePos.toPoint());
518 QSignalSpy touchXSpy(edgeDragArea, SIGNAL(touchXChanged(qreal)));
519 QSignalSpy touchSceneXSpy(edgeDragArea, SIGNAL(touchSceneXChanged(qreal)));
521 touchScenePos.rx() = view->width() / 2;
522 QTest::touchEvent(view, device).move(0, touchScenePos.toPoint());
524 QCOMPARE(touchXSpy.count(), 1);
525 QCOMPARE(touchSceneXSpy.count(), 1);
526 QCOMPARE(edgeDragArea->touchX(), touchScenePos.x() - edgeDragArea->x());
527 QCOMPARE(edgeDragArea->touchSceneX(), touchScenePos.x());
531 Checks that it informs the Y coordinate of the touch point in local and scene coordinates
534void tst_DirectionalDragArea::sceneYAndY()
536 DirectionalDragArea *edgeDragArea =
537 view->rootObject()->findChild<DirectionalDragArea*>("vnDragArea");
538 QVERIFY(edgeDragArea != 0);
539 edgeDragArea->setRecognitionTimer(fakeTimer);
540 edgeDragArea->setTimeSource(fakeTimeSource);
542 QPointF touchScenePos(view->width()/2.0f, view->height() - (edgeDragArea->height()/2.0f));
544 QTest::touchEvent(view, device).press(0, touchScenePos.toPoint());
546 QSignalSpy touchYSpy(edgeDragArea, SIGNAL(touchYChanged(qreal)));
547 QSignalSpy touchSceneYSpy(edgeDragArea, SIGNAL(touchSceneYChanged(qreal)));
549 touchScenePos.ry() = view->height() / 2;
550 QTest::touchEvent(view, device).move(0, touchScenePos.toPoint());
552 QCOMPARE(touchYSpy.count(), 1);
553 QCOMPARE(touchSceneYSpy.count(), 1);
554 QCOMPARE(edgeDragArea->touchY(), touchScenePos.y() - edgeDragArea->y());
555 QCOMPARE(edgeDragArea->touchSceneY(), touchScenePos.y());
559 Regression test for https://bugs.launchpad.net/bugs/1228336
561 Perform a quick two-finger double-tap and check that DirectionalDragArea properly
562 rejects those touch points. In the bug above it got confused and crashed.
564void tst_DirectionalDragArea::twoFingerTap()
566 DirectionalDragArea *edgeDragArea =
567 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
568 QVERIFY(edgeDragArea != 0);
569 edgeDragArea->setRecognitionTimer(fakeTimer);
570 edgeDragArea->setTimeSource(fakeTimeSource);
572 // Make touches evenly spaced along the edgeDragArea
573 QPoint touchAPos(edgeDragArea->width()/2.0f, view->height()*0.33f);
574 QPoint touchBPos(edgeDragArea->width()/2.0f, view->height()*0.66f);
576 qint64 timeStepMsecs = 5; // some arbitrary, small value
578 // Perform the first two-finger tap
579 // NB: using move() instead of stationary() becasue in the latter you cannot provide
580 // the touch position and therefore it's left with some garbage numbers.
581 QTest::touchEvent(view, device)
582 .press(0, touchAPos);
584 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
586 passTime(timeStepMsecs);
587 QTest::touchEvent(view, device)
589 .press(1, touchBPos);
591 // A second touch point appeared during recognition, reject immediately as this
592 // can't be a single-touch gesture anymore.
593 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
595 passTime(timeStepMsecs);
596 QTest::touchEvent(view, device)
597 .release(0, touchAPos)
600 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
602 passTime(timeStepMsecs);
603 QTest::touchEvent(view, device)
604 .release(1, touchBPos);
606 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
608 // Perform the second two-finger tap
610 passTime(timeStepMsecs);
611 QTest::touchEvent(view, device)
612 .press(0, touchAPos);
614 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
616 passTime(timeStepMsecs);
617 QTest::touchEvent(view, device)
619 .press(1, touchBPos);
621 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
623 passTime(timeStepMsecs);
624 QTest::touchEvent(view, device)
625 .release(0, touchAPos)
628 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
630 passTime(timeStepMsecs);
631 QTest::touchEvent(view, device)
632 .release(1, touchBPos);
634 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
638 Tests that gesture recognition works normally even if the DirectionalDragArea moves
640 This effectively means that we have to do gesture recognition with scene coordinates
641 instead of local item coordinates.
643void tst_DirectionalDragArea::movingDDA()
645 QQuickItem *rightwardsLauncher = view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
646 Q_ASSERT(rightwardsLauncher != 0);
648 DirectionalDragArea *edgeDragArea =
649 rightwardsLauncher->findChild<DirectionalDragArea*>("hpDragArea");
650 Q_ASSERT(edgeDragArea != 0);
651 edgeDragArea->setRecognitionTimer(fakeTimer);
652 edgeDragArea->setTimeSource(fakeTimeSource);
654 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
655 QPointF touchPoint = initialTouchPos;
657 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0f;
658 QPointF dragDirectionVector(1.0f, 0.0f);
660 qreal movementStepDistance = edgeDragArea->distanceThreshold() * 0.1f;
661 QPointF touchMovement = dragDirectionVector * movementStepDistance;
662 int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
663 int movementTimeStepMs = (edgeDragArea->compositionTime() * 1.5f) / totalMovementSteps;
665 QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
667 // Move it far ahead along the direction of the gesture
668 // rightwardsLauncher is a parent of our DirectionalDragArea. So moving it will move our DDA
669 rightwardsLauncher->setX(rightwardsLauncher->x() + edgeDragArea->distanceThreshold() * 5.0f);
671 for (int i = 0; i < totalMovementSteps; ++i) {
672 touchPoint += touchMovement;
673 passTime(movementTimeStepMs);
674 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
677 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
679 QTest::touchEvent(view, device).release(0, touchPoint.toPoint());
683 The presence of and old, rejected, touch point lying on the DirectionalDragArea
684 shouldn't impede the recognition of a gesture from a new touch point.
686void tst_DirectionalDragArea::ignoreOldFinger()
688 DirectionalDragArea *edgeDragArea =
689 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
690 Q_ASSERT(edgeDragArea != 0);
691 edgeDragArea->setRecognitionTimer(fakeTimer);
692 edgeDragArea->setTimeSource(fakeTimeSource);
694 // Make touches evenly spaced along the edgeDragArea
695 QPoint touch0Pos(edgeDragArea->width()/2.0f, view->height()*0.33f);
696 QPoint touch1Pos(edgeDragArea->width()/2.0f, view->height()*0.66f);
698 QTest::touchEvent(view, device).press(0, touch0Pos);
700 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
702 // leave it lying around for some time
703 passTime(qMax(edgeDragArea->maxSilenceTime(), edgeDragArea->compositionTime()) * 10);
705 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
707 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0f;
708 QPointF dragDirectionVector(1.0f, 0.0f);
710 qreal movementStepDistance = edgeDragArea->distanceThreshold() * 0.1f;
711 QPointF touchMovement = dragDirectionVector * movementStepDistance;
712 int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
713 int movementTimeStepMs = (edgeDragArea->compositionTime() * 1.5f) / totalMovementSteps;
715 QTest::touchEvent(view, device)
717 .press(1, touch1Pos);
719 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
721 for (int i = 0; i < totalMovementSteps; ++i) {
722 touch1Pos += touchMovement.toPoint();
723 passTime(movementTimeStepMs);
724 QTest::touchEvent(view, device)
729 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
731 QTest::touchEvent(view, device)
733 .release(1, touch1Pos);
735 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
738QTEST_MAIN(tst_DirectionalDragArea)
740#include "tst_DirectionalDragArea.moc"
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list