@@ -83,6 +83,10 @@ private Q_SLOTS:
83 void twoFingerTap();
83 void twoFingerTap();
84 void movingDDA();
84 void movingDDA();
85 void ignoreOldFinger();
85 void ignoreOldFinger();
87+ void sceneDistance();
88+ void sceneDistance_data();
89+ void disabledWhileDragging();
88 void passTime(qint64 timeSpan);
92 void passTime(qint64 timeSpan);
@@ -99,6 +103,14 @@ void tst_DirectionalDragArea::init()
100 GestureTest::init();
104 GestureTest::init();
106+ // We shouldn't need the three lines below, but a compiz/unity7
107+ // regression means we don't pass the test without them because
108+ // the window doesn't have the proper size. Can be removed in the
109+ // future if the regression is fixed and tests pass again
110+ m_view->resize(m_view->rootObject()->width(), m_view->rootObject()->height());
111+ QTRY_COMPARE(m_view->width(), (int)m_view->rootObject()->width());
112+ QTRY_COMPARE(m_view->height(), (int)m_view->rootObject()->height());
102 fakeTimeSource.reset(new FakeTimeSource);
114 fakeTimeSource.reset(new FakeTimeSource);
103 fakeTimer = new FakeTimer(fakeTimeSource);
115 fakeTimer = new FakeTimer(fakeTimeSource);
@@ -131,18 +143,10 @@ void tst_DirectionalDragArea::passTime(qint64 timeSpan)
133namespace {
145namespace {
134−QPointF calculateInitialTouchPos(DirectionalDragArea *edgeDragArea, QQuickView *view)
146+QPointF calculateInitialTouchPos(DirectionalDragArea *edgeDragArea)
136− switch (edgeDragArea->direction()) {
148+ QPointF localCenter(edgeDragArea->width() / 2., edgeDragArea->height() / 2.);
137− case Direction::Upwards:
138− return QPointF(view->width()/2.0f, view->height() - (edgeDragArea->height()/2.0f));
139− case Direction::Downwards:
140− return QPointF(view->width()/2.0f, edgeDragArea->height()/2.0f);
141− case Direction::Leftwards:
142− return QPointF(view->width() - (edgeDragArea->width()/2.0f), view->height()/2.0f);
143− default: // Direction::Rightwards:
144− return QPointF(edgeDragArea->width()/2.0f, view->height()/2.0f);
149+ return edgeDragArea->mapToScene(localCenter);
148QPointF calculateDirectionVector(DirectionalDragArea *edgeDragArea,
152QPointF calculateDirectionVector(DirectionalDragArea *edgeDragArea,
@@ -193,7 +197,7 @@ void tst_DirectionalDragArea::edgeDrag()
194 QSignalSpy draggingSpy(edgeDragArea, SIGNAL(draggingChanged(bool)));
198 QSignalSpy draggingSpy(edgeDragArea, SIGNAL(draggingChanged(bool)));
196− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
200+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
197 QPointF touchPoint = initialTouchPos;
201 QPointF touchPoint = initialTouchPos;
199 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*dragDistanceFactor;
203 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*dragDistanceFactor;
@@ -300,7 +304,7 @@ void tst_DirectionalDragArea::dragWithShortDirectionChange()
300 edgeDragArea->setRecognitionTimer(fakeTimer);
304 edgeDragArea->setRecognitionTimer(fakeTimer);
301 edgeDragArea->setTimeSource(fakeTimeSource);
305 edgeDragArea->setTimeSource(fakeTimeSource);
303− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
307+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
304 QPointF touchPoint = initialTouchPos;
308 QPointF touchPoint = initialTouchPos;
306 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0;
310 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0;
@@ -360,7 +364,7 @@ void tst_DirectionalDragArea::minSpeed()
361 edgeDragArea->setMinSpeed(minSpeed);
365 edgeDragArea->setMinSpeed(minSpeed);
363− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
367+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
364 QPointF touchPoint = initialTouchPos;
368 QPointF touchPoint = initialTouchPos;
366 QPointF dragDirectionVector(1.0, 0.0);
370 QPointF dragDirectionVector(1.0, 0.0);
@@ -408,7 +412,7 @@ void tst_DirectionalDragArea::recognitionTimerUsage()
409 int timeStepMs = 5; // some arbitrary small value.
413 int timeStepMs = 5; // some arbitrary small value.
411− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
415+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
412 QPointF touchPoint = initialTouchPos;
416 QPointF touchPoint = initialTouchPos;
414 QPointF dragDirectionVector(1.0, 0.0);
418 QPointF dragDirectionVector(1.0, 0.0);
@@ -452,7 +456,7 @@ void tst_DirectionalDragArea::maxSilenceTime()
452 // Make sure this property is not disabled
456 // Make sure this property is not disabled
453 edgeDragArea->setMaxSilenceTime(100);
457 edgeDragArea->setMaxSilenceTime(100);
455− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
459+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
456 QPointF touchPoint = initialTouchPos;
460 QPointF touchPoint = initialTouchPos;
458 QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
462 QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
@@ -620,7 +624,7 @@ void tst_DirectionalDragArea::movingDDA()
620 edgeDragArea->setRecognitionTimer(fakeTimer);
624 edgeDragArea->setRecognitionTimer(fakeTimer);
621 edgeDragArea->setTimeSource(fakeTimeSource);
625 edgeDragArea->setTimeSource(fakeTimeSource);
623− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
627+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
624 QPointF touchPoint = initialTouchPos;
628 QPointF touchPoint = initialTouchPos;
626 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0f;
630 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0f;
@@ -704,6 +708,147 @@ void tst_DirectionalDragArea::ignoreOldFinger()
704 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
708 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
712+ A Rightwards DDA that is rotated 90 degrees clockwise should recognize gestures
713+ that are done downwards in scene coordinates. I.e. the gesture recognition direction
714+ should be in local coordinates, not scene coordinates.
716+void tst_DirectionalDragArea::rotated()
718+ QQuickItem *baseItem = m_view->rootObject()->findChild<QQuickItem*>("baseItem");
719+ baseItem->setRotation(90.);
721+ QQuickItem *rightwardsLauncher = m_view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
722+ Q_ASSERT(rightwardsLauncher != 0);
724+ DirectionalDragArea *edgeDragArea =
725+ rightwardsLauncher->findChild<DirectionalDragArea*>("hpDragArea");
726+ Q_ASSERT(edgeDragArea != 0);
727+ edgeDragArea->setRecognitionTimer(fakeTimer);
728+ edgeDragArea->setTimeSource(fakeTimeSource);
730+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
731+ QPointF touchPoint = initialTouchPos;
733+ qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0f;
734+ QPointF dragDirectionVector(0.0f, 1.0f);
736+ qreal movementStepDistance = edgeDragArea->distanceThreshold() * 0.1f;
737+ QPointF touchMovement = dragDirectionVector * movementStepDistance;
738+ int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
739+ int movementTimeStepMs = (edgeDragArea->compositionTime() * 1.5f) / totalMovementSteps;
741+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
743+ for (int i = 0; i < totalMovementSteps; ++i) {
744+ touchPoint += touchMovement;
745+ passTime(movementTimeStepMs);
746+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
749+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
751+ QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
754+void tst_DirectionalDragArea::sceneDistance()
756+ QQuickItem *baseItem = m_view->rootObject()->findChild<QQuickItem*>("baseItem");
757+ QFETCH(qreal, rotation);
758+ QFETCH(QPointF, dragDirectionVector);
759+ baseItem->setRotation(rotation);
761+ QQuickItem *rightwardsLauncher = m_view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
762+ Q_ASSERT(rightwardsLauncher != 0);
764+ DirectionalDragArea *edgeDragArea =
765+ rightwardsLauncher->findChild<DirectionalDragArea*>("hpDragArea");
766+ Q_ASSERT(edgeDragArea != 0);
767+ edgeDragArea->setRecognitionTimer(fakeTimer);
768+ edgeDragArea->setTimeSource(fakeTimeSource);
770+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
771+ QPointF touchPoint = initialTouchPos;
773+ qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0f;
775+ qreal movementStepDistance = edgeDragArea->distanceThreshold() * 0.1f;
776+ QPointF touchMovement = dragDirectionVector * movementStepDistance;
777+ int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
778+ int movementTimeStepMs = (edgeDragArea->compositionTime() * 1.5f) / totalMovementSteps;
780+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
782+ for (int i = 0; i < totalMovementSteps; ++i) {
783+ touchPoint += touchMovement;
784+ passTime(movementTimeStepMs);
785+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
788+ qreal actualDragDistance = ((qreal)totalMovementSteps) * movementStepDistance;
790+ // DirectionalDragArea::sceneDistance() must match the actual drag distance as the
791+ // drag was aligned with the gesture direction
792+ // NB: qFuzzyCompare(), used internally by QCOMPARE(), is broken.
793+ QVERIFY(qAbs(edgeDragArea->sceneDistance() - actualDragDistance) < 0.001);
795+ QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
798+void tst_DirectionalDragArea::sceneDistance_data()
800+ QTest::addColumn<qreal>("rotation");
801+ QTest::addColumn<QPointF>("dragDirectionVector");
803+ QTest::newRow("not rotated") << 0. << QPointF(1., 0.);
804+ QTest::newRow("rotated by 90 degrees") << 90. << QPointF(0., 1.);
808+ Regression test for https://bugs.launchpad.net/unity8/+bug/1276122
811+ If setting "enabled: false" while the DirectionalDragArea's (DDA) dragging
812+ property is true, the DDA stays in that state and doesn't recover any more.
814+void tst_DirectionalDragArea::disabledWhileDragging()
816+ DirectionalDragArea *edgeDragArea =
817+ m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
818+ Q_ASSERT(edgeDragArea != 0);
819+ edgeDragArea->setRecognitionTimer(fakeTimer);
820+ edgeDragArea->setTimeSource(fakeTimeSource);
822+ QPointF touchPoint = calculateInitialTouchPos(edgeDragArea);
824+ qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0f;
825+ QPointF dragDirectionVector(1., 0.); // horizontal positive
827+ qreal movementStepDistance = edgeDragArea->distanceThreshold() * 0.1f;
828+ QPointF touchMovement = dragDirectionVector * movementStepDistance;
829+ int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
830+ int movementTimeStepMs = (edgeDragArea->compositionTime() * 1.5f) / totalMovementSteps;
832+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
834+ for (int i = 0; i < totalMovementSteps; ++i) {
835+ touchPoint += touchMovement;
836+ passTime(movementTimeStepMs);
837+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
840+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
841+ QCOMPARE(edgeDragArea->dragging(), true);
843+ // disable the dragArea while it's being dragged.
844+ edgeDragArea->setEnabled(false);
846+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
847+ QCOMPARE(edgeDragArea->dragging(), false);
849+ QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
707QTEST_MAIN(tst_DirectionalDragArea)
852QTEST_MAIN(tst_DirectionalDragArea)
709#include "tst_DirectionalDragArea.moc"
854#include "tst_DirectionalDragArea.moc"