@@ -83,6 +83,10 @@ private Q_SLOTS:
8383 void twoFingerTap();
8484 void movingDDA();
8585 void ignoreOldFinger();
86+ void rotated();
87+ void sceneDistance();
88+ void sceneDistance_data();
89+ void disabledWhileDragging();
8690
8791private:
8892 void passTime(qint64 timeSpan);
@@ -131,18 +135,10 @@ void tst_DirectionalDragArea::passTime(qint64 timeSpan)
131135}
132136
133137namespace {
134−QPointF calculateInitialTouchPos(DirectionalDragArea *edgeDragArea, QQuickView *view)
138+QPointF calculateInitialTouchPos(DirectionalDragArea *edgeDragArea)
135139{
136− switch (edgeDragArea->direction()) {
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);
145− }
140+ QPointF localCenter(edgeDragArea->width() / 2., edgeDragArea->height() / 2.);
141+ return edgeDragArea->mapToScene(localCenter);
146142}
147143
148144QPointF calculateDirectionVector(DirectionalDragArea *edgeDragArea,
@@ -193,7 +189,7 @@ void tst_DirectionalDragArea::edgeDrag()
193189
194190 QSignalSpy draggingSpy(edgeDragArea, SIGNAL(draggingChanged(bool)));
195191
196− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
192+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
197193 QPointF touchPoint = initialTouchPos;
198194
199195 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*dragDistanceFactor;
@@ -300,7 +296,7 @@ void tst_DirectionalDragArea::dragWithShortDirectionChange()
300296 edgeDragArea->setRecognitionTimer(fakeTimer);
301297 edgeDragArea->setTimeSource(fakeTimeSource);
302298
303− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
299+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
304300 QPointF touchPoint = initialTouchPos;
305301
306302 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0;
@@ -360,7 +356,7 @@ void tst_DirectionalDragArea::minSpeed()
360356
361357 edgeDragArea->setMinSpeed(minSpeed);
362358
363− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
359+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
364360 QPointF touchPoint = initialTouchPos;
365361
366362 QPointF dragDirectionVector(1.0, 0.0);
@@ -408,7 +404,7 @@ void tst_DirectionalDragArea::recognitionTimerUsage()
408404
409405 int timeStepMs = 5; // some arbitrary small value.
410406
411− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
407+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
412408 QPointF touchPoint = initialTouchPos;
413409
414410 QPointF dragDirectionVector(1.0, 0.0);
@@ -452,7 +448,7 @@ void tst_DirectionalDragArea::maxSilenceTime()
452448 // Make sure this property is not disabled
453449 edgeDragArea->setMaxSilenceTime(100);
454450
455− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
451+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
456452 QPointF touchPoint = initialTouchPos;
457453
458454 QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
@@ -620,7 +616,7 @@ void tst_DirectionalDragArea::movingDDA()
620616 edgeDragArea->setRecognitionTimer(fakeTimer);
621617 edgeDragArea->setTimeSource(fakeTimeSource);
622618
623− QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
619+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
624620 QPointF touchPoint = initialTouchPos;
625621
626622 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0f;
@@ -704,6 +700,147 @@ void tst_DirectionalDragArea::ignoreOldFinger()
704700 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
705701}
706702
703+/*
704+ A Rightwards DDA that is rotated 90 degrees clockwise should recognize gestures
705+ that are done downwards in scene coordinates. I.e. the gesture recognition direction
706+ should be in local coordinates, not scene coordinates.
707+ */
708+void tst_DirectionalDragArea::rotated()
709+{
710+ QQuickItem *baseItem = m_view->rootObject()->findChild<QQuickItem*>("baseItem");
711+ baseItem->setRotation(90.);
712+
713+ QQuickItem *rightwardsLauncher = m_view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
714+ Q_ASSERT(rightwardsLauncher != 0);
715+
716+ DirectionalDragArea *edgeDragArea =
717+ rightwardsLauncher->findChild<DirectionalDragArea*>("hpDragArea");
718+ Q_ASSERT(edgeDragArea != 0);
719+ edgeDragArea->setRecognitionTimer(fakeTimer);
720+ edgeDragArea->setTimeSource(fakeTimeSource);
721+
722+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
723+ QPointF touchPoint = initialTouchPos;
724+
725+ qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0f;
726+ QPointF dragDirectionVector(0.0f, 1.0f);
727+
728+ qreal movementStepDistance = edgeDragArea->distanceThreshold() * 0.1f;
729+ QPointF touchMovement = dragDirectionVector * movementStepDistance;
730+ int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
731+ int movementTimeStepMs = (edgeDragArea->compositionTime() * 1.5f) / totalMovementSteps;
732+
733+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
734+
735+ for (int i = 0; i < totalMovementSteps; ++i) {
736+ touchPoint += touchMovement;
737+ passTime(movementTimeStepMs);
738+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
739+ }
740+
741+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
742+
743+ QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
744+}
745+
746+void tst_DirectionalDragArea::sceneDistance()
747+{
748+ QQuickItem *baseItem = m_view->rootObject()->findChild<QQuickItem*>("baseItem");
749+ QFETCH(qreal, rotation);
750+ QFETCH(QPointF, dragDirectionVector);
751+ baseItem->setRotation(rotation);
752+
753+ QQuickItem *rightwardsLauncher = m_view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
754+ Q_ASSERT(rightwardsLauncher != 0);
755+
756+ DirectionalDragArea *edgeDragArea =
757+ rightwardsLauncher->findChild<DirectionalDragArea*>("hpDragArea");
758+ Q_ASSERT(edgeDragArea != 0);
759+ edgeDragArea->setRecognitionTimer(fakeTimer);
760+ edgeDragArea->setTimeSource(fakeTimeSource);
761+
762+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
763+ QPointF touchPoint = initialTouchPos;
764+
765+ qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0f;
766+
767+ qreal movementStepDistance = edgeDragArea->distanceThreshold() * 0.1f;
768+ QPointF touchMovement = dragDirectionVector * movementStepDistance;
769+ int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
770+ int movementTimeStepMs = (edgeDragArea->compositionTime() * 1.5f) / totalMovementSteps;
771+
772+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
773+
774+ for (int i = 0; i < totalMovementSteps; ++i) {
775+ touchPoint += touchMovement;
776+ passTime(movementTimeStepMs);
777+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
778+ }
779+
780+ qreal actualDragDistance = ((qreal)totalMovementSteps) * movementStepDistance;
781+
782+ // DirectionalDragArea::sceneDistance() must match the actual drag distance as the
783+ // drag was aligned with the gesture direction
784+ // NB: qFuzzyCompare(), used internally by QCOMPARE(), is broken.
785+ QVERIFY(qAbs(edgeDragArea->sceneDistance() - actualDragDistance) < 0.001);
786+
787+ QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
788+}
789+
790+void tst_DirectionalDragArea::sceneDistance_data()
791+{
792+ QTest::addColumn<qreal>("rotation");
793+ QTest::addColumn<QPointF>("dragDirectionVector");
794+
795+ QTest::newRow("not rotated") << 0. << QPointF(1., 0.);
796+ QTest::newRow("rotated by 90 degrees") << 90. << QPointF(0., 1.);
797+}
798+
799+/*
800+ Regression test for https://bugs.launchpad.net/unity8/+bug/1276122
801+
802+ The bug:
803+ If setting "enabled: false" while the DirectionalDragArea's (DDA) dragging
804+ property is true, the DDA stays in that state and doesn't recover any more.
805+*/
806+void tst_DirectionalDragArea::disabledWhileDragging()
807+{
808+ DirectionalDragArea *edgeDragArea =
809+ m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
810+ Q_ASSERT(edgeDragArea != 0);
811+ edgeDragArea->setRecognitionTimer(fakeTimer);
812+ edgeDragArea->setTimeSource(fakeTimeSource);
813+
814+ QPointF touchPoint = calculateInitialTouchPos(edgeDragArea);
815+
816+ qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0f;
817+ QPointF dragDirectionVector(1., 0.); // horizontal positive
818+
819+ qreal movementStepDistance = edgeDragArea->distanceThreshold() * 0.1f;
820+ QPointF touchMovement = dragDirectionVector * movementStepDistance;
821+ int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
822+ int movementTimeStepMs = (edgeDragArea->compositionTime() * 1.5f) / totalMovementSteps;
823+
824+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
825+
826+ for (int i = 0; i < totalMovementSteps; ++i) {
827+ touchPoint += touchMovement;
828+ passTime(movementTimeStepMs);
829+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
830+ }
831+
832+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
833+ QCOMPARE(edgeDragArea->dragging(), true);
834+
835+ // disable the dragArea while it's being dragged.
836+ edgeDragArea->setEnabled(false);
837+
838+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
839+ QCOMPARE(edgeDragArea->dragging(), false);
840+
841+ QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
842+}
843+
707844QTEST_MAIN(tst_DirectionalDragArea)
708845
709846#include "tst_DirectionalDragArea.moc"