diff options
Diffstat (limited to 'tests/auto/quick/qquickmultipointtoucharea')
14 files changed, 387 insertions, 129 deletions
diff --git a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST index abe504d20c..c79f4b6a29 100644 --- a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST +++ b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST @@ -1,4 +1,10 @@ [nonOverlapping] ubuntu-20.04 +ubuntu-22.04 [nested] ubuntu-20.04 +ubuntu-22.04 + +# QTBUG-118065 +[mouseGestureStarted] +opensuse-leap diff --git a/tests/auto/quick/qquickmultipointtoucharea/CMakeLists.txt b/tests/auto/quick/qquickmultipointtoucharea/CMakeLists.txt index 1902b3fefa..277df556cc 100644 --- a/tests/auto/quick/qquickmultipointtoucharea/CMakeLists.txt +++ b/tests/auto/quick/qquickmultipointtoucharea/CMakeLists.txt @@ -1,9 +1,18 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + # Generated from qquickmultipointtoucharea.pro. ##################################################################### ## tst_qquickmultipointtoucharea Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qquickmultipointtoucharea LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + # Collect test data file(GLOB_RECURSE test_data_glob RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} @@ -12,21 +21,14 @@ list(APPEND test_data ${test_data_glob}) qt_internal_add_test(tst_qquickmultipointtoucharea SOURCES - ../../shared/util.cpp ../../shared/util.h - ../shared/geometrytestutil.cpp ../shared/geometrytestutil.h - ../shared/viewtestutil.cpp ../shared/viewtestutil.h - ../shared/visualtestutil.cpp ../shared/visualtestutil.h tst_qquickmultipointtoucharea.cpp - DEFINES - QT_QMLTEST_DATADIR=\\\"${CMAKE_CURRENT_SOURCE_DIR}/data\\\" - INCLUDE_DIRECTORIES - ../../shared - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::Gui Qt::GuiPrivate Qt::QmlPrivate Qt::QuickPrivate + Qt::QuickTestUtilsPrivate TESTDATA ${test_data} ) @@ -35,10 +37,10 @@ qt_internal_add_test(tst_qquickmultipointtoucharea qt_internal_extend_target(tst_qquickmultipointtoucharea CONDITION ANDROID OR IOS DEFINES - QT_QMLTEST_DATADIR=\\\":/data\\\" + QT_QMLTEST_DATADIR=":/data" ) qt_internal_extend_target(tst_qquickmultipointtoucharea CONDITION NOT ANDROID AND NOT IOS DEFINES - QT_QMLTEST_DATADIR=\\\"${CMAKE_CURRENT_SOURCE_DIR}/data\\\" + QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data" ) diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/cancel.qml b/tests/auto/quick/qquickmultipointtoucharea/data/cancel.qml index e108003bca..493257ac7e 100644 --- a/tests/auto/quick/qquickmultipointtoucharea/data/cancel.qml +++ b/tests/auto/quick/qquickmultipointtoucharea/data/cancel.qml @@ -30,12 +30,12 @@ MultiPointTouchArea { property int touchCount: 0 property bool touchUpdatedHandled: false - onPressed: { touchPointPressCount = touchPoints.length } - onUpdated: { touchPointUpdateCount = touchPoints.length } - onReleased: { touchPointReleaseCount = touchPoints.length } - onCanceled: { touchPointCancelCount = touchPoints.length } - onTouchUpdated: { - touchCount = touchPoints.length + onPressed: (points) => { touchPointPressCount = points.length } + onUpdated: (points) => { touchPointUpdateCount = points.length } + onReleased: (points) => { touchPointReleaseCount = v.length } + onCanceled: (points) => { touchPointCancelCount = points.length } + onTouchUpdated: (points) => { + touchCount = points.length touchUpdatedHandled = true } } diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/inFlickable.qml b/tests/auto/quick/qquickmultipointtoucharea/data/inFlickable.qml index 32733613b3..e03ad43816 100644 --- a/tests/auto/quick/qquickmultipointtoucharea/data/inFlickable.qml +++ b/tests/auto/quick/qquickmultipointtoucharea/data/inFlickable.qml @@ -32,7 +32,7 @@ Rectangle { anchors.fill: parent minimumTouchPoints: 2 maximumTouchPoints: 2 - onGestureStarted: { + onGestureStarted: (gesture) => { if ((Math.abs(point2.x - point2.startX) > gesture.dragThreshold/2) && (Math.abs(point1.x - point1.startX) > gesture.dragThreshold/2)) { gesture.grab() @@ -43,8 +43,8 @@ Rectangle { TouchPoint { id: point2; objectName: "point2" } ] - onCanceled: root.cancelCount = touchPoints.length - onTouchUpdated: root.touchCount = touchPoints.length + onCanceled: (touchPoints) => root.cancelCount = touchPoints.length + onTouchUpdated: (touchPoints) => root.touchCount = touchPoints.length Text { text: "①" diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/mouse.qml b/tests/auto/quick/qquickmultipointtoucharea/data/mouse.qml index b0410dac4a..6b9dd5b7c7 100644 --- a/tests/auto/quick/qquickmultipointtoucharea/data/mouse.qml +++ b/tests/auto/quick/qquickmultipointtoucharea/data/mouse.qml @@ -17,10 +17,10 @@ MultiPointTouchArea { TouchPoint { objectName: "point2" } ] - onPressed: { touchCount = touchPoints.length } - onTouchUpdated: { touchCount = touchPoints.length } - onCanceled: { cancelCount = touchPoints.length } - onGestureStarted: { + onPressed: (points) => { touchCount = points.length } + onTouchUpdated: (points) => { touchCount = points.length } + onCanceled: (points) => { cancelCount = points.length } + onGestureStarted: (gesture) => { gestureStartedX = gesture.touchPoints[0].startX gestureStartedY = gesture.touchPoints[0].startY if (grabGesture) diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/nested.qml b/tests/auto/quick/qquickmultipointtoucharea/data/nested.qml index 8ab10a6926..dca1ffa07b 100644 --- a/tests/auto/quick/qquickmultipointtoucharea/data/nested.qml +++ b/tests/auto/quick/qquickmultipointtoucharea/data/nested.qml @@ -66,7 +66,7 @@ MultiPointTouchArea { anchors.fill: parent minimumTouchPoints: 3 maximumTouchPoints: 3 - onGestureStarted: if (grabInnerArea) gesture.grab() + onGestureStarted: (gesture) => { if (grabInnerArea) gesture.grab() } touchPoints: [ TouchPoint { id: point21; objectName: "point21" }, TouchPoint { id: point22; objectName: "point22" }, diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/nestedMouseArea.qml b/tests/auto/quick/qquickmultipointtoucharea/data/nestedMouseArea.qml new file mode 100644 index 0000000000..7ca3f187d6 --- /dev/null +++ b/tests/auto/quick/qquickmultipointtoucharea/data/nestedMouseArea.qml @@ -0,0 +1,26 @@ +import QtQuick 2.12 + +Item { + id: root + width: 300; height: 300 + property point mptaPoint + property point maPoint + MultiPointTouchArea { + anchors.fill : parent + onPressed: function(touchPoints) { + root.mptaPoint = Qt.point(touchPoints[0].x, touchPoints[0].y) + } + MouseArea { + id: ma + width: 100; height: 100 + anchors.centerIn: parent + onPressed: function(mouse) { + root.maPoint = Qt.point(mouse.x, mouse.y) + } + } + Rectangle { + anchors.fill: ma + border.color: "grey" + } + } +} diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/nestedPinchArea.qml b/tests/auto/quick/qquickmultipointtoucharea/data/nestedPinchArea.qml new file mode 100644 index 0000000000..0e51804b30 --- /dev/null +++ b/tests/auto/quick/qquickmultipointtoucharea/data/nestedPinchArea.qml @@ -0,0 +1,44 @@ +import QtQuick 2.15 + +MultiPointTouchArea { + width: 240 + height: 320 + mouseEnabled: true + property int pressedCount: 0 + property int updatedCount: 0 + property int releasedCount: 0 + + onPressed: (points) => { pressedCount = points.length } + onUpdated: (points) => { updatedCount = points.length } + onReleased: (points) => { releasedCount = points.length } + + touchPoints: [ + TouchPoint { + id: point1 + objectName: "point1" + }, + TouchPoint { + id: point2 + objectName: "point2" + } + ] + + PinchArea { + anchors.fill: parent + } + + Rectangle { + width: 30; height: 30 + color: "green" + x: point1.x + y: point1.y + } + + Rectangle { + id: rectangle + width: 30; height: 30 + color: "yellow" + x: point2.x + y: point2.y + } +} diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/nestedTouchPosCheck.qml b/tests/auto/quick/qquickmultipointtoucharea/data/nestedTouchPosCheck.qml new file mode 100644 index 0000000000..700f06a3ac --- /dev/null +++ b/tests/auto/quick/qquickmultipointtoucharea/data/nestedTouchPosCheck.qml @@ -0,0 +1,52 @@ +import QtQuick +import QtTest + +Item { + width: 300; height: 200 + id: topLevelItem + MultiPointTouchArea { + objectName: "topMPTA" + anchors.fill: parent + Column { + width: parent.width + height: parent.height + + Rectangle { + width: parent.width + height: 100 + color: "green" + } + Rectangle { + id: rect + width: parent.width + height: 600 + color: "red" + + MultiPointTouchArea { + + property var xPressed: 0 + property var yPressed: 0 + property var xReleased: 0 + property var yReleased: 0 + + objectName: "bottomMPTA" + anchors.fill: parent + onPressed: (touchPoints) => { + for (let tp in touchPoints) { + let touch = touchPoints[tp] + xPressed = touch.x + yPressed = touch.y + } + } + onReleased: (touchPoints) => { + for (let tp in touchPoints) { + let touch = touchPoints[tp] + xReleased = touch.x + yReleased = touch.y + } + } + } + } + } + } +} diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/nonOverlapping.qml b/tests/auto/quick/qquickmultipointtoucharea/data/nonOverlapping.qml index 027f90c7f4..4130bc8dde 100644 --- a/tests/auto/quick/qquickmultipointtoucharea/data/nonOverlapping.qml +++ b/tests/auto/quick/qquickmultipointtoucharea/data/nonOverlapping.qml @@ -9,7 +9,7 @@ Rectangle { height: 160 minimumTouchPoints: 2 maximumTouchPoints: 2 - onGestureStarted: gesture.grab() + onGestureStarted: (gesture) => gesture.grab() touchPoints: [ TouchPoint { id: point11; objectName: "point11" }, TouchPoint { id: point12; objectName: "point12" } @@ -34,7 +34,7 @@ Rectangle { y: 160 minimumTouchPoints: 3 maximumTouchPoints: 3 - onGestureStarted: gesture.grab() + onGestureStarted: (gesture) => gesture.grab() touchPoints: [ TouchPoint { id: point21; objectName: "point21" }, TouchPoint { id: point22; objectName: "point22" }, diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/signalTest.qml b/tests/auto/quick/qquickmultipointtoucharea/data/signalTest.qml index 54b160c182..9ba3029193 100644 --- a/tests/auto/quick/qquickmultipointtoucharea/data/signalTest.qml +++ b/tests/auto/quick/qquickmultipointtoucharea/data/signalTest.qml @@ -20,11 +20,17 @@ MultiPointTouchArea { maximumTouchPoints: 5 - onPressed: { touchPointPressCount = touchPoints.length } - onUpdated: { touchPointUpdateCount = touchPoints.length } + // recommended syntax for a signal handler + onPressed: (points) => { touchPointPressCount = points.length } + + // one with "touchPoints" being the signal argument rather than the property + onUpdated: (touchPoints) => { touchPointUpdateCount = touchPoints.length } + + // one without the formal parameter, to test that it still works (with a warning) onReleased: { touchPointReleaseCount = touchPoints.length } - onTouchUpdated: { - touchCount = touchPoints.length + + onTouchUpdated: (points) => { + touchCount = points.length touchUpdatedHandled = true } } diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/touchOverMouseArea.qml b/tests/auto/quick/qquickmultipointtoucharea/data/touchOverMouseArea.qml new file mode 100644 index 0000000000..ffe3751ec3 --- /dev/null +++ b/tests/auto/quick/qquickmultipointtoucharea/data/touchOverMouseArea.qml @@ -0,0 +1,21 @@ + +import QtQuick + +Rectangle { + x: 20 + y: 20 + width: 300 + height: 200 + + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + } + + MultiPointTouchArea { + id: touchArea + anchors.fill: parent + enabled: false + } +} diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/transformedMultiPointTouchArea.qml b/tests/auto/quick/qquickmultipointtoucharea/data/transformedMultiPointTouchArea.qml index 296bf7996f..02985581e0 100644 --- a/tests/auto/quick/qquickmultipointtoucharea/data/transformedMultiPointTouchArea.qml +++ b/tests/auto/quick/qquickmultipointtoucharea/data/transformedMultiPointTouchArea.qml @@ -19,8 +19,8 @@ Rectangle { property int pointCount: 0 - onPressed: pointCount = touchPoints.length; - onTouchUpdated: pointCount = touchPoints.length; + onPressed: (points) => pointCount = points.length; + onTouchUpdated: (points) => pointCount = points.length; } } } diff --git a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp index b5ab520055..b233ed0232 100644 --- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp +++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp @@ -1,33 +1,9 @@ -/**************************************************************************** -** -** Copyright (C) 2020 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$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtTest/QtTest> #include <QtTest/QSignalSpy> +#include <private/qquickitem_p.h> #include <private/qquickmultipointtoucharea_p.h> #include <private/qquickflickable_p.h> #include <private/qquickmousearea_p.h> @@ -36,17 +12,20 @@ #include <QtQuick/qquickview.h> #include <QtGui/QScreen> #include <QtGui/private/qevent_p.h> +#include <QtGui/private/qeventpoint_p.h> #include <QtGui/private/qpointingdevice_p.h> -#include "../../shared/util.h" -#include "../shared/viewtestutil.h" +#include <QtQuickTestUtils/private/qmlutils_p.h> +#include <QtQuickTestUtils/private/viewtestutils_p.h> Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests") +using namespace Qt::StringLiterals; + class tst_QQuickMultiPointTouchArea : public QQmlDataTest { Q_OBJECT public: - tst_QQuickMultiPointTouchArea() { } + tst_QQuickMultiPointTouchArea() : QQmlDataTest(QT_QMLTEST_DATADIR) { } private slots: void cleanupTestCase() {} @@ -57,6 +36,7 @@ private slots: void reuse(); void nonOverlapping(); void nested(); + void nestedTouchPosCheck(); void inFlickable(); void inFlickable2(); void inFlickableWithPressDelay(); @@ -71,6 +51,9 @@ private slots: void mouseGestureStarted(); void cancel(); void stationaryTouchWithChangingPressure(); + void touchFiltering(); + void nestedPinchAreaMouse(); + void disabledIgnoresHover(); private: QQuickView *createAndShowView(const QString &file); @@ -94,6 +77,12 @@ void tst_QQuickMultiPointTouchArea::properties() void tst_QQuickMultiPointTouchArea::signalTest() { +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) + QTest::ignoreMessage(QtWarningMsg, QString(testFileUrl("signalTest.qml").toString() + + u":30:5 Parameter \"touchPoints\" is not declared. Injection of parameters into signal handlers " + "is deprecated. Use JavaScript functions with formal parameters instead."_s).toLatin1().constData()); +#endif + QScopedPointer<QQuickView> window(createAndShowView("signalTest.qml")); QVERIFY(window->rootObject() != nullptr); @@ -572,6 +561,30 @@ void tst_QQuickMultiPointTouchArea::nested() QQuickTouchUtils::flush(window.data()); } + +void tst_QQuickMultiPointTouchArea::nestedTouchPosCheck() +{ + QScopedPointer<QQuickView> window(createAndShowView("nestedTouchPosCheck.qml")); + QVERIFY(window->rootObject() != nullptr); + + auto *bottomMPTA = window->rootObject()->findChild<QQuickMultiPointTouchArea *>("bottomMPTA"); + QVERIFY(bottomMPTA != nullptr); + + QTest::QTouchEventSequence sequence = QTest::touchEvent(window.data(), device); + + sequence.press(0, QPoint(10, 110)).commit(); + QQuickTouchUtils::flush(window.data()); + + sequence.release(0, QPoint(10, 110)).commit(); + QQuickTouchUtils::flush(window.data()); + + QCOMPARE(bottomMPTA->property("xPressed").toInt(), 10); + QCOMPARE(bottomMPTA->property("yPressed").toInt(), 10); + QCOMPARE(bottomMPTA->property("xReleased").toInt(), 10); + QCOMPARE(bottomMPTA->property("yReleased").toInt(), 10); + +} + void tst_QQuickMultiPointTouchArea::inFlickable() { QScopedPointer<QQuickView> window(createAndShowView("inFlickable.qml")); @@ -592,7 +605,7 @@ void tst_QQuickMultiPointTouchArea::inFlickable() QPoint p1(20,100); QPoint p2(40,100); - // moving one point vertically + // moving one point vertically: flickable gets the grab QTest::touchEvent(window.data(), device).press(0, p1); QQuickTouchUtils::flush(window.data()); @@ -616,10 +629,14 @@ void tst_QQuickMultiPointTouchArea::inFlickable() QTRY_VERIFY(!flickable->isMoving()); - // moving two points vertically + // moving two points vertically: MPTAs handle them, Flickable ignores multi-touch. + // The stray mouse events simulate OS-level synth-from-touch, and should not interfere. p1 = QPoint(20,100); QTest::touchEvent(window.data(), device).press(0, p1).press(1, p2); - QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, p1); + QWindowSystemInterface::handleMouseEvent(window.data(), device, p1, window->mapToGlobal(p1), + Qt::LeftButton, Qt::LeftButton, QEvent::MouseButtonPress, + Qt::NoModifier, Qt::MouseEventSynthesizedBySystem); + qApp->processEvents(); QQuickTouchUtils::flush(window.data()); QCOMPARE(point11->pressed(), true); @@ -632,20 +649,26 @@ void tst_QQuickMultiPointTouchArea::inFlickable() QTest::qWait(250); p1 += delta; p2 += delta; QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2); - QTest::mouseMove(window.data(), p1); + QWindowSystemInterface::handleMouseEvent(window.data(), device, p1, window->mapToGlobal(p1), + Qt::LeftButton, Qt::NoButton, QEvent::MouseMove, + Qt::NoModifier, Qt::MouseEventSynthesizedBySystem); + qApp->processEvents(); QQuickTouchUtils::flush(window.data()); qCDebug(lcTests, "after drags %d to %d,%d and %d,%d contentY is %lf", i, p1.x(), p1.y(), p2.x(), p2.y(), flickable->contentY()); } - QVERIFY(flickable->contentY() < 0); - QCOMPARE(point11->pressed(), false); - QCOMPARE(point12->pressed(), false); - QCOMPARE(window->rootObject()->property("cancelCount").toInt(), 2); - QCOMPARE(window->rootObject()->property("touchCount").toInt(), 0); + QCOMPARE(flickable->contentY(), 0); + QCOMPARE(point11->pressed(), true); + QCOMPARE(point12->pressed(), true); + QCOMPARE(window->rootObject()->property("cancelCount").toInt(), 0); + QCOMPARE(window->rootObject()->property("touchCount").toInt(), 2); QTest::touchEvent(window.data(), device).release(0, p1).release(1, p2); - QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, p1); + QWindowSystemInterface::handleMouseEvent(window.data(), device, p1, window->mapToGlobal(p1), + Qt::NoButton, Qt::LeftButton, QEvent::MouseButtonRelease, + Qt::NoModifier, Qt::MouseEventSynthesizedBySystem); + qApp->processEvents(); QQuickTouchUtils::flush(window.data()); QTRY_VERIFY(!flickable->isMoving()); @@ -655,10 +678,15 @@ void tst_QQuickMultiPointTouchArea::inFlickable() p2 = QPoint(40,100); QTest::touchEvent(window.data(), device).press(0, p1).press(1, p2); QQuickTouchUtils::flush(window.data()); + QCOMPARE(point11->pressed(), true); + QCOMPARE(point12->pressed(), true); // ensure that mouse events do not fall through to the Flickable mpta->setMaximumTouchPoints(3); mpta->setAcceptedMouseButtons(Qt::LeftButton); - QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, p1); + QWindowSystemInterface::handleMouseEvent(window.data(), device, p1, window->mapToGlobal(p1), + Qt::LeftButton, Qt::LeftButton, QEvent::MouseButtonPress, + Qt::NoModifier, Qt::MouseEventSynthesizedBySystem); + qApp->processEvents(); QCOMPARE(point11->pressed(), true); QCOMPARE(point12->pressed(), true); @@ -671,32 +699,40 @@ void tst_QQuickMultiPointTouchArea::inFlickable() delta = QPoint(0, 15); p1 += delta; p2 += delta; QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2); - QTest::mouseMove(window.data(), p1); + QWindowSystemInterface::handleMouseEvent(window.data(), device, p1, window->mapToGlobal(p1), + Qt::LeftButton, Qt::NoButton, QEvent::MouseMove, + Qt::NoModifier, Qt::MouseEventSynthesizedBySystem); + qApp->processEvents(); QQuickTouchUtils::flush(window.data()); qCDebug(lcTests, "after drags %d to %d,%d and %d,%d contentY is %lf", i, p1.x(), p1.y(), p2.x(), p2.y(), flickable->contentY()); } - QEXPECT_FAIL("", "currently flickable does grab the actual mouse", Continue); QCOMPARE(flickable->contentY(), qreal(0)); QCOMPARE(point11->pressed(), true); - QEXPECT_FAIL("", "currently flickable does grab the actual mouse", Continue); QCOMPARE(point12->pressed(), true); QTest::touchEvent(window.data(), device).release(0, p1).release(1, p2); - QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, p1); + QWindowSystemInterface::handleMouseEvent(window.data(), device, p1, window->mapToGlobal(p1), + Qt::NoButton, Qt::LeftButton, QEvent::MouseButtonRelease, + Qt::NoModifier, Qt::MouseEventSynthesizedBySystem); + qApp->processEvents(); QQuickTouchUtils::flush(window.data()); } // test that dragging out of a Flickable containing a MPTA doesn't harm Flickable's state. void tst_QQuickMultiPointTouchArea::inFlickable2() { + const int dragThreshold = QGuiApplication::styleHints()->startDragDistance(); QScopedPointer<QQuickView> window(createAndShowView("inFlickable2.qml")); QVERIFY(window->rootObject() != nullptr); QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable"); QVERIFY(flickable != nullptr); + QQuickMultiPointTouchArea *mpta = window->rootObject()->findChild<QQuickMultiPointTouchArea*>(); + QVERIFY(mpta); + QQuickTouchPoint *point11 = window->rootObject()->findChild<QQuickTouchPoint*>("point1"); QVERIFY(point11); @@ -709,25 +745,12 @@ void tst_QQuickMultiPointTouchArea::inFlickable2() QQuickTouchUtils::flush(window.data()); QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, p1); - p1 += QPoint(15,0); - QTest::touchEvent(window.data(), device).move(0, p1); - QQuickTouchUtils::flush(window.data()); - QTest::mouseMove(window.data(), p1); - - p1 += QPoint(15,0); - QTest::touchEvent(window.data(), device).move(0, p1); - QQuickTouchUtils::flush(window.data()); - QTest::mouseMove(window.data(), p1); - - p1 += QPoint(15,0); - QTest::touchEvent(window.data(), device).move(0, p1); - QQuickTouchUtils::flush(window.data()); - QTest::mouseMove(window.data(), p1); - - p1 += QPoint(15,0); - QTest::touchEvent(window.data(), device).move(0, p1); - QQuickTouchUtils::flush(window.data()); - QTest::mouseMove(window.data(), p1); + for (int i = 0; i < 4; ++i) { + p1 += QPoint(dragThreshold, 0); + QTest::touchEvent(window.data(), device).move(0, p1); + QQuickTouchUtils::flush(window.data()); + QTest::mouseMove(window.data(), p1); + } QVERIFY(!flickable->isMoving()); QVERIFY(point11->pressed()); @@ -740,27 +763,21 @@ void tst_QQuickMultiPointTouchArea::inFlickable2() QTRY_VERIFY(!flickable->isMoving()); // Check that we can still move the Flickable + QSignalSpy gestureStartedSpy(mpta, &QQuickMultiPointTouchArea::gestureStarted); p1 = QPoint(50,100); QTest::touchEvent(window.data(), device).press(0, p1); QQuickTouchUtils::flush(window.data()); QCOMPARE(point11->pressed(), true); - p1 += QPoint(0,15); - QTest::touchEvent(window.data(), device).move(0, p1); - QQuickTouchUtils::flush(window.data()); - - p1 += QPoint(0,15); - QTest::touchEvent(window.data(), device).move(0, p1); - QQuickTouchUtils::flush(window.data()); - - p1 += QPoint(0,15); - QTest::touchEvent(window.data(), device).move(0, p1); - QQuickTouchUtils::flush(window.data()); - - p1 += QPoint(0,15); - QTest::touchEvent(window.data(), device).move(0, p1); - QQuickTouchUtils::flush(window.data()); + for (int i = 0; i < 4; ++i) { + p1 += QPoint(0, dragThreshold); + QTest::touchEvent(window.data(), device).move(0, p1); + QQuickTouchUtils::flush(window.data()); + // QTBUG-113653: gestureStarted is emitted when touch delta exceeds drag threshold, + // regardless of the filtering Flickable parent + QCOMPARE(gestureStartedSpy.size(), i > 0 ? 1 : 0); + } QVERIFY(flickable->contentY() < 0); QVERIFY(flickable->isMoving()); @@ -1051,10 +1068,13 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint() QPoint touch1(10,10); QPoint touch2(100,10); - touch1rect->setX(10); - touch1rect->setY(10); - touch2rect->setX(20); - touch2rect->setY(10); + // do not break the QML bindings + auto t1priv = QQuickItemPrivate::get(touch1rect); + auto t2priv = QQuickItemPrivate::get(touch2rect); + t1priv->x.setValueBypassingBindings(10); + t1priv->y.setValueBypassingBindings(10); + t2priv->x.setValueBypassingBindings(20); + t2priv->y.setValueBypassingBindings(10); // Start with mouse, move it, touch a point, move it, touch another. // Mouse is ignored, both touch points are heeded. @@ -1257,26 +1277,26 @@ void tst_QQuickMultiPointTouchArea::mouseGestureStarted() // QTBUG-70258 area->setProperty("grabGesture", grabGesture); QQuickTouchPoint *point1 = view->rootObject()->findChild<QQuickTouchPoint*>("point1"); QCOMPARE(point1->pressed(), false); - QSignalSpy gestureStartedSpy(area, SIGNAL(gestureStarted(QQuickGrabGestureEvent *))); + QSignalSpy gestureStartedSpy(area, SIGNAL(gestureStarted(QQuickGrabGestureEvent*))); QPoint p1 = QPoint(distanceFromOrigin, distanceFromOrigin); QTest::mousePress(view.data(), Qt::LeftButton, Qt::NoModifier, p1); - QCOMPARE(gestureStartedSpy.count(), 0); + QCOMPARE(gestureStartedSpy.size(), 0); p1 += QPoint(dragThreshold, dragThreshold); QTest::mouseMove(view.data(), p1); - QCOMPARE(gestureStartedSpy.count(), 0); + QCOMPARE(gestureStartedSpy.size(), 0); p1 += QPoint(1, 1); QTest::mouseMove(view.data(), p1); - QTRY_COMPARE(gestureStartedSpy.count(), 1); + QTRY_COMPARE(gestureStartedSpy.size(), 1); QTRY_COMPARE(area->property("gestureStartedX").toInt(), distanceFromOrigin); QCOMPARE(area->property("gestureStartedY").toInt(), distanceFromOrigin); p1 += QPoint(10, 10); QTest::mouseMove(view.data(), p1); // if nobody called gesteure->grab(), gestureStarted will keep happening - QTRY_COMPARE(gestureStartedSpy.count(), grabGesture ? 1 : 2); + QTRY_COMPARE(gestureStartedSpy.size(), grabGesture ? 1 : 2); QCOMPARE(area->property("gestureStartedX").toInt(), distanceFromOrigin); QCOMPARE(area->property("gestureStartedY").toInt(), distanceFromOrigin); @@ -1346,26 +1366,26 @@ void tst_QQuickMultiPointTouchArea::stationaryTouchWithChangingPressure() // QTB QCOMPARE(point1->pressed(), false); QPoint p1(20,100); - QMutableEventPoint tp1(1); + QEventPoint tp1(1); - tp1.setGlobalPosition(window->mapToGlobal(p1)); - tp1.setState(QEventPoint::State::Pressed); - tp1.setPressure(0.5); + QMutableEventPoint::setGlobalPosition(tp1, window->mapToGlobal(p1)); + QMutableEventPoint::setState(tp1, QEventPoint::State::Pressed); + QMutableEventPoint::setPressure(tp1, 0.5); qt_handleTouchEvent(window.data(), device, {tp1}); QQuickTouchUtils::flush(window.data()); QCOMPARE(point1->pressed(), true); QCOMPARE(point1->pressure(), 0.5); - tp1.setState(QEventPoint::State::Stationary); - tp1.setPressure(0.6); + QMutableEventPoint::setState(tp1, QEventPoint::State::Stationary); + QMutableEventPoint::setPressure(tp1, 0.6); qt_handleTouchEvent(window.data(), device, {tp1}); QQuickTouchUtils::flush(window.data()); QCOMPARE(point1->pressure(), 0.6); - tp1.setState(QEventPoint::State::Released); - tp1.setPressure(0); + QMutableEventPoint::setState(tp1, QEventPoint::State::Released); + QMutableEventPoint::setPressure(tp1, 0); qt_handleTouchEvent(window.data(), device, {tp1}); QQuickTouchUtils::flush(window.data()); @@ -1373,6 +1393,87 @@ void tst_QQuickMultiPointTouchArea::stationaryTouchWithChangingPressure() // QTB QCOMPARE(point1->pressure(), 0); } +void tst_QQuickMultiPointTouchArea::touchFiltering() // QTBUG-74028 +{ + QScopedPointer<QQuickView> window(createAndShowView("nestedMouseArea.qml")); + QVERIFY(window->rootObject() != nullptr); + QQuickMultiPointTouchArea *mpta = window->rootObject()->findChild<QQuickMultiPointTouchArea*>(); + QVERIFY(mpta); + QQuickMouseArea *ma = window->rootObject()->findChild<QQuickMouseArea*>(); + QVERIFY(ma); + + QSignalSpy mptaSpy(mpta, &QQuickMultiPointTouchArea::pressed); + const QPoint pt = window->rootObject()->boundingRect().center().toPoint(); + QTest::touchEvent(window.data(), device).press(1, pt); + QQuickTouchUtils::flush(window.data()); + QTRY_COMPARE(mpta->parentItem()->property("mptaPoint").toPoint(), pt); + QCOMPARE(mpta->parentItem()->property("maPoint").toPoint(), ma->boundingRect().center().toPoint()); + QCOMPARE(mptaSpy.size(), 1); +} + +void tst_QQuickMultiPointTouchArea::nestedPinchAreaMouse() // QTBUG-83662 +{ + QScopedPointer<QQuickView> window(createAndShowView("nestedPinchArea.qml")); + QQuickMultiPointTouchArea *mpta = qobject_cast<QQuickMultiPointTouchArea *>(window->rootObject()); + QVERIFY(mpta); + + QQuickTouchPoint *point1 = mpta->findChild<QQuickTouchPoint*>("point1"); + QCOMPARE(point1->pressed(), false); + QQuickTouchPoint *point2 = mpta->findChild<QQuickTouchPoint*>("point2"); + QCOMPARE(point2->pressed(), false); + QSignalSpy pressedSpy(mpta, &QQuickMultiPointTouchArea::pressed); + QSignalSpy updatedSpy(mpta, &QQuickMultiPointTouchArea::updated); + QSignalSpy releasedSpy(mpta, &QQuickMultiPointTouchArea::released); + + QPoint p1(20, 20); + QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, p1); + QCOMPARE(point1->pressed(), true); + QCOMPARE(point2->pressed(), false); + QCOMPARE(pressedSpy.size(), 1); + QCOMPARE(mpta->property("pressedCount").toInt(), 1); + QCOMPARE(updatedSpy.size(), 0); + QCOMPARE(mpta->property("updatedCount").toInt(), 0); + QCOMPARE(releasedSpy.size(), 0); + QCOMPARE(mpta->property("releasedCount").toInt(), 0); + + p1 += QPoint(0, 15); + QTest::mouseMove(window.data(), p1); + QCOMPARE(point1->pressed(), true); + QCOMPARE(point2->pressed(), false); + QCOMPARE(pressedSpy.size(), 1); + QCOMPARE(mpta->property("pressedCount").toInt(), 1); + QCOMPARE(updatedSpy.size(), 1); + QCOMPARE(mpta->property("updatedCount").toInt(), 1); + QCOMPARE(releasedSpy.size(), 0); + QCOMPARE(mpta->property("releasedCount").toInt(), 0); + + QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, p1); + QCOMPARE(point1->pressed(), false); + QCOMPARE(point2->pressed(), false); + QCOMPARE(pressedSpy.size(), 1); + QCOMPARE(mpta->property("pressedCount").toInt(), 1); + QCOMPARE(updatedSpy.size(), 1); + QCOMPARE(mpta->property("updatedCount").toInt(), 1); + QCOMPARE(releasedSpy.size(), 1); + QCOMPARE(mpta->property("releasedCount").toInt(), 1); +} + +/* + A disabled MultiPointTouchArea should not interfere with hover event + propagation to siblings underneath. +*/ +void tst_QQuickMultiPointTouchArea::disabledIgnoresHover() +{ + QScopedPointer<QQuickView> window(createAndShowView("touchOverMouseArea.qml")); + QQuickItem *root = qobject_cast<QQuickItem *>(window->rootObject()); + QVERIFY(root); + + QQuickMouseArea *mouseArea = root->findChild<QQuickMouseArea *>(); + + QTest::mouseMove(window.data(), QPoint(40, 40)); + QTest::mouseMove(window.data(), QPoint(50, 50)); + QVERIFY(mouseArea->hovered()); +} QTEST_MAIN(tst_QQuickMultiPointTouchArea) |