diff options
author | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2022-05-06 17:46:37 +0200 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2022-05-28 15:37:12 +0200 |
commit | 375e4003902e56e1cfd4192cee47566161b7b32d (patch) | |
tree | 11847fb62455231f592ac25fde744bfe1997b174 /tests | |
parent | 6d2d4914f884fc1a88382ba5cb6eeeeab272874e (diff) |
Implement support for passive grabbers with mouse/touch events
Send mouse and touch events through passive grabbers.
With support for passive grabbers, the drawer can now make itself a
passive grabber for the mouse when it is pressed inside the margin
area. It will then see the update events that are delivered to the
exclusive grabber, and can try to grab the mouse when the e.g. move
has progressed enough. Then the earlier grabber gets an ungrab event
that allows it to cancel the action.
Done-with: Doris Verria <doris.verria@qt.io>
Fixes: QTBUG-59141
Change-Id: Ie8e79c2ec2aa1f5a00056f23856bd0bed19af2d6
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/quick/qquickdeliveryagent/data/passiveGrabberItem.qml | 34 | ||||
-rw-r--r-- | tests/auto/quick/qquickdeliveryagent/tst_qquickdeliveryagent.cpp | 129 |
2 files changed, 163 insertions, 0 deletions
diff --git a/tests/auto/quick/qquickdeliveryagent/data/passiveGrabberItem.qml b/tests/auto/quick/qquickdeliveryagent/data/passiveGrabberItem.qml new file mode 100644 index 0000000000..71e0ac8989 --- /dev/null +++ b/tests/auto/quick/qquickdeliveryagent/data/passiveGrabberItem.qml @@ -0,0 +1,34 @@ +import QtQuick + +import Test + +Item { + width: 320 + height: 240 + property alias exclusiveGrabber: exGrabber + property alias passiveGrabber: psGrabber + ExclusiveGrabber { + id: exGrabber + width: parent.width + height: 30 + color: "blue" + anchors.verticalCenter: parent.verticalCenter + Text { + anchors.centerIn: parent + text: "Exclusive Grabber" + } + } + PassiveGrabber { + id: psGrabber + width: parent.width * 0.3 + height: parent.height + color: "yellow" + opacity: 0.5 + Text { + anchors.centerIn: parent + text: "Passive Grabber" + rotation: 90 + } + } +} + diff --git a/tests/auto/quick/qquickdeliveryagent/tst_qquickdeliveryagent.cpp b/tests/auto/quick/qquickdeliveryagent/tst_qquickdeliveryagent.cpp index ac00cfede7..cd6eb3a93c 100644 --- a/tests/auto/quick/qquickdeliveryagent/tst_qquickdeliveryagent.cpp +++ b/tests/auto/quick/qquickdeliveryagent/tst_qquickdeliveryagent.cpp @@ -34,6 +34,7 @@ #include <QtQuick/QQuickItem> #include <QtQuick/QQuickView> #include <QtQuick/QQuickWindow> +#include <QtQuick/private/qquickrectangle_p.h> #include <QtQuick/private/qquickflickable_p.h> #include <QtQuick/private/qquickpointhandler_p.h> #include <QtQuick/private/qquickshadereffectsource_p.h> @@ -153,6 +154,7 @@ public: private slots: void passiveGrabberOrder(); + void passiveGrabberItems(); void tapHandlerDoesntOverrideSubsceneGrabber(); void touchCompression(); void hoverPropagation_nested_data(); @@ -216,6 +218,133 @@ void tst_qquickdeliveryagent::passiveGrabberOrder() QCOMPARE(spy.senders.last(), rootTap); } +class PassiveGrabberItem : public QQuickRectangle +{ +public: + PassiveGrabberItem(QQuickItem *parent = nullptr) : QQuickRectangle(parent) { + setAcceptedMouseButtons(Qt::LeftButton); + } + void mousePressEvent(QMouseEvent *event) override { + qCDebug(lcTests) << "Passive grabber pressed"; + lastPressed = true; + event->addPassiveGrabber(event->point(0), this); + event->ignore(); + } + void mouseMoveEvent(QMouseEvent *event) override { + qCDebug(lcTests) << "Mouse move handled by passive grabber"; + const QPointF pos = event->scenePosition(); + const int threshold = 20; + bool overThreshold = pos.x() >= threshold; + if (overThreshold) { + event->setExclusiveGrabber(event->point(0), this); + this->setKeepMouseGrab(true); + event->accept(); + } else { + event->ignore(); + } + } + void mouseReleaseEvent(QMouseEvent *event) override { + qCDebug(lcTests) << "Passive grabber released"; + lastPressed = false; + event->ignore(); + } + + bool lastPressed = false; +}; + +class ExclusiveGrabberItem : public QQuickRectangle +{ +public: + ExclusiveGrabberItem(QQuickItem *parent = nullptr) : QQuickRectangle(parent) { + setAcceptedMouseButtons(Qt::LeftButton); + } + void mousePressEvent(QMouseEvent *event) override { + qCDebug(lcTests) << "Exclusive grabber pressed"; + lastPressed = true; + event->accept(); + } + void mouseMoveEvent(QMouseEvent *event) override { + event->accept(); + } + void mouseReleaseEvent(QMouseEvent *event) override { + qCDebug(lcTests) << "Exclusive grabber released"; + lastPressed = false; + event->accept(); + } + void mouseUngrabEvent() override { + qCDebug(lcTests) << "Exclusive grab ended"; + ungrabbed = true; + } + + bool lastPressed = false; + bool ungrabbed = false; +}; + +void tst_qquickdeliveryagent::passiveGrabberItems() +{ + QQuickView view; + QQmlComponent component(view.engine()); + qmlRegisterType<PassiveGrabberItem>("Test", 1, 0, "PassiveGrabber"); + qmlRegisterType<ExclusiveGrabberItem>("Test", 1, 0, "ExclusiveGrabber"); + component.loadUrl(testFileUrl("passiveGrabberItem.qml")); + view.setContent(QUrl(), &component, component.create()); + QQuickItem *root = qobject_cast<QQuickItem*>(view.rootObject()); + QVERIFY(root); + ExclusiveGrabberItem *exclusiveGrabber = root->property("exclusiveGrabber").value<ExclusiveGrabberItem*>(); + PassiveGrabberItem *passiveGrabber = root->property("passiveGrabber").value<PassiveGrabberItem *>(); + QVERIFY(exclusiveGrabber); + QVERIFY(passiveGrabber); + + view.show(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, QPoint(exclusiveGrabber->x() + 1, exclusiveGrabber->y() + 1)); + auto devPriv = QPointingDevicePrivate::get(QPointingDevice::primaryPointingDevice()); + const auto &persistentPoint = devPriv->activePoints.values().first(); + QTRY_COMPARE(persistentPoint.passiveGrabbers.count(), 1); + QCOMPARE(persistentPoint.passiveGrabbers.first(), passiveGrabber); + QCOMPARE(persistentPoint.exclusiveGrabber, exclusiveGrabber); + QVERIFY(exclusiveGrabber->lastPressed); + QVERIFY(passiveGrabber->lastPressed); + + // Mouse move bigger than threshold -> passive grabber becomes exclusive grabber + QTest::mouseMove(&view); + QTRY_COMPARE(persistentPoint.exclusiveGrabber, passiveGrabber); + QVERIFY(exclusiveGrabber->ungrabbed); + + QTest::mouseRelease(&view, Qt::LeftButton); + // Only the passive grabber got the release event + // since it became the exclusive grabber on mouseMove + QTRY_VERIFY(!passiveGrabber->lastPressed); + QVERIFY(exclusiveGrabber->lastPressed); + QCOMPARE(persistentPoint.passiveGrabbers.count(), 0); + QCOMPARE(persistentPoint.exclusiveGrabber, nullptr); + + exclusiveGrabber->lastPressed = false; + exclusiveGrabber->ungrabbed = false; + passiveGrabber->lastPressed = false; + + QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, QPoint(exclusiveGrabber->x() + 1, exclusiveGrabber->y() + 1)); + const auto &pressedPoint = devPriv->activePoints.values().first(); + QTRY_COMPARE(pressedPoint.passiveGrabbers.count(), 1); + QCOMPARE(pressedPoint.passiveGrabbers.first(), passiveGrabber); + QCOMPARE(pressedPoint.exclusiveGrabber, exclusiveGrabber); + QVERIFY(exclusiveGrabber->lastPressed); + QVERIFY(passiveGrabber->lastPressed); + + // Mouse move smaller than threshold -> grab remains with the exclusive grabber + QTest::mouseMove(&view, QPoint(exclusiveGrabber->x(), exclusiveGrabber->y())); + QTRY_COMPARE(pressedPoint.exclusiveGrabber, exclusiveGrabber); + + QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, QPoint(exclusiveGrabber->x(), exclusiveGrabber->y())); + + // Both the passive and the exclusive grabber get the mouseRelease event + QTRY_VERIFY(!passiveGrabber->lastPressed); + QVERIFY(!exclusiveGrabber->lastPressed); + QCOMPARE(pressedPoint.passiveGrabbers.count(), 0); + QCOMPARE(pressedPoint.exclusiveGrabber, nullptr); +} + void tst_qquickdeliveryagent::tapHandlerDoesntOverrideSubsceneGrabber() // QTBUG-94012 { QQuickView window; |