From bae1598c2a0db724626c5a8e37a5874f2a46354a Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 25 Mar 2021 22:48:20 +0100 Subject: DragHandler: don't try to handle native gesture events No gesture handling has been implemented in DragHandler (although we could). It just made the target item jump unintentionally. QQuickMultiPointHandler::wantsPointerEvent() returns true for gestures, because PinchHandler handles them, and the pattern is that base classes only rule out some kinds of events but leave the final decision up to the leaf class. The autotest has to use a touchpad now, not the primary pointing device, because QQuickPointerDeviceHandler::wantsPointerEvent() returns false if pointerType != Finger and acceptedButtons() is not satisfied. Fixes: QTBUG-92165 Change-Id: I984de750c9ae892f3ee61c7ed5b3ac4a7d187024 Reviewed-by: Richard Moe Gustavsen (cherry picked from commit 73051631545dc59d4419a5ef2202355349aab480) Reviewed-by: Shawn Rutledge Reviewed-by: Fabian Kosmale --- src/quick/handlers/qquickdraghandler.cpp | 13 +++++ src/quick/handlers/qquickdraghandler_p.h | 1 + .../qquickpinchhandler/data/pinchAndDrag.qml | 62 ++++++++++++++++++++++ .../qquickpinchhandler/tst_qquickpinchhandler.cpp | 52 +++++++++++------- 4 files changed, 108 insertions(+), 20 deletions(-) create mode 100644 tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchAndDrag.qml diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp index e5e9b03f32..980481303f 100644 --- a/src/quick/handlers/qquickdraghandler.cpp +++ b/src/quick/handlers/qquickdraghandler.cpp @@ -179,6 +179,19 @@ void QQuickDragHandler::onActiveChanged() } } +bool QQuickDragHandler::wantsPointerEvent(QPointerEvent *event) +{ + if (!QQuickMultiPointHandler::wantsPointerEvent(event)) + return false; + +#if QT_CONFIG(gestures) + if (event->type() == QEvent::NativeGesture) + return false; +#endif + + return true; +} + void QQuickDragHandler::handlePointerEventImpl(QPointerEvent *event) { QQuickMultiPointHandler::handlePointerEventImpl(event); diff --git a/src/quick/handlers/qquickdraghandler_p.h b/src/quick/handlers/qquickdraghandler_p.h index c1ff108e13..dfd0961b49 100644 --- a/src/quick/handlers/qquickdraghandler_p.h +++ b/src/quick/handlers/qquickdraghandler_p.h @@ -94,6 +94,7 @@ Q_SIGNALS: Q_REVISION(2, 14) void snapModeChanged(); protected: + bool wantsPointerEvent(QPointerEvent *event) override; void onActiveChanged() override; void onGrabChanged(QQuickPointerHandler *grabber, QPointingDevice::GrabTransition transition, QPointerEvent *event, QEventPoint &point) override; diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchAndDrag.qml b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchAndDrag.qml new file mode 100644 index 0000000000..2c75603261 --- /dev/null +++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchAndDrag.qml @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick + +Rectangle { + id: whiteRect + property real scale: -1.0 + property int activeCount : 0 + property int deactiveCount : 0 + width: 320; height: 320 + color: "white" + Rectangle { + id: blackRect + objectName: "blackrect" + color: "black" + y: 50 + x: 50 + width: 100 + height: 100 + Text { color: "white"; text: "opacity: " + blackRect.opacity + "\nscale: " + blackRect.scale} + Rectangle { + color: "red" + width: 6; height: 6; radius: 3 + visible: pincharea.active + x: pincharea.centroid.position.x - radius + y: pincharea.centroid.position.y - radius + } + + DragHandler { } + + PinchHandler { + id: pincharea + objectName: "pinchHandler" + } + } + } diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp index 3c46c415f6..6df672e4e8 100644 --- a/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp @@ -50,6 +50,7 @@ private slots: void pinchProperties(); void scale(); void scaleThreeFingers(); + void scaleNativeGesture_data(); void scaleNativeGesture(); void pan(); void dragAxesEnabled_data(); @@ -61,7 +62,8 @@ private slots: private: QQuickView *createView(); - QPointingDevice *device = QTest::createTouchDevice(); + QPointingDevice *touchscreen = QTest::createTouchDevice(); + QPointingDevice *touchpad = QTest::createTouchDevice(QInputDevice::DeviceType::TouchPad); }; void tst_QQuickPinchHandler::cleanupTestCase() @@ -220,7 +222,7 @@ void tst_QQuickPinchHandler::scale() QPoint p0(80, 80); QPoint p1(100, 100); { - QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device); + QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, touchscreen); pinchSequence.press(0, p0, window).commit(); QQuickTouchUtils::flush(window); // In order for the stationary point to remember its previous position, @@ -266,7 +268,7 @@ void tst_QQuickPinchHandler::scale() // scale beyond bound p1 += QPoint(20, 20); { - QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device); + QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, touchscreen); pinchSequence.stationary(0).move(1, p1, window).commit(); QQuickTouchUtils::flush(window); QCOMPARE(blackRect->scale(), qreal(4)); // qquickpinchhandler does not manipulate scale property @@ -301,7 +303,7 @@ void tst_QQuickPinchHandler::scaleThreeFingers() QPoint p1(220, 80); QPoint p2(150, 220); { - QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device); + QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, touchscreen); pinchSequence.press(0, p0, window).commit(); QQuickTouchUtils::flush(window); // In order for the stationary point to remember its previous position, @@ -354,11 +356,21 @@ void tst_QQuickPinchHandler::scaleThreeFingers() QCOMPARE(pinchHandler->active(), false); } +void tst_QQuickPinchHandler::scaleNativeGesture_data() +{ + QTest::addColumn("qmlfile"); + + QTest::newRow("just pinch") << "pinchproperties.qml"; + QTest::newRow("pinch & drag") << "pinchAndDrag.qml"; +} + void tst_QQuickPinchHandler::scaleNativeGesture() { + QFETCH(QString, qmlfile); + QQuickView *window = createView(); QScopedPointer scope(window); - window->setSource(testFileUrl("pinchproperties.qml")); + window->setSource(testFileUrl(qmlfile)); window->show(); QVERIFY(QTest::qWaitForWindowExposed(window)); QVERIFY(window->rootObject() != nullptr); @@ -382,9 +394,9 @@ void tst_QQuickPinchHandler::scaleNativeGesture() // so as to compensate for the change in size, to hold the centroid in place const QPointF expectedPos = targetPos + QPointF( (pinchPos.x() - target->x()) * (expectedScale - 1), (pinchPos.y() - target->y()) * (expectedScale - 1) ); - QWindowSystemInterface::handleGestureEvent(window, ts++, QPointingDevice::primaryPointingDevice(), + QWindowSystemInterface::handleGestureEvent(window, ts++, touchpad, Qt::BeginNativeGesture, pinchPos, pinchPos); - QWindowSystemInterface::handleGestureEventWithRealValue(window, ts++, QPointingDevice::primaryPointingDevice(), + QWindowSystemInterface::handleGestureEventWithRealValue(window, ts++, touchpad, Qt::ZoomNativeGesture, expectedScale - 1, pinchPos, pinchPos); QTRY_COMPARE(target->scale(), expectedScale); QCOMPARE(pinchHandler->active(), true); @@ -396,7 +408,7 @@ void tst_QQuickPinchHandler::scaleNativeGesture() QCOMPARE(pinchHandler->activeScale(), expectedScale); QCOMPARE(pinchHandler->translation(), QVector2D()); QCOMPARE(pinchHandler->rotation(), 0); - QWindowSystemInterface::handleGestureEvent(window, ts++, QPointingDevice::primaryPointingDevice(), + QWindowSystemInterface::handleGestureEvent(window, ts++, touchpad, Qt::EndNativeGesture, pinchPos, pinchPos); QTRY_COMPARE(pinchHandler->active(), false); QCOMPARE(target->scale(), expectedScale); @@ -409,9 +421,9 @@ void tst_QQuickPinchHandler::scaleNativeGesture() const qreal reverseScale = (1 / expectedScale); pinchPos = QPointF(125, 125); pinchLocalPos = target->mapFromScene(pinchPos); - QWindowSystemInterface::handleGestureEvent(window, ts++, QPointingDevice::primaryPointingDevice(), + QWindowSystemInterface::handleGestureEvent(window, ts++, touchpad, Qt::BeginNativeGesture, pinchPos, pinchPos); - QWindowSystemInterface::handleGestureEventWithRealValue(window, ts++, QPointingDevice::primaryPointingDevice(), + QWindowSystemInterface::handleGestureEventWithRealValue(window, ts++, touchpad, Qt::ZoomNativeGesture, reverseScale - 1, pinchPos, pinchPos); QTRY_COMPARE(target->scale(), 1); QCOMPARE(pinchHandler->active(), true); @@ -419,7 +431,7 @@ void tst_QQuickPinchHandler::scaleNativeGesture() QCOMPARE(pinchHandler->centroid().scenePosition(), pinchPos); QCOMPARE(pinchHandler->scale(), 1); QCOMPARE(pinchHandler->activeScale(), reverseScale); - QWindowSystemInterface::handleGestureEvent(window, ts++, QPointingDevice::primaryPointingDevice(), + QWindowSystemInterface::handleGestureEvent(window, ts++, touchpad, Qt::EndNativeGesture, pinchPos, pinchPos); QTRY_COMPARE(pinchHandler->active(), false); QCOMPARE(target->scale(), 1); @@ -451,7 +463,7 @@ void tst_QQuickPinchHandler::pan() QPoint p1(100, 100); { const int dragThreshold = QGuiApplication::styleHints()->startDragDistance(); - QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device); + QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, touchscreen); pinchSequence.press(0, p0, window).commit(); QQuickTouchUtils::flush(window); // In order for the stationary point to remember its previous position, @@ -517,13 +529,13 @@ void tst_QQuickPinchHandler::pan() // pan x beyond bound p0 += QPoint(100,100); p1 += QPoint(100,100); - QTest::touchEvent(window, device).move(0, p0, window).move(1, p1, window); + QTest::touchEvent(window, touchscreen).move(0, p0, window).move(1, p1, window); QQuickTouchUtils::flush(window); QCOMPARE(blackRect->x(), 140.0); QCOMPARE(blackRect->y(), 170.0); - QTest::touchEvent(window, device).release(0, p0, window).release(1, p1, window); + QTest::touchEvent(window, touchscreen).release(0, p0, window).release(1, p1, window); QQuickTouchUtils::flush(window); QVERIFY(!root->property("pinchActive").toBool()); } @@ -563,7 +575,7 @@ void tst_QQuickPinchHandler::dragAxesEnabled() QPoint blackRectPos = blackRect->position().toPoint(); // press two points, one above the rectangle's center and one below - QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device); + QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, touchscreen); pinchSequence.press(0, p0, window).press(1, p1, window).commit(); QQuickTouchUtils::flush(window); @@ -600,7 +612,7 @@ void tst_QQuickPinchHandler::dragAxesEnabled() QCOMPARE(blackRect->position().toPoint().x(), xEnabled ? 140 : blackRectPos.x()); // because of xAxis.maximum QCOMPARE(blackRect->position().toPoint().y(), yEnabled ? 170 : blackRectPos.y()); // because of yAxis.maximum - QTest::touchEvent(window, device).release(0, p0, window).release(1, p1, window); + QTest::touchEvent(window, touchscreen).release(0, p0, window).release(1, p1, window); QQuickTouchUtils::flush(window); } @@ -629,7 +641,7 @@ void tst_QQuickPinchHandler::retouch() QPoint p0(80, 80); QPoint p1(100, 100); { - QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device); + QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, touchscreen); pinchSequence.press(0, p0, window).commit(); QQuickTouchUtils::flush(window); // In order for the stationary point to remember its previous position, @@ -712,7 +724,7 @@ void tst_QQuickPinchHandler::cancel() QPoint p0(80, 80); QPoint p1(100, 100); { - QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device); + QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, touchscreen); pinchSequence.press(0, p0, window).commit(); QQuickTouchUtils::flush(window); // In order for the stationary point to remember its previous position, @@ -742,7 +754,7 @@ void tst_QQuickPinchHandler::cancel() QSKIP("cancel is not supported atm"); - QTouchEvent cancelEvent(QEvent::TouchCancel, device); + QTouchEvent cancelEvent(QEvent::TouchCancel, touchscreen); QCoreApplication::sendEvent(window, &cancelEvent); QQuickTouchUtils::flush(window); @@ -798,7 +810,7 @@ void tst_QQuickPinchHandler::transformedpinchHandler() const int threshold = qApp->styleHints()->startDragDistance(); { - QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(view, device); + QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(view, touchscreen); // start pinchHandler pinchSequence.press(0, p0, view).commit(); QQuickTouchUtils::flush(view); -- cgit v1.2.3