aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quick/pointerhandlers/qquicktaphandler
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/quick/pointerhandlers/qquicktaphandler')
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/BLACKLIST8
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/CMakeLists.txt6
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml18
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/FlashAnimation.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml14
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/dragReleaseMenu.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/nested.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/nestedAndSibling.qml39
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/simpleTapHandler.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp380
12 files changed, 400 insertions, 77 deletions
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/BLACKLIST b/tests/auto/quick/pointerhandlers/qquicktaphandler/BLACKLIST
index d13d25390b..1559014480 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/BLACKLIST
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/BLACKLIST
@@ -1,11 +1,3 @@
-# QTBUG-95939
-[touchGesturePolicyDragThreshold]
-opensuse-leap
-
-# QTBUG-95939
-[mouseGesturePolicyDragThreshold]
-opensuse-leap
-
# QTBUG-103072
[gesturePolicyDragWithinBounds]
android
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/CMakeLists.txt b/tests/auto/quick/pointerhandlers/qquicktaphandler/CMakeLists.txt
index cab8fc1a0d..94834e04c6 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquicktaphandler Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquicktaphandler LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml
index fa58d76e4a..fc1e623902 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
@@ -10,13 +10,20 @@ Rectangle {
property alias pressed: tap.pressed
property bool checked: false
property alias gesturePolicy: tap.gesturePolicy
+ property alias longPressThreshold: tap.longPressThreshold
property point tappedPosition: Qt.point(0, 0)
+ property real timeHeldWhenTapped: 0
+ property real timeHeldWhenLongPressed: 0
signal tapped
signal canceled
width: label.implicitWidth * 1.5; height: label.implicitHeight * 2.0
border.color: "#9f9d9a"; border.width: 1; radius: height / 4; antialiasing: true
+ function assignUndefinedLongPressThreshold() {
+ tap.longPressThreshold = undefined
+ }
+
gradient: Gradient {
GradientStop { position: 0.0; color: tap.pressed ? "#b8b5b2" : "#efebe7" }
GradientStop { position: 1.0; color: "#b8b5b2" }
@@ -25,14 +32,17 @@ Rectangle {
TapHandler {
id: tap
objectName: label.text
- longPressThreshold: 100 // CI can be insanely slow, so don't demand a timely release to generate onTapped
onSingleTapped: console.log("Single tap")
onDoubleTapped: console.log("Double tap")
- onTapped: {
- console.log("Tapped")
+ onTapped: (eventPoint, button) => {
+ console.log("Tapped", button, eventPoint)
tapFlash.start()
root.tappedPosition = point.scenePosition
root.tapped()
+ root.timeHeldWhenTapped = tap.timeHeld // eventPoint.timeHeld is already 0
+ }
+ onLongPressed: {
+ root.timeHeldWhenLongPressed = tap.timeHeld
}
onCanceled: root.canceled()
}
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/FlashAnimation.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/FlashAnimation.qml
index e3f15f399f..9483a12d1c 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/FlashAnimation.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/FlashAnimation.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml
index c5f2f6e1ae..b36fcdef08 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml
index 5731f51f38..04fbbc176b 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
@@ -9,19 +9,25 @@ Item {
Button {
objectName: "DragThreshold"
label: "DragThreshold"
- x: 10; y: 10; width: parent.width - 20; height: 40
+ x: 10; y: 10; width: 300; height: 40
gesturePolicy: TapHandler.DragThreshold
}
Button {
objectName: "WithinBounds"
label: "WithinBounds"
- x: 10; y: 60; width: parent.width - 20; height: 40
+ x: 10; y: 60; width: 300; height: 40
gesturePolicy: TapHandler.WithinBounds
}
Button {
objectName: "ReleaseWithinBounds"
label: "ReleaseWithinBounds"
- x: 10; y: 110; width: parent.width - 20; height: 40
+ x: 10; y: 110; width: 300; height: 40
gesturePolicy: TapHandler.ReleaseWithinBounds
}
+ Button {
+ objectName: "DragWithinBounds"
+ label: "DragWithinBounds"
+ x: 10; y: 160; width: 300; height: 40
+ gesturePolicy: TapHandler.DragWithinBounds
+ }
}
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/dragReleaseMenu.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/dragReleaseMenu.qml
index 1f819a937f..5f60ef879e 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/dragReleaseMenu.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/dragReleaseMenu.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nested.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nested.qml
index f9db2d7179..c0f0b10bf4 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nested.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nested.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
Item {
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nestedAndSibling.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nestedAndSibling.qml
new file mode 100644
index 0000000000..7732c42082
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nestedAndSibling.qml
@@ -0,0 +1,39 @@
+import QtQuick 2.15
+import QtQuick.Window 2.15
+import QtQuick.Controls 2.15
+
+Item {
+ width: 360
+ height: 280
+
+ Rectangle {
+ width: 200; height: 200; x: 100; y: 10
+ color: th1.pressed ? "blue" : "lightblue"
+
+ TapHandler {
+ id: th1
+ objectName: "th1"
+ }
+
+ Rectangle {
+ width: 200; height: 200; x: 50; y: 50
+ color: th2.pressed ? "steelblue" : "lightsteelblue"
+
+ TapHandler {
+ id: th2
+ objectName: "th2"
+ }
+ }
+ }
+
+ Rectangle {
+ width: 200; height: 200; x: 10; y: 50
+ color: th3.pressed ? "goldenrod" : "beige"
+
+ TapHandler {
+ id: th3
+ objectName: "th3"
+ }
+ }
+}
+
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml
index 3517afe9c3..85f5c87b39 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/simpleTapHandler.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/simpleTapHandler.qml
index 54adc87c54..026be48f83 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/simpleTapHandler.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/simpleTapHandler.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
index f000d48171..1dab0836cd 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -44,10 +44,12 @@ private slots:
void touchMultiTap();
void mouseMultiTap_data();
void mouseMultiTap();
+ void mouseMultiTapLeftRight_data();
+ void mouseMultiTapLeftRight();
void singleTapDoubleTap_data();
void singleTapDoubleTap();
- void touchLongPress();
- void mouseLongPress();
+ void longPress_data();
+ void longPress();
void buttonsMultiTouch();
void componentUserBehavioralOverride();
void rightLongPressIgnoreWheel();
@@ -55,6 +57,8 @@ private slots:
void nonTopLevelParentWindow();
void nestedDoubleTap_data();
void nestedDoubleTap();
+ void nestedAndSiblingPropagation_data();
+ void nestedAndSiblingPropagation();
private:
void createView(QScopedPointer<QQuickView> &window, const char *fileName,
@@ -507,6 +511,23 @@ void tst_TapHandler::touchMultiTap()
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!button->property("pressed").toBool());
QCOMPARE(tappedSpy.size(), 4);
+
+ // Test a stray touch begin
+ tappedSpy.clear();
+ constexpr int count = 2;
+ for (int i = 0; i < count; ++i) {
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ p1 -= QPoint(dragThreshold, dragThreshold);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(dragThreshold, dragThreshold);
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ }
+ QCOMPARE(tappedSpy.count(), count);
}
void tst_TapHandler::mouseMultiTap_data()
@@ -592,6 +613,66 @@ void tst_TapHandler::mouseMultiTap()
QCOMPARE(singleTapSpy.size(), expectedSingleTapsAfterWaiting);
}
+void tst_TapHandler::mouseMultiTapLeftRight_data()
+{
+ QTest::addColumn<QQuickTapHandler::ExclusiveSignals>("exclusiveSignals");
+ QTest::addColumn<int>("expectedSingleTaps");
+ QTest::addColumn<int>("expectedDoubleTaps");
+ QTest::addColumn<int>("expectedTabCount2");
+ QTest::addColumn<int>("expectedTabCount3");
+
+ QTest::newRow("NotExclusive") << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::NotExclusive)
+ << 3 << 0 << 1 << 1;
+ QTest::newRow("SingleTap") << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::SingleTap)
+ << 3 << 0 << 1 << 1;
+ QTest::newRow("DoubleTap") << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::DoubleTap)
+ << 0 << 0 << 1 << 1;
+ QTest::newRow("SingleTap|DoubleTap") << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::SingleTap | QQuickTapHandler::DoubleTap)
+ << 0 << 0 << 1 << 1;
+}
+
+void tst_TapHandler::mouseMultiTapLeftRight() //QTBUG-111557
+{
+ QFETCH(QQuickTapHandler::ExclusiveSignals, exclusiveSignals);
+ QFETCH(int, expectedSingleTaps);
+ QFETCH(int, expectedDoubleTaps);
+ QFETCH(int, expectedTabCount2);
+ QFETCH(int, expectedTabCount3);
+
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "buttons.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *button = window->rootObject()->findChild<QQuickItem*>("DragThreshold");
+ QVERIFY(button);
+ QQuickTapHandler *tapHandler = button->findChild<QQuickTapHandler*>();
+ QVERIFY(tapHandler);
+ tapHandler->setExclusiveSignals(exclusiveSignals);
+ tapHandler->setAcceptedButtons(Qt::LeftButton | Qt::RightButton);
+ QSignalSpy tappedSpy(button, SIGNAL(tapped()));
+ QSignalSpy singleTapSpy(tapHandler, &QQuickTapHandler::singleTapped);
+ QSignalSpy doubleTapSpy(tapHandler, &QQuickTapHandler::doubleTapped);
+
+ // Click once with the left button
+ QPoint p1 = button->mapToScene(QPointF(2, 2)).toPoint();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
+
+ // Click again with the right button -> should reset tabCount()
+ QTest::mousePress(window, Qt::RightButton, Qt::NoModifier, p1, 10);
+ QTest::mouseRelease(window, Qt::RightButton, Qt::NoModifier, p1, 10);
+
+ QCOMPARE(tapHandler->tapCount(), expectedTabCount2);
+
+ // Click again with the left button -> should reset tabCount()
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
+
+ QCOMPARE(tapHandler->tapCount(), expectedTabCount3);
+ QCOMPARE(singleTapSpy.size(), expectedSingleTaps);
+ QCOMPARE(doubleTapSpy.size(), expectedDoubleTaps);
+}
+
void tst_TapHandler::singleTapDoubleTap_data()
{
QTest::addColumn<QPointingDevice::DeviceType>("deviceType");
@@ -653,12 +734,13 @@ void tst_TapHandler::singleTapDoubleTap()
QSignalSpy singleTapSpy(tapHandler, &QQuickTapHandler::singleTapped);
QSignalSpy doubleTapSpy(tapHandler, &QQuickTapHandler::doubleTapped);
- auto tap = [window, tapHandler, deviceType, this](const QPoint &p1) {
+ auto tap = [window, tapHandler, deviceType, this](const QPoint &p1, int delay = 10) {
switch (static_cast<QPointingDevice::DeviceType>(deviceType)) {
case QPointingDevice::DeviceType::Mouse:
- QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
+ QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, p1, delay);
break;
case QPointingDevice::DeviceType::TouchScreen:
+ QTest::qWait(delay);
QTest::touchEvent(window, touchDevice).press(0, p1, window);
QTRY_VERIFY(tapHandler->isPressed());
QTest::touchEvent(window, touchDevice).release(0, p1, window);
@@ -679,78 +761,211 @@ void tst_TapHandler::singleTapDoubleTap()
QTRY_COMPARE(doubleTapSpy.size(), expectedDoubleTapCount);
QCOMPARE(tappedSpy.size(), 2);
QCOMPARE(singleTapSpy.size(), expectedEndingSingleTapCount);
-}
-void tst_TapHandler::touchLongPress()
-{
- QScopedPointer<QQuickView> windowPtr;
- createView(windowPtr, "buttons.qml");
- QQuickView * window = windowPtr.data();
+ // wait past the double-tap interval, then do it again
+ const auto delay = qApp->styleHints()->mouseDoubleClickInterval() + 10;
+ tappedSpy.clear();
+ singleTapSpy.clear();
+ doubleTapSpy.clear();
- QQuickItem *button = window->rootObject()->findChild<QQuickItem*>("DragThreshold");
- QVERIFY(button);
- QQuickTapHandler *tapHandler = button->findChild<QQuickTapHandler*>("DragThreshold");
- QVERIFY(tapHandler);
- QSignalSpy tappedSpy(button, SIGNAL(tapped()));
- QSignalSpy longPressThresholdChangedSpy(tapHandler, SIGNAL(longPressThresholdChanged()));
- QSignalSpy timeHeldSpy(tapHandler, SIGNAL(timeHeldChanged()));
- QSignalSpy longPressedSpy(tapHandler, SIGNAL(longPressed()));
+ // tap once with delay
+ tap(p1, delay);
+ QCOMPARE(tappedSpy.size(), 1);
+ QCOMPARE(doubleTapSpy.size(), 0);
- // Reduce the threshold so that we can get a long press quickly
- tapHandler->setLongPressThreshold(0.5);
- QCOMPARE(longPressThresholdChangedSpy.size(), 1);
+ // tap again immediately afterwards
+ tap(p1);
+ QTRY_COMPARE(doubleTapSpy.size(), expectedDoubleTapCount);
+ QCOMPARE(tappedSpy.size(), 2);
+ QCOMPARE(singleTapSpy.size(), expectedEndingSingleTapCount);
+}
- // Press and hold
- QPoint p1 = button->mapToScene(button->clipRect().center()).toPoint();
- QTest::touchEvent(window, touchDevice).press(1, p1, window);
- QQuickTouchUtils::flush(window);
- QTRY_VERIFY(button->property("pressed").toBool());
- QTRY_COMPARE(longPressedSpy.size(), 1);
- timeHeldSpy.wait(); // the longer we hold it, the more this will occur
- qDebug() << "held" << tapHandler->timeHeld() << "secs; timeHeld updated" << timeHeldSpy.size() << "times";
- QVERIFY(timeHeldSpy.size() > 0);
- QVERIFY(tapHandler->timeHeld() > 0.4); // Should be > 0.5 but slow CI and timer granularity can interfere
+void tst_TapHandler::longPress_data()
+{
+ QTest::addColumn<const QPointingDevice *>("device");
+ QTest::addColumn<QString>("buttonName");
+ QTest::addColumn<qreal>("longPressThreshold");
+ QTest::addColumn<QPoint>("releaseOffset");
+ QTest::addColumn<bool>("expectLongPress");
+ QTest::addColumn<bool>("expectTapped");
- // Release and verify that tapped was not emitted
- QTest::touchEvent(window, touchDevice).release(1, p1, window);
- QQuickTouchUtils::flush(window);
- QTRY_VERIFY(!button->property("pressed").toBool());
- QCOMPARE(tappedSpy.size(), 0);
+ const QPointingDevice *constTouchDevice = touchDevice;
+
+ // Reduce the threshold so that we can get a long press quickly (faster in CI)
+ const qreal longPressThreshold = 0.3;
+ QTest::newRow("mouse, lpt longPressThreshold: DragThreshold")
+ << QPointingDevice::primaryPointingDevice() << "DragThreshold"
+ << longPressThreshold << QPoint(0, 0) << true << false;
+ QTest::newRow("touch, lpt longPressThreshold: DragThreshold")
+ << constTouchDevice << "DragThreshold" << longPressThreshold
+ << QPoint(0, 0) << true << false;
+ QTest::newRow("mouse, lpt longPressThreshold: DragThreshold, drag")
+ << QPointingDevice::primaryPointingDevice() << "DragThreshold"
+ << longPressThreshold << QPoint(50, 0) << false << false;
+ QTest::newRow("touch, lpt longPressThreshold: DragThreshold, drag")
+ << constTouchDevice << "DragThreshold"
+ << longPressThreshold << QPoint(50, 0) << false << false;
+
+ QTest::newRow("mouse, lpt longPressThreshold: WithinBounds")
+ << QPointingDevice::primaryPointingDevice() << "WithinBounds"
+ << longPressThreshold << QPoint(0, 0) << true << false;
+ QTest::newRow("touch, lpt longPressThreshold: WithinBounds")
+ << constTouchDevice << "WithinBounds"
+ << longPressThreshold << QPoint(0, 0) << true << false;
+ QTest::newRow("mouse, lpt longPressThreshold: WithinBounds, drag")
+ << QPointingDevice::primaryPointingDevice() << "WithinBounds"
+ << longPressThreshold << QPoint(50, 0) << true << false;
+ QTest::newRow("touch, lpt longPressThreshold: WithinBounds, drag")
+ << constTouchDevice << "WithinBounds"
+ << longPressThreshold << QPoint(50, 0) << true << false;
+ QTest::newRow("mouse, lpt longPressThreshold: WithinBounds, drag out")
+ << QPointingDevice::primaryPointingDevice() << "WithinBounds"
+ << longPressThreshold << QPoint(155, 0) << false << false;
+ QTest::newRow("touch, lpt longPressThreshold: WithinBounds, drag out")
+ << constTouchDevice << "WithinBounds"
+ << longPressThreshold << QPoint(155, 0) << false << false;
+
+ QTest::newRow("mouse, lpt longPressThreshold: ReleaseWithinBounds")
+ << QPointingDevice::primaryPointingDevice() << "ReleaseWithinBounds"
+ << longPressThreshold << QPoint(0, 0) << true << false;
+ QTest::newRow("touch, lpt longPressThreshold: ReleaseWithinBounds")
+ << constTouchDevice << "ReleaseWithinBounds"
+ << longPressThreshold << QPoint(0, 0) << true << false;
+ QTest::newRow("mouse, lpt longPressThreshold: ReleaseWithinBounds, drag")
+ << QPointingDevice::primaryPointingDevice() << "ReleaseWithinBounds"
+ << longPressThreshold << QPoint(50, 0) << true << false;
+ QTest::newRow("touch, lpt longPressThreshold: ReleaseWithinBounds, drag")
+ << constTouchDevice << "ReleaseWithinBounds"
+ << longPressThreshold << QPoint(50, 0) << true << false;
+ QTest::newRow("mouse, lpt longPressThreshold: ReleaseWithinBounds, drag out")
+ << QPointingDevice::primaryPointingDevice() << "ReleaseWithinBounds"
+ << longPressThreshold << QPoint(155, 0) << false << false;
+ QTest::newRow("touch, lpt longPressThreshold: ReleaseWithinBounds, drag out")
+ << constTouchDevice << "ReleaseWithinBounds"
+ << longPressThreshold << QPoint(155, 0) << false << false;
+
+ QTest::newRow("mouse, lpt longPressThreshold: DragWithinBounds")
+ << QPointingDevice::primaryPointingDevice() << "DragWithinBounds"
+ << longPressThreshold << QPoint(0, 0) << true << false;
+ QTest::newRow("touch, lpt longPressThreshold: DragWithinBounds")
+ << constTouchDevice << "DragWithinBounds"
+ << longPressThreshold << QPoint(0, 0) << true << false;
+ QTest::newRow("mouse, lpt longPressThreshold: DragWithinBounds, drag")
+ << QPointingDevice::primaryPointingDevice() << "DragWithinBounds"
+ << longPressThreshold << QPoint(50, 0) << true << false;
+ QTest::newRow("touch, lpt longPressThreshold: DragWithinBounds, drag")
+ << constTouchDevice << "DragWithinBounds"
+ << longPressThreshold << QPoint(50, 0) << true << false;
+ QTest::newRow("mouse, lpt longPressThreshold: DragWithinBounds, drag out")
+ << QPointingDevice::primaryPointingDevice() << "DragWithinBounds"
+ << longPressThreshold << QPoint(155, 0) << false << false;
+ QTest::newRow("touch, lpt longPressThreshold: DragWithinBounds, drag out")
+ << constTouchDevice << "DragWithinBounds"
+ << longPressThreshold << QPoint(155, 0) << false << false;
+
+ // Zero or negative threshold means long press is disabled
+ QTest::newRow("mouse, lpt 0: DragThreshold")
+ << QPointingDevice::primaryPointingDevice() << "DragThreshold"
+ << qreal(0) << QPoint(0, 0) << false << true;
+ QTest::newRow("mouse, lpt -1: DragThreshold")
+ << QPointingDevice::primaryPointingDevice() << "DragThreshold"
+ << qreal(-1) << QPoint(0, 0) << true << false;
+ QTest::newRow("touch, lpt 0: DragThreshold")
+ << constTouchDevice << "DragThreshold"
+ << qreal(0) << QPoint(0, 0) << false << true;
+
+ QTest::newRow("mouse, lpt 0: WithinBounds")
+ << QPointingDevice::primaryPointingDevice() << "WithinBounds"
+ << qreal(0) << QPoint(0, 0) << false << true;
+ QTest::newRow("mouse, lpt -1: WithinBounds")
+ << QPointingDevice::primaryPointingDevice() << "WithinBounds"
+ << qreal(-1) << QPoint(0, 0) << true << false;
+ QTest::newRow("touch, lpt 0: WithinBounds")
+ << constTouchDevice << "WithinBounds"
+ << qreal(0) << QPoint(0, 0) << false << true;
+
+ QTest::newRow("mouse, lpt 0: ReleaseWithinBounds")
+ << QPointingDevice::primaryPointingDevice() << "ReleaseWithinBounds"
+ << qreal(0) << QPoint(0, 0) << false << true;
+ QTest::newRow("mouse, lpt -1: ReleaseWithinBounds")
+ << QPointingDevice::primaryPointingDevice() << "ReleaseWithinBounds"
+ << qreal(-1) << QPoint(0, 0) << true << false;
+ QTest::newRow("touch, lpt 0: ReleaseWithinBounds")
+ << constTouchDevice << "ReleaseWithinBounds"
+ << qreal(0) << QPoint(0, 0) << false << true;
+
+ QTest::newRow("mouse, lpt 0: DragWithinBounds")
+ << QPointingDevice::primaryPointingDevice() << "DragWithinBounds"
+ << qreal(0) << QPoint(0, 0) << false << true;
+ QTest::newRow("mouse, lpt -1: DragWithinBounds")
+ << QPointingDevice::primaryPointingDevice() << "DragWithinBounds"
+ << qreal(-1) << QPoint(0, 0) << true << false;
+ QTest::newRow("touch, lpt 0: DragWithinBounds")
+ << constTouchDevice << "DragWithinBounds"
+ << qreal(0) << QPoint(0, 0) << false << true;
}
-void tst_TapHandler::mouseLongPress()
+void tst_TapHandler::longPress()
{
- QScopedPointer<QQuickView> windowPtr;
- createView(windowPtr, "buttons.qml");
- QQuickView * window = windowPtr.data();
+ QFETCH(const QPointingDevice *, device);
+ QFETCH(QString, buttonName);
+ QFETCH(qreal, longPressThreshold);
+ QFETCH(QPoint, releaseOffset);
+ QFETCH(bool, expectLongPress);
+ QFETCH(bool, expectTapped);
- QQuickItem *button = window->rootObject()->findChild<QQuickItem*>("DragThreshold");
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("buttons.qml")));
+
+ QQuickItem *button = window.rootObject()->findChild<QQuickItem*>(buttonName);
QVERIFY(button);
- QQuickTapHandler *tapHandler = button->findChild<QQuickTapHandler*>("DragThreshold");
+ QQuickTapHandler *tapHandler = button->findChild<QQuickTapHandler*>(buttonName);
QVERIFY(tapHandler);
QSignalSpy tappedSpy(button, SIGNAL(tapped()));
QSignalSpy longPressThresholdChangedSpy(tapHandler, SIGNAL(longPressThresholdChanged()));
QSignalSpy timeHeldSpy(tapHandler, SIGNAL(timeHeldChanged()));
QSignalSpy longPressedSpy(tapHandler, SIGNAL(longPressed()));
- // Reduce the threshold so that we can get a long press quickly
- tapHandler->setLongPressThreshold(0.5);
- QCOMPARE(longPressThresholdChangedSpy.size(), 1);
+ const qreal defaultThreshold = tapHandler->longPressThreshold();
+ qsizetype changedCount = 0;
+ QCOMPARE_GT(defaultThreshold, 0);
+ tapHandler->setLongPressThreshold(longPressThreshold);
+ if (longPressThreshold > 0)
+ QCOMPARE(longPressThresholdChangedSpy.size(), ++changedCount);
+ QVERIFY(QMetaObject::invokeMethod(button, "assignUndefinedLongPressThreshold"));
+ if (longPressThreshold > 0)
+ QCOMPARE(longPressThresholdChangedSpy.size(), ++changedCount);
+ QCOMPARE(tapHandler->longPressThreshold(), defaultThreshold);
+ tapHandler->setLongPressThreshold(longPressThreshold);
// Press and hold
QPoint p1 = button->mapToScene(button->clipRect().center()).toPoint();
- QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QQuickTest::pointerPress(device, &window, 1, p1);
QTRY_VERIFY(button->property("pressed").toBool());
- QTRY_COMPARE(longPressedSpy.size(), 1);
+ QTRY_COMPARE(longPressedSpy.size(), expectLongPress ? 1 : 0);
timeHeldSpy.wait(); // the longer we hold it, the more this will occur
qDebug() << "held" << tapHandler->timeHeld() << "secs; timeHeld updated" << timeHeldSpy.size() << "times";
- QVERIFY(timeHeldSpy.size() > 0);
- QVERIFY(tapHandler->timeHeld() > 0.4); // Should be > 0.5 but slow CI and timer granularity can interfere
+ QCOMPARE_GT(timeHeldSpy.size(), 0);
+ if (expectLongPress) {
+ // Should be > longPressThreshold but slow CI and timer granularity can interfere
+ QCOMPARE_GT(tapHandler->timeHeld(), longPressThreshold - 0.1);
+ } else {
+ // Should be quite small, but event delivery is not instantaneous
+ QCOMPARE_LT(tapHandler->timeHeld(), 0.3);
+ }
+
+ // If we have an offset, we need a move between press and release for realistic simulation
+ if (!releaseOffset.isNull())
+ QQuickTest::pointerMove(device, &window, 1, p1 + releaseOffset);
- // Release and verify that tapped was not emitted
- QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1, 500);
+ // Release (optionally at an offset) and check whether tapped was emitted
+ QQuickTest::pointerRelease(device, &window, 1, p1 + releaseOffset);
QTRY_VERIFY(!button->property("pressed").toBool());
- QCOMPARE(tappedSpy.size(), 0);
+ if (expectLongPress)
+ QCOMPARE_GT(button->property("timeHeldWhenLongPressed").toReal(), longPressThreshold - 0.1);
+ QCOMPARE(tapHandler->timeHeld(), -1);
+ QCOMPARE(tappedSpy.size(), expectTapped ? 1 : 0);
+ QCOMPARE(longPressedSpy.size(), expectLongPress ? 1 : 0);
}
void tst_TapHandler::buttonsMultiTouch()
@@ -866,8 +1081,8 @@ void tst_TapHandler::componentUserBehavioralOverride()
QQuickTapHandler *userTapHandler = button->findChild<QQuickTapHandler*>("override");
QVERIFY(userTapHandler);
QSignalSpy tappedSpy(button, SIGNAL(tapped()));
- QSignalSpy innerGrabChangedSpy(innerTapHandler, SIGNAL(grabChanged(QPointingDevice::GrabTransition, QEventPoint)));
- QSignalSpy userGrabChangedSpy(userTapHandler, SIGNAL(grabChanged(QPointingDevice::GrabTransition, QEventPoint)));
+ QSignalSpy innerGrabChangedSpy(innerTapHandler, SIGNAL(grabChanged(QPointingDevice::GrabTransition,QEventPoint)));
+ QSignalSpy userGrabChangedSpy(userTapHandler, SIGNAL(grabChanged(QPointingDevice::GrabTransition,QEventPoint)));
QSignalSpy innerPressedChangedSpy(innerTapHandler, SIGNAL(pressedChanged()));
QSignalSpy userPressedChangedSpy(userTapHandler, SIGNAL(pressedChanged()));
@@ -1019,6 +1234,61 @@ void tst_TapHandler::nestedDoubleTap() // QTBUG-102625
childGesturePolicy == QQuickTapHandler::GesturePolicy::DragThreshold ? 4 : 2);
}
+void tst_TapHandler::nestedAndSiblingPropagation_data()
+{
+ QTest::addColumn<const QPointingDevice *>("device");
+ QTest::addColumn<QQuickTapHandler::GesturePolicy>("gesturePolicy");
+ QTest::addColumn<bool>("expectPropagation");
+
+ const QPointingDevice *constTouchDevice = touchDevice;
+
+ QTest::newRow("primary, DragThreshold") << QPointingDevice::primaryPointingDevice()
+ << QQuickTapHandler::GesturePolicy::DragThreshold << true;
+ QTest::newRow("primary, WithinBounds") << QPointingDevice::primaryPointingDevice()
+ << QQuickTapHandler::GesturePolicy::WithinBounds << false;
+ QTest::newRow("primary, ReleaseWithinBounds") << QPointingDevice::primaryPointingDevice()
+ << QQuickTapHandler::GesturePolicy::ReleaseWithinBounds << false;
+ QTest::newRow("primary, DragWithinBounds") << QPointingDevice::primaryPointingDevice()
+ << QQuickTapHandler::GesturePolicy::DragWithinBounds << false;
+
+ QTest::newRow("touch, DragThreshold") << constTouchDevice
+ << QQuickTapHandler::GesturePolicy::DragThreshold << true;
+ QTest::newRow("touch, WithinBounds") << constTouchDevice
+ << QQuickTapHandler::GesturePolicy::WithinBounds << false;
+ QTest::newRow("touch, ReleaseWithinBounds") << constTouchDevice
+ << QQuickTapHandler::GesturePolicy::ReleaseWithinBounds << false;
+ QTest::newRow("touch, DragWithinBounds") << constTouchDevice
+ << QQuickTapHandler::GesturePolicy::DragWithinBounds << false;
+}
+
+void tst_TapHandler::nestedAndSiblingPropagation() // QTBUG-117387
+{
+ QFETCH(const QPointingDevice *, device);
+ QFETCH(QQuickTapHandler::GesturePolicy, gesturePolicy);
+ QFETCH(bool, expectPropagation);
+
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("nestedAndSibling.qml")));
+ QQuickItem *root = window.rootObject();
+ QQuickTapHandler *th1 = root->findChild<QQuickTapHandler*>("th1");
+ QVERIFY(th1);
+ th1->setGesturePolicy(gesturePolicy);
+ QQuickTapHandler *th2 = root->findChild<QQuickTapHandler*>("th2");
+ QVERIFY(th2);
+ th2->setGesturePolicy(gesturePolicy);
+ QQuickTapHandler *th3 = root->findChild<QQuickTapHandler*>("th3");
+ QVERIFY(th3);
+ th3->setGesturePolicy(gesturePolicy);
+
+ QPoint middle(180, 140);
+ QQuickTest::pointerPress(device, &window, 0, middle);
+ QVERIFY(th3->isPressed()); // it's on top
+ QCOMPARE(th2->isPressed(), expectPropagation);
+ QCOMPARE(th1->isPressed(), expectPropagation);
+
+ QQuickTest::pointerRelease(device, &window, 0, middle);
+}
+
QTEST_MAIN(tst_TapHandler)
#include "tst_qquicktaphandler.moc"