From 33eb0fc79d410263849ec0ba3c7971523210afc3 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 1 Sep 2022 07:23:44 +0200 Subject: PinchHandler: Enforce min/max scale limits with native gestures So far the qBound() using m_minimumScale and m_maximumScale was only applied for normal pointer events: there were no limits when using a touchpad that sends native gestures. Fixes: QTBUG-106110 Change-Id: Ibf8d955e5f1dac517e0a3e9588fb117d83f443a6 Reviewed-by: Fabian Kosmale (cherry picked from commit 5cb3ba93da2673b20abae8a544a961b7b57dff45) Reviewed-by: Qt Cherry-pick Bot --- src/quick/handlers/qquickpinchhandler.cpp | 1 + .../qquickpinchhandler/data/pinchproperties.qml | 2 +- .../qquickpinchhandler/tst_qquickpinchhandler.cpp | 43 +++++++++++++--------- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp index e275f7b377..5f36c11a95 100644 --- a/src/quick/handlers/qquickpinchhandler.cpp +++ b/src/quick/handlers/qquickpinchhandler.cpp @@ -272,6 +272,7 @@ void QQuickPinchHandler::handlePointerEventImpl(QPointerEvent *event) return; case Qt::ZoomNativeGesture: m_activeScale *= 1 + gesture->value(); + m_activeScale = qBound(m_minimumScale, m_activeScale, m_maximumScale); break; case Qt::RotateNativeGesture: m_activeRotation += gesture->value(); diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchproperties.qml b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchproperties.qml index 3cabde5f59..425494ced6 100644 --- a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchproperties.qml +++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchproperties.qml @@ -56,7 +56,7 @@ Rectangle { PinchHandler { id: pincharea objectName: "pinchHandler" - minimumScale: 1.0 + minimumScale: 0.5 maximumScale: 4.0 minimumRotation: 0.0 maximumRotation: 90.0 diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp index da84bb0a63..b064ffcf13 100644 --- a/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp @@ -154,19 +154,19 @@ void tst_QQuickPinchHandler::pinchProperties() QSignalSpy scaleMinSpy(pinchHandler, SIGNAL(minimumScaleChanged())); QSignalSpy scaleMaxSpy(pinchHandler, SIGNAL(maximumScaleChanged())); - QCOMPARE(pinchHandler->minimumScale(), 1.0); + QCOMPARE(pinchHandler->minimumScale(), 0.5); QCOMPARE(pinchHandler->maximumScale(), 4.0); - pinchHandler->setMinimumScale(0.5); + pinchHandler->setMinimumScale(0.25); pinchHandler->setMaximumScale(1.5); - QCOMPARE(pinchHandler->minimumScale(), 0.5); + QCOMPARE(pinchHandler->minimumScale(), 0.25); QCOMPARE(pinchHandler->maximumScale(), 1.5); QCOMPARE(scaleMinSpy.count(),1); QCOMPARE(scaleMaxSpy.count(),1); - pinchHandler->setMinimumScale(0.5); + pinchHandler->setMinimumScale(0.25); pinchHandler->setMaximumScale(1.5); QCOMPARE(scaleMinSpy.count(),1); @@ -373,14 +373,18 @@ void tst_QQuickPinchHandler::scaleThreeFingers() void tst_QQuickPinchHandler::scaleNativeGesture_data() { QTest::addColumn("qmlfile"); + QTest::addColumn("scale"); - QTest::newRow("just pinch") << "pinchproperties.qml"; - QTest::newRow("pinch & drag") << "pinchAndDrag.qml"; + QTest::newRow("just pinch") << "pinchproperties.qml" << 1.1; + QTest::newRow("pinch & drag") << "pinchAndDrag.qml" << 1.1; + QTest::newRow("bigger than limit") << "pinchproperties.qml" << 5.0; + QTest::newRow("smaller than limit") << "pinchproperties.qml" << 0.25; } void tst_QQuickPinchHandler::scaleNativeGesture() { QFETCH(QString, qmlfile); + QFETCH(qreal, scale); QQuickView *window = QQuickViewTestUtils::createView(); QScopedPointer scope(window); @@ -400,8 +404,8 @@ void tst_QQuickPinchHandler::scaleNativeGesture() QPointF targetPos = target->position(); ulong ts = 1; - // first pinch: scale it up - const qreal expectedScale = 1.1; + // first pinch: scale it + const qreal expectedScale = qBound(qreal(0.5), scale, qreal(4)); QPointF pinchPos(75, 75); QPointF pinchLocalPos = target->mapFromScene(pinchPos); // target position is adjusted in QQuickItemPrivate::adjustedPosForTransform() @@ -411,11 +415,11 @@ void tst_QQuickPinchHandler::scaleNativeGesture() QWindowSystemInterface::handleGestureEvent(window, ts++, touchpad, Qt::BeginNativeGesture, pinchPos, pinchPos); QWindowSystemInterface::handleGestureEventWithRealValue(window, ts++, touchpad, - Qt::ZoomNativeGesture, expectedScale - 1, pinchPos, pinchPos); + Qt::ZoomNativeGesture, scale - 1, pinchPos, pinchPos); QTRY_COMPARE(target->scale(), expectedScale); QCOMPARE(pinchHandler->active(), true); - QCOMPARE(pinchHandler->centroid().position(), pinchLocalPos); - QCOMPARE(pinchHandler->centroid().scenePosition(), pinchPos); + QCOMPARE(pinchHandler->centroid().position().toPoint(), pinchLocalPos.toPoint()); + QCOMPARE(pinchHandler->centroid().scenePosition().toPoint(), pinchPos.toPoint()); QVERIFY(qAbs(target->position().x() - expectedPos.x()) < 0.001); QVERIFY(qAbs(target->position().y() - expectedPos.y()) < 0.001); QCOMPARE(pinchHandler->scale(), expectedScale); @@ -431,9 +435,12 @@ void tst_QQuickPinchHandler::scaleNativeGesture() QCOMPARE(pinchHandler->translation(), QVector2D()); QCOMPARE(pinchHandler->rotation(), 0); - // second pinch at a different position: scale it down to original size again + // second pinch at a different position: scale it back to original size again + // but remove the limits first, so that we can scale arbitrarily + pinchHandler->setMaximumScale(qInf()); + pinchHandler->setMinimumScale(-qInf()); const qreal reverseScale = (1 / expectedScale); - pinchPos = QPointF(125, 125); + pinchPos = QPointF(110, 110); pinchLocalPos = target->mapFromScene(pinchPos); QWindowSystemInterface::handleGestureEvent(window, ts++, touchpad, Qt::BeginNativeGesture, pinchPos, pinchPos); @@ -441,8 +448,8 @@ void tst_QQuickPinchHandler::scaleNativeGesture() Qt::ZoomNativeGesture, reverseScale - 1, pinchPos, pinchPos); QTRY_COMPARE(target->scale(), 1); QCOMPARE(pinchHandler->active(), true); - QCOMPARE(pinchHandler->centroid().position(), pinchLocalPos); - QCOMPARE(pinchHandler->centroid().scenePosition(), pinchPos); + QCOMPARE(pinchHandler->centroid().position().toPoint(), pinchLocalPos.toPoint()); + QCOMPARE(pinchHandler->centroid().scenePosition().toPoint(), pinchPos.toPoint()); QCOMPARE(pinchHandler->scale(), 1); QCOMPARE(pinchHandler->activeScale(), reverseScale); QWindowSystemInterface::handleGestureEvent(window, ts++, touchpad, @@ -680,7 +687,7 @@ void tst_QQuickPinchHandler::retouch() // accept some slack QVERIFY(withinBounds(1.4, root->property("scale").toReal(), 1.6)); - QCOMPARE(pinchHandler->centroid().position(), QPointF(40, 40)); // blackrect is at 50,50 + QCOMPARE(pinchHandler->centroid().position().toPoint(), QPoint(40, 40)); // blackrect is at 50,50 QVERIFY(withinBounds(1.4, blackRect->scale(), 1.6)); QCOMPARE(root->property("activeCount").toInt(), 1); @@ -763,7 +770,7 @@ void tst_QQuickPinchHandler::cancel() QQuickTouchUtils::flush(window); QVERIFY(withinBounds(1.4, root->property("scale").toReal(), 1.6)); - QCOMPARE(pinchHandler->centroid().position(), QPointF(40, 40)); // blackrect is at 50,50 + QCOMPARE(pinchHandler->centroid().position().toPoint(), QPoint(40, 40)); // blackrect is at 50,50 QVERIFY(withinBounds(1.4, blackRect->scale(), 1.6)); QSKIP("cancel is not supported atm"); @@ -773,7 +780,7 @@ void tst_QQuickPinchHandler::cancel() QQuickTouchUtils::flush(window); QCOMPARE(root->property("scale").toReal(), 1.0); - QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50 + QCOMPARE(root->property("center").toPoint(), QPoint(40, 40)); // blackrect is at 50,50 QCOMPARE(blackRect->scale(), 1.0); QVERIFY(!root->property("pinchActive").toBool()); } -- cgit v1.2.3