From 83a16630c13969e68cd3a5aaab73335ccb0d4414 Mon Sep 17 00:00:00 2001 From: Aaron McCarthy Date: Wed, 18 Feb 2015 15:53:09 +1000 Subject: Handle TouchCancel events in QQuickPinchArea QQuickPinchArea did not handle TouchCancel events and would recursively call QQuickItem::event(). Cancel the pinch gesture by restoring the pinch state to the start state. Don't recursively call QQuickItem::event(), instead call QQuickItem::touchEvent() for unhandled touch events. [ChangeLog][QtQuick][PinchArea] Fix infinite recursion when TouchCancel events are received. Change-Id: Ifce4af91aec4285873cb701069e007bcee180851 Reviewed-by: Martin Jones --- .../quick/qquickpincharea/tst_qquickpincharea.cpp | 64 ++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'tests/auto/quick/qquickpincharea') diff --git a/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp index 3d5dcaaaaf..8063453993 100644 --- a/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp +++ b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp @@ -54,6 +54,7 @@ private slots: void scale(); void pan(); void retouch(); + void cancel(); void transformedPinchArea_data(); void transformedPinchArea(); @@ -421,6 +422,69 @@ void tst_QQuickPinchArea::retouch() } } +void tst_QQuickPinchArea::cancel() +{ + QQuickView *window = createView(); + QScopedPointer scope(window); + window->setSource(testFileUrl("pinchproperties.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + QVERIFY(window->rootObject() != 0); + qApp->processEvents(); + + QQuickPinchArea *pinchArea = window->rootObject()->findChild("pincharea"); + QQuickPinch *pinch = pinchArea->pinch(); + QVERIFY(pinchArea != 0); + QVERIFY(pinch != 0); + + QQuickItem *root = qobject_cast(window->rootObject()); + QVERIFY(root != 0); + + // target + QQuickItem *blackRect = window->rootObject()->findChild("blackrect"); + QVERIFY(blackRect != 0); + + QPoint p1(80, 80); + QPoint p2(100, 100); + { + QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device); + pinchSequence.press(0, p1, window).commit(); + QQuickTouchUtils::flush(window); + // In order for the stationary point to remember its previous position, + // we have to reuse the same pinchSequence object. Otherwise if we let it + // be destroyed and then start a new sequence, point 0 will default to being + // stationary at 0, 0, and PinchArea will filter out that touchpoint because + // it is outside its bounds. + pinchSequence.stationary(0).press(1, p2, window).commit(); + QQuickTouchUtils::flush(window); + p1 -= QPoint(10,10); + p2 += QPoint(10,10); + pinchSequence.move(0, p1,window).move(1, p2,window).commit(); + QQuickTouchUtils::flush(window); + + QCOMPARE(root->property("scale").toReal(), 1.0); + QVERIFY(root->property("pinchActive").toBool()); + + p1 -= QPoint(10,10); + p2 += QPoint(10,10); + pinchSequence.move(0, p1,window).move(1, p2,window).commit(); + QQuickTouchUtils::flush(window); + + QCOMPARE(root->property("scale").toReal(), 1.5); + QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50 + QCOMPARE(blackRect->scale(), 1.5); + + QTouchEvent cancelEvent(QEvent::TouchCancel); + QCoreApplication::sendEvent(window, &cancelEvent); + QQuickTouchUtils::flush(window); + + QCOMPARE(root->property("scale").toReal(), 1.0); + QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50 + QCOMPARE(blackRect->scale(), 1.0); + QVERIFY(!root->property("pinchActive").toBool()); + } +} + void tst_QQuickPinchArea::transformedPinchArea_data() { QTest::addColumn("p1"); -- cgit v1.2.3