aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Belyavsky <[email protected]>2024-10-24 16:22:18 +0300
committerShawn Rutledge <[email protected]>2024-10-26 10:52:39 +0200
commit49fbf2f86afa62b8c1c2be330620a0b310584a34 (patch)
treee8ea2d10a9c5f8d8c69337cc1c744d2d526246ec
parent27ee3aa4403c7e3f3d189220228876690eb4308b (diff)
PinchHandler: Set target properties only if respective axis enabled
If the user has disabled the rotation or scale axis, the target item's rotation or scale property must not be set at all, to avoid breaking bindings that were set differently. Fixes: QTBUG-130517 Pick-to: 6.8 6.5 Change-Id: I8f84f6845532f748bbdcc3af91a398d6659156ca Reviewed-by: Richard Moe Gustavsen <[email protected]>
-rw-r--r--src/quick/handlers/qquickpinchhandler.cpp12
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp96
2 files changed, 77 insertions, 31 deletions
diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp
index 64a571a999..fa790ecfa5 100644
--- a/src/quick/handlers/qquickpinchhandler.cpp
+++ b/src/quick/handlers/qquickpinchhandler.cpp
@@ -697,9 +697,17 @@ void QQuickPinchHandler::handlePointerEventImpl(QPointerEvent *event)
m_xAxis.updateValue(activeTranslation.x(), m_xAxis.persistentValue() + delta.x(), delta.x());
m_yAxis.updateValue(activeTranslation.y(), m_yAxis.persistentValue() + delta.y(), delta.y());
emit translationChanged(delta);
+ // xAxis or yAxis may be disabled; nevertheless, we use setPosition() to compensate for
+ // other aspects of the transform. So it should not be skipped. Above, we've already
+ // subtracted activeTranslation if necessary.
t->setPosition(pos);
- t->setRotation(m_rotationAxis.persistentValue());
- t->setScale(m_scaleAxis.persistentValue());
+ // Set rotation and scale properties only if the respective axes are enabled.
+ // We've already checked above, so we don't expect activeScale or activeRotation to change
+ // if the axis is disabled; but then don't call the setter at all, to avoid breaking bindings.
+ if (m_rotationAxis.enabled())
+ t->setRotation(m_rotationAxis.persistentValue());
+ if (m_scaleAxis.enabled())
+ t->setScale(m_scaleAxis.persistentValue());
} else {
auto activeTranslation = centroid().scenePosition() - centroid().scenePressPosition();
auto accumulated = QPointF(m_xAxis.m_startValue, m_yAxis.m_startValue) + activeTranslation;
diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp
index 350dfeff88..4c171cdfac 100644
--- a/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp
@@ -217,14 +217,17 @@ 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;
+ QTest::addColumn<bool>("axisEnabled");
+ QTest::newRow("targetModifying") << testFileUrl("pinchproperties.qml") << true << true;
+ QTest::newRow("nullTarget") << testFileUrl("nullTarget.qml") << false << true;
+ QTest::newRow("axisDiabled") << testFileUrl("pinchproperties.qml") << true << false;
}
void tst_QQuickPinchHandler::scale()
{
QFETCH(QUrl, qmlfile);
QFETCH(bool, hasTarget);
+ QFETCH(bool, axisEnabled);
QQuickView window;
QVERIFY(QQuickTest::showView(window, qmlfile));
@@ -232,6 +235,7 @@ void tst_QQuickPinchHandler::scale()
QVERIFY(root != nullptr);
auto *pinchHandler = static_cast<PinchHandler *>(root->findChild<QQuickPinchHandler*>());
QVERIFY(pinchHandler != nullptr);
+ pinchHandler->scaleAxis()->setEnabled(axisEnabled);
QQuickItem *blackRect = (hasTarget ? pinchHandler->target() : pinchHandler->parentItem());
QVERIFY(blackRect != nullptr);
QSignalSpy grabChangedSpy(pinchHandler, SIGNAL(grabChanged(QPointingDevice::GrabTransition,QEventPoint)));
@@ -271,10 +275,13 @@ void tst_QQuickPinchHandler::scale()
QCOMPARE(grabChangedSpy.size(), 3);
QLineF line(p0, p1);
const qreal startLength = line.length();
+ // to be redefined below
+ qreal lastScale = pinchHandler->persistentScale();
+ qreal expectedIncrement = 0;
// move the same point even further and observe the change in scale
for (int i = 0; i < 2; ++i) {
- qreal lastScale = pinchHandler->activeScale();
+ lastScale = pinchHandler->activeScale();
p1 += pd;
pinchSequence.stationary(0).move(1, p1, &window).commit();
QQuickTouchUtils::flush(&window);
@@ -284,21 +291,27 @@ void tst_QQuickPinchHandler::scale()
qCDebug(lcPointerTests) << "pinchScale" << root->property("pinchScale").toReal()
<< "expected" << expectedScale << "; target scale" << blackRect->scale()
<< "increments" << scaleChangedSpy.size()
- << "multiplier" << scaleChangedSpy.last().first().toReal();
- QVERIFY(qFloatDistance(root->property("pinchScale").toReal(), expectedScale) < 10);
- QVERIFY(qFloatDistance(blackRect->scale(), expectedScale) < 10);
+ << "multiplier" << (scaleChangedSpy.isEmpty() ? 1 : scaleChangedSpy.last().first().toReal());
+ if (axisEnabled) {
+ QVERIFY(qFloatDistance(root->property("pinchScale").toReal(), expectedScale) < 10);
+ QVERIFY(qFloatDistance(blackRect->scale(), expectedScale) < 10);
+ } else {
+ QCOMPARE(root->property("pinchScale").toInt(), 1);
+ QCOMPARE(blackRect->scale(), 1);
+ }
QCOMPARE(pinchHandler->persistentScale(), root->property("pinchScale").toReal());
QCOMPARE(pinchHandler->persistentScale(), pinchHandler->activeScale()); // in sync for the first gesture
QCOMPARE(pinchHandler->scaleAxis()->persistentValue(), pinchHandler->activeScale());
QCOMPARE(pinchHandler->scaleAxis()->activeValue(), pinchHandler->activeScale());
- const qreal expectedIncrement = pinchHandler->activeScale() / lastScale;
- QCOMPARE(scaleChangedSpy.size(), i + 1);
- QCOMPARE(scaleChangedSpy.last().first().toReal(), expectedIncrement);
+ expectedIncrement = pinchHandler->activeScale() / lastScale;
+ QCOMPARE(scaleChangedSpy.size(), axisEnabled ? i + 1 : 0);
+ if (axisEnabled)
+ QCOMPARE(scaleChangedSpy.last().first().toReal(), expectedIncrement);
QPointF expectedCentroid = p0 + (p1 - p0) / 2;
QCOMPARE(pinchHandler->centroid().scenePosition(), expectedCentroid);
}
- qreal lastScale = pinchHandler->persistentScale();
+ lastScale = pinchHandler->persistentScale();
pinchSequence.release(0, p0, &window).release(1, p1, &window).commit();
QQuickTouchUtils::flush(&window);
if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
@@ -328,21 +341,29 @@ void tst_QQuickPinchHandler::scale()
pinchSequence.stationary(0).move(1, p1, &window).commit();
QQuickTouchUtils::flush(&window);
if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
- QCOMPARE_GT(pinchHandler->persistentScale(), lastScale);
+ if (axisEnabled)
+ QCOMPARE_GT(pinchHandler->persistentScale(), lastScale);
+ else
+ QCOMPARE(pinchHandler->persistentScale(), 1);
line.setP2(p1);
qreal expectedActiveScale = line.length() / startLength;
qCDebug(lcPointerTests) << i << "activeScale" << pinchHandler->activeScale()
<< "expected" << expectedActiveScale << "; scale" << pinchHandler->persistentScale()
<< "increments" << scaleChangedSpy.size()
- << "multiplier" << scaleChangedSpy.last().first().toReal();
- QVERIFY(qFloatDistance(pinchHandler->activeScale(), expectedActiveScale) < 10);
+ << "multiplier" << (scaleChangedSpy.isEmpty() ? 1 : scaleChangedSpy.last().first().toReal());
+ if (axisEnabled) {
+ QVERIFY(qFloatDistance(pinchHandler->activeScale(), expectedActiveScale) < 10);
+ QCOMPARE_NE(pinchHandler->persistentScale(), pinchHandler->activeScale()); // not in sync anymore
+ } else {
+ QCOMPARE(pinchHandler->persistentScale(), pinchHandler->activeScale());
+ }
QCOMPARE(pinchHandler->persistentScale(), root->property("pinchScale").toReal());
QCOMPARE(pinchHandler->scaleAxis()->persistentValue(), root->property("pinchScale").toReal());
- QCOMPARE_NE(pinchHandler->persistentScale(), pinchHandler->activeScale()); // not in sync anymore
QCOMPARE(pinchHandler->scaleAxis()->activeValue(), pinchHandler->activeScale());
- const qreal expectedIncrement = pinchHandler->persistentScale() / lastScale;
- QCOMPARE(scaleChangedSpy.size(), i + 3);
- QCOMPARE(scaleChangedSpy.last().first().toReal(), expectedIncrement);
+ expectedIncrement = pinchHandler->persistentScale() / lastScale;
+ QCOMPARE(scaleChangedSpy.size(), axisEnabled ? i + 3 : 0);
+ if (axisEnabled)
+ QCOMPARE(scaleChangedSpy.last().first().toReal(), expectedIncrement);
}
// scale beyond maximumScale
@@ -351,12 +372,13 @@ void tst_QQuickPinchHandler::scale()
pinchSequence.stationary(0).move(1, p1, &window).commit();
QQuickTouchUtils::flush(&window);
if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
- QCOMPARE(blackRect->scale(), qreal(4));
- QCOMPARE(pinchHandler->persistentScale(), qreal(4)); // limited by maximumScale
- QCOMPARE(pinchHandler->scaleAxis()->persistentValue(), 4);
- const qreal expectedIncrement = pinchHandler->activeScale() / lastScale;
- QCOMPARE(scaleChangedSpy.size(), 5);
- QCOMPARE(scaleChangedSpy.last().first().toReal(), expectedIncrement);
+ QCOMPARE(blackRect->scale(), axisEnabled ? 4 : 1);
+ QCOMPARE(pinchHandler->persistentScale(), axisEnabled ? 4 : 1); // limited by maximumScale
+ QCOMPARE(pinchHandler->scaleAxis()->persistentValue(), axisEnabled ? 4 : 1);
+ expectedIncrement = pinchHandler->activeScale() / lastScale;
+ QCOMPARE(scaleChangedSpy.size(), axisEnabled ? 5 : 0);
+ if (axisEnabled)
+ QCOMPARE(scaleChangedSpy.last().first().toReal(), expectedIncrement);
pinchSequence.release(0, p0, &window).release(1, p1, &window).commit();
QQuickTouchUtils::flush(&window);
QCOMPARE(pinchHandler->active(), false);
@@ -559,19 +581,25 @@ void tst_QQuickPinchHandler::cumulativeNativeGestures_data()
QTest::addColumn<const QPointingDevice*>("device");
QTest::addColumn<Qt::NativeGestureType>("gesture");
QTest::addColumn<qreal>("value");
+ QTest::addColumn<bool>("scalingEnabled");
+ QTest::addColumn<bool>("rotationEnabled");
QTest::addColumn<QList<QPoint>>("expectedTargetTranslations");
const auto *touchpadDevice = touchpad.get();
const auto *mouse = QPointingDevice::primaryPointingDevice();
- QTest::newRow("touchpad: rotate") << touchpadDevice << Qt::RotateNativeGesture << 5.0
+ QTest::newRow("touchpad: rotate") << touchpadDevice << Qt::RotateNativeGesture << 5.0 << true << true
<< QList<QPoint>{{-2, 2}, {-5, 4}, {-7, 6}, {-10, 7}};
- QTest::newRow("touchpad: scale") << touchpadDevice << Qt::ZoomNativeGesture << 0.1
+ QTest::newRow("touchpad: scale") << touchpadDevice << Qt::ZoomNativeGesture << 0.1 << true << true
+ << QList<QPoint>{{3, 3}, {5, 5}, {8, 8}, {12, 12}};
+ QTest::newRow("touchpad: rotate disabled") << touchpadDevice << Qt::RotateNativeGesture << 5.0 << true << false
+ << QList<QPoint>{{-2, 2}, {-5, 4}, {-7, 6}, {-10, 7}};
+ QTest::newRow("touchpad: scale disabled") << touchpadDevice << Qt::ZoomNativeGesture << 0.1 << false << true
<< QList<QPoint>{{3, 3}, {5, 5}, {8, 8}, {12, 12}};
if (mouse->type() == QInputDevice::DeviceType::Mouse) {
- QTest::newRow("mouse: rotate") << mouse << Qt::RotateNativeGesture << 5.0
+ QTest::newRow("mouse: rotate") << mouse << Qt::RotateNativeGesture << 5.0 << true << true
<< QList<QPoint>{{-2, 2}, {-5, 4}, {-7, 6}, {-10, 7}};
- QTest::newRow("mouse: scale") << mouse << Qt::ZoomNativeGesture << 0.1
+ QTest::newRow("mouse: scale") << mouse << Qt::ZoomNativeGesture << 0.1 << true << true
<< QList<QPoint>{{3, 3}, {5, 5}, {8, 8}, {12, 12}};
} else {
qCWarning(lcPointerTests) << "skipping mouse tests: primary device is not a mouse" << mouse;
@@ -583,6 +611,8 @@ void tst_QQuickPinchHandler::cumulativeNativeGestures()
QFETCH(const QPointingDevice*, device);
QFETCH(Qt::NativeGestureType, gesture);
QFETCH(qreal, value);
+ QFETCH(bool, scalingEnabled);
+ QFETCH(bool, rotationEnabled);
QFETCH(QList<QPoint>, expectedTargetTranslations);
QCOMPARE(expectedTargetTranslations.size(), 4);
@@ -596,6 +626,8 @@ void tst_QQuickPinchHandler::cumulativeNativeGestures()
QVERIFY(root != nullptr);
QQuickPinchHandler *pinchHandler = root->findChild<QQuickPinchHandler*>("pinchHandler");
QVERIFY(pinchHandler != nullptr);
+ pinchHandler->scaleAxis()->setEnabled(scalingEnabled);
+ pinchHandler->rotationAxis()->setEnabled(rotationEnabled);
QQuickItem *target = root->findChild<QQuickItem*>("blackrect");
QVERIFY(target != nullptr);
QCOMPARE(pinchHandler->target(), target);
@@ -622,6 +654,10 @@ void tst_QQuickPinchHandler::cumulativeNativeGestures()
default:
break; // PinchHandler doesn't react to the others
}
+ if (!rotationEnabled)
+ expectedRotation = 0;
+ if (!scalingEnabled)
+ expectedScale = 1;
qCDebug(lcPointerTests) << i << gesture << "with value" << value
<< ": scale" << target->scale() << "expected" << expectedScale
@@ -643,8 +679,10 @@ void tst_QQuickPinchHandler::cumulativeNativeGestures()
qCDebug(lcPointerTests) << "target moved by" << delta << "to" << target->position()
<< "active trans" << pinchHandler->activeTranslation()
<< "perst trans" << pinchHandler->persistentTranslation();
- QCOMPARE_NE(target->position(), initialTargetPos);
- QCOMPARE(delta.toPoint(), expectedTargetTranslations.at(i - 1));
+ if (scalingEnabled && rotationEnabled) {
+ QCOMPARE_NE(target->position(), initialTargetPos);
+ QCOMPARE(delta.toPoint(), expectedTargetTranslations.at(i - 1));
+ }
// The native pinch gesture cannot include a translation component (and
// the cursor doesn't move while you are performing the gesture on a touchpad).
QCOMPARE(pinchHandler->activeTranslation(), QPointF());