diff options
4 files changed, 133 insertions, 5 deletions
diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp index 467bedd3bf..2c8272301f 100644 --- a/src/quick/handlers/qquickpinchhandler.cpp +++ b/src/quick/handlers/qquickpinchhandler.cpp @@ -203,8 +203,8 @@ void QQuickPinchHandler::onActiveChanged() m_startRotation = t->rotation(); m_startPos = t->position(); } else { - m_startScale = 1; - m_startRotation = 0; + m_startScale = m_accumulatedScale; + m_startRotation = 0; // TODO m_accumulatedRotation (QTBUG-94168) } qCDebug(lcPinchHandler) << "activated with starting scale" << m_startScale << "rotation" << m_startRotation; } else { diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/nullTarget.qml b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/nullTarget.qml new file mode 100644 index 0000000000..a348938aca --- /dev/null +++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/nullTarget.qml @@ -0,0 +1,33 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick 2.15 + +Item { + width: 320; height: 320 + property alias pinchScale: pinch.scale + + Rectangle { + objectName: "blackrect" + width: 200; height: 200 + color: "black" + antialiasing: true + scale: pinch.scale + rotation: pinch.rotation + x: pinch.translation.x + y: pinch.translation.y + + PinchHandler { + id: pinch + target: null + minimumScale: 0.5 + maximumScale: 4 + } + + Text { + color: "cyan" + anchors.centerIn: parent + text: "scale " + pinch.scale.toFixed(2) + " activeScale " + pinch.activeScale.toFixed(2) + } + } +} diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp index 5ffc49f802..4104fea7e2 100644 --- a/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp @@ -29,6 +29,7 @@ public: private slots: void cleanupTestCase(); void pinchProperties(); + void scale_data(); void scale(); void scaleThreeFingers(); void scaleNativeGesture_data(); @@ -179,16 +180,26 @@ QEventPoint makeTouchPoint(int id, QPoint p, QQuickView *v, QQuickItem *i) return touchPoint; } +void tst_QQuickPinchHandler::scale_data() +{ + QTest::addColumn<QUrl>("qmlfile"); + QTest::addColumn<bool>("hasTarget"); + QTest::newRow("targetModifying") << testFileUrl("pinchproperties.qml") << true; + QTest::newRow("nullTarget") << testFileUrl("nullTarget.qml") << false; +} + void tst_QQuickPinchHandler::scale() { - QQuickView window; - QVERIFY(QQuickTest::showView(window, testFileUrl("pinchproperties.qml"))); + QFETCH(QUrl, qmlfile); + QFETCH(bool, hasTarget); + QQuickView window; + QVERIFY(QQuickTest::showView(window, qmlfile)); QQuickItem *root = qobject_cast<QQuickItem*>(window.rootObject()); QVERIFY(root != nullptr); auto *pinchHandler = static_cast<PinchHandler *>(root->findChild<QQuickPinchHandler*>()); QVERIFY(pinchHandler != nullptr); - QQuickItem *blackRect = pinchHandler->target(); + QQuickItem *blackRect = (hasTarget ? pinchHandler->target() : pinchHandler->parentItem()); QVERIFY(blackRect != nullptr); QSignalSpy grabChangedSpy(pinchHandler, SIGNAL(grabChanged(QPointingDevice::GrabTransition, QEventPoint))); @@ -240,6 +251,40 @@ void tst_QQuickPinchHandler::scale() QCOMPARE(pinchHandler->centroid().scenePosition(), expectedCentroid); } + qreal lastScale = pinchHandler->scale(); + pinchSequence.release(0, p0, &window).release(1, p1, &window).commit(); + QQuickTouchUtils::flush(&window); + if (lcPointerTests().isDebugEnabled()) QTest::qWait(500); + // scale property is persistent after release + QCOMPARE(pinchHandler->scale(), lastScale); + + // pinch a second time: scale picks up where we left off + p0 = QPoint(80, 80); + p1 = QPoint(100, 100); + pinchSequence.press(0, p0, &window).press(1, p1, &window).commit(); + // move one point until PinchHandler activates + for (int pi = 0; pi < 10 && !pinchHandler->active(); ++pi) { + p1 += pd; + pinchSequence.stationary(0).move(1, p1, &window).commit(); + QQuickTouchUtils::flush(&window); + } + if (lcPointerTests().isDebugEnabled()) QTest::qWait(500); + QCOMPARE(pinchHandler->active(), true); + QCOMPARE(pinchHandler->scale(), lastScale); // just activated, not scaling further yet + for (int i = 0; i < 2; ++i) { + lastScale = pinchHandler->scale(); + p1 += pd; + pinchSequence.stationary(0).move(1, p1, &window).commit(); + QQuickTouchUtils::flush(&window); + if (lcPointerTests().isDebugEnabled()) QTest::qWait(500); + QCOMPARE_GT(pinchHandler->scale(), lastScale); + line.setP2(p1); + qreal expectedActiveScale = line.length() / startLength; + QVERIFY(qFloatDistance(pinchHandler->activeScale(), expectedActiveScale) < 10); + QCOMPARE(pinchHandler->scale(), root->property("pinchScale").toReal()); + QCOMPARE_NE(pinchHandler->scale(), pinchHandler->activeScale()); // not in sync anymore + } + // scale beyond maximumScale p1 = QPoint(310, 310); pinchSequence.stationary(0).move(1, p1, &window).commit(); diff --git a/tests/manual/pointer/pinchNullTarget.qml b/tests/manual/pointer/pinchNullTarget.qml new file mode 100644 index 0000000000..79c6047991 --- /dev/null +++ b/tests/manual/pointer/pinchNullTarget.qml @@ -0,0 +1,50 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick 2.15 + +Rectangle { + width: 1024; height: 600 + color: "#eee" + + function getTransformationDetails(item, pinchhandler) { + return "\n\npinch.scale:" + pinchhandler.scale.toFixed(2) + + "\npinch.activeScale:" + pinchhandler.activeScale.toFixed(2) + + "\npinch.rotation:" + pinchhandler.rotation.toFixed(2) + + "\npinch.translation:" + "(" + pinchhandler.translation.x.toFixed(2) + "," + pinchhandler.translation.y.toFixed(2) + ")" + + "\nrect.scale: " + item.scale.toFixed(2) + + "\nrect.rotation: " + item.rotation.toFixed(2) + + "\nrect.position: " + "(" + item.x.toFixed(2) + "," + item.y.toFixed(2) + ")" + } + + Rectangle { + width: parent.width - 100; height: parent.height - 100; x: 50; y: 50 + color: "lightsteelblue" + antialiasing: true + scale: pinch.scale + + PinchHandler { + id: pinch + target: null + minimumScale: 0.5 + maximumScale: 3 + } + + Text { + text: "Pinch with 2 fingers to scale, rotate and translate" + + getTransformationDetails(parent, pinch) + } + } + + Rectangle { + id: centroidIndicator + x: pinch.centroid.scenePosition.x - radius + y: pinch.centroid.scenePosition.y - radius + z: 1 + visible: pinch.active + radius: width / 2 + width: 10 + height: width + color: "red" + } +} |