From a2e2c8a329768e783b205564e44b2f486b777d74 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 18 May 2017 11:23:25 +0200 Subject: Let passive-grabbing PointerHandlers see all point updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit even if all points are accepted or grabbed. A passive grab isn't much good if there are cases where the handler is prevented from monitoring. This enables e.g. the PinchHandler to steal the grab when the right number of touchpoints are present and have moved past the drag threshold, and enables completion of a couple of autotests. Change-Id: I78dc6fc585f80bfb3c13e0c6e757ef815fb94afe Reviewed-by: Jan Arve Sæther --- .../tst_multipointtoucharea_interop.cpp | 92 ++++++++++++++-------- .../qquickdraghandler/tst_qquickdraghandler.cpp | 9 +-- 2 files changed, 63 insertions(+), 38 deletions(-) (limited to 'tests/auto') diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp index c6990f5656..a2934eee32 100644 --- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp +++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp @@ -111,10 +111,10 @@ void tst_MptaInterop::touchDrag() QQuickTouchUtils::flush(window); auto pointerEvent = QQuickWindowPrivate::get(window)->pointerEventInstance(touchPointerDevice); QCOMPARE(tp.at(0)->property("pressed").toBool(), false); -// QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), mpta); + QTRY_VERIFY(pointerEvent->point(0)->passiveGrabbers().contains(drag)); // Start moving - // DragHandler gets keeps monitoring, due to its passive grab, + // DragHandler keeps monitoring, due to its passive grab, // and eventually steals the exclusive grab from MPTA int dragStoleGrab = 0; for (int i = 0; i < 4; ++i) { @@ -123,9 +123,9 @@ void tst_MptaInterop::touchDrag() QQuickTouchUtils::flush(window); if (!dragStoleGrab && pointerEvent->point(0)->exclusiveGrabber() == drag) dragStoleGrab = i; -// QCOMPARE(tp.at(0)->property("pressed").toBool(), !dragStoleGrab); } - qCDebug(lcPointerTests, "DragHandler stole the grab after %d events", dragStoleGrab); + if (dragStoleGrab) + qCDebug(lcPointerTests, "DragHandler stole the grab after %d events", dragStoleGrab); QVERIFY(dragStoleGrab > 1); touch.release(1, p1).commit(); @@ -150,6 +150,7 @@ void tst_MptaInterop::touchesThenPinch() QVERIFY(tp.at(3)); // the QML declares four touchpoints QSignalSpy mptaPressedSpy(mpta, SIGNAL(pressed(QList))); QSignalSpy mptaReleasedSpy(mpta, SIGNAL(released(QList))); + QSignalSpy mptaCanceledSpy(mpta, SIGNAL(canceled(QList))); QTest::QTouchEventSequence touch = QTest::touchEvent(window, touchDevice); auto pointerEvent = QQuickWindowPrivate::get(window)->pointerEventInstance(touchPointerDevice); @@ -162,7 +163,6 @@ void tst_MptaInterop::touchesThenPinch() QQuickTouchUtils::flush(window); QTRY_COMPARE(pointerEvent->point(0)->exclusiveGrabber(), nullptr); QTRY_COMPARE(pointerEvent->point(0)->passiveGrabbers().first(), drag); -// QTRY_VERIFY(tp.at(0)->property("pressed").toBool()); // Press a second touchpoint: MPTA grabs it QPoint p2 = mpta->mapToScene(QPointF(200, 30)).toPoint(); @@ -190,48 +190,59 @@ void tst_MptaInterop::touchesThenPinch() QCOMPARE(tp.at(1)->property("pressed").toBool(), false); QCOMPARE(tp.at(2)->property("pressed").toBool(), false); QCOMPARE(mptaPressedSpy.count(), 1); + QCOMPARE(mptaCanceledSpy.count(), 1); + QTRY_COMPARE(pointerEvent->point(0)->exclusiveGrabber(), pinch); + QTRY_COMPARE(pointerEvent->point(1)->exclusiveGrabber(), pinch); QTRY_COMPARE(pointerEvent->point(2)->exclusiveGrabber(), pinch); QVERIFY(pinch->active()); - // Move some more: PinchHandler reacts + // Start moving: PinchHandler steals the exclusive grab from MPTA as soon as dragThreshold is exceeded + int pinchStoleGrab = 0; for (int i = 0; i < 8; ++i) { - p1 += QPoint(4, 4); - p2 += QPoint(4, 4); - p3 += QPoint(-4, 4); + p1 += QPoint(dragThreshold / 2, dragThreshold / 2); + p2 += QPoint(dragThreshold / 2, dragThreshold / 2); + p3 += QPoint(-dragThreshold / 2, dragThreshold / 2); touch.move(1, p1).move(2, p2).move(3, p3).commit(); + QQuickTouchUtils::flush(window); QTRY_COMPARE(tp.at(0)->property("pressed").toBool(), false); QCOMPARE(tp.at(1)->property("pressed").toBool(), false); QCOMPARE(tp.at(2)->property("pressed").toBool(), false); + if (!pinchStoleGrab && pointerEvent->point(0)->exclusiveGrabber() == pinch) + pinchStoleGrab = i; } - qCDebug(lcPointerTests) << "scale" << pinch->scale() << "rot" << pinch->rotation(); - QTRY_VERIFY(pinch->rotation() > 10); + qCDebug(lcPointerTests) << "pinch started after" << pinchStoleGrab << "moves; ended with scale" << pinch->scale() << "rot" << pinch->rotation(); + QTRY_VERIFY(pinch->rotation() > 8); QVERIFY(pinch->scale() > 1); // Press one more point (pinkie finger) QPoint p4 = mpta->mapToScene(QPointF(300, 200)).toPoint(); - touch.stationary(1).stationary(2).stationary(3).press(4, p4).commit(); - // MPTA grabs p4 (which is at index 3) -// QTRY_COMPARE(pointerEvent->point(3)->exclusiveGrabber(), mpta); - // PinchHandler wantsPointerEvent declines, because it wants exactly 3 touchpoints, and there are now 4. - // Move some more... MPTA reacts, in spite of not grabbing all the points + touch.move(1, p1).move(2, p2).move(3, p3).press(4, p4).commit(); + // PinchHandler gives up its grabs (only on non-stationary points at this time: see QQuickPointerHandler::handlePointerEvent()) + // because it has minimum touch points 3, maximum touch points 3, and now there are 4 points. + // MPTA grabs all points which are not already grabbed + QTRY_COMPARE(pointerEvent->point(0)->exclusiveGrabber(), mpta); + QCOMPARE(pointerEvent->point(1)->exclusiveGrabber(), mpta); + QCOMPARE(pointerEvent->point(2)->exclusiveGrabber(), mpta); + QCOMPARE(pointerEvent->point(3)->exclusiveGrabber(), mpta); + // Move some more... MPTA keeps reacting for (int i = 0; i < 8; ++i) { p1 += QPoint(4, 4); p2 += QPoint(4, 4); p3 += QPoint(-4, 4); p4 += QPoint(-4, -4); touch.move(1, p1).move(2, p2).move(3, p3).move(4, p4).commit(); -// QTRY_COMPARE(pointerEvent->point(0)->exclusiveGrabber(), nullptr); -// QCOMPARE(pointerEvent->point(1)->exclusiveGrabber(), nullptr); -// QCOMPARE(pointerEvent->point(2)->exclusiveGrabber(), nullptr); -// QCOMPARE(pointerEvent->point(3)->exclusiveGrabber(), mpta); -// QCOMPARE(tp.at(0)->property("pressed").toBool(), true); -// QCOMPARE(tp.at(1)->property("pressed").toBool(), true); -// QCOMPARE(tp.at(2)->property("pressed").toBool(), true); -// QCOMPARE(tp.at(3)->property("pressed").toBool(), true); + QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), mpta); + QCOMPARE(pointerEvent->point(1)->exclusiveGrabber(), mpta); + QCOMPARE(pointerEvent->point(2)->exclusiveGrabber(), mpta); + QCOMPARE(pointerEvent->point(3)->exclusiveGrabber(), mpta); + QCOMPARE(tp.at(0)->property("pressed").toBool(), true); + QCOMPARE(tp.at(1)->property("pressed").toBool(), true); + QCOMPARE(tp.at(2)->property("pressed").toBool(), true); + QCOMPARE(tp.at(3)->property("pressed").toBool(), true); } - // Release the pinkie - touch.stationary(1).stationary(2).stationary(3).release(4, p4).commit(); + // Release the pinkie: PinchHandler acquires passive grabs on the 3 remaining points + touch.move(1, p1).move(2, p2).move(3, p3).release(4, p4).commit(); // Move some more: PinchHander grabs again, and reacts for (int i = 0; i < 8; ++i) { p1 -= QPoint(4, 4); @@ -239,21 +250,36 @@ void tst_MptaInterop::touchesThenPinch() p3 -= QPoint(-4, 4); touch.move(1, p1).move(2, p2).move(3, p3).commit(); QTRY_COMPARE(pointerEvent->point(0)->exclusiveGrabber(), pinch); + QCOMPARE(pointerEvent->point(1)->exclusiveGrabber(), pinch); + QCOMPARE(pointerEvent->point(2)->exclusiveGrabber(), pinch); } // Release the first finger touch.stationary(2).stationary(3).release(1, p1).commit(); - // Move some more: PinchHander isn't interested in a mere 2 points, and MPTA should react... but it doesn't (TODO?) + // Move some more: PinchHander isn't interested in a mere 2 points. + // MPTA could maybe react; but QQuickWindowPrivate::deliverTouchEvent() calls + // deliverPressOrReleaseEvent() in a way which "starts over" with event delivery + // only for handlers, not for Items; therefore MPTA is not visited at this time. for (int i = 0; i < 8; ++i) { - p1 -= QPoint(4, 4); - p2 += QPoint(4, 4); - touch.move(1, p1).move(2, p2).commit(); - QTest::qWait(100); + p2 -= QPoint(4, 4); + p3 += QPoint(4, 4); + touch.move(2, p2).move(3, p3).commit(); + QQuickTouchUtils::flush(window); + } + + // Release another finger + touch.stationary(2).release(3, p3).commit(); + // Move some more: DragHandler reacts. + // It had a passive grab this whole time; now it activates and gets an exclusive grab. + for (int i = 0; i < 8; ++i) { + p2 += QPoint(8, -8); + touch.move(2, p2).commit(); + QTRY_COMPARE(pointerEvent->point(0)->exclusiveGrabber(), drag); } - touch.release(1, p1).release(2, p2).release(3, p3).commit(); + touch.release(2, p2).commit(); QQuickTouchUtils::flush(window); -// QTRY_COMPARE(mptaReleasedSpy.count(), 1); // all points at once + QTRY_COMPARE(mptaReleasedSpy.count(), 1); } QTEST_MAIN(tst_MptaInterop) diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp index cd60be6a4c..8dc035949e 100644 --- a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp @@ -314,11 +314,10 @@ void tst_DragHandler::touchDragMultiSliders_data() 0 << QVector { 0, 1, 2 } << QVector { 0, 0, 0 } << QVector { {0, 60}, {0, 60}, {0, 60} }; QTest::newRow("Drag Knob: start on the knobs, drag diagonally downward") << 0 << QVector { 0, 1, 2 } << QVector { 0, 0, 0 } << QVector { {20, 40}, {20, 60}, {20, 80} }; - // TOOD these fail -// QTest::newRow("Drag Anywhere: start on the knobs, drag down") << -// 1 << QVector { 0, 1, 2 } << QVector { 0, 0, 0 } << QVector { {0, 60}, {0, 60}, {0, 60} }; -// QTest::newRow("Drag Anywhere: start on the knobs, drag diagonally downward") << -// 1 << QVector { 0, 1, 2 } << QVector { 0, 0, 0 } << QVector { {20, 40}, {20, 60}, {20, 80} }; + QTest::newRow("Drag Anywhere: start on the knobs, drag down") << + 1 << QVector { 0, 1, 2 } << QVector { 0, 0, 0 } << QVector { {0, 60}, {0, 60}, {0, 60} }; + QTest::newRow("Drag Anywhere: start on the knobs, drag diagonally downward") << + 1 << QVector { 0, 1, 2 } << QVector { 0, 0, 0 } << QVector { {20, 40}, {20, 60}, {20, 80} }; // TODO these next two fail because the DragHandler grabs when a finger // drags across it from outside, but should rather start only if it is pressed inside // QTest::newRow("Drag Knob: start above the knobs, drag down") << -- cgit v1.2.3