aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quick/pointerhandlers
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/quick/pointerhandlers')
-rw-r--r--tests/auto/quick/pointerhandlers/CMakeLists.txt3
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST22
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/CMakeLists.txt24
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/FlashAnimation.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/TapHandlerButton.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnFlickable.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnTable.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/pinchOnFlickable.qml49
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/pinchOnFlickableWithParentTapHandler.qml24
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnFlickable.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnList.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnTable.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp319
-rw-r--r--tests/auto/quick/pointerhandlers/mousearea_interop/BLACKLIST7
-rw-r--r--tests/auto/quick/pointerhandlers/mousearea_interop/CMakeLists.txt24
-rw-r--r--tests/auto/quick/pointerhandlers/mousearea_interop/data/dragHandlerInMouseAreaGrandparent.qml20
-rw-r--r--tests/auto/quick/pointerhandlers/mousearea_interop/data/dragTakeOverFromSibling.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/mousearea_interop/data/hoverHandlerInGrandparentOfHoverableItem.qml33
-rw-r--r--tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp103
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/BLACKLIST5
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/CMakeLists.txt24
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/dragParentOfMPTA.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/pinchDragMPTA.qml33
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/unloadHandlerOnPress.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp55
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/BLACKLIST9
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/CMakeLists.txt24
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/DragAnywhereSlider.qml33
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/FlashAnimation.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/Slider.qml33
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/dragAndWheel.qml32
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/dragHandlerUnderModalLayer.qml34
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml33
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/draghandler_and_pinchhandler.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/multipleSliders.qml55
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/simpleTapAndDragHandlers.qml37
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/snapMode.qml49
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp464
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/BLACKLIST5
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/CMakeLists.txt24
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/data/changingCursor.qml37
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverDeviceCursors.qml55
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverHandler.qml17
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml181
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/data/nohandler.qml15
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/data/windowCursorShape.qml13
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp523
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/BLACKLIST3
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/CMakeLists.txt24
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/data/nullTarget.qml33
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchAndDrag.qml37
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchproperties.qml88
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/data/threeFingers.qml36
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/data/transformedPinchHandler.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp743
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/CMakeLists.txt24
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/data/clip.qml36
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/data/grabberSceneChange.qml78
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/data/itemOnly.qml24
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/data/reparenting.qml40
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp291
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointhandler/BLACKLIST2
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointhandler/CMakeLists.txt24
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointhandler/data/multiPointTracker.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointhandler/data/pointTracker.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp215
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/BLACKLIST3
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/CMakeLists.txt24
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml46
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/FlashAnimation.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml41
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/dragReleaseMenu.qml64
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/nested.qml35
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/nestedAndSibling.qml39
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/simpleTapHandler.qml14
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/tapHandlersOverlapped.qml60
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp814
-rw-r--r--tests/auto/quick/pointerhandlers/qquickwheelhandler/CMakeLists.txt24
-rw-r--r--tests/auto/quick/pointerhandlers/qquickwheelhandler/data/nested.qml29
-rw-r--r--tests/auto/quick/pointerhandlers/qquickwheelhandler/data/rectWheel.qml45
-rw-r--r--tests/auto/quick/pointerhandlers/qquickwheelhandler/tst_qquickwheelhandler.cpp92
87 files changed, 4026 insertions, 2058 deletions
diff --git a/tests/auto/quick/pointerhandlers/CMakeLists.txt b/tests/auto/quick/pointerhandlers/CMakeLists.txt
index f8ac22d531..fcd00cddc6 100644
--- a/tests/auto/quick/pointerhandlers/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# Generated from pointerhandlers.pro.
if(QT_FEATURE_private_tests)
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST b/tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST
index 47c11f14d8..f5259a9e64 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST
@@ -5,7 +5,23 @@ opensuse-leap
windows gcc
[touchDragFlickableBehindButton]
windows gcc
+# QTBUG-95887
+[mouseDragSlider]
+opensuse-leap
+# QTBUG-95887
+[touchDragFlickableBehindButton]
+opensuse-leap
+# QTBUG-95887
+[mouseClickButton]
+opensuse-leap
+# QTBUG-95887
+[mouseDragFlickableBehindSlider]
+opensuse-leap
+# QTBUG-103061
+[touchDragFlickableBehindItemWithHandlers]
+android
+[mouseDragFlickableBehindItemWithHandlers]
+android
[touchAndDragHandlerOnFlickable]
-macos # QTBUG-86729
-[touchDragSliderAndFlickable]
-* # QTBUG-86729
+android
+
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/CMakeLists.txt b/tests/auto/quick/pointerhandlers/flickableinterop/CMakeLists.txt
index f67f9a0a59..3836aefbb2 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/CMakeLists.txt
@@ -1,9 +1,18 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# Generated from flickableinterop.pro.
#####################################################################
## tst_flickableinterop Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_flickableinterop 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_flickableinterop
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_flickableinterop.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}
)
@@ -38,10 +40,10 @@ qt_internal_add_test(tst_flickableinterop
qt_internal_extend_target(tst_flickableinterop CONDITION ANDROID OR IOS
DEFINES
- QT_QMLTEST_DATADIR=\\\":/data\\\"
+ QT_QMLTEST_DATADIR=":/data"
)
qt_internal_extend_target(tst_flickableinterop 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/pointerhandlers/flickableinterop/data/FlashAnimation.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/FlashAnimation.qml
index 4b2935b52e..9483a12d1c 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/FlashAnimation.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/FlashAnimation.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the manual tests 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) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml
index 7a32170bed..ec790c9b99 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 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) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml
index b3d621c447..cba135269f 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 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) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/TapHandlerButton.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/TapHandlerButton.qml
index 2c9fa30a70..99b53e6afb 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/TapHandlerButton.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/TapHandlerButton.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnFlickable.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnFlickable.qml
index 7bdae0e76b..f6748da19c 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnFlickable.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnFlickable.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml
index 00f3d66049..562dc156f9 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnTable.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnTable.qml
index ee63c1aa79..bbd5f5b278 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnTable.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnTable.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml
index 5693a6acd2..740b698fd4 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/pinchOnFlickable.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/pinchOnFlickable.qml
new file mode 100644
index 0000000000..e594f165b2
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/pinchOnFlickable.qml
@@ -0,0 +1,49 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Flickable {
+ id: root
+ width: 800
+ height: 480
+ contentWidth: 1000
+ contentHeight: 600
+
+ Rectangle {
+ id: pinchable
+ objectName: "pinchable"
+ border.color: "black"
+ color: pinch.active ? "salmon" : "peachpuff"
+ x: 100
+ y: 100
+ width: 200
+ height: 200
+ radius: 80
+ PinchHandler {
+ id: pinch
+ }
+ PointHandler {
+ id: p1
+ target: Rectangle {
+ parent: pinchable
+ color: "green"
+ visible: p1.active
+ x: p1.point.position.x - width / 2
+ y: p1.point.position.y - height / 2
+ width: 9; height: width; radius: width / 2
+ }
+ }
+ PointHandler {
+ id: p0
+ target: Rectangle {
+ parent: pinchable
+ color: "red"
+ visible: p0.active
+ x: p0.point.position.x - width / 2
+ y: p0.point.position.y - height / 2
+ width: 9; height: width; radius: width / 2
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/pinchOnFlickableWithParentTapHandler.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/pinchOnFlickableWithParentTapHandler.qml
new file mode 100644
index 0000000000..2660952f16
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/pinchOnFlickableWithParentTapHandler.qml
@@ -0,0 +1,24 @@
+import QtQuick
+
+Rectangle {
+ width: 320
+ height: 320
+
+ TapHandler {
+ onTapped: color = "tomato"
+ }
+
+ Flickable {
+ anchors.fill: parent
+ contentWidth: content.width
+ contentHeight: content.height
+ Rectangle {
+ id: content
+ objectName: "pinchable"
+ width: 150
+ height: 150
+ color: "wheat"
+ PinchHandler {}
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnFlickable.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnFlickable.qml
index 56ae514b96..dc32b1d82c 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnFlickable.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnFlickable.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnList.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnList.qml
index 2ad92e8b71..f4c0e5daaa 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnList.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnList.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnTable.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnTable.qml
index 46b01ee577..0293ad03b0 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnTable.qml
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnTable.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp
index 869ba80658..790c7c771e 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module 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) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -36,6 +11,7 @@
#include <QtQuick/private/qquickitemview_p.h>
#include <QtQuick/private/qquickpointerhandler_p.h>
#include <QtQuick/private/qquickdraghandler_p.h>
+#include <QtQuick/private/qquickpinchhandler_p.h>
#include <QtQuick/private/qquicktaphandler_p.h>
#include <QtQuick/private/qquicktableview_p.h>
#include <qpa/qwindowsysteminterface.h>
@@ -45,8 +21,8 @@
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlproperty.h>
-#include "../../../shared/util.h"
-#include "../../shared/viewtestutil.h"
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtQuickTestUtils/private/viewtestutils_p.h>
Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
@@ -55,7 +31,7 @@ class tst_FlickableInterop : public QQmlDataTest
Q_OBJECT
public:
tst_FlickableInterop()
- :touchDevice(QTest::createTouchDevice())
+ : QQmlDataTest(QT_QMLTEST_DATADIR)
{}
private slots:
@@ -79,10 +55,15 @@ private slots:
void touchDragSliderAndFlickable();
void touchAndDragHandlerOnFlickable_data();
void touchAndDragHandlerOnFlickable();
+ void pinchHandlerOnFlickable();
+ void nativeGesturePinchOnFlickableWithParentTapHandler_data();
+ void nativeGesturePinchOnFlickableWithParentTapHandler();
private:
void createView(QScopedPointer<QQuickView> &window, const char *fileName);
- QPointingDevice *touchDevice;
+ QScopedPointer<QPointingDevice> touchDevice = QScopedPointer<QPointingDevice>(QTest::createTouchDevice());
+ QScopedPointer<QPointingDevice> touchpad = QScopedPointer<QPointingDevice>(
+ QTest::createTouchDevice(QInputDevice::DeviceType::TouchPad));
};
void tst_FlickableInterop::createView(QScopedPointer<QQuickView> &window, const char *fileName)
@@ -90,8 +71,8 @@ void tst_FlickableInterop::createView(QScopedPointer<QQuickView> &window, const
window.reset(new QQuickView);
window->setSource(testFileUrl(fileName));
QTRY_COMPARE(window->status(), QQuickView::Ready);
- QQuickViewTestUtil::centerOnScreen(window.data());
- QQuickViewTestUtil::moveMouseAway(window.data());
+ QQuickViewTestUtils::centerOnScreen(window.data());
+ QQuickViewTestUtils::moveMouseAway(window.data());
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
@@ -121,27 +102,27 @@ void tst_FlickableInterop::touchTapButton()
// Button changes pressed state and emits tapped on release
QPoint p1 = button->mapToScene(QPointF(20, 20)).toPoint();
- QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).press(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(button->property("pressed").toBool());
- QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).release(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!button->property("pressed").toBool());
- QCOMPARE(tappedSpy.count(), 1);
+ QCOMPARE(tappedSpy.size(), 1);
// We can drag <= dragThreshold and the button still acts normal, Flickable doesn't grab
p1 = button->mapToScene(QPointF(20, 20)).toPoint();
- QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).press(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(button->property("pressed").toBool());
p1 += QPoint(dragThreshold, 0);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(button->property("pressed").toBool());
- QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).release(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!button->property("pressed").toBool());
- QCOMPARE(tappedSpy.count(), 2);
+ QCOMPARE(tappedSpy.size(), 2);
}
void tst_FlickableInterop::touchDragFlickableBehindButton_data()
@@ -169,11 +150,11 @@ void tst_FlickableInterop::touchDragFlickableBehindButton()
tappedSpy.clear();
QPoint p1 = button->mapToScene(QPointF(20, 20)).toPoint();
- QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).press(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(button->property("pressed").toBool());
p1 += QPoint(dragThreshold, 0);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(button->property("pressed").toBool());
int i = 0;
@@ -181,17 +162,17 @@ void tst_FlickableInterop::touchDragFlickableBehindButton()
// Button is no longer pressed because Flickable steals the grab
for (; i < 100 && !flickable->isMoving(); ++i) {
p1 += QPoint(1, 0);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
}
qCDebug(lcPointerTests) << "flickable started moving after" << i << "moves, when we got to" << p1;
QVERIFY(flickable->isMoving());
QCOMPARE(i, 2);
QVERIFY(!button->property("pressed").toBool());
- QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).release(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(!button->property("pressed").toBool());
- QCOMPARE(tappedSpy.count(), 0);
+ QCOMPARE(tappedSpy.size(), 0);
}
void tst_FlickableInterop::mouseClickButton_data()
@@ -221,7 +202,7 @@ void tst_FlickableInterop::mouseClickButton()
QTRY_VERIFY(button->property("pressed").toBool());
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
QTRY_VERIFY(!button->property("pressed").toBool());
- QCOMPARE(tappedSpy.count(), 1);
+ QCOMPARE(tappedSpy.size(), 1);
// We can drag <= dragThreshold and the button still acts normal, Flickable doesn't grab
p1 = button->mapToScene(QPointF(20, 20)).toPoint();
@@ -232,7 +213,7 @@ void tst_FlickableInterop::mouseClickButton()
QVERIFY(button->property("pressed").toBool());
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
QTRY_VERIFY(!button->property("pressed").toBool());
- QCOMPARE(tappedSpy.count(), 2);
+ QCOMPARE(tappedSpy.size(), 2);
}
void tst_FlickableInterop::mouseDragFlickableBehindButton_data()
@@ -265,7 +246,7 @@ void tst_FlickableInterop::mouseDragFlickableBehindButton()
QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
QTRY_VERIFY(button->property("pressed").toBool());
p1 += QPoint(dragThreshold, 0);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QVERIFY(button->property("pressed").toBool());
int i = 0;
for (; i < 100 && !flickable->isMoving(); ++i) {
@@ -278,7 +259,7 @@ void tst_FlickableInterop::mouseDragFlickableBehindButton()
QVERIFY(!button->property("pressed").toBool());
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
QVERIFY(!button->property("pressed").toBool());
- QCOMPARE(tappedSpy.count(), 0);
+ QCOMPARE(tappedSpy.size(), 0);
}
void tst_FlickableInterop::touchDragSlider()
@@ -297,24 +278,24 @@ void tst_FlickableInterop::touchDragSlider()
QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>();
QVERIFY(flickable);
QSignalSpy tappedSpy(knob->parent(), SIGNAL(tapped()));
- QSignalSpy translationChangedSpy(drag, SIGNAL(translationChanged()));
+ QSignalSpy translationChangedSpy(drag, &QQuickDragHandler::translationChanged);
// Drag the slider in the allowed (vertical) direction
tappedSpy.clear();
QPoint p1 = knob->mapToScene(knob->clipRect().center()).toPoint() - QPoint(0, 8);
- QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).press(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(slider->property("pressed").toBool());
p1 += QPoint(0, dragThreshold);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(slider->property("pressed").toBool());
QCOMPARE(slider->property("value").toInt(), 49);
p1 += QPoint(0, 1);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
p1 += QPoint(0, 10);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(slider->property("value").toInt() < 49);
QVERIFY(!flickable->isMoving());
@@ -323,15 +304,15 @@ void tst_FlickableInterop::touchDragSlider()
// Now that the DragHandler is active, the Flickable will not steal the grab
// even if we move a large distance horizontally
p1 += QPoint(dragThreshold * 2, 0);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(!flickable->isMoving());
// Release, and do not expect the tapped signal
- QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).release(1, p1, window);
QQuickTouchUtils::flush(window);
- QCOMPARE(tappedSpy.count(), 0);
- QCOMPARE(translationChangedSpy.count(), 1);
+ QCOMPARE(tappedSpy.size(), 0);
+ QCOMPARE(translationChangedSpy.size(), 1);
}
void tst_FlickableInterop::mouseDragSlider_data()
@@ -377,7 +358,7 @@ void tst_FlickableInterop::mouseDragSlider()
QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>();
QVERIFY(flickable);
QSignalSpy tappedSpy(knob->parent(), SIGNAL(tapped()));
- QSignalSpy translationChangedSpy(drag, SIGNAL(translationChanged()));
+ QSignalSpy translationChangedSpy(drag, &QQuickDragHandler::translationChanged);
// Drag the slider
tappedSpy.clear();
@@ -415,8 +396,8 @@ void tst_FlickableInterop::mouseDragSlider()
// Release, and do not expect the tapped signal
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
- QCOMPARE(tappedSpy.count(), 0);
- QCOMPARE(translationChangedSpy.count(), expectedDragHandlerActive ? 1 : 0);
+ QCOMPARE(tappedSpy.size(), 0);
+ QCOMPARE(translationChangedSpy.size(), expectedDragHandlerActive ? 1 : 0);
}
void tst_FlickableInterop::touchDragFlickableBehindSlider()
@@ -435,34 +416,34 @@ void tst_FlickableInterop::touchDragFlickableBehindSlider()
QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>();
QVERIFY(flickable);
QSignalSpy tappedSpy(knob->parent(), SIGNAL(tapped()));
- QSignalSpy translationChangedSpy(drag, SIGNAL(translationChanged()));
+ QSignalSpy translationChangedSpy(drag, &QQuickDragHandler::translationChanged);
// Button is no longer pressed if touchpoint goes beyond dragThreshold,
// because Flickable steals the grab
tappedSpy.clear();
QPoint p1 = knob->mapToScene(knob->clipRect().center()).toPoint();
- QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).press(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(slider->property("pressed").toBool());
p1 += QPoint(dragThreshold, 0);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(slider->property("pressed").toBool());
int i = 0;
for (; i < 100 && !flickable->isMoving(); ++i) {
p1 += QPoint(1, 0);
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
}
qCDebug(lcPointerTests) << "flickable started moving after" << i << "moves, when we got to" << p1;
QVERIFY(flickable->isMoving());
QCOMPARE(i, 2);
QVERIFY(!slider->property("pressed").toBool());
- QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).release(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(!slider->property("pressed").toBool());
- QCOMPARE(tappedSpy.count(), 0);
- QCOMPARE(translationChangedSpy.count(), 0);
+ QCOMPARE(tappedSpy.size(), 0);
+ QCOMPARE(translationChangedSpy.size(), 0);
}
void tst_FlickableInterop::mouseDragFlickableBehindSlider()
@@ -481,7 +462,7 @@ void tst_FlickableInterop::mouseDragFlickableBehindSlider()
QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>();
QVERIFY(flickable);
QSignalSpy tappedSpy(knob->parent(), SIGNAL(tapped()));
- QSignalSpy translationChangedSpy(drag, SIGNAL(translationChanged()));
+ QSignalSpy translationChangedSpy(drag, &QQuickDragHandler::translationChanged);
// Button is no longer pressed if touchpoint goes beyond dragThreshold,
// because Flickable steals the grab
@@ -503,8 +484,8 @@ void tst_FlickableInterop::mouseDragFlickableBehindSlider()
QCOMPARE(i, 2);
QVERIFY(!slider->property("pressed").toBool());
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
- QCOMPARE(tappedSpy.count(), 0);
- QCOMPARE(translationChangedSpy.count(), 0);
+ QCOMPARE(tappedSpy.size(), 0);
+ QCOMPARE(translationChangedSpy.size(), 0);
}
void tst_FlickableInterop::touchDragFlickableBehindItemWithHandlers_data()
@@ -532,19 +513,19 @@ void tst_FlickableInterop::touchDragFlickableBehindItemWithHandlers()
QPoint p1 = rect->mapToScene(rect->clipRect().center()).toPoint();
QPoint originP1 = p1;
- QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).press(1, p1, window);
QQuickTouchUtils::flush(window);
for (int i = 0; i < dragThreshold * 3; ++i) {
p1 = originP1;
p1.rx() += i;
- QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).move(1, p1, window);
QQuickTouchUtils::flush(window);
}
QCOMPARE(flickable->isMoving(), expectedFlickableMoving);
if (!expectedFlickableMoving) {
QVERIFY(rect->mapToScene(rect->clipRect().center()).toPoint().x() > originP1.x());
}
- QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QTest::touchEvent(window, touchDevice.get()).release(1, p1, window);
QQuickTouchUtils::flush(window);
}
@@ -609,7 +590,7 @@ void tst_FlickableInterop::touchDragSliderAndFlickable()
QVERIFY(knob);
QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>();
QVERIFY(flickable);
- QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window, touchDevice, false);
+ QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window, touchDevice.get(), false);
// The knob is initially centered over the slider's "groove"
qreal initialXOffset = qAbs(knob->mapToScene(knob->clipRect().center()).x() - slider->mapToScene
@@ -647,7 +628,10 @@ void tst_FlickableInterop::touchDragSliderAndFlickable()
QQuickTouchUtils::flush(window);
qCDebug(lcPointerTests) << "step" << i << ": fingers @" << p1 << p2 << "is Flickable moving yet?" << flickable->isMoving();
}
- QVERIFY(flickable->isMoving());
+ // In Qt 6, Flickable doesn't see the second touchpoint, so it doesn't move.
+ // One way to see this is that Flickable is more immune to stray touches than it otherwise would be.
+ // But time will tell if we are missing out on something useful, which was possible in Qt 5 (QTBUG-123490).
+ QCOMPARE(flickable->isMoving(), false);
qreal knobSliderXOffset = qAbs(knob->mapToScene(knob->clipRect().center()).toPoint().x() -
slider->mapToScene(slider->clipRect().center()).toPoint().x()) - initialXOffset;
if (knobSliderXOffset > 1)
@@ -739,7 +723,7 @@ void tst_FlickableInterop::touchAndDragHandlerOnFlickable()
}
// Drag one finger on the Flickable (between delegates) and make sure it flicks
- QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window, touchDevice, false);
+ QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window, touchDevice.get(), false);
QPoint p1(780, 460);
if (delegate)
p1 = delegate->mapToScene(delegate->clipRect().bottomRight()).toPoint() + QPoint(-1, 1);
@@ -806,6 +790,187 @@ void tst_FlickableInterop::touchAndDragHandlerOnFlickable()
touchSeq.release(1, p1, window).commit();
}
+void tst_FlickableInterop::pinchHandlerOnFlickable()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("pinchOnFlickable.qml")));
+ QQuickFlickable *flickable = qmlobject_cast<QQuickFlickable*>(window.rootObject());
+ QVERIFY(flickable);
+ QQuickPointerHandler *pinchHandler = flickable->findChild<QQuickPointerHandler*>();
+ QVERIFY(pinchHandler);
+ QQuickItem *pinchable = pinchHandler->target();
+ QVERIFY(pinchable);
+
+ QSignalSpy flickMoveSpy(flickable, &QQuickFlickable::movementStarted);
+ QSignalSpy grabChangedSpy(touchDevice.get(), &QPointingDevice::grabChanged);
+
+ QObject *grabber = nullptr;
+ connect(touchDevice.get(), &QPointingDevice::grabChanged,
+ [&grabber](QObject *g, QPointingDevice::GrabTransition transition, const QPointerEvent *, const QEventPoint &) {
+ if (transition == QPointingDevice::GrabTransition::GrabExclusive)
+ grabber = g;
+ });
+
+ QPoint p0 = pinchable->mapToScene({50, 100}).toPoint();
+ QPoint p1 = pinchable->mapToScene({150, 100}).toPoint();
+ QTest::QTouchEventSequence touch = QTest::touchEvent(&window, touchDevice.get());
+
+ touch.press(0, p0, &window).press(1, p1, &window).commit();
+ QQuickTouchUtils::flush(&window);
+ int activeStep = -1;
+ int grabTransitionCount = 0;
+ // drag two fingers down: PinchHandler moves the item; Flickable doesn't grab, because there are 2 points
+ for (int i = 0; i < 4; ++i) {
+ p0 += QPoint(0, dragThreshold);
+ p1 += QPoint(0, dragThreshold);
+ touch.move(0, p0, &window).move(1, p1, &window).commit();
+ QQuickTouchUtils::flush(&window);
+ if (pinchHandler->active() && activeStep < 0) {
+ qCDebug(lcPointerTests) << "pinch began at step" << i;
+ activeStep = i;
+ QCOMPARE(grabber, pinchHandler);
+ grabTransitionCount = grabChangedSpy.count();
+ }
+ }
+ QVERIFY(pinchHandler->active());
+ QCOMPARE(grabChangedSpy.count(), grabTransitionCount);
+ QCOMPARE(grabber, pinchHandler);
+ qreal scale = pinchable->scale();
+ QCOMPARE(scale, 1);
+ qreal rot = pinchable->rotation();
+ QCOMPARE(rot, 0);
+ // start expanding and rotating
+ for (int i = 0; i < 4; ++i) {
+ p0 += QPoint(-5, 10);
+ p1 += QPoint(5, -10);
+ touch.move(0, p0, &window).move(1, p1, &window).commit();
+ QQuickTouchUtils::flush(&window);
+ QVERIFY(pinchHandler->active());
+ // PinchHandler keeps grab: no more transitions
+ QCOMPARE(grabChangedSpy.count(), grabTransitionCount);
+ QCOMPARE(grabber, pinchHandler);
+ QTRY_COMPARE_GT(pinchable->scale(), scale);
+ scale = pinchable->scale();
+ QCOMPARE_LT(pinchable->rotation(), rot);
+ rot = pinchable->rotation();
+ }
+ touch.release(0, p0, &window).release(1, p1, &window).commit();
+ QQuickTouchUtils::flush(&window);
+ QTRY_COMPARE(pinchHandler->active(), false);
+ QCOMPARE(flickMoveSpy.count(), 0); // Flickable never moved
+}
+
+void tst_FlickableInterop::nativeGesturePinchOnFlickableWithParentTapHandler_data()
+{
+ QTest::addColumn<const QPointingDevice*>("device");
+ QTest::addColumn<Qt::MouseButton>("button");
+ QTest::addColumn<Qt::NativeGestureType>("gesture");
+ QTest::addColumn<qreal>("value");
+ QTest::addColumn<qreal>("expectedPropertyValue");
+
+ const QPointingDevice *constTouchPad = touchpad.data();
+
+ QTest::newRow("touchpad: left and rotate") << constTouchPad << Qt::LeftButton << Qt::RotateNativeGesture << 5.0 << 10.0;
+ QTest::newRow("touchpad: right and rotate") << constTouchPad << Qt::RightButton << Qt::RotateNativeGesture << 5.0 << 10.0;
+ QTest::newRow("touchpad: left and scale") << constTouchPad << Qt::LeftButton << Qt::ZoomNativeGesture << 0.1 << 1.21;
+ QTest::newRow("touchpad: right and scale") << constTouchPad << Qt::RightButton << Qt::ZoomNativeGesture << 0.1 << 1.21;
+
+ const auto *mouse = QPointingDevice::primaryPointingDevice();
+ if (mouse->type() == QInputDevice::DeviceType::Mouse) {
+ QTest::newRow("mouse: left and rotate") << mouse << Qt::LeftButton << Qt::RotateNativeGesture << 5.0 << 10.0;
+ QTest::newRow("mouse: right and rotate") << mouse << Qt::RightButton << Qt::RotateNativeGesture << 5.0 << 10.0;
+ QTest::newRow("mouse: left and scale") << mouse << Qt::LeftButton << Qt::ZoomNativeGesture << 0.1 << 1.21;
+ QTest::newRow("mouse: right and scale") << mouse << Qt::RightButton << Qt::ZoomNativeGesture << 0.1 << 1.21;
+ } else {
+ qCWarning(lcPointerTests) << "skipping mouse tests: primary device is not a mouse" << mouse;
+ }
+}
+
+void tst_FlickableInterop::nativeGesturePinchOnFlickableWithParentTapHandler()
+{
+ QFETCH(const QPointingDevice*, device);
+ QFETCH(Qt::MouseButton, button);
+ QFETCH(Qt::NativeGestureType, gesture);
+ QFETCH(qreal, value);
+ QFETCH(qreal, expectedPropertyValue);
+
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("pinchOnFlickableWithParentTapHandler.qml")));
+ QQuickFlickable *flickable = window.rootObject()->findChild<QQuickFlickable*>();
+ QVERIFY(flickable);
+ QQuickPointerHandler *pinchHandler = flickable->findChild<QQuickPinchHandler*>();
+ QVERIFY(pinchHandler);
+ QQuickItem *pinchable = pinchHandler->target();
+ QVERIFY(pinchable);
+ QQuickTapHandler *tapHandler = window.rootObject()->findChild<QQuickTapHandler*>();
+ QVERIFY(tapHandler);
+ const bool expectTap = button & tapHandler->acceptedButtons();
+
+ QSignalSpy flickMoveSpy(flickable, &QQuickFlickable::movementStarted);
+ QSignalSpy grabChangedSpy(touchDevice.get(), &QPointingDevice::grabChanged);
+ QSignalSpy tapActiveSpy(tapHandler, &QQuickTapHandler::activeChanged);
+ QSignalSpy tapSpy(tapHandler, &QQuickTapHandler::tapped);
+
+ QObject *grabber = nullptr;
+ connect(device, &QPointingDevice::grabChanged,
+ [&grabber](QObject *g, QPointingDevice::GrabTransition transition, const QPointerEvent *, const QEventPoint &) {
+ if (transition == QPointingDevice::GrabTransition::GrabExclusive)
+ grabber = g;
+ });
+
+ const QPoint pinchPos(75, 75);
+ const QPoint outsidePos(200, 200);
+
+ // move to position
+ QTest::mouseMove(&window, pinchPos);
+
+ // pinch via native gesture
+ ulong ts = 502; // after the mouse move, which is at time 501 in practice
+ QWindowSystemInterface::handleGestureEvent(&window, ts++, touchpad.get(),
+ Qt::BeginNativeGesture, pinchPos, pinchPos);
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
+ for (int i = 0; i < 2; ++i) {
+ QWindowSystemInterface::handleGestureEventWithRealValue(&window, ts++, touchpad.get(),
+ gesture, value, pinchPos, pinchPos);
+ }
+ if (gesture == Qt::RotateNativeGesture)
+ QTRY_COMPARE(pinchHandler->parentItem()->rotation(), expectedPropertyValue);
+ else if (gesture == Qt::ZoomNativeGesture)
+ QTRY_COMPARE(pinchHandler->parentItem()->scale(), expectedPropertyValue);
+ QVERIFY(pinchHandler->active());
+ QCOMPARE(grabChangedSpy.count(), 0);
+ QCOMPARE(grabber, nullptr);
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
+ QWindowSystemInterface::handleGestureEvent(&window, ts++, touchpad.get(),
+ Qt::EndNativeGesture, pinchPos, pinchPos);
+
+ // tap in square: TapHandler detects tap iff acceptedButtons permits
+ // TODO delay; unfortunately this also begins at timestamp 502 because we don't have testlib
+ // functions to send gesture events, and QQuickTest::pointerPress() doesn't take a delay value
+ QQuickTest::pointerPress(device, &window, 0, pinchPos, button);
+ QCOMPARE(tapHandler->point().id(), expectTap ? 0 : -1);
+ QQuickTest::pointerRelease(device, &window, 0, pinchPos, button);
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
+ QCOMPARE(tapSpy.size() != 0, expectTap);
+ QCOMPARE(tapActiveSpy.size(), 0);
+ QCOMPARE(tapHandler->point().id(), -1); // does not keep tracking after release
+
+ // move outside: nothing should happen;
+ // but QTBUG-108896 happened because TapHandler was setting pointInfo to track this moving point
+ QQuickTest::pointerMove(device, &window, 0, outsidePos);
+ QCOMPARE(tapHandler->point().id(), -1); // does not track after mouse move
+
+ // tap outside: nothing happens
+ tapSpy.clear();
+ tapActiveSpy.clear();
+ QQuickTest::pointerPress(device, &window, 0, outsidePos, button);
+ QQuickTest::pointerRelease(device, &window, 0, outsidePos, button);
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
+ QCOMPARE(tapSpy.size(), 0);
+ QCOMPARE(tapActiveSpy.size(), 0);
+}
+
QTEST_MAIN(tst_FlickableInterop)
#include "tst_flickableinterop.moc"
diff --git a/tests/auto/quick/pointerhandlers/mousearea_interop/BLACKLIST b/tests/auto/quick/pointerhandlers/mousearea_interop/BLACKLIST
new file mode 100644
index 0000000000..74d29b4ac3
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/mousearea_interop/BLACKLIST
@@ -0,0 +1,7 @@
+# QTBUG-95938
+[dragHandlerInSiblingStealingGrabFromMouseAreaViaTouch]
+opensuse-leap
+
+# QTBUG-95938
+[dragHandlerInSiblingStealingGrabFromMouseAreaViaMouse]
+opensuse-leap
diff --git a/tests/auto/quick/pointerhandlers/mousearea_interop/CMakeLists.txt b/tests/auto/quick/pointerhandlers/mousearea_interop/CMakeLists.txt
index f799de97b8..22123e6385 100644
--- a/tests/auto/quick/pointerhandlers/mousearea_interop/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/mousearea_interop/CMakeLists.txt
@@ -1,9 +1,18 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# Generated from mousearea_interop.pro.
#####################################################################
## tst_mousearea_interop Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_mousearea_interop 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_mousearea_interop
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_mousearea_interop.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}
)
@@ -38,10 +40,10 @@ qt_internal_add_test(tst_mousearea_interop
qt_internal_extend_target(tst_mousearea_interop CONDITION ANDROID OR IOS
DEFINES
- QT_QMLTEST_DATADIR=\\\":/data\\\"
+ QT_QMLTEST_DATADIR=":/data"
)
qt_internal_extend_target(tst_mousearea_interop 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/pointerhandlers/mousearea_interop/data/dragHandlerInMouseAreaGrandparent.qml b/tests/auto/quick/pointerhandlers/mousearea_interop/data/dragHandlerInMouseAreaGrandparent.qml
new file mode 100644
index 0000000000..7adb205a1f
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/mousearea_interop/data/dragHandlerInMouseAreaGrandparent.qml
@@ -0,0 +1,20 @@
+import QtQuick 2.12
+
+Rectangle {
+ width: 200; height: 200
+
+ DragHandler { }
+
+ Rectangle {
+ objectName: "button"
+ width: 100; height: 40; x: 10; y: 10
+ border.color: "orange"
+ color: ma.pressed ? "lightsteelblue" : "beige"
+
+ MouseArea {
+ id: ma
+ anchors.fill: parent
+ onDoubleClicked: console.log("__")
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/mousearea_interop/data/dragTakeOverFromSibling.qml b/tests/auto/quick/pointerhandlers/mousearea_interop/data/dragTakeOverFromSibling.qml
index 48b1dc86f0..1bde433dba 100644
--- a/tests/auto/quick/pointerhandlers/mousearea_interop/data/dragTakeOverFromSibling.qml
+++ b/tests/auto/quick/pointerhandlers/mousearea_interop/data/dragTakeOverFromSibling.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/mousearea_interop/data/hoverHandlerInGrandparentOfHoverableItem.qml b/tests/auto/quick/pointerhandlers/mousearea_interop/data/hoverHandlerInGrandparentOfHoverableItem.qml
new file mode 100644
index 0000000000..a3b957a1f7
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/mousearea_interop/data/hoverHandlerInGrandparentOfHoverableItem.qml
@@ -0,0 +1,33 @@
+import QtQuick 2.12
+
+Item {
+ width: 320
+ height: 240
+
+ Rectangle {
+ color: hh.hovered ? "orange" : "gray"
+ anchors.fill: container
+ }
+
+ Item {
+ id: container
+ anchors.fill: parent
+ anchors.margins: 40
+
+ Rectangle {
+ width: parent.width
+ height: 40
+ color: ma.pressed ? "blue" : ma.containsMouse ? "aquamarine" : "beige"
+
+ MouseArea {
+ id: ma
+ anchors.fill: parent
+ hoverEnabled: true
+ }
+ }
+
+ HoverHandler {
+ id: hh
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp b/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp
index 4709622245..b1a480b9cf 100644
--- a/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp
+++ b/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp
@@ -1,43 +1,22 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module 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) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
+#include <QtGui/qstylehints.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlproperty.h>
#include <QtQuick/private/qquickdraghandler_p.h>
+#include <QtQuick/private/qquickhoverhandler_p.h>
#include <QtQuick/private/qquickmousearea_p.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.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>
+
+#include <QtCore/qpointer.h>
Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
@@ -46,12 +25,15 @@ class tst_MouseAreaInterop : public QQmlDataTest
Q_OBJECT
public:
tst_MouseAreaInterop()
+ : QQmlDataTest(QT_QMLTEST_DATADIR)
{}
private slots:
void dragHandlerInSiblingStealingGrabFromMouseAreaViaMouse();
void dragHandlerInSiblingStealingGrabFromMouseAreaViaTouch_data();
void dragHandlerInSiblingStealingGrabFromMouseAreaViaTouch();
+ void hoverHandlerDoesntHoverOnPress();
+ void doubleClickInMouseAreaWithDragHandlerInGrandparent();
private:
void createView(QScopedPointer<QQuickView> &window, const char *fileName);
@@ -63,8 +45,8 @@ void tst_MouseAreaInterop::createView(QScopedPointer<QQuickView> &window, const
window.reset(new QQuickView);
window->setSource(testFileUrl(fileName));
QTRY_COMPARE(window->status(), QQuickView::Ready);
- QQuickViewTestUtil::centerOnScreen(window.data());
- QQuickViewTestUtil::moveMouseAway(window.data());
+ QQuickViewTestUtils::centerOnScreen(window.data());
+ QQuickViewTestUtils::moveMouseAway(window.data());
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
@@ -86,7 +68,7 @@ void tst_MouseAreaInterop::dragHandlerInSiblingStealingGrabFromMouseAreaViaMouse
QPoint p1(150, 150);
QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
QCOMPARE(window->mouseGrabberItem(), ma);
- QCOMPARE(ma->pressed(), true);
+ QCOMPARE(ma->isPressed(), true);
// Start dragging
// DragHandler keeps monitoring, due to its passive grab,
@@ -104,7 +86,7 @@ void tst_MouseAreaInterop::dragHandlerInSiblingStealingGrabFromMouseAreaViaMouse
qCDebug(lcPointerTests, "DragHandler stole the grab after %d events", dragStoleGrab);
QVERIFY(dragStoleGrab > 1);
QCOMPARE(handler->active(), true);
- QCOMPARE(ma->pressed(), false);
+ QCOMPARE(ma->isPressed(), false);
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
QCOMPARE(handler->active(), false);
@@ -145,7 +127,7 @@ void tst_MouseAreaInterop::dragHandlerInSiblingStealingGrabFromMouseAreaViaTouch
QVERIFY(epd);
QVERIFY(epd->passiveGrabbers.contains(handler.data()));
QCOMPARE(epd->exclusiveGrabber, ma);
- QCOMPARE(ma->pressed(), true);
+ QCOMPARE(ma->isPressed(), true);
// Start dragging
// DragHandler keeps monitoring, due to its passive grab,
@@ -163,11 +145,11 @@ void tst_MouseAreaInterop::dragHandlerInSiblingStealingGrabFromMouseAreaViaTouch
if (preventStealing) {
QCOMPARE(dragStoleGrab, 0);
QCOMPARE(handler->active(), false);
- QCOMPARE(ma->pressed(), true);
+ QCOMPARE(ma->isPressed(), true);
} else {
QVERIFY(dragStoleGrab > 1);
QCOMPARE(handler->active(), true);
- QCOMPARE(ma->pressed(), false);
+ QCOMPARE(ma->isPressed(), false);
}
touch.release(1, p1).commit();
@@ -175,6 +157,55 @@ void tst_MouseAreaInterop::dragHandlerInSiblingStealingGrabFromMouseAreaViaTouch
QCOMPARE(handler->active(), false);
}
+void tst_MouseAreaInterop::hoverHandlerDoesntHoverOnPress() // QTBUG-72843
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("hoverHandlerInGrandparentOfHoverableItem.qml")));
+
+ QPointer<QQuickHoverHandler> handler = window.rootObject()->findChild<QQuickHoverHandler*>();
+ QVERIFY(handler);
+ QQuickMouseArea *ma = window.rootObject()->findChild<QQuickMouseArea*>();
+ QVERIFY(ma);
+ QPoint p = ma->mapToScene(ma->boundingRect().center()).toPoint();
+
+ // move the mouse below the "button" but within HoverHandler's region of interest
+ QTest::mouseMove(&window, p + QPoint(0, 50));
+ QTRY_COMPARE(handler->isHovered(), true);
+ // move the mouse into the "button"
+ QTest::mouseMove(&window, p);
+ // both the hoverhandler and the mouse area should now be hovered!
+ QTRY_COMPARE(handler->isHovered(), true);
+ QCOMPARE(ma->hovered(), true);
+
+ QSignalSpy hoveredChangedSpy(handler, SIGNAL(hoveredChanged()));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, p);
+ QTRY_COMPARE(ma->isPressed(), true);
+ QCOMPARE(handler->isHovered(), true);
+ QCOMPARE(hoveredChangedSpy.size(), 0);
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, p);
+ QTRY_COMPARE(ma->isPressed(), false);
+ QCOMPARE(handler->isHovered(), true);
+ QCOMPARE(hoveredChangedSpy.size(), 0);
+}
+
+void tst_MouseAreaInterop::doubleClickInMouseAreaWithDragHandlerInGrandparent()
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("dragHandlerInMouseAreaGrandparent.qml")));
+
+ QQuickDragHandler *handler = window.rootObject()->findChild<QQuickDragHandler*>();
+ QVERIFY(handler);
+ QSignalSpy dragActiveSpy(handler, &QQuickDragHandler::activeChanged);
+ QQuickMouseArea *ma = window.rootObject()->findChild<QQuickMouseArea*>();
+ QVERIFY(ma);
+ QSignalSpy dClickSpy(ma, &QQuickMouseArea::doubleClicked);
+ QPoint p = ma->mapToScene(ma->boundingRect().center()).toPoint();
+
+ QTest::mouseDClick(&window, Qt::LeftButton, Qt::NoModifier, p);
+ QCOMPARE(dClickSpy.size(), 1);
+ QCOMPARE(dragActiveSpy.size(), 0);
+}
+
QTEST_MAIN(tst_MouseAreaInterop)
#include "tst_mousearea_interop.moc"
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/BLACKLIST b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/BLACKLIST
index 3f01d3a7d4..80d6dd0ee8 100644
--- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/BLACKLIST
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/BLACKLIST
@@ -1,2 +1,3 @@
-[touchesThenPinch]
-* # QTBUG-86729
+# QTBUG-118062
+[touchDrag]
+opensuse-leap
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/CMakeLists.txt b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/CMakeLists.txt
index 4aac9440f9..9f19e8b427 100644
--- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/CMakeLists.txt
@@ -1,9 +1,18 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# Generated from multipointtoucharea_interop.pro.
#####################################################################
## tst_multipointtoucharea_interop Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_multipointtoucharea_interop 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_multipointtoucharea_interop
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_multipointtoucharea_interop.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}
)
@@ -38,10 +40,10 @@ qt_internal_add_test(tst_multipointtoucharea_interop
qt_internal_extend_target(tst_multipointtoucharea_interop CONDITION ANDROID OR IOS
DEFINES
- QT_QMLTEST_DATADIR=\\\":/data\\\"
+ QT_QMLTEST_DATADIR=":/data"
)
qt_internal_extend_target(tst_multipointtoucharea_interop 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/pointerhandlers/multipointtoucharea_interop/data/dragParentOfMPTA.qml b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/dragParentOfMPTA.qml
index dc7e5f6411..ad4494eb25 100644
--- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/dragParentOfMPTA.qml
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/dragParentOfMPTA.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/pinchDragMPTA.qml b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/pinchDragMPTA.qml
index f1591a412e..199292e015 100644
--- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/pinchDragMPTA.qml
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/pinchDragMPTA.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
@@ -60,8 +35,8 @@ Rectangle {
Item {
id: crosshairs
property TouchPoint touchPoint
- x: touchPoint.x - width / 2
- y: touchPoint.y - height / 2
+ x: touchPoint?.x - width / 2
+ y: touchPoint?.y - height / 2
width: 300; height: 300
visible: touchPoint.pressed
rotation: touchPoint.rotation
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/unloadHandlerOnPress.qml b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/unloadHandlerOnPress.qml
index 1bd20c6bcb..868a5265a6 100644
--- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/unloadHandlerOnPress.qml
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/unloadHandlerOnPress.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
index 0312ed0141..a4cc182422 100644
--- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module 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) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -37,8 +12,10 @@
#include <QtQuick/qquickview.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>
+
+#include <QtCore/qpointer.h>
Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
@@ -47,6 +24,7 @@ class tst_MptaInterop : public QQmlDataTest
Q_OBJECT
public:
tst_MptaInterop()
+ : QQmlDataTest(QT_QMLTEST_DATADIR)
{}
private slots:
@@ -67,8 +45,8 @@ void tst_MptaInterop::createView(QScopedPointer<QQuickView> &window, const char
window.reset(new QQuickView);
window->setSource(testFileUrl(fileName));
QTRY_COMPARE(window->status(), QQuickView::Ready);
- QQuickViewTestUtil::centerOnScreen(window.data());
- QQuickViewTestUtil::moveMouseAway(window.data());
+ QQuickViewTestUtils::centerOnScreen(window.data());
+ QQuickViewTestUtils::moveMouseAway(window.data());
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
@@ -169,7 +147,7 @@ void tst_MptaInterop::touchesThenPinch()
QQuickTouchUtils::flush(window);
QVERIFY(tp.at(0)->property("pressed").toBool());
QTRY_VERIFY(tp.at(1)->property("pressed").toBool());
- QCOMPARE(mptaPressedSpy.count(), 2);
+ QCOMPARE(mptaPressedSpy.size(), 2);
// Press a third touchpoint: MPTA grabs it too
QPoint p3 = mpta->mapToScene(QPointF(110, 200)).toPoint();
@@ -178,8 +156,8 @@ void tst_MptaInterop::touchesThenPinch()
QCOMPARE(tp.at(0)->property("pressed").toBool(), true);
QCOMPARE(tp.at(1)->property("pressed").toBool(), true);
QCOMPARE(tp.at(2)->property("pressed").toBool(), true);
- QCOMPARE(mptaPressedSpy.count(), 3);
- QCOMPARE(mptaCanceledSpy.count(), 0);
+ QCOMPARE(mptaPressedSpy.size(), 3);
+ QCOMPARE(mptaCanceledSpy.size(), 0);
QCOMPARE(devPriv->pointById(1)->exclusiveGrabber, mpta);
QCOMPARE(devPriv->pointById(2)->exclusiveGrabber, mpta);
QCOMPARE(devPriv->pointById(3)->exclusiveGrabber, mpta);
@@ -272,13 +250,14 @@ void tst_MptaInterop::touchesThenPinch()
if (!dragTookGrab && devPriv->pointById(2)->exclusiveGrabber == drag)
dragTookGrab = i;
}
- qCDebug(lcPointerTests) << "drag started after" << dragTookGrab << "moves; ended with translation" << drag->translation();
- QCOMPARE(devPriv->pointById(1)->exclusiveGrabber, drag);
- QTRY_VERIFY(drag->translation().x() > 0);
+ qCDebug(lcPointerTests) << "drag started after" << dragTookGrab
+ << "moves; ended with translation" << drag->activeTranslation();
+ QCOMPARE(devPriv->pointById(2)->exclusiveGrabber, drag);
+ QTRY_VERIFY(drag->activeTranslation().x() > 0);
touch.release(2, p2).commit();
QQuickTouchUtils::flush(window);
- QTRY_COMPARE(mptaReleasedSpy.count(), 1);
+ QTRY_COMPARE(mptaReleasedSpy.size(), 1);
}
void tst_MptaInterop::unloadHandlerWithPassiveGrab()
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/BLACKLIST b/tests/auto/quick/pointerhandlers/qquickdraghandler/BLACKLIST
new file mode 100644
index 0000000000..e555a4bb61
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/BLACKLIST
@@ -0,0 +1,9 @@
+# QTBUG-103064
+[touchDragMulti]
+android
+[touchDrag]
+android
+[touchDragMultiSliders]
+android
+[touchPassiveGrabbers]
+android
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/CMakeLists.txt b/tests/auto/quick/pointerhandlers/qquickdraghandler/CMakeLists.txt
index 85c664f8ca..23087c1d48 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/CMakeLists.txt
@@ -1,9 +1,18 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# Generated from qquickdraghandler.pro.
#####################################################################
## tst_qquickdraghandler Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickdraghandler 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_qquickdraghandler
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_qquickdraghandler.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}
)
@@ -38,10 +40,10 @@ qt_internal_add_test(tst_qquickdraghandler
qt_internal_extend_target(tst_qquickdraghandler CONDITION ANDROID OR IOS
DEFINES
- QT_QMLTEST_DATADIR=\\\":/data\\\"
+ QT_QMLTEST_DATADIR=":/data"
)
qt_internal_extend_target(tst_qquickdraghandler 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/pointerhandlers/qquickdraghandler/data/DragAnywhereSlider.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/DragAnywhereSlider.qml
index 778a799d70..065b0aaed8 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/DragAnywhereSlider.qml
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/DragAnywhereSlider.qml
@@ -1,32 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-import QtQuick 2.12
+import QtQuick
Item {
id: root
@@ -38,7 +13,7 @@ Item {
property alias pressed: tap.pressed
signal tapped
width: 140
- height: 400
+ height: 260
DragHandler {
id: dragHandler
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/FlashAnimation.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/FlashAnimation.qml
index 158a02b7a6..9483a12d1c 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/FlashAnimation.qml
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/FlashAnimation.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/Slider.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/Slider.qml
index 782750b783..200e846207 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/Slider.qml
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/Slider.qml
@@ -1,32 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-import QtQuick 2.12
+import QtQuick
Item {
id: root
@@ -38,7 +13,7 @@ Item {
property alias pressed: tap.pressed
signal tapped
width: 140
- height: 400
+ height: 260
Rectangle {
id: slot
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/dragAndWheel.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/dragAndWheel.qml
new file mode 100644
index 0000000000..811326aaba
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/dragAndWheel.qml
@@ -0,0 +1,32 @@
+import QtQuick 2.15
+
+Item {
+ id: root
+
+ property bool gotWheel: false
+ property int changeCount: 0
+ property alias wheelHandlerEnabled: wheelHandler.enabled
+
+ width: 640
+ height: 480
+
+ Rectangle {
+ color: "blue"
+ width: 200
+ height: 200
+
+ DragHandler {
+ id: dragHandler
+ }
+
+ WheelHandler {
+ id: wheelHandler
+
+ enabled: !dragHandler.active
+ onEnabledChanged: root.changeCount++
+ onWheel: root.gotWheel = true
+ }
+
+ }
+
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/dragHandlerUnderModalLayer.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/dragHandlerUnderModalLayer.qml
new file mode 100644
index 0000000000..b24812c914
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/dragHandlerUnderModalLayer.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.15
+
+import Test 1.0
+
+Item {
+ width: 640
+ height: 480
+
+ Rectangle {
+ anchors.fill: parent
+ color: "grey"
+
+ Rectangle {
+ x: 200
+ y: 200
+ width: 100
+ height: 100
+ color: "orange"
+ DragHandler {
+ grabPermissions: DragHandler.CanTakeOverFromAnything // but not anything with keepMouseGrab!
+ }
+ }
+ }
+
+ ModalLayer {
+ anchors.fill: parent
+
+ Rectangle {
+ anchors.fill: parent
+ color: "red"
+ opacity: 0.4
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml
index 81fa20f3bb..47be6052ad 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the manual tests 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
import QtQuick 2.15
@@ -54,7 +29,9 @@ Item {
color: "white"
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
- text: ball.objectName + "\n" + dragHandler.centroid.position.x.toFixed(1) + "," + dragHandler.centroid.position.y.toFixed(1)
+ text: ball.objectName + "\n"
+ + dragHandler.centroid.position.x.toFixed(1) + "," + dragHandler.centroid.position.y.toFixed(1) + "\n"
+ + ball.x.toFixed(1) + "," + ball.y.toFixed(1)
}
}
}
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draghandler_and_pinchhandler.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draghandler_and_pinchhandler.qml
index 08b85aef50..5d700cdd08 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draghandler_and_pinchhandler.qml
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draghandler_and_pinchhandler.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the manual tests 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) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/multipleSliders.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/multipleSliders.qml
index f6042f4461..ea71da5623 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/multipleSliders.qml
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/multipleSliders.qml
@@ -1,40 +1,35 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-import QtQuick 2.12
+import QtQuick
Rectangle {
id: root
- width: 900
- height: 850
+ width: 600
+ height: 540
objectName: "root"
color: "#222222"
+ Instantiator {
+ model: 3
+ // non-interfering, just for visual monitoring of points
+ delegate: PointHandler {
+ id: ph
+ required property int index
+ objectName: "ph" + index
+ parent: root
+
+ target: Rectangle {
+ parent: root
+ visible: ph.active
+ x: ph.point.position.x - width / 2
+ y: ph.point.position.y - height / 2
+ width: 10; height: width; radius: width / 2
+ color: Qt.rgba(1, 0.33 * ph.index, 1 - 0.3 * ph.index)
+ }
+ }
+ }
+
Grid {
objectName: "grid"
anchors.fill: parent
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/simpleTapAndDragHandlers.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/simpleTapAndDragHandlers.qml
index 6e5574787c..6c7a25c148 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/simpleTapAndDragHandlers.qml
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/simpleTapAndDragHandlers.qml
@@ -1,37 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the manual tests 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) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-import QtQuick 2.12
+import QtQuick
Rectangle {
id: root
- width: 900
- height: 850
+ width: 320
+ height: 240
objectName: "root"
color: "#222222"
@@ -105,7 +80,5 @@ Rectangle {
}
}
}
-
-
}
}
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/snapMode.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/snapMode.qml
index d6eb791700..30b28ac9e8 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/snapMode.qml
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/snapMode.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
@@ -34,6 +9,26 @@ Item {
width: 640
height: 480
+ Instantiator {
+ model: 3
+ // non-interfering, just for visual monitoring of points
+ delegate: PointHandler {
+ id: ph
+ required property int index
+ objectName: "ph" + index
+ parent: root
+
+ target: Rectangle {
+ parent: root
+ visible: ph.active
+ x: ph.point.position.x - width / 2
+ y: ph.point.position.y - height / 2
+ width: 10; height: width; radius: width / 2
+ color: Qt.rgba(1, 0.33 * ph.index, 1 - 0.3 * ph.index)
+ }
+ }
+ }
+
Rectangle {
id: rect1
objectName: "rect1"
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
index c33c70b9e9..15df656b93 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
@@ -1,33 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module 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) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
+#include <QtGui/qstylehints.h>
+#include <QtQml/private/qqmlglobal_p.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlproperty.h>
#include <QtQuick/private/qquickdraghandler_p.h>
@@ -37,8 +14,10 @@
#include <QtQuick/qquickview.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>
+
+#include <QtCore/qpointer.h>
Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
@@ -47,7 +26,8 @@ class tst_DragHandler : public QQmlDataTest
Q_OBJECT
public:
tst_DragHandler()
- :touchDevice(QTest::createTouchDevice())
+ : QQmlDataTest(QT_QMLTEST_DATADIR)
+ , touchDevice(QTest::createTouchDevice())
{}
private slots:
@@ -69,8 +49,12 @@ private slots:
void touchPassiveGrabbers_data();
void touchPassiveGrabbers();
void touchPinchAndMouseMove();
+ void unsuitableEventDuringDrag();
+ void underModalLayer();
+ void interruptedByIrrelevantButton();
private:
+ void sendWheelEvent(QQuickView &window, QPoint pos, QPoint angleDelta, QPoint pixelDelta, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase, bool inverted);
void createView(QScopedPointer<QQuickView> &window, const char *fileName);
QSet<QQuickPointerHandler *> passiveGrabbers(QQuickWindow *window, int pointId = 0);
QPointingDevice *touchDevice;
@@ -81,8 +65,8 @@ void tst_DragHandler::createView(QScopedPointer<QQuickView> &window, const char
window.reset(new QQuickView);
window->setSource(testFileUrl(fileName));
QTRY_COMPARE(window->status(), QQuickView::Ready);
- QQuickViewTestUtil::centerOnScreen(window.data());
- QQuickViewTestUtil::moveMouseAway(window.data());
+ QQuickViewTestUtils::centerOnScreen(window.data());
+ QQuickViewTestUtils::moveMouseAway(window.data());
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
@@ -124,7 +108,8 @@ void tst_DragHandler::defaultPropertyValues()
QVERIFY(dragHandler);
QCOMPARE(dragHandler->acceptedButtons(), Qt::LeftButton);
- QCOMPARE(dragHandler->translation(), QVector2D());
+ QCOMPARE(dragHandler->persistentTranslation(), QVector2D());
+ QCOMPARE(dragHandler->activeTranslation(), QVector2D());
QCOMPARE(dragHandler->centroid().position(), QPointF());
QCOMPARE(dragHandler->centroid().scenePosition(), QPointF());
QCOMPARE(dragHandler->centroid().pressPosition(), QPointF());
@@ -159,8 +144,9 @@ void tst_DragHandler::touchDrag()
dragHandler->setDragThreshold(dragThreshold);
}
- QSignalSpy translationChangedSpy(dragHandler, SIGNAL(translationChanged()));
+ QSignalSpy translationChangedSpy(dragHandler, &QQuickDragHandler::translationChanged);
QSignalSpy centroidChangedSpy(dragHandler, SIGNAL(centroidChanged()));
+ QSignalSpy xDeltaSpy(dragHandler->xAxis(), &QQuickDragAxis::activeValueChanged);
QPointF ballCenter = ball->clipRect().center();
QPointF scenePressPos = ball->mapToScene(ballCenter);
@@ -173,22 +159,24 @@ void tst_DragHandler::touchDrag()
QCOMPARE(dragHandler->centroid().scenePosition(), scenePressPos);
QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
QCOMPARE(dragHandler->centroid().velocity(), QVector2D());
- QCOMPARE(centroidChangedSpy.count(), 1);
+ QCOMPARE(centroidChangedSpy.size(), 1);
p1 += QPoint(dragThreshold, 0);
QTest::touchEvent(window, touchDevice).move(1, p1, window);
QQuickTouchUtils::flush(window);
qCDebug(lcPointerTests) << "velocity after drag" << dragHandler->centroid().velocity();
if (dragThreshold > 0)
QTRY_VERIFY(!qFuzzyIsNull(dragHandler->centroid().velocity().x()));
- QCOMPARE(centroidChangedSpy.count(), 2);
+ QCOMPARE(centroidChangedSpy.size(), 2);
QVERIFY(!dragHandler->active());
p1 += QPoint(1, 0);
QTest::touchEvent(window, touchDevice).move(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(dragHandler->active());
- QCOMPARE(translationChangedSpy.count(), 0);
- QCOMPARE(centroidChangedSpy.count(), 3);
- QCOMPARE(dragHandler->translation().x(), 0.0);
+ QCOMPARE(translationChangedSpy.size(), 0);
+ QCOMPARE(xDeltaSpy.size(), 0);
+ QCOMPARE(centroidChangedSpy.size(), 3);
+ QCOMPARE(dragHandler->persistentTranslation().x(), 0);
+ QCOMPARE(dragHandler->activeTranslation().x(), 0);
QPointF sceneGrabPos = p1;
QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos);
p1 += QPoint(19, 0);
@@ -200,18 +188,79 @@ void tst_DragHandler::touchDrag()
QCOMPARE(dragHandler->centroid().scenePosition(), ball->mapToScene(ballCenter));
QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos);
- QCOMPARE(dragHandler->translation().x(), dragThreshold + 20.0);
- QCOMPARE(dragHandler->translation().y(), 0.0);
+ QCOMPARE(dragHandler->persistentTranslation().x(), dragThreshold + 20);
+ QCOMPARE(dragHandler->activeTranslation().x(), dragThreshold + 20);
+ QCOMPARE(dragHandler->persistentTranslation().y(), 0);
+ QCOMPARE(dragHandler->activeTranslation().y(), 0);
+ QCOMPARE(translationChangedSpy.size(), 1);
+ QCOMPARE(translationChangedSpy.first().first().value<QVector2D>(), QVector2D(dragThreshold + 20, 0));
QVERIFY(dragHandler->centroid().velocity().x() > 0);
- QCOMPARE(centroidChangedSpy.count(), 4);
+ QCOMPARE(centroidChangedSpy.size(), 4);
QTest::touchEvent(window, touchDevice).release(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!dragHandler->active());
QCOMPARE(dragHandler->centroid().pressedButtons(), Qt::NoButton);
QCOMPARE(dragHandler->centroid().velocity(), QVector2D());
QCOMPARE(ball->mapToScene(ballCenter).toPoint(), p1);
- QCOMPARE(translationChangedSpy.count(), 1);
- QCOMPARE(centroidChangedSpy.count(), 5);
+ QCOMPARE(translationChangedSpy.size(), 1);
+ QCOMPARE(xDeltaSpy.size(), 1);
+ QCOMPARE(xDeltaSpy.first().first().toReal(), dragThreshold + 20);
+ QCOMPARE(centroidChangedSpy.size(), 5);
+ QCOMPARE(dragHandler->persistentTranslation().x(), dragThreshold + 20);
+
+ // Drag again: activeTranslation starts over, while persistentTranslation accumulates
+ p1 = ball->mapToScene(ballCenter).toPoint();
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(dragHandler->persistentTranslation().x(), dragThreshold + 20);
+ p1 += QPoint(dragThreshold, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(1, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(dragHandler->active());
+ p1 += QPoint(9, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(xDeltaSpy.size(), 2);
+ QCOMPARE(xDeltaSpy.last().first().toReal(), dragThreshold + 10);
+ p1 += QPoint(10, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(dragHandler->activeTranslation().x(), dragThreshold + 20);
+ QCOMPARE(dragHandler->persistentTranslation().x(), dragThreshold * 2 + 40);
+ QCOMPARE(xDeltaSpy.size(), 3);
+ QCOMPARE(xDeltaSpy.last().first().toReal(), 10);
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+
+ // Call setPersistentTranslation and drag yet again:
+ // activeTranslation starts over, while persistentTranslation adds the drags onto the new basis
+ dragHandler->setPersistentTranslation({10, 10});
+ p1 = ball->mapToScene(ballCenter).toPoint();
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(dragHandler->persistentTranslation().x(), 10);
+ p1 += QPoint(dragThreshold, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(1, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(dragHandler->active());
+ p1 += QPoint(9, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(10, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(dragHandler->activeTranslation().x(), dragThreshold + 20);
+ QCOMPARE(dragHandler->persistentTranslation().x(), dragThreshold + 30);
+ QCOMPARE(xDeltaSpy.size(), 6);
+ QCOMPARE(xDeltaSpy.last().first().toReal(), 10);
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
}
void tst_DragHandler::mouseDrag_data()
@@ -241,8 +290,9 @@ void tst_DragHandler::mouseDrag()
QVERIFY(dragHandler);
dragHandler->setAcceptedButtons(acceptedButtons); // QTBUG-76875
- QSignalSpy translationChangedSpy(dragHandler, SIGNAL(translationChanged()));
+ QSignalSpy translationChangedSpy(dragHandler, &QQuickDragHandler::translationChanged);
QSignalSpy centroidChangedSpy(dragHandler, SIGNAL(centroidChanged()));
+ QSignalSpy xDeltaSpy(dragHandler->xAxis(), &QQuickDragAxis::activeValueChanged);
QPointF ballCenter = ball->clipRect().center();
QPointF scenePressPos = ball->mapToScene(ballCenter);
@@ -258,13 +308,13 @@ void tst_DragHandler::mouseDrag()
QCOMPARE(dragHandler->centroid().scenePosition(), scenePressPos);
QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
QCOMPARE(dragHandler->centroid().velocity(), QVector2D());
- QCOMPARE(centroidChangedSpy.count(), 1);
+ QCOMPARE(centroidChangedSpy.size(), 1);
}
p1 += QPoint(dragThreshold, 0);
QTest::mouseMove(window, p1);
if (shouldDrag) {
-// QTRY_VERIFY(dragHandler->centroid().velocity().x() > 0); // TODO QTBUG-33891
- QCOMPARE(centroidChangedSpy.count(), 2);
+ QVERIFY(dragHandler->centroid().velocity().x() > 0);
+ QCOMPARE(centroidChangedSpy.size(), 2);
QVERIFY(!dragHandler->active());
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::ArrowCursor);
@@ -276,10 +326,12 @@ void tst_DragHandler::mouseDrag()
QTRY_VERIFY(dragHandler->active());
else
QVERIFY(!dragHandler->active());
- QCOMPARE(translationChangedSpy.count(), 0);
+ QCOMPARE(translationChangedSpy.size(), 0);
+ QCOMPARE(xDeltaSpy.size(), 0);
if (shouldDrag)
- QCOMPARE(centroidChangedSpy.count(), 3);
- QCOMPARE(dragHandler->translation().x(), 0.0);
+ QCOMPARE(centroidChangedSpy.size(), 3);
+ QCOMPARE(dragHandler->persistentTranslation().x(), 0.0);
+ QCOMPARE(dragHandler->activeTranslation().x(), 0.0);
QPointF sceneGrabPos = p1;
if (shouldDrag)
QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos);
@@ -292,10 +344,12 @@ void tst_DragHandler::mouseDrag()
QCOMPARE(dragHandler->centroid().scenePosition(), ball->mapToScene(ballCenter));
QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos);
- QCOMPARE(dragHandler->translation().x(), dragThreshold + 20.0);
- QCOMPARE(dragHandler->translation().y(), 0.0);
-// QVERIFY(dragHandler->centroid().velocity().x() > 0); // TODO QTBUG-33891
- QCOMPARE(centroidChangedSpy.count(), 4);
+ QCOMPARE(dragHandler->persistentTranslation().x(), dragThreshold + 20.0);
+ QCOMPARE(dragHandler->activeTranslation().x(), dragThreshold + 20.0);
+ QCOMPARE(dragHandler->persistentTranslation().y(), 0.0);
+ QCOMPARE(dragHandler->activeTranslation().y(), 0.0);
+ QVERIFY(dragHandler->centroid().velocity().x() > 0);
+ QCOMPARE(centroidChangedSpy.size(), 4);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::ClosedHandCursor);
#endif
@@ -303,10 +357,13 @@ void tst_DragHandler::mouseDrag()
QTest::mouseRelease(window, static_cast<Qt::MouseButton>(int(dragButton)), Qt::NoModifier, p1);
QTRY_VERIFY(!dragHandler->active());
QCOMPARE(dragHandler->centroid().pressedButtons(), Qt::NoButton);
- if (shouldDrag)
+ QCOMPARE(translationChangedSpy.size(), shouldDrag ? 1 : 0);
+ if (shouldDrag) {
QCOMPARE(ball->mapToScene(ballCenter).toPoint(), p1);
- QCOMPARE(translationChangedSpy.count(), shouldDrag ? 1 : 0);
- QCOMPARE(centroidChangedSpy.count(), shouldDrag ? 5 : 0);
+ QCOMPARE(translationChangedSpy.first().first().value<QVector2D>(), QVector2D(dragThreshold + 20, 0));
+ }
+ QCOMPARE(xDeltaSpy.size(), shouldDrag ? 1 : 0);
+ QCOMPARE(centroidChangedSpy.size(), shouldDrag ? 5 : 0);
#if QT_CONFIG(cursor)
QTest::mouseMove(window, p1 + QPoint(1, 0)); // TODO after fixing QTBUG-53987, don't send mouseMove
QCOMPARE(window->cursor().shape(), Qt::ArrowCursor);
@@ -340,8 +397,9 @@ void tst_DragHandler::mouseDragThreshold()
dragHandler->setDragThreshold(dragThreshold);
}
- QSignalSpy translationChangedSpy(dragHandler, SIGNAL(translationChanged()));
+ QSignalSpy translationChangedSpy(dragHandler, &QQuickDragHandler::translationChanged);
QSignalSpy centroidChangedSpy(dragHandler, SIGNAL(centroidChanged()));
+ QSignalSpy xDeltaSpy(dragHandler->xAxis(), &QQuickDragAxis::activeValueChanged);
QPointF ballCenter = ball->clipRect().center();
QPointF scenePressPos = ball->mapToScene(ballCenter);
@@ -353,20 +411,28 @@ void tst_DragHandler::mouseDragThreshold()
QCOMPARE(dragHandler->centroid().scenePosition(), scenePressPos);
QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
QCOMPARE(dragHandler->centroid().velocity(), QVector2D());
- QCOMPARE(centroidChangedSpy.count(), 1);
+ QCOMPARE(centroidChangedSpy.size(), 1);
p1 += QPoint(qMax(1, dragThreshold), 0); // QTBUG-85431: zero-distance mouse moves are not delivered
QTest::mouseMove(window, p1);
if (dragThreshold > 0)
QTRY_VERIFY(dragHandler->centroid().velocity().x() > 0);
- QCOMPARE(centroidChangedSpy.count(), 2);
+ QCOMPARE(centroidChangedSpy.size(), 2);
// the handler is not yet active, unless the drag threshold was already exceeded
QCOMPARE(dragHandler->active(), dragThreshold == 0);
p1 += QPoint(1, 0);
QTest::mouseMove(window, p1);
QTRY_VERIFY(dragHandler->active());
- QCOMPARE(translationChangedSpy.count(), dragThreshold ? 0 : 1);
- QCOMPARE(centroidChangedSpy.count(), 3);
+ QCOMPARE(translationChangedSpy.size(), dragThreshold ? 0 : 1);
+ if (!dragThreshold)
+ QCOMPARE(translationChangedSpy.first().first().value<QVector2D>(), QVector2D(2, 0));
+ QCOMPARE(xDeltaSpy.size(), dragThreshold ? 0 : 1);
+ QCOMPARE(centroidChangedSpy.size(), 3);
+#if QT_DEPRECATED_SINCE(6, 2)
+QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
QCOMPARE(dragHandler->translation().x(), dragThreshold ? 0 : 2);
+QT_WARNING_POP
+#endif
+ QCOMPARE(dragHandler->activeTranslation().x(), dragThreshold ? 0 : 2);
QPointF sceneGrabPos = dragThreshold ? p1 : p1 - QPoint(1, 0);
QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos);
p1 += QPoint(19, 0);
@@ -377,16 +443,26 @@ void tst_DragHandler::mouseDragThreshold()
QCOMPARE(dragHandler->centroid().scenePosition(), ball->mapToScene(ballCenter));
QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos);
+#if QT_DEPRECATED_SINCE(6, 2)
+QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
QCOMPARE(dragHandler->translation().x(), dragThreshold + (dragThreshold ? 20 : 21));
QCOMPARE(dragHandler->translation().y(), 0.0);
+QT_WARNING_POP
+#endif
+ QCOMPARE(dragHandler->activeTranslation().x(), dragThreshold + (dragThreshold ? 20 : 21));
+ QCOMPARE(dragHandler->activeTranslation().y(), 0.0);
+ QCOMPARE(translationChangedSpy.size(), dragThreshold ? 1 : 2);
+ QCOMPARE(translationChangedSpy.first().first().value<QVector2D>(),
+ QVector2D(dragThreshold ? dragThreshold + 20 : 2, 0));
QVERIFY(dragHandler->centroid().velocity().x() > 0);
- QCOMPARE(centroidChangedSpy.count(), 4);
+ QCOMPARE(centroidChangedSpy.size(), 4);
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
QTRY_VERIFY(!dragHandler->active());
QCOMPARE(dragHandler->centroid().pressedButtons(), Qt::NoButton);
QCOMPARE(ball->mapToScene(ballCenter).toPoint(), p1);
- QCOMPARE(translationChangedSpy.count(), dragThreshold ? 1 : 2);
- QCOMPARE(centroidChangedSpy.count(), 5);
+ QCOMPARE(translationChangedSpy.size(), dragThreshold ? 1 : 2);
+ QCOMPARE(xDeltaSpy.size(), dragThreshold ? 1 : 2);
+ QCOMPARE(centroidChangedSpy.size(), 5);
}
void tst_DragHandler::dragFromMargin() // QTBUG-74966
@@ -416,8 +492,14 @@ void tst_DragHandler::dragFromMargin() // QTBUG-74966
QTRY_VERIFY(dragHandler->active());
QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
QCOMPARE(dragHandler->centroid().sceneGrabPosition(), p1);
+#if QT_DEPRECATED_SINCE(6, 2)
+QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
QCOMPARE(dragHandler->translation().x(), 0.0); // hmm that's odd
QCOMPARE(dragHandler->translation().y(), 0.0);
+QT_WARNING_POP
+#endif
+ QCOMPARE(dragHandler->activeTranslation().x(), 0.0); // hmm that's odd
+ QCOMPARE(dragHandler->activeTranslation().y(), 0.0);
QCOMPARE(draggableItem->position(), originalPos + QPointF(dragThreshold * 2, 0));
#if QT_CONFIG(cursor)
// The cursor doesn't change until the next event after the handler becomes active.
@@ -516,15 +598,17 @@ void tst_DragHandler::touchDragMulti()
QVERIFY(ball1);
QQuickDragHandler *dragHandler1 = ball1->findChild<QQuickDragHandler*>();
QVERIFY(dragHandler1);
- QSignalSpy translationChangedSpy1(dragHandler1, SIGNAL(translationChanged()));
+ QSignalSpy translationChangedSpy1(dragHandler1, &QQuickDragHandler::translationChanged);
QSignalSpy centroidChangedSpy1(dragHandler1, SIGNAL(centroidChanged()));
+ QSignalSpy xDeltaSpy1(dragHandler1->xAxis(), &QQuickDragAxis::activeValueChanged);
QQuickItem *ball2 = window->rootObject()->childItems().at(1);
QVERIFY(ball2);
QQuickDragHandler *dragHandler2 = ball2->findChild<QQuickDragHandler*>();
QVERIFY(dragHandler2);
- QSignalSpy translationChangedSpy2(dragHandler2, SIGNAL(translationChanged()));
+ QSignalSpy translationChangedSpy2(dragHandler2, &QQuickDragHandler::translationChanged);
QSignalSpy centroidChangedSpy2(dragHandler1, SIGNAL(centroidChanged()));
+ QSignalSpy yDeltaSpy2(dragHandler2->yAxis(), &QQuickDragAxis::activeValueChanged);
QPointF ball1Center = ball1->clipRect().center();
QPointF scenePressPos1 = ball1->mapToScene(ball1Center);
@@ -534,16 +618,18 @@ void tst_DragHandler::touchDragMulti()
QPoint p2 = scenePressPos2.toPoint();
QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window, touchDevice, false);
- touchSeq.press(1, p1, window).press(2, p2, window).commit();
+ touchSeq.press(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ touchSeq.stationary(1).press(2, p2, window).commit();
QQuickTouchUtils::flush(window);
QVERIFY(!dragHandler1->active());
- QCOMPARE(centroidChangedSpy1.count(), 1);
+ QCOMPARE(centroidChangedSpy1.size(), 2);
QCOMPARE(dragHandler1->centroid().position(), ball1Center);
QCOMPARE(dragHandler1->centroid().pressPosition(), ball1Center);
QCOMPARE(dragHandler1->centroid().scenePosition(), scenePressPos1);
QCOMPARE(dragHandler1->centroid().scenePressPosition(), scenePressPos1);
QVERIFY(!dragHandler2->active());
- QCOMPARE(centroidChangedSpy2.count(), 1);
+ QCOMPARE(centroidChangedSpy2.size(), 2);
QCOMPARE(dragHandler2->centroid().position(), ball2Center);
QCOMPARE(dragHandler2->centroid().pressPosition(), ball2Center);
QCOMPARE(dragHandler2->centroid().scenePosition(), scenePressPos2);
@@ -553,13 +639,13 @@ void tst_DragHandler::touchDragMulti()
touchSeq.move(1, p1, window).move(2, p2, window).commit();
QQuickTouchUtils::flush(window);
QVERIFY(!dragHandler1->active());
- QCOMPARE(centroidChangedSpy1.count(), 2);
+ QCOMPARE(centroidChangedSpy1.size(), 3);
QCOMPARE(dragHandler1->centroid().position(), ball1Center + QPointF(dragThreshold, 0));
QCOMPARE(dragHandler1->centroid().pressPosition(), ball1Center);
QCOMPARE(dragHandler1->centroid().scenePosition().toPoint(), p1);
QCOMPARE(dragHandler1->centroid().scenePressPosition(), scenePressPos1);
QVERIFY(!dragHandler2->active());
- QCOMPARE(centroidChangedSpy2.count(), 2);
+ QCOMPARE(centroidChangedSpy2.size(), 3);
QCOMPARE(dragHandler2->centroid().position(), ball2Center + QPointF(0, dragThreshold));
QCOMPARE(dragHandler2->centroid().pressPosition(), ball2Center);
QCOMPARE(dragHandler2->centroid().scenePosition().toPoint(), p2);
@@ -570,8 +656,14 @@ void tst_DragHandler::touchDragMulti()
QQuickTouchUtils::flush(window);
QTRY_VERIFY(dragHandler1->active());
QVERIFY(dragHandler2->active());
- QCOMPARE(translationChangedSpy1.count(), 0);
+ QCOMPARE(translationChangedSpy1.size(), 0);
+ QCOMPARE(xDeltaSpy1.size(), 0);
+#if QT_DEPRECATED_SINCE(6, 2)
+QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
QCOMPARE(dragHandler1->translation().x(), 0.0);
+QT_WARNING_POP
+#endif
+ QCOMPARE(dragHandler1->activeTranslation().x(), 0.0);
QPointF sceneGrabPos1 = p1;
QPointF sceneGrabPos2 = p2;
QCOMPARE(dragHandler1->centroid().sceneGrabPosition(), sceneGrabPos1);
@@ -579,8 +671,14 @@ void tst_DragHandler::touchDragMulti()
p1 += QPoint(19, 0);
p2 += QPoint(0, 19);
QVERIFY(dragHandler2->active());
- QCOMPARE(translationChangedSpy2.count(), 0);
+ QCOMPARE(translationChangedSpy2.size(), 0);
+ QCOMPARE(yDeltaSpy2.size(), 0);
+#if QT_DEPRECATED_SINCE(6, 2)
+QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
QCOMPARE(dragHandler2->translation().x(), 0.0);
+QT_WARNING_POP
+#endif
+ QCOMPARE(dragHandler2->activeTranslation().x(), 0.0);
QCOMPARE(dragHandler2->centroid().sceneGrabPosition(), sceneGrabPos2);
touchSeq.move(1, p1, window).move(2, p2, window).commit();
QQuickTouchUtils::flush(window);
@@ -591,27 +689,47 @@ void tst_DragHandler::touchDragMulti()
QCOMPARE(dragHandler1->centroid().scenePosition(), ball1->mapToScene(ball1Center));
QCOMPARE(dragHandler1->centroid().scenePressPosition(), scenePressPos1);
QCOMPARE(dragHandler1->centroid().sceneGrabPosition(), sceneGrabPos1);
+#if QT_DEPRECATED_SINCE(6, 2)
+QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
QCOMPARE(dragHandler1->translation().x(), dragThreshold + 20.0);
QCOMPARE(dragHandler1->translation().y(), 0.0);
+QT_WARNING_POP
+#endif
+ QCOMPARE(dragHandler1->activeTranslation().x(), dragThreshold + 20.0);
+ QCOMPARE(dragHandler1->activeTranslation().y(), 0.0);
QCOMPARE(dragHandler2->centroid().position(), ball2Center);
QCOMPARE(dragHandler2->centroid().pressPosition(), ball2Center);
QCOMPARE(dragHandler2->centroid().scenePosition(), ball2->mapToScene(ball2Center));
QCOMPARE(dragHandler2->centroid().scenePressPosition(), scenePressPos2);
QCOMPARE(dragHandler2->centroid().sceneGrabPosition(), sceneGrabPos2);
+#if QT_DEPRECATED_SINCE(6, 2)
+QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
QCOMPARE(dragHandler2->translation().x(), 0.0);
QCOMPARE(dragHandler2->translation().y(), dragThreshold + 20.0);
+QT_WARNING_POP
+#endif
+ QCOMPARE(dragHandler2->activeTranslation().x(), 0.0);
+ QCOMPARE(dragHandler2->activeTranslation().y(), dragThreshold + 20.0);
+ QCOMPARE(xDeltaSpy1.size(), 1);
+ QCOMPARE(xDeltaSpy1.first().first().toReal(), dragThreshold + 20);
+ QCOMPARE(yDeltaSpy2.size(), 1);
+ QCOMPARE(yDeltaSpy2.first().first().toReal(), dragThreshold + 20);
+ QCOMPARE(translationChangedSpy1.size(), 1);
+ QCOMPARE(translationChangedSpy1.first().first().value<QVector2D>(), QVector2D(dragThreshold + 20, 0));
+ QCOMPARE(translationChangedSpy2.size(), 1);
+ QCOMPARE(translationChangedSpy2.first().first().value<QVector2D>(), QVector2D(0, dragThreshold + 20));
touchSeq.release(1, p1, window).stationary(2).commit();
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!dragHandler1->active());
QVERIFY(dragHandler2->active());
QCOMPARE(dragHandler1->centroid().pressedButtons(), Qt::NoButton);
QCOMPARE(ball1->mapToScene(ball1Center).toPoint(), p1);
- QCOMPARE(translationChangedSpy1.count(), 1);
+ QCOMPARE(translationChangedSpy1.size(), 1);
touchSeq.release(2, p2, window).commit();
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!dragHandler2->active());
QCOMPARE(ball2->mapToScene(ball2Center).toPoint(), p2);
- QCOMPARE(translationChangedSpy2.count(), 1);
+ QCOMPARE(translationChangedSpy2.size(), 1);
}
void tst_DragHandler::touchDragMultiSliders_data()
@@ -700,7 +818,7 @@ void tst_DragHandler::touchDragMultiSliders()
expectedEndPosition = startPoints[sli].toPoint();
qCDebug(lcPointerTests) << "slider " << knobs[sli]->objectName() << "started @" << startPoints[sli]
<< "tried to move by" << movements[sli] << "ended up @" << endPosition << "expected" << expectedEndPosition;
- QTRY_COMPARE(endPosition, expectedEndPosition);
+ QCOMPARE(endPosition, expectedEndPosition);
}
// Release
@@ -817,10 +935,198 @@ void tst_DragHandler::touchPinchAndMouseMove()
for (int i = 0; i < 10; ++i) {
p1 += delta;
QTest::mouseMove(window, p1);
- QCOMPARE(rectMovedSpy.count(), 0);
+ QCOMPARE(rectMovedSpy.size(), 0);
}
}
+void tst_DragHandler::unsuitableEventDuringDrag()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "dragAndWheel.qml");
+ QQuickView *window = windowPtr.data();
+ auto root = window->rootObject();
+ QQmlProperty changeCount(root, "changeCount");
+ QQmlProperty wheelHandlerEnabled(root, "wheelHandlerEnabled");
+ bool ok = false;
+ QCOMPARE(changeCount.read().toInt(&ok), 0);
+ QVERIFY(ok);
+ QCOMPARE(wheelHandlerEnabled.read().toBool(), true);
+
+ QPoint p1(100, 100);
+ QPoint p2(150, 150);
+
+ QTest::QTouchEventSequence touch = QTest::touchEvent(window, touchDevice);
+ // When we start dragging...
+ touch.press(3,p1).commit();
+ touch.move(3, p2).commit();
+ QQuickTouchUtils::flush(window);
+ // the DragHandler becomes active
+ ok = false;
+ QCOMPARE(changeCount.read().toInt(&ok), 1);
+ QVERIFY(ok);
+ QCOMPARE(wheelHandlerEnabled.read().toBool(), false);
+
+ // When a scroll event arrives while we are dragging
+ sendWheelEvent(*window, p2, QPoint(160, 120), QPoint(-360, 120), Qt::NoModifier, Qt::ScrollBegin, false);
+ // nothing changes because the DragHandler is still active, and the wheel handler stays disabled
+ ok = false;
+ QCOMPARE(changeCount.read().toInt(&ok), 1);
+ QVERIFY(ok);
+ QCOMPARE(wheelHandlerEnabled.read().toBool(), false);
+
+ // When we stop dragging...
+ touch.release(3, p2).commit();
+ QQuickTouchUtils::flush(window);
+
+ // the wheel handler becomes active again
+ ok = false;
+ QCOMPARE(changeCount.read().toInt(&ok), 2);
+ QVERIFY(ok);
+ QCOMPARE(wheelHandlerEnabled.read().toBool(), true);
+
+ // During the whole sequence the wheel handler never got a wheel event
+ // as it was disabled:
+ QQmlProperty gotWheel(root, "gotWheel");
+ QVERIFY(!gotWheel.read().toBool());
+
+ // If the WheelHandler is unconditionally enabled...
+ wheelHandlerEnabled.write(true);
+ // it receives scroll events during drags.
+ touch.press(4,p2).commit();
+ touch.move(4, p1).commit();
+ QQuickTouchUtils::flush(window);
+ sendWheelEvent(*window, p2, QPoint(160, 120), QPoint(-360, 120), Qt::NoModifier, Qt::ScrollBegin, false);
+ touch.release(4, p2).commit();
+ QQuickTouchUtils::flush(window);
+ QVERIFY(gotWheel.read().toBool());
+}
+
+void tst_DragHandler::sendWheelEvent(QQuickView &window, QPoint pos, QPoint angleDelta, QPoint pixelDelta, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase, bool inverted)
+{
+ QWheelEvent wheelEvent(pos, window.mapToGlobal(pos), pixelDelta, angleDelta,
+ Qt::NoButton, modifiers, phase, inverted);
+ QGuiApplication::sendEvent(&window, &wheelEvent);
+ qApp->processEvents();
+ QQuickTouchUtils::flush(&window);
+}
+
+class ModalLayer : public QQuickItem {
+public:
+ explicit ModalLayer(QQuickItem* parent = nullptr) : QQuickItem(parent) {
+ this->setAcceptedMouseButtons(Qt::AllButtons);
+ this->setAcceptTouchEvents(true);
+ this->setKeepMouseGrab(true);
+ this->setKeepTouchGrab(true);
+ }
+
+ bool event(QEvent* event) override {
+ switch (event->type()) {
+ case QEvent::KeyPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseTrackingChange:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::Wheel:
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchCancel:
+ case QEvent::TouchEnd: {
+ qCDebug(lcPointerTests) << "BLOCK!" << event->type();
+ return true;
+ }
+ default: break;
+ }
+ return QQuickItem::event(event);
+ }
+};
+
+void tst_DragHandler::underModalLayer() // QTBUG-78258
+{
+ qmlRegisterType<ModalLayer>("Test", 1, 0, "ModalLayer");
+
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "dragHandlerUnderModalLayer.qml");
+ QQuickView * window = windowPtr.data();
+ QPointer<QQuickDragHandler> dragHandler = window->rootObject()->findChild<QQuickDragHandler*>();
+ QVERIFY(dragHandler);
+
+ QPoint p1(250, 250);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ p1 += QPoint(dragThreshold, dragThreshold);
+ QTest::mouseMove(window, p1);
+ QVERIFY(!dragHandler->active());
+ p1 += QPoint(dragThreshold, dragThreshold);
+ QTest::mouseMove(window, p1);
+ QVERIFY(!dragHandler->active());
+ QTest::mouseRelease(window, Qt::LeftButton);
+}
+
+void tst_DragHandler::interruptedByIrrelevantButton() // QTBUG-102201
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("draggables.qml")));
+
+ QQuickItem *ball = window.rootObject()->childItems().first();
+ QVERIFY(ball);
+ QQuickDragHandler *dragHandler = ball->findChild<QQuickDragHandler*>();
+ QVERIFY(dragHandler);
+
+ QCOMPARE(dragHandler->acceptedButtons(), Qt::LeftButton); // the default
+
+ QSignalSpy translationChangedSpy(dragHandler, &QQuickDragHandler::translationChanged);
+ QSignalSpy cancelSpy(dragHandler, &QQuickDragHandler::canceled);
+ QSignalSpy activeSpy(dragHandler, &QQuickDragHandler::activeChanged);
+ QSignalSpy grabSpy(dragHandler, &QQuickDragHandler::grabChanged);
+
+ QPoint p1 = ball->mapToScene(ball->clipRect().center()).toPoint();
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, p1);
+ QCOMPARE(grabSpy.size(), 1); // passive grab
+ p1 += QPoint(dragThreshold + 1, 0);
+ QTest::mouseMove(&window, p1);
+ QVERIFY(dragHandler->active());
+ QCOMPARE(activeSpy.size(), 1);
+ QCOMPARE(grabSpy.size(), 2); // exclusive grab
+ QCOMPARE(translationChangedSpy.size(), 0);
+ p1 += QPoint(1, 0);
+ QTest::mouseMove(&window, p1);
+ QCOMPARE(translationChangedSpy.size(), 1);
+
+ // Left button is already held, now press right button too (chording)
+ QTest::mousePress(&window, Qt::RightButton, Qt::NoModifier, p1);
+ // DragHandler will ungrab and deactivate, but not cancel
+ QCOMPARE(dragHandler->active(), false);
+ QCOMPARE(translationChangedSpy.size(), 1);
+ QCOMPARE(cancelSpy.size(), 0);
+ QCOMPARE(activeSpy.size(), 2);
+ QCOMPARE_GT(grabSpy.size(), 2); // lost grabs
+
+ // Release right button: no change in state
+ QTest::mouseRelease(&window, Qt::RightButton, Qt::NoModifier, p1);
+ QCOMPARE(dragHandler->active(), false);
+ QCOMPARE(translationChangedSpy.size(), 1);
+ QCOMPARE(cancelSpy.size(), 0);
+ QCOMPARE(activeSpy.size(), 2);
+ auto grabChangedCount = grabSpy.size();
+
+ // But the left button is still held, and it's possible to resume dragging
+ p1 += QPoint(dragThreshold + 1, 0);
+ QTest::mouseMove(&window, p1);
+ QCOMPARE_GT(grabSpy.size(), grabChangedCount); // re-grabbed
+ p1 += QPoint(1, 0);
+ QTest::mouseMove(&window, p1);
+ QVERIFY(dragHandler->active());
+ QCOMPARE(activeSpy.size(), 3);
+ QCOMPARE(translationChangedSpy.size(), 2);
+
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, p1);
+ QVERIFY(!dragHandler->active());
+ QCOMPARE(activeSpy.size(), 4);
+ QCOMPARE(cancelSpy.size(), 0); // none of this caused a canceled() signal
+}
+
QTEST_MAIN(tst_DragHandler)
#include "tst_qquickdraghandler.moc"
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/BLACKLIST b/tests/auto/quick/pointerhandlers/qquickhoverhandler/BLACKLIST
index 9bb35c4770..c0d73ff05f 100644
--- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/BLACKLIST
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/BLACKLIST
@@ -1,3 +1,8 @@
[movingItemWithHoverHandler]
macos # Can't move cursor (QTBUG-76312)
+# QTBUG-103065
+[movingItemWithHoverHandler]
+android
+[window]
+opensuse-leap # QTBUG-122405
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/CMakeLists.txt b/tests/auto/quick/pointerhandlers/qquickhoverhandler/CMakeLists.txt
index 654bf1c366..a2e7d640d5 100644
--- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/CMakeLists.txt
@@ -1,9 +1,18 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# Generated from qquickhoverhandler.pro.
#####################################################################
## tst_qquickhoverhandler Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickhoverhandler 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_qquickhoverhandler
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_qquickhoverhandler.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}
)
@@ -38,10 +40,10 @@ qt_internal_add_test(tst_qquickhoverhandler
qt_internal_extend_target(tst_qquickhoverhandler CONDITION ANDROID OR IOS
DEFINES
- QT_QMLTEST_DATADIR=\\\":/data\\\"
+ QT_QMLTEST_DATADIR=":/data"
)
qt_internal_extend_target(tst_qquickhoverhandler 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/pointerhandlers/qquickhoverhandler/data/changingCursor.qml b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/changingCursor.qml
new file mode 100644
index 0000000000..42b658a4d4
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/changingCursor.qml
@@ -0,0 +1,37 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick 2.15
+
+
+Rectangle {
+ id: brownRect
+ objectName: "brownRect"
+
+ width: 400
+ height: 400
+
+ HoverHandler {
+ id: hh
+ cursorShape: parent.colorIndex == 0 ?
+ Qt.CrossCursor :
+ Qt.OpenHandCursor
+ }
+
+ property list<color> colors: ["beige", "brown"]
+ property int colorIndex: 0
+
+ color: colors[colorIndex]
+
+ Timer {
+ id: colorTimer
+ interval: 200
+ running: true
+ repeat: true
+
+ onTriggered: {
+ parent.colorIndex = (parent.colorIndex + 1) % parent.colors.length;
+ parent.color = parent.colors[parent.colorIndex];
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverDeviceCursors.qml b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverDeviceCursors.qml
new file mode 100644
index 0000000000..48e130a35e
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverDeviceCursors.qml
@@ -0,0 +1,55 @@
+import QtQuick
+
+Item {
+ width: 200; height: 200
+
+ Rectangle {
+ width: 100; height: 100
+ anchors.centerIn: parent
+ border.color: "black"
+
+ HoverHandler {
+ objectName: "stylus"
+ acceptedDevices: PointerDevice.Stylus
+ acceptedPointerTypes: PointerDevice.Pen
+ cursorShape: Qt.CrossCursor
+ }
+
+ HoverHandler {
+ objectName: "stylus eraser"
+ acceptedDevices: PointerDevice.Stylus
+ acceptedPointerTypes: PointerDevice.Eraser
+ cursorShape: Qt.PointingHandCursor
+ }
+
+ HoverHandler {
+ objectName: "airbrush"
+ acceptedDevices: PointerDevice.Airbrush
+ acceptedPointerTypes: PointerDevice.Pen
+ cursorShape: Qt.BusyCursor
+ }
+
+ HoverHandler {
+ objectName: "airbrush eraser"
+ acceptedDevices: PointerDevice.Airbrush
+ acceptedPointerTypes: PointerDevice.Eraser
+ cursorShape: Qt.OpenHandCursor
+ }
+
+ HoverHandler {
+ objectName: "mouse"
+ acceptedDevices: PointerDevice.Mouse
+ // acceptedPointerTypes can be omitted because Mouse is not ambiguous.
+ // When a genuine mouse move is sent, there's a conflict, and this one should win.
+ cursorShape: Qt.IBeamCursor
+ }
+
+ HoverHandler {
+ objectName: "conflictingMouse"
+ acceptedDevices: PointerDevice.Mouse
+ // acceptedPointerTypes can be omitted because Mouse is not ambiguous.
+ // When a genuine mouse move is sent, there's a conflict, and this one should lose.
+ cursorShape: Qt.ClosedHandCursor
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverHandler.qml b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverHandler.qml
new file mode 100644
index 0000000000..60dfc53c40
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverHandler.qml
@@ -0,0 +1,17 @@
+import QtQuick
+
+Item {
+ width: 320
+ height: 240
+
+ Rectangle {
+ width: 100
+ height: 100
+ anchors.centerIn: parent
+ color: hh.hovered ? "lightsteelblue" : "beige"
+
+ HoverHandler {
+ id: hh
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml
index 38a19c57c5..ca30a7fe99 100644
--- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** 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
import QtQuick 2.15
@@ -34,59 +9,96 @@ Rectangle {
height: 480
color: "#444"
- Component {
- id: buttonsAndStuff
- Column {
- anchors.fill: parent
- anchors.margins: 8
- spacing: 8
-
- Rectangle {
- objectName: "buttonWithMA"
- width: parent.width
- height: 30
- color: buttonMA.pressed ? "lightsteelblue" : "#999"
- border.color: buttonMA.containsMouse ? "cyan" : "transparent"
-
- MouseArea {
- id: buttonMA
- objectName: "buttonMA"
- hoverEnabled: true
- cursorShape: Qt.UpArrowCursor
- anchors.fill: parent
- onClicked: console.log("clicked MA")
- }
+ component CheckBox: Row {
+ id: cbRoot
+ property bool checked : true
+ property string label : "CheckBox"
+ spacing: 4
+ Rectangle {
+ width: 16; height: 16
+ // comment out this color change to test whether we rely on "dirty" items to
+ // trigger QQuickDeliveryAgentPrivate::flushFrameSynchronousEvents() to update hover state
+ color: cbRoot.checked ? "cadetblue" : "transparent"
+ border.color: "black"
+ TapHandler { onTapped: cbRoot.checked = !cbRoot.checked }
+ }
+ Text { text: cbRoot.label }
+ }
- Text {
- anchors.centerIn: parent
- text: "MouseArea"
- }
+ component ButtonsAndStuff: Column {
+ anchors.fill: parent
+ anchors.margins: 8
+ spacing: 8
+ function toggleMAEnabled() { maButtonCB.checked = !maButtonCB.checked }
+ function toggleMAHover() { maButtonHoverCB.checked = !maButtonHoverCB.checked }
+ function toggleHHEnabled() { hhButtonHoverCB.checked = !hhButtonHoverCB.checked }
+
+ CheckBox {
+ id: maButtonCB
+ label: "enabled"
+ }
+
+ CheckBox {
+ id: maButtonHoverCB
+ label: "hover enabled"
+ }
+
+ Rectangle {
+ objectName: "buttonWithMA"
+ width: parent.width
+ height: 30
+ color: buttonMA.pressed ? "lightsteelblue" : "#999"
+ border.color: buttonMA.containsMouse ? "cyan" : "transparent"
+
+ MouseArea {
+ id: buttonMA
+ objectName: "buttonMA"
+ enabled: maButtonCB.checked
+ hoverEnabled: maButtonHoverCB.checked
+ cursorShape: Qt.UpArrowCursor
+ anchors.fill: parent
}
- Rectangle {
- objectName: "buttonWithHH"
- width: parent.width
- height: 30
- color: flash ? "#999" : "white"
- border.color: buttonHH.hovered ? "cyan" : "transparent"
- property bool flash: true
-
- HoverHandler {
- id: buttonHH
- objectName: "buttonHH"
- acceptedDevices: PointerDevice.AllDevices
- cursorShape: tapHandler.pressed ? Qt.BusyCursor : Qt.PointingHandCursor
- }
+ Text {
+ anchors.centerIn: parent
+ text: "MouseArea"
+ }
+ }
- TapHandler {
- id: tapHandler
- }
+ CheckBox {
+ id: hhButtonHoverCB
+ label: "hover enabled"
+ }
+
+ Rectangle {
+ id: buttonRoot
+ objectName: "buttonWithHH"
+ width: parent.width
+ height: 30
+ color: flash ? "#999" : "white"
+ border.color: buttonHH.hovered ? "cyan" : "transparent"
+ property bool flash: true
+
+ HoverHandler {
+ id: buttonHH
+ objectName: "buttonHH"
+ acceptedDevices: PointerDevice.AllDevices
+ enabled: hhButtonHoverCB.checked
+ cursorShape: tapHandler.pressed ? Qt.BusyCursor : Qt.PointingHandCursor
+ }
- Text {
- anchors.centerIn: parent
- text: "HoverHandler"
+ TapHandler {
+ id: tapHandler
+ onTapped: {
+ console.log("buttonRoot tapped")
+ buttonHH.enabled = !buttonHH.enabled
}
}
+
+ Text {
+ anchors.centerIn: parent
+ text: "HoverHandler"
+ }
}
}
@@ -134,10 +146,22 @@ Rectangle {
cursorShape: Qt.OpenHandCursor
}
- Loader {
- objectName: "topSidebarLoader"
- sourceComponent: buttonsAndStuff
+ ButtonsAndStuff {
+ id: tbs
+ objectName: "topSidebarContents"
anchors.fill: parent
+ Shortcut {
+ sequence: "Ctrl+E"
+ onActivated: tbs.toggleMAEnabled()
+ }
+ Shortcut {
+ sequence: "Ctrl+M"
+ onActivated: tbs.toggleMAHover()
+ }
+ Shortcut {
+ sequence: "Ctrl+H"
+ onActivated: tbs.toggleHHEnabled()
+ }
}
}
@@ -161,9 +185,8 @@ Rectangle {
anchors.fill: parent
}
- Loader {
- objectName: "bottomSidebarLoader"
- sourceComponent: buttonsAndStuff
+ ButtonsAndStuff {
+ objectName: "bottomSidebarContents"
anchors.fill: parent
}
}
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/nohandler.qml b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/nohandler.qml
new file mode 100644
index 0000000000..ed3728e278
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/nohandler.qml
@@ -0,0 +1,15 @@
+import QtQuick 2.15
+import QtQuick.Window 2.15
+
+Window {
+ width: 320
+ height: 240
+ visible: true
+
+ Rectangle {
+ objectName: "childItem"
+ width: 100
+ height: 100
+ color: "lightblue"
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/windowCursorShape.qml b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/windowCursorShape.qml
new file mode 100644
index 0000000000..b5c1f3d2ef
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/windowCursorShape.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.15
+import QtQuick.Window 2.15
+
+Window {
+ width: 320
+ height: 240
+ visible: true
+ color: hh.hovered ? "lightsteelblue" : "beige"
+ HoverHandler {
+ id: hh
+ cursorShape: Qt.OpenHandCursor
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp
index 11a5393390..0569fed472 100644
--- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp
@@ -1,36 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 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) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/private/qquickhoverhandler_p.h>
+#include <QtQuick/private/qquickpointerhandler_p_p.h>
#include <QtQuick/private/qquickmousearea_p.h>
#include <qpa/qwindowsysteminterface.h>
@@ -38,9 +14,10 @@
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlproperty.h>
+#include <QQmlComponent>
-#include "../../../shared/util.h"
-#include "../../shared/viewtestutil.h"
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtQuickTestUtils/private/viewtestutils_p.h>
Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
@@ -54,17 +31,30 @@ class tst_HoverHandler : public QQmlDataTest
Q_OBJECT
public:
tst_HoverHandler()
+ : QQmlDataTest(QT_QMLTEST_DATADIR)
{}
private slots:
+ void hoverHandlerAndUnderlyingHoverHandler_data();
void hoverHandlerAndUnderlyingHoverHandler();
void mouseAreaAndUnderlyingHoverHandler();
void hoverHandlerAndUnderlyingMouseArea();
+ void disabledHoverHandlerAndUnderlyingMouseArea();
+ void hoverHandlerOnDisabledItem();
void movingItemWithHoverHandler();
void margin();
+ void window();
+ void deviceCursor_data();
+ void deviceCursor();
+ void addHandlerFromCpp();
+ void ensureHoverHandlerWorksWhenItemHasHoverDisabled();
+ void changeCursor();
+ void touchDrag();
private:
void createView(QScopedPointer<QQuickView> &window, const char *fileName);
+
+ QScopedPointer<QPointingDevice> touchscreen = QScopedPointer<QPointingDevice>(QTest::createTouchDevice());
};
void tst_HoverHandler::createView(QScopedPointer<QQuickView> &window, const char *fileName)
@@ -72,16 +62,26 @@ void tst_HoverHandler::createView(QScopedPointer<QQuickView> &window, const char
window.reset(new QQuickView);
window->setSource(testFileUrl(fileName));
QTRY_COMPARE(window->status(), QQuickView::Ready);
- QQuickViewTestUtil::centerOnScreen(window.data());
- QQuickViewTestUtil::moveMouseAway(window.data());
+ QQuickViewTestUtils::centerOnScreen(window.data());
+ QQuickViewTestUtils::moveMouseAway(window.data());
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
QVERIFY(window->rootObject() != nullptr);
}
+void tst_HoverHandler::hoverHandlerAndUnderlyingHoverHandler_data()
+{
+ QTest::addColumn<bool>("blocking");
+
+ QTest::newRow("default: nonblocking") << false;
+ QTest::newRow("blocking") << true;
+}
+
void tst_HoverHandler::hoverHandlerAndUnderlyingHoverHandler()
{
+ QFETCH(bool, blocking);
+
QScopedPointer<QQuickView> windowPtr;
createView(windowPtr, "lesHoverables.qml");
QQuickView * window = windowPtr.data();
@@ -94,6 +94,9 @@ void tst_HoverHandler::hoverHandlerAndUnderlyingHoverHandler()
QQuickHoverHandler *buttonHH = button->findChild<QQuickHoverHandler *>("buttonHH");
QVERIFY(buttonHH);
+ QCOMPARE(buttonHH->isBlocking(), false); // default property value
+ buttonHH->setBlocking(blocking);
+
QPoint buttonCenter(button->mapToScene(QPointF(button->width() / 2, button->height() / 2)).toPoint());
QPoint rightOfButton(button->mapToScene(QPointF(button->width() + 2, button->height() / 2)).toPoint());
QPoint outOfSidebar(topSidebar->mapToScene(QPointF(topSidebar->width() + 2, topSidebar->height() / 2)).toPoint());
@@ -102,45 +105,45 @@ void tst_HoverHandler::hoverHandlerAndUnderlyingHoverHandler()
QTest::mouseMove(window, outOfSidebar);
QCOMPARE(topSidebarHH->isHovered(), false);
- QCOMPARE(sidebarHoveredSpy.count(), 0);
+ QCOMPARE(sidebarHoveredSpy.size(), 0);
QCOMPARE(buttonHH->isHovered(), false);
- QCOMPARE(buttonHoveredSpy.count(), 0);
+ QCOMPARE(buttonHoveredSpy.size(), 0);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::ArrowCursor);
#endif
QTest::mouseMove(window, rightOfButton);
QCOMPARE(topSidebarHH->isHovered(), true);
- QCOMPARE(sidebarHoveredSpy.count(), 1);
+ QCOMPARE(sidebarHoveredSpy.size(), 1);
QCOMPARE(buttonHH->isHovered(), false);
- QCOMPARE(buttonHoveredSpy.count(), 0);
+ QCOMPARE(buttonHoveredSpy.size(), 0);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::OpenHandCursor);
#endif
QTest::mouseMove(window, buttonCenter);
- QCOMPARE(topSidebarHH->isHovered(), true);
- QCOMPARE(sidebarHoveredSpy.count(), 1);
+ QCOMPARE(topSidebarHH->isHovered(), !blocking);
+ QCOMPARE(sidebarHoveredSpy.size(), blocking ? 2 : 1);
QCOMPARE(buttonHH->isHovered(), true);
- QCOMPARE(buttonHoveredSpy.count(), 1);
+ QCOMPARE(buttonHoveredSpy.size(), 1);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::PointingHandCursor);
#endif
QTest::mouseMove(window, rightOfButton);
QCOMPARE(topSidebarHH->isHovered(), true);
- QCOMPARE(sidebarHoveredSpy.count(), 1);
+ QCOMPARE(sidebarHoveredSpy.size(), blocking ? 3 : 1);
QCOMPARE(buttonHH->isHovered(), false);
- QCOMPARE(buttonHoveredSpy.count(), 2);
+ QCOMPARE(buttonHoveredSpy.size(), 2);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::OpenHandCursor);
#endif
QTest::mouseMove(window, outOfSidebar);
QCOMPARE(topSidebarHH->isHovered(), false);
- QCOMPARE(sidebarHoveredSpy.count(), 2);
+ QCOMPARE(sidebarHoveredSpy.size(), blocking ? 4 : 2);
QCOMPARE(buttonHH->isHovered(), false);
- QCOMPARE(buttonHoveredSpy.count(), 2);
+ QCOMPARE(buttonHoveredSpy.size(), 2);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::ArrowCursor);
#endif
@@ -158,6 +161,13 @@ void tst_HoverHandler::mouseAreaAndUnderlyingHoverHandler()
QQuickHoverHandler *topSidebarHH = topSidebar->findChild<QQuickHoverHandler *>("topSidebarHH");
QVERIFY(topSidebarHH);
+ // Ensure that we don't get extra hover events delivered on the
+ // side, since it can affect the number of hover move events we receive below.
+ QQuickWindowPrivate::get(window)->deliveryAgentPrivate()->frameSynchronousHoverEnabled = false;
+ // And flush out any mouse events that might be queued up
+ // in QPA, since QTest::mouseMove() calls processEvents.
+ qGuiApp->processEvents();
+
QPoint buttonCenter(buttonMA->mapToScene(QPointF(buttonMA->width() / 2, buttonMA->height() / 2)).toPoint());
QPoint rightOfButton(buttonMA->mapToScene(QPointF(buttonMA->width() + 2, buttonMA->height() / 2)).toPoint());
QPoint outOfSidebar(topSidebar->mapToScene(QPointF(topSidebar->width() + 2, topSidebar->height() / 2)).toPoint());
@@ -166,45 +176,45 @@ void tst_HoverHandler::mouseAreaAndUnderlyingHoverHandler()
QTest::mouseMove(window, outOfSidebar);
QCOMPARE(topSidebarHH->isHovered(), false);
- QCOMPARE(sidebarHoveredSpy.count(), 0);
+ QCOMPARE(sidebarHoveredSpy.size(), 0);
QCOMPARE(buttonMA->hovered(), false);
- QCOMPARE(buttonHoveredSpy.count(), 0);
+ QCOMPARE(buttonHoveredSpy.size(), 0);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::ArrowCursor);
#endif
QTest::mouseMove(window, rightOfButton);
QCOMPARE(topSidebarHH->isHovered(), true);
- QCOMPARE(sidebarHoveredSpy.count(), 1);
+ QCOMPARE(sidebarHoveredSpy.size(), 1);
QCOMPARE(buttonMA->hovered(), false);
- QCOMPARE(buttonHoveredSpy.count(), 0);
+ QCOMPARE(buttonHoveredSpy.size(), 0);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::OpenHandCursor);
#endif
QTest::mouseMove(window, buttonCenter);
QCOMPARE(topSidebarHH->isHovered(), true);
- QCOMPARE(sidebarHoveredSpy.count(), 1);
+ QCOMPARE(sidebarHoveredSpy.size(), 1);
QCOMPARE(buttonMA->hovered(), true);
- QCOMPARE(buttonHoveredSpy.count(), 1);
+ QCOMPARE(buttonHoveredSpy.size(), 1);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::UpArrowCursor);
#endif
QTest::mouseMove(window, rightOfButton);
QCOMPARE(topSidebarHH->isHovered(), true);
- QCOMPARE(sidebarHoveredSpy.count(), 1);
+ QCOMPARE(sidebarHoveredSpy.size(), 1);
QCOMPARE(buttonMA->hovered(), false);
- QCOMPARE(buttonHoveredSpy.count(), 2);
+ QCOMPARE(buttonHoveredSpy.size(), 2);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::OpenHandCursor);
#endif
QTest::mouseMove(window, outOfSidebar);
QCOMPARE(topSidebarHH->isHovered(), false);
- QCOMPARE(sidebarHoveredSpy.count(), 2);
+ QCOMPARE(sidebarHoveredSpy.size(), 2);
QCOMPARE(buttonMA->hovered(), false);
- QCOMPARE(buttonHoveredSpy.count(), 2);
+ QCOMPARE(buttonHoveredSpy.size(), 2);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::ArrowCursor);
#endif
@@ -232,50 +242,131 @@ void tst_HoverHandler::hoverHandlerAndUnderlyingMouseArea()
QTest::mouseMove(window, outOfSidebar);
QCOMPARE(bottomSidebarMA->hovered(), false);
- QCOMPARE(sidebarHoveredSpy.count(), 0);
+ QCOMPARE(sidebarHoveredSpy.size(), 0);
QCOMPARE(buttonHH->isHovered(), false);
- QCOMPARE(buttonHoveredSpy.count(), 0);
+ QCOMPARE(buttonHoveredSpy.size(), 0);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::ArrowCursor);
#endif
QTest::mouseMove(window, rightOfButton);
QCOMPARE(bottomSidebarMA->hovered(), true);
- QCOMPARE(sidebarHoveredSpy.count(), 1);
+ QCOMPARE(sidebarHoveredSpy.size(), 1);
QCOMPARE(buttonHH->isHovered(), false);
- QCOMPARE(buttonHoveredSpy.count(), 0);
+ QCOMPARE(buttonHoveredSpy.size(), 0);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::ClosedHandCursor);
#endif
QTest::mouseMove(window, buttonCenter);
QCOMPARE(bottomSidebarMA->hovered(), false);
- QCOMPARE(sidebarHoveredSpy.count(), 2);
+ QCOMPARE(sidebarHoveredSpy.size(), 2);
QCOMPARE(buttonHH->isHovered(), true);
- QCOMPARE(buttonHoveredSpy.count(), 1);
+ QCOMPARE(buttonHoveredSpy.size(), 1);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::PointingHandCursor);
#endif
QTest::mouseMove(window, rightOfButton);
QCOMPARE(bottomSidebarMA->hovered(), true);
- QCOMPARE(sidebarHoveredSpy.count(), 3);
+ QCOMPARE(sidebarHoveredSpy.size(), 3);
QCOMPARE(buttonHH->isHovered(), false);
- QCOMPARE(buttonHoveredSpy.count(), 2);
+ QCOMPARE(buttonHoveredSpy.size(), 2);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::ClosedHandCursor);
#endif
QTest::mouseMove(window, outOfSidebar);
QCOMPARE(bottomSidebarMA->hovered(), false);
- QCOMPARE(sidebarHoveredSpy.count(), 4);
+ QCOMPARE(sidebarHoveredSpy.size(), 4);
QCOMPARE(buttonHH->isHovered(), false);
- QCOMPARE(buttonHoveredSpy.count(), 2);
+ QCOMPARE(buttonHoveredSpy.size(), 2);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::ArrowCursor);
#endif
}
+void tst_HoverHandler::disabledHoverHandlerAndUnderlyingMouseArea()
+{
+ // Check that if a disabled HoverHandler is installed on an item, it
+ // will not participate in hover event delivery, and as such, also
+ // not block propagation to siblings.
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "lesHoverables.qml");
+ QQuickView * window = windowPtr.data();
+ QQuickItem * bottomSidebar = window->rootObject()->findChild<QQuickItem *>("bottomSidebar");
+ QVERIFY(bottomSidebar);
+ QQuickMouseArea *bottomSidebarMA = bottomSidebar->findChild<QQuickMouseArea *>("bottomSidebarMA");
+ QVERIFY(bottomSidebarMA);
+ QQuickItem * button = bottomSidebar->findChild<QQuickItem *>("buttonWithHH");
+ QVERIFY(button);
+ QQuickHoverHandler *buttonHH = button->findChild<QQuickHoverHandler *>("buttonHH");
+ QVERIFY(buttonHH);
+
+ // By disabling the HoverHandler, it should no longer
+ // block the sibling MouseArea underneath from receiving hover events.
+ buttonHH->setEnabled(false);
+
+ QPoint buttonCenter(button->mapToScene(QPointF(button->width() / 2, button->height() / 2)).toPoint());
+ QPoint rightOfButton(button->mapToScene(QPointF(button->width() + 2, button->height() / 2)).toPoint());
+ QPoint outOfSidebar(bottomSidebar->mapToScene(QPointF(bottomSidebar->width() + 2, bottomSidebar->height() / 2)).toPoint());
+ QSignalSpy sidebarHoveredSpy(bottomSidebarMA, SIGNAL(hoveredChanged()));
+ QSignalSpy buttonHoveredSpy(buttonHH, SIGNAL(hoveredChanged()));
+
+ QTest::mouseMove(window, outOfSidebar);
+ QCOMPARE(bottomSidebarMA->hovered(), false);
+ QCOMPARE(sidebarHoveredSpy.size(), 0);
+ QCOMPARE(buttonHH->isHovered(), false);
+ QCOMPARE(buttonHoveredSpy.size(), 0);
+
+ QTest::mouseMove(window, buttonCenter);
+ QCOMPARE(bottomSidebarMA->hovered(), true);
+ QCOMPARE(sidebarHoveredSpy.size(), 1);
+ QCOMPARE(buttonHH->isHovered(), false);
+ QCOMPARE(buttonHoveredSpy.size(), 0);
+
+ QTest::mouseMove(window, rightOfButton);
+ QCOMPARE(bottomSidebarMA->hovered(), true);
+ QCOMPARE(sidebarHoveredSpy.size(), 1);
+ QCOMPARE(buttonHH->isHovered(), false);
+ QCOMPARE(buttonHoveredSpy.size(), 0);
+}
+
+void tst_HoverHandler::hoverHandlerOnDisabledItem()
+{
+ // Check that if HoverHandler on a disabled item will
+ // continue to receive hover events (QTBUG-30801)
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "lesHoverables.qml");
+ QQuickView * window = windowPtr.data();
+ QQuickItem * bottomSidebar = window->rootObject()->findChild<QQuickItem *>("bottomSidebar");
+ QVERIFY(bottomSidebar);
+ QQuickItem * button = bottomSidebar->findChild<QQuickItem *>("buttonWithHH");
+ QVERIFY(button);
+ QQuickHoverHandler *buttonHH = button->findChild<QQuickHoverHandler *>("buttonHH");
+ QVERIFY(buttonHH);
+
+ // Disable the button/rectangle item. This should not
+ // block its HoverHandler from being hovered
+ button->setEnabled(false);
+
+ QPoint buttonCenter(button->mapToScene(QPointF(button->width() / 2, button->height() / 2)).toPoint());
+ QPoint rightOfButton(button->mapToScene(QPointF(button->width() + 2, button->height() / 2)).toPoint());
+ QSignalSpy buttonHoveredSpy(buttonHH, SIGNAL(hoveredChanged()));
+
+ QTest::mouseMove(window, rightOfButton);
+ QCOMPARE(buttonHH->isHovered(), false);
+ QCOMPARE(buttonHoveredSpy.size(), 0);
+
+ QTest::mouseMove(window, buttonCenter);
+ QCOMPARE(buttonHH->isHovered(), true);
+ QCOMPARE(buttonHoveredSpy.size(), 1);
+
+ QTest::mouseMove(window, rightOfButton);
+ QCOMPARE(buttonHH->isHovered(), false);
+ QCOMPARE(buttonHoveredSpy.size(), 2);
+}
+
void tst_HoverHandler::movingItemWithHoverHandler()
{
if (isPlatformWayland())
@@ -306,7 +397,7 @@ void tst_HoverHandler::movingItemWithHoverHandler()
paddle->setX(100);
QTRY_COMPARE(paddleHH->isHovered(), false);
- paddle->setX(p.x());
+ paddle->setX(p.x() - paddle->width() / 2);
QTRY_COMPARE(paddleHH->isHovered(), true);
paddle->setX(540);
@@ -329,21 +420,21 @@ void tst_HoverHandler::margin() // QTBUG-85303
QTest::mouseMove(window, {10, 10});
QCOMPARE(hh->isHovered(), false);
- QCOMPARE(hoveredSpy.count(), 0);
+ QCOMPARE(hoveredSpy.size(), 0);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::ArrowCursor);
#endif
QTest::mouseMove(window, leftMargin);
QCOMPARE(hh->isHovered(), true);
- QCOMPARE(hoveredSpy.count(), 1);
+ QCOMPARE(hoveredSpy.size(), 1);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::OpenHandCursor);
#endif
QTest::mouseMove(window, itemCenter);
QCOMPARE(hh->isHovered(), true);
- QCOMPARE(hoveredSpy.count(), 1);
+ QCOMPARE(hoveredSpy.size(), 1);
#if QT_CONFIG(cursor)
QCOMPARE(window->cursor().shape(), Qt::OpenHandCursor);
#endif
@@ -363,6 +454,306 @@ void tst_HoverHandler::margin() // QTBUG-85303
#endif
}
+void tst_HoverHandler::window() // QTBUG-98717
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("windowCursorShape.qml"));
+ QScopedPointer<QQuickWindow> window(qobject_cast<QQuickWindow *>(component.create()));
+ QVERIFY(!window.isNull());
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+#if QT_CONFIG(cursor)
+ if (isPlatformWayland())
+ QSKIP("Wayland: QCursor::setPos() doesn't work.");
+ auto cursorPos = window->mapToGlobal(QPoint(100, 100));
+ qCDebug(lcPointerTests) << "in window @" << window->position() << "setting cursor pos" << cursorPos;
+ QCursor::setPos(cursorPos);
+ if (!QTest::qWaitFor([cursorPos]{ return QCursor::pos() == cursorPos; }))
+ QSKIP("QCursor::setPos() doesn't work (QTBUG-76312).");
+ QTRY_COMPARE(window->cursor().shape(), Qt::OpenHandCursor);
+#endif
+}
+
+void tst_HoverHandler::deviceCursor_data()
+{
+ QTest::addColumn<bool>("synthMouseForTabletEvents");
+ QTest::addColumn<bool>("earlierTabletBeforeMouse");
+
+ QTest::newRow("nosynth, tablet wins") << false << false;
+ QTest::newRow("synth, tablet wins") << true << false;
+ QTest::newRow("synth, mouse wins") << true << true;
+}
+
+void tst_HoverHandler::deviceCursor()
+{
+#if !QT_CONFIG(tabletevent)
+ QSKIP("This test depends on QTabletEvent delivery.");
+#endif
+ QFETCH(bool, synthMouseForTabletEvents);
+ QFETCH(bool, earlierTabletBeforeMouse);
+ qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTabletEvents, synthMouseForTabletEvents);
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("hoverDeviceCursors.qml")));
+ // Ensure that we don't get extra hover events delivered on the side
+ QQuickWindowPrivate::get(&window)->deliveryAgentPrivate()->frameSynchronousHoverEnabled = false;
+ // And flush out any mouse events that might be queued up in QPA, since QTest::mouseMove() calls processEvents.
+ qGuiApp->processEvents();
+ const QQuickItem *root = window.rootObject();
+ QQuickHoverHandler *stylusHandler = root->findChild<QQuickHoverHandler *>("stylus");
+ QVERIFY(stylusHandler);
+ QQuickHoverHandler *eraserHandler = root->findChild<QQuickHoverHandler *>("stylus eraser");
+ QVERIFY(eraserHandler);
+ QQuickHoverHandler *aibrushHandler = root->findChild<QQuickHoverHandler *>("airbrush");
+ QVERIFY(aibrushHandler);
+ QQuickHoverHandler *airbrushEraserHandler = root->findChild<QQuickHoverHandler *>("airbrush eraser");
+ QVERIFY(airbrushEraserHandler);
+ QQuickHoverHandler *mouseHandler = root->findChild<QQuickHoverHandler *>("mouse");
+ QVERIFY(mouseHandler);
+
+ QPoint point(100, 100);
+
+ const qint64 stylusId = 1234567890;
+ QElapsedTimer timer;
+ timer.start();
+ auto testStylusDevice = [&](QInputDevice::DeviceType dt, QPointingDevice::PointerType pt,
+ Qt::CursorShape expectedCursor, QQuickHoverHandler* expectedActiveHandler) {
+ // We will follow up with a mouse event afterwards, and we want to simulate that the tablet events occur
+ // either slightly before (earlierTabletBeforeMouse == true) or some time before.
+ // It turns out that the first mouse move happens at timestamp 501 (simulated).
+ const ulong timestamp = (earlierTabletBeforeMouse ? 0 : 400) + timer.elapsed();
+ qCDebug(lcPointerTests) << "@" << timestamp << "sending" << dt << pt << "expecting" << expectedCursor << expectedActiveHandler->objectName();
+ QWindowSystemInterface::handleTabletEvent(&window, timestamp, point, window.mapToGlobal(point),
+ int(dt), int(pt), Qt::NoButton, 0, 0, 0, 0, 0, 0, stylusId, Qt::NoModifier);
+ point += QPoint(1, 0);
+#if QT_CONFIG(cursor)
+ // QQuickItem::setCursor() doesn't get called: we only have HoverHandlers in this test
+ QCOMPARE(root->cursor().shape(), Qt::ArrowCursor);
+ QTRY_COMPARE(window.cursor().shape(), expectedCursor);
+#endif
+ QCOMPARE(stylusHandler->isHovered(), stylusHandler == expectedActiveHandler);
+ QCOMPARE(eraserHandler->isHovered(), eraserHandler == expectedActiveHandler);
+ QCOMPARE(aibrushHandler->isHovered(), aibrushHandler == expectedActiveHandler);
+ QCOMPARE(airbrushEraserHandler->isHovered(), airbrushEraserHandler == expectedActiveHandler);
+ };
+
+ // simulate move events from various tablet stylus types
+ testStylusDevice(QInputDevice::DeviceType::Stylus, QPointingDevice::PointerType::Pen,
+ Qt::CrossCursor, stylusHandler);
+ testStylusDevice(QInputDevice::DeviceType::Stylus, QPointingDevice::PointerType::Eraser,
+ Qt::PointingHandCursor, eraserHandler);
+ testStylusDevice(QInputDevice::DeviceType::Airbrush, QPointingDevice::PointerType::Pen,
+ Qt::BusyCursor, aibrushHandler);
+ testStylusDevice(QInputDevice::DeviceType::Airbrush, QPointingDevice::PointerType::Eraser,
+ Qt::OpenHandCursor, airbrushEraserHandler);
+
+ qCDebug(lcPointerTests) << "---- no more tablet events, now we send a mouse move";
+
+ // move the mouse: the mouse-specific HoverHandler gets to set the cursor only if
+ // more than kCursorOverrideTimeout ms have elapsed (100ms)
+ QTest::mouseMove(&window, point, 100);
+ QTRY_IMPL(mouseHandler->isHovered() == true, 500);
+ const bool afterTimeout =
+ QQuickPointerHandlerPrivate::get(airbrushEraserHandler)->lastEventTime + 100 <
+ QQuickPointerHandlerPrivate::get(mouseHandler)->lastEventTime;
+ qCDebug(lcPointerTests) << "airbrush handler reacted last time:" << QQuickPointerHandlerPrivate::get(airbrushEraserHandler)->lastEventTime
+ << "and the mouse handler reacted at time:" << QQuickPointerHandlerPrivate::get(mouseHandler)->lastEventTime
+ << "so > 100 ms have elapsed?" << afterTimeout;
+ if (afterTimeout)
+ QCOMPARE(mouseHandler->isHovered(), true);
+ else
+ QSKIP("Failed to delay mouse move 100ms after the previous tablet event");
+
+#if QT_CONFIG(cursor)
+ QCOMPARE(window.cursor().shape(), afterTimeout ? Qt::IBeamCursor : Qt::OpenHandCursor);
+#endif
+ QCOMPARE(stylusHandler->isHovered(), false);
+ QCOMPARE(eraserHandler->isHovered(), false);
+ QCOMPARE(aibrushHandler->isHovered(), false);
+ QCOMPARE(airbrushEraserHandler->isHovered(), true); // there was no fresh QTabletEvent to tell it not to be hovered
+
+ // hover with the stylus again, then move the mouse outside the handlers' parent item
+ testStylusDevice(QInputDevice::DeviceType::Stylus, QPointingDevice::PointerType::Pen,
+ Qt::CrossCursor, stylusHandler);
+ QTest::mouseMove(&window, QPoint(180, 180));
+ // the mouse has left the item: all its HoverHandlers should be unhovered (QTBUG-116505)
+ QCOMPARE(stylusHandler->isHovered(), false);
+ QCOMPARE(eraserHandler->isHovered(), false);
+ QCOMPARE(aibrushHandler->isHovered(), false);
+ QCOMPARE(airbrushEraserHandler->isHovered(), false);
+ QCOMPARE(mouseHandler->isHovered(), false);
+}
+
+void tst_HoverHandler::addHandlerFromCpp()
+{
+ // Check that you can create a hover handler from c++, and add it
+ // as a child of an existing item. Continue to check that you can
+ // also change the parent item at runtime.
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("nohandler.qml"));
+ QScopedPointer<QQuickWindow> window(qobject_cast<QQuickWindow *>(component.create()));
+ QVERIFY(!window.isNull());
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickItem *childItem = window->findChild<QQuickItem *>("childItem");
+ QVERIFY(childItem);
+
+ // Move mouse outside child
+ const QPoint outside(200, 200);
+ const QPoint inside(50, 50);
+ QTest::mouseMove(window.data(), outside);
+
+ QQuickHoverHandler *handler = new QQuickHoverHandler(childItem);
+ QSignalSpy spy(handler, &QQuickHoverHandler::hoveredChanged);
+
+ // Move mouse inside child
+ QTest::mouseMove(window.data(), inside);
+ QVERIFY(handler->isHovered());
+ QCOMPARE(spy.size(), 1);
+
+ // Move mouse outside child
+ QTest::mouseMove(window.data(), outside);
+ QVERIFY(!handler->isHovered());
+ QCOMPARE(spy.size(), 2);
+
+ // Remove the parent item from the handler
+ spy.clear();
+ handler->setParentItem(nullptr);
+
+ // Move mouse inside child
+ QTest::mouseMove(window.data(), inside);
+ QVERIFY(!handler->isHovered());
+ QCOMPARE(spy.size(), 0);
+
+ // Move mouse outside child
+ QTest::mouseMove(window.data(), outside);
+ QVERIFY(!handler->isHovered());
+ QCOMPARE(spy.size(), 0);
+
+ // Reparent back the item to the handler
+ spy.clear();
+ handler->setParentItem(childItem);
+
+ // Move mouse inside child
+ QTest::mouseMove(window.data(), inside);
+ QVERIFY(handler->isHovered());
+ QCOMPARE(spy.size(), 1);
+
+ // Move mouse outside child
+ QTest::mouseMove(window.data(), outside);
+ QVERIFY(!handler->isHovered());
+ QCOMPARE(spy.size(), 2);
+}
+
+void tst_HoverHandler::ensureHoverHandlerWorksWhenItemHasHoverDisabled()
+{
+ // Check that a hover handler with a leaf item as parent, continues to
+ // receive hover, even if the item itself stops listening for hover.
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("nohandler.qml"));
+ QScopedPointer<QQuickWindow> window(qobject_cast<QQuickWindow *>(component.create()));
+ QVERIFY(!window.isNull());
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickItem *childItem = window->findChild<QQuickItem *>("childItem");
+ QVERIFY(childItem);
+
+ // Move mouse outside child
+ const QPoint outside(200, 200);
+ const QPoint inside(50, 50);
+ QTest::mouseMove(window.data(), outside);
+
+ QQuickHoverHandler *handler = new QQuickHoverHandler(childItem);
+
+ // Toggle hover on the item. This should not clear subtreeHoverEnabled
+ // on the item as a whole, since it still has a hover handler.
+ childItem->setAcceptHoverEvents(true);
+ childItem->setAcceptHoverEvents(false);
+ QSignalSpy spy(handler, &QQuickHoverHandler::hoveredChanged);
+
+ // Move mouse inside child
+ QTest::mouseMove(window.data(), inside);
+ QVERIFY(handler->isHovered());
+ QCOMPARE(spy.size(), 1);
+
+ // Move mouse outside child
+ QTest::mouseMove(window.data(), outside);
+ QVERIFY(!handler->isHovered());
+ QCOMPARE(spy.size(), 2);
+}
+
+void tst_HoverHandler::changeCursor()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "changingCursor.qml");
+ QQuickView * window = windowPtr.data();
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickItem *item = window->findChild<QQuickItem *>("brownRect");
+ QVERIFY(item);
+ QQuickHoverHandler *hh = item->findChild<QQuickHoverHandler *>();
+ QVERIFY(hh);
+
+ QPoint itemCenter(item->mapToScene(QPointF(item->width() / 2, item->height() / 2)).toPoint());
+ QSignalSpy hoveredSpy(hh, SIGNAL(hoveredChanged()));
+
+ QTest::mouseMove(window, itemCenter);
+
+ QTRY_COMPARE(hoveredSpy.size(), 1);
+
+#if QT_CONFIG(cursor)
+ QTRY_COMPARE(window->cursor().shape(), Qt::CrossCursor);
+ QTRY_COMPARE(window->cursor().shape(), Qt::OpenHandCursor);
+ QTRY_COMPARE(window->cursor().shape(), Qt::CrossCursor);
+ QTRY_COMPARE(window->cursor().shape(), Qt::OpenHandCursor);
+#endif
+}
+
+void tst_HoverHandler::touchDrag()
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("hoverHandler.qml")));
+ const QQuickItem *root = window.rootObject();
+ QQuickHoverHandler *handler = root->findChild<QQuickHoverHandler *>();
+ QVERIFY(handler);
+
+ // polishAndSync() calls flushFrameSynchronousEvents() before emitting afterAnimating()
+ QSignalSpy frameSyncSpy(&window, &QQuickWindow::afterAnimating);
+
+ const QPoint out(root->width() - 1, root->height() / 2);
+ QPoint in(root->width() / 2, root->height() / 2);
+
+ QTest::touchEvent(&window, touchscreen.get()).press(0, out, &window);
+ QQuickTouchUtils::flush(&window);
+ QCOMPARE(handler->isHovered(), false);
+
+ frameSyncSpy.clear();
+ QTest::touchEvent(&window, touchscreen.get()).move(0, in, &window);
+ QQuickTouchUtils::flush(&window);
+ QTRY_COMPARE(handler->isHovered(), true);
+ QCOMPARE(handler->point().scenePosition(), in);
+
+ in += {10, 10};
+ QTest::touchEvent(&window, touchscreen.get()).move(0, in, &window);
+ QQuickTouchUtils::flush(&window);
+ // ensure that the color change is visible
+ QTRY_COMPARE_GE(frameSyncSpy.size(), 1);
+ QCOMPARE(handler->isHovered(), true);
+ QCOMPARE(handler->point().scenePosition(), in);
+
+ QTest::touchEvent(&window, touchscreen.get()).move(0, out, &window);
+ QQuickTouchUtils::flush(&window);
+ QTRY_COMPARE_GE(frameSyncSpy.size(), 2);
+ QCOMPARE(handler->isHovered(), false);
+
+ QTest::touchEvent(&window, touchscreen.get()).release(0, out, &window);
+}
+
QTEST_MAIN(tst_HoverHandler)
#include "tst_qquickhoverhandler.moc"
diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/BLACKLIST b/tests/auto/quick/pointerhandlers/qquickpinchhandler/BLACKLIST
new file mode 100644
index 0000000000..701cdae344
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/BLACKLIST
@@ -0,0 +1,3 @@
+# QTBUG-103066
+[scaleNativeGesture]
+android
diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/CMakeLists.txt b/tests/auto/quick/pointerhandlers/qquickpinchhandler/CMakeLists.txt
index 09550b143d..1334607ab2 100644
--- a/tests/auto/quick/pointerhandlers/qquickpinchhandler/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/CMakeLists.txt
@@ -1,9 +1,18 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# Generated from qquickpinchhandler.pro.
#####################################################################
## tst_qquickpinchhandler Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickpinchhandler 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_qquickpinchhandler
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_qquickpinchhandler.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}
)
@@ -38,10 +40,10 @@ qt_internal_add_test(tst_qquickpinchhandler
qt_internal_extend_target(tst_qquickpinchhandler CONDITION ANDROID OR IOS
DEFINES
- QT_QMLTEST_DATADIR=\\\":/data\\\"
+ QT_QMLTEST_DATADIR=":/data"
)
qt_internal_extend_target(tst_qquickpinchhandler 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/pointerhandlers/qquickpinchhandler/data/nullTarget.qml b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/nullTarget.qml
new file mode 100644
index 0000000000..9d9903fc0e
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/nullTarget.qml
@@ -0,0 +1,33 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick 2.15
+
+Item {
+ width: 320; height: 320
+ property alias pinchScale: pinch.scale
+
+ Rectangle {
+ objectName: "blackrect"
+ width: 200; height: 200
+ color: "black"
+ antialiasing: true
+ scale: pinch.scale
+ rotation: pinch.rotation
+ x: pinch.translation.x
+ y: pinch.translation.y
+
+ PinchHandler {
+ id: pinch
+ target: null
+ minimumScale: 0.5
+ maximumScale: 4
+ }
+
+ Text {
+ color: "cyan"
+ anchors.centerIn: parent
+ text: "scale " + pinch.scale.toFixed(2) + " activeScale " + pinch.activeScale.toFixed(2)
+ }
+ }
+}
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..ddd63ec720
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchAndDrag.qml
@@ -0,0 +1,37 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+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/data/pinchproperties.qml b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchproperties.qml
index 3cabde5f59..2b9b3eb156 100644
--- a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchproperties.qml
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchproperties.qml
@@ -1,40 +1,49 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 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) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
Rectangle {
id: whiteRect
- property real scale: -1.0
+ property real pinchScale: -1.0
property int activeCount : 0
property int deactiveCount : 0
width: 320; height: 320
color: "white"
+
+ PointHandler {
+ id: ph1
+ acceptedDevices: PointerDevice.TouchScreen
+ target: Rectangle {
+ parent: whiteRect
+ color: "cyan"
+ x: ph1.point.position.x - 3
+ y: ph1.point.position.y - 3
+ width: 6; height: 6; radius: 3
+ }
+ }
+
+ PointHandler {
+ id: ph2
+ acceptedDevices: PointerDevice.TouchScreen
+ target: Rectangle {
+ parent: whiteRect
+ color: "lightgreen"
+ x: ph2.point.position.x - 3
+ y: ph2.point.position.y - 3
+ width: 6; height: 6; radius: 3
+ }
+ }
+
+ Text {
+ color: "magenta"
+ z: 1
+ text: "scale: " + blackRect.scale +
+ "\npos: " + blackRect.x.toFixed(2) + ", " + blackRect.y.toFixed(2) +
+ "\ntranslation: active " + pincharea.activeTranslation.x.toFixed(2) + ", " + pincharea.activeTranslation.y.toFixed(2) +
+ "\n persistent " + pincharea.persistentTranslation.x.toFixed(2) + ", " + pincharea.persistentTranslation.y.toFixed(2)
+ }
+
Rectangle {
id: blackRect
objectName: "blackrect"
@@ -43,8 +52,7 @@ Rectangle {
x: 50
width: 100
height: 100
- opacity: (whiteRect.width-blackRect.x+whiteRect.height-blackRect.y-199)/200
- Text { color: "white"; text: "opacity: " + blackRect.opacity + "\nscale: " + blackRect.scale}
+
Rectangle {
color: "red"
width: 6; height: 6; radius: 3
@@ -56,22 +64,30 @@ Rectangle {
PinchHandler {
id: pincharea
objectName: "pinchHandler"
- minimumScale: 1.0
+ minimumScale: 0.5
maximumScale: 4.0
minimumRotation: 0.0
maximumRotation: 90.0
xAxis.maximum: 140
yAxis.maximum: 170
onActiveChanged: {
- whiteRect.scale = pincharea.scale
+ whiteRect.pinchScale = pincharea.scale
if (active) ++activeCount
else ++deactiveCount;
}
onUpdated: {
- whiteRect.scale = pincharea.scale
+ whiteRect.pinchScale = pincharea.scale
//whiteRect.pointCount = pincharea.pointCount
}
- }
- }
- }
+ }
+ }
+
+ Rectangle {
+ color: "transparent"; border.color: "green"
+ width: 12; height: 12; radius: 6; border.width: 2
+ visible: pincharea.active
+ x: pincharea.centroid.scenePosition.x - radius
+ y: pincharea.centroid.scenePosition.y - radius
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/threeFingers.qml b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/threeFingers.qml
index 4d1a520c01..ed9220f99e 100644
--- a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/threeFingers.qml
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/threeFingers.qml
@@ -1,39 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 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) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-import QtQuick 2.12
+import QtQuick
Rectangle {
id: root
- property variant centroid : pinchHandler.centroid
- property real scale: pinchHandler.scale
- property int pointCount: 0
- property bool pinchActive: pinchHandler.active
width: 240; height: 320
Rectangle {
@@ -48,6 +19,7 @@ Rectangle {
PinchHandler {
id: pinchHandler
objectName: "pinchHandler"
+ dragThreshold: 10
minimumScale: 0.5
maximumScale: 2.0
minimumRotation: 0.0
diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/transformedPinchHandler.qml b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/transformedPinchHandler.qml
index 46e9ccca87..f25d0e9f38 100644
--- a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/transformedPinchHandler.qml
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/transformedPinchHandler.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 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) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp
index cd24d8643e..78483c5bdb 100644
--- a/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp
@@ -1,55 +1,41 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
#include <QtGui/QStyleHints>
-#include <QtGui/private/qevent_p.h>
+#include <QtGui/private/qeventpoint_p.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtQuick/private/qquickpinchhandler_p.h>
#include <QtQuick/private/qquickrectangle_p.h>
#include <QtQuick/qquickview.h>
#include <QtQml/qqmlcontext.h>
-#include "../../../shared/util.h"
-#include "../../shared/viewtestutil.h"
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtQuickTestUtils/private/viewtestutils_p.h>
Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
+class PinchHandler : public QQuickPinchHandler {
+public:
+ const QQuickHandlerPoint &firstPoint() { return currentPoints().first(); }
+ const QQuickHandlerPoint &lastPoint() { return currentPoints().last(); }
+};
+
class tst_QQuickPinchHandler: public QQmlDataTest
{
Q_OBJECT
public:
- tst_QQuickPinchHandler() { }
+ tst_QQuickPinchHandler() : QQmlDataTest(QT_QMLTEST_DATADIR) { }
private slots:
void cleanupTestCase();
void pinchProperties();
+ void scale_data();
void scale();
void scaleThreeFingers();
+ void scaleNativeGesture_data();
+ void scaleNativeGesture();
+ void cumulativeNativeGestures_data();
+ void cumulativeNativeGestures();
void pan();
void dragAxesEnabled_data();
void dragAxesEnabled();
@@ -59,8 +45,8 @@ private slots:
void transformedpinchHandler();
private:
- QQuickView *createView();
- QPointingDevice *device = QTest::createTouchDevice();
+ QScopedPointer<QPointingDevice> touchscreen = QScopedPointer<QPointingDevice>(QTest::createTouchDevice());
+ QScopedPointer<QPointingDevice> touchpad = QScopedPointer<QPointingDevice>(QTest::createTouchDevice(QInputDevice::DeviceType::TouchPad));
};
void tst_QQuickPinchHandler::cleanupTestCase()
@@ -75,7 +61,7 @@ static bool withinBounds(qreal lower, qreal num, qreal upper)
void tst_QQuickPinchHandler::pinchProperties()
{
- QScopedPointer<QQuickView> window(createView());
+ QScopedPointer<QQuickView> window(QQuickViewTestUtils::createView());
window->setSource(testFileUrl("pinchproperties.qml"));
window->show();
QVERIFY(window->rootObject() != nullptr);
@@ -91,193 +77,292 @@ void tst_QQuickPinchHandler::pinchProperties()
QVERIFY(rootItem != nullptr);
QSignalSpy targetSpy(pinchHandler, SIGNAL(targetChanged()));
pinchHandler->setTarget(rootItem);
- QCOMPARE(targetSpy.count(),1);
+ QCOMPARE(targetSpy.size(),1);
pinchHandler->setTarget(rootItem);
- QCOMPARE(targetSpy.count(),1);
-
- // axis
- /*
- QCOMPARE(pinchHandler->axis(), QQuickPinch::XAndYAxis);
- QSignalSpy axisSpy(pinchHandler, SIGNAL(dragAxisChanged()));
- pinchHandler->setAxis(QQuickPinch::XAxis);
- QCOMPARE(pinchHandler->axis(), QQuickPinch::XAxis);
- QCOMPARE(axisSpy.count(),1);
- pinchHandler->setAxis(QQuickPinch::XAxis);
- QCOMPARE(axisSpy.count(),1);
+ QCOMPARE(targetSpy.size(),1);
+
+ // drag axes
+ QCOMPARE(pinchHandler->xAxis()->enabled(), true);
+ QCOMPARE(pinchHandler->yAxis()->enabled(), true);
+ QSignalSpy xEnabledSpy(pinchHandler->xAxis(), &QQuickDragAxis::enabledChanged);
+ QSignalSpy yEnabledSpy(pinchHandler->yAxis(), &QQuickDragAxis::enabledChanged);
+ QSignalSpy scaleEnabledSpy(pinchHandler->scaleAxis(), &QQuickDragAxis::enabledChanged);
+ QSignalSpy rotationEnabledSpy(pinchHandler->rotationAxis(), &QQuickDragAxis::enabledChanged);
+ pinchHandler->xAxis()->setEnabled(false);
+ QCOMPARE(xEnabledSpy.count(), 1);
+ pinchHandler->yAxis()->setEnabled(false);
+ QCOMPARE(yEnabledSpy.count(), 1);
+ pinchHandler->scaleAxis()->setEnabled(false);
+ QCOMPARE(scaleEnabledSpy.count(), 1);
+ pinchHandler->rotationAxis()->setEnabled(false);
+ QCOMPARE(rotationEnabledSpy.count(), 1);
// minimum and maximum drag properties
- QSignalSpy xminSpy(pinchHandler, SIGNAL(minimumXChanged()));
- QSignalSpy xmaxSpy(pinchHandler, SIGNAL(maximumXChanged()));
- QSignalSpy yminSpy(pinchHandler, SIGNAL(minimumYChanged()));
- QSignalSpy ymaxSpy(pinchHandler, SIGNAL(maximumYChanged()));
-
- QCOMPARE(pinchHandler->xmin(), 0.0);
- QCOMPARE(pinchHandler->xmax(), rootItem->width()-blackRect->width());
- QCOMPARE(pinchHandler->ymin(), 0.0);
- QCOMPARE(pinchHandler->ymax(), rootItem->height()-blackRect->height());
-
- pinchHandler->setXmin(10);
- pinchHandler->setXmax(10);
- pinchHandler->setYmin(10);
- pinchHandler->setYmax(10);
-
- QCOMPARE(pinchHandler->xmin(), 10.0);
- QCOMPARE(pinchHandler->xmax(), 10.0);
- QCOMPARE(pinchHandler->ymin(), 10.0);
- QCOMPARE(pinchHandler->ymax(), 10.0);
+ QSignalSpy xminSpy(pinchHandler->xAxis(), &QQuickDragAxis::minimumChanged);
+ QSignalSpy xmaxSpy(pinchHandler->xAxis(), &QQuickDragAxis::maximumChanged);
+ QSignalSpy yminSpy(pinchHandler->yAxis(), &QQuickDragAxis::minimumChanged);
+ QSignalSpy ymaxSpy(pinchHandler->yAxis(), &QQuickDragAxis::maximumChanged);
+
+ QCOMPARE(pinchHandler->xAxis()->minimum(), std::numeric_limits<qreal>::lowest());
+ QCOMPARE(pinchHandler->xAxis()->maximum(), 140);
+ QCOMPARE(pinchHandler->yAxis()->minimum(), std::numeric_limits<qreal>::lowest());
+ QCOMPARE(pinchHandler->yAxis()->maximum(), 170);
+
+ pinchHandler->xAxis()->setMinimum(10);
+ pinchHandler->xAxis()->setMaximum(10);
+ pinchHandler->yAxis()->setMinimum(10);
+ pinchHandler->yAxis()->setMaximum(10);
+
+ QCOMPARE(pinchHandler->xAxis()->minimum(), 10);
+ QCOMPARE(pinchHandler->xAxis()->maximum(), 10);
+ QCOMPARE(pinchHandler->yAxis()->minimum(), 10);
+ QCOMPARE(pinchHandler->yAxis()->maximum(), 10);
QCOMPARE(xminSpy.count(),1);
QCOMPARE(xmaxSpy.count(),1);
QCOMPARE(yminSpy.count(),1);
QCOMPARE(ymaxSpy.count(),1);
- pinchHandler->setXmin(10);
- pinchHandler->setXmax(10);
- pinchHandler->setYmin(10);
- pinchHandler->setYmax(10);
+ pinchHandler->xAxis()->setMinimum(10);
+ pinchHandler->xAxis()->setMaximum(10);
+ pinchHandler->yAxis()->setMinimum(10);
+ pinchHandler->yAxis()->setMaximum(10);
QCOMPARE(xminSpy.count(),1);
QCOMPARE(xmaxSpy.count(),1);
QCOMPARE(yminSpy.count(),1);
QCOMPARE(ymaxSpy.count(),1);
- */
// minimum and maximum scale properties
- QSignalSpy scaleMinSpy(pinchHandler, SIGNAL(minimumScaleChanged()));
- QSignalSpy scaleMaxSpy(pinchHandler, SIGNAL(maximumScaleChanged()));
-
- QCOMPARE(pinchHandler->minimumScale(), 1.0);
- QCOMPARE(pinchHandler->maximumScale(), 4.0);
+ QSignalSpy scaleAxisMinSpy(pinchHandler->scaleAxis(), &QQuickDragAxis::minimumChanged);
+ QSignalSpy scaleAxisMaxSpy(pinchHandler->scaleAxis(), &QQuickDragAxis::maximumChanged);
- pinchHandler->setMinimumScale(0.5);
- pinchHandler->setMaximumScale(1.5);
+ QCOMPARE(pinchHandler->scaleAxis()->minimum(), 0.5);
+ QCOMPARE(pinchHandler->scaleAxis()->maximum(), 4);
+#if QT_DEPRECATED_SINCE(6, 5)
+QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
QCOMPARE(pinchHandler->minimumScale(), 0.5);
- QCOMPARE(pinchHandler->maximumScale(), 1.5);
-
- QCOMPARE(scaleMinSpy.count(),1);
- QCOMPARE(scaleMaxSpy.count(),1);
+ QCOMPARE(pinchHandler->maximumScale(), 4);
+QT_WARNING_POP
+#endif
- pinchHandler->setMinimumScale(0.5);
- pinchHandler->setMaximumScale(1.5);
+ pinchHandler->scaleAxis()->setMinimum(0.25);
+ pinchHandler->scaleAxis()->setMaximum(1.5);
- QCOMPARE(scaleMinSpy.count(),1);
- QCOMPARE(scaleMaxSpy.count(),1);
+ QCOMPARE(pinchHandler->scaleAxis()->minimum(), 0.25);
+ QCOMPARE(pinchHandler->scaleAxis()->maximum(), 1.5);
- // minimum and maximum rotation properties
- QSignalSpy rotMinSpy(pinchHandler, SIGNAL(minimumRotationChanged()));
- QSignalSpy rotMaxSpy(pinchHandler, SIGNAL(maximumRotationChanged()));
-
- QCOMPARE(pinchHandler->minimumRotation(), 0.0);
- QCOMPARE(pinchHandler->maximumRotation(), 90.0);
-
- pinchHandler->setMinimumRotation(-90.0);
- pinchHandler->setMaximumRotation(45.0);
+#if QT_DEPRECATED_SINCE(6, 5)
+QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
+ QCOMPARE(pinchHandler->minimumScale(), 0.25);
+ QCOMPARE(pinchHandler->maximumScale(), 1.5);
+QT_WARNING_POP
+#endif
- QCOMPARE(pinchHandler->minimumRotation(), -90.0);
- QCOMPARE(pinchHandler->maximumRotation(), 45.0);
+ QCOMPARE(scaleAxisMinSpy.size(),1);
+ QCOMPARE(scaleAxisMaxSpy.size(),1);
- QCOMPARE(rotMinSpy.count(),1);
- QCOMPARE(rotMaxSpy.count(),1);
+ pinchHandler->scaleAxis()->setMinimum(0.25);
+ pinchHandler->scaleAxis()->setMaximum(1.5);
- pinchHandler->setMinimumRotation(-90.0);
- pinchHandler->setMaximumRotation(45.0);
+ QCOMPARE(scaleAxisMinSpy.size(),1);
+ QCOMPARE(scaleAxisMaxSpy.size(),1);
- QCOMPARE(rotMinSpy.count(),1);
- QCOMPARE(rotMaxSpy.count(),1);
+ // minimum and maximum rotation properties
+ QSignalSpy rotAxisMinSpy(pinchHandler->rotationAxis(), &QQuickDragAxis::minimumChanged);
+ QSignalSpy rotAxisMaxSpy(pinchHandler->rotationAxis(), &QQuickDragAxis::maximumChanged);
+
+#if QT_DEPRECATED_SINCE(6, 5)
+QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
+ QCOMPARE(pinchHandler->minimumRotation(), 0);
+ QCOMPARE(pinchHandler->maximumRotation(), 90);
+QT_WARNING_POP
+#endif
+ QCOMPARE(pinchHandler->rotationAxis()->minimum(), 0);
+ QCOMPARE(pinchHandler->rotationAxis()->maximum(), 90);
+
+ pinchHandler->rotationAxis()->setMinimum(-90);
+ pinchHandler->rotationAxis()->setMaximum(45);
+
+#if QT_DEPRECATED_SINCE(6, 5)
+QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
+ QCOMPARE(pinchHandler->minimumRotation(), -90);
+ QCOMPARE(pinchHandler->maximumRotation(), 45);
+QT_WARNING_POP
+#endif
+
+ QCOMPARE(rotAxisMinSpy.size(),1);
+ QCOMPARE(rotAxisMaxSpy.size(),1);
+
+ pinchHandler->rotationAxis()->setMinimum(-90);
+ pinchHandler->rotationAxis()->setMaximum(45);
+
+ QCOMPARE(rotAxisMinSpy.size(),1);
+ QCOMPARE(rotAxisMaxSpy.size(),1);
}
-QMutableEventPoint makeTouchPoint(int id, QPoint p, QQuickView *v, QQuickItem *i)
+QEventPoint makeTouchPoint(int id, QPoint p, QQuickView *v, QQuickItem *i)
{
- QMutableEventPoint touchPoint(id);
- touchPoint.setPosition(i->mapFromScene(p));
- touchPoint.setGlobalPosition(v->mapToGlobal(p));
- touchPoint.setScenePosition(p);
+ QEventPoint touchPoint(id);
+ QMutableEventPoint::setPosition(touchPoint, i->mapFromScene(p));
+ QMutableEventPoint::setGlobalPosition(touchPoint, v->mapToGlobal(p));
+ QMutableEventPoint::setScenePosition(touchPoint, p);
return touchPoint;
}
-void tst_QQuickPinchHandler::scale()
+void tst_QQuickPinchHandler::scale_data()
{
- QQuickView *window = createView();
- QScopedPointer<QQuickView> scope(window);
- window->setSource(testFileUrl("pinchproperties.qml"));
- window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window));
- QVERIFY(window->rootObject() != nullptr);
- qApp->processEvents();
+ QTest::addColumn<QUrl>("qmlfile");
+ QTest::addColumn<bool>("hasTarget");
+ QTest::newRow("targetModifying") << testFileUrl("pinchproperties.qml") << true;
+ QTest::newRow("nullTarget") << testFileUrl("nullTarget.qml") << false;
+}
- QQuickPinchHandler *pinchHandler = window->rootObject()->findChild<QQuickPinchHandler*>("pinchHandler");
- QVERIFY(pinchHandler != nullptr);
+void tst_QQuickPinchHandler::scale()
+{
+ QFETCH(QUrl, qmlfile);
+ QFETCH(bool, hasTarget);
- QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, qmlfile));
+ QQuickItem *root = qobject_cast<QQuickItem*>(window.rootObject());
QVERIFY(root != nullptr);
-
- // target
- QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
+ auto *pinchHandler = static_cast<PinchHandler *>(root->findChild<QQuickPinchHandler*>());
+ QVERIFY(pinchHandler != nullptr);
+ QQuickItem *blackRect = (hasTarget ? pinchHandler->target() : pinchHandler->parentItem());
QVERIFY(blackRect != nullptr);
+ QSignalSpy grabChangedSpy(pinchHandler, SIGNAL(grabChanged(QPointingDevice::GrabTransition,QEventPoint)));
+ QSignalSpy scaleChangedSpy(pinchHandler, &QQuickPinchHandler::scaleChanged);
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
QPoint p0(80, 80);
QPoint p1(100, 100);
- {
- QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
- pinchSequence.press(0, p0, window).commit();
- QQuickTouchUtils::flush(window);
- // In order for the stationary point to remember its previous position,
- // we have to reuse the same pinchSequence object. Otherwise if we let it
- // be destroyed and then start a new sequence, point 0 will default to being
- // stationary at 0, 0, and pinchHandler will filter out that touchpoint because
- // it is outside its bounds.
- pinchSequence.stationary(0).press(1, p1, window).commit();
- QQuickTouchUtils::flush(window);
-
- QPoint pd(10, 10);
- // move one point until PinchHandler activates
- for (int pi = 0; pi < 10 && !pinchHandler->active(); ++pi) {
- p1 += pd;
- pinchSequence.stationary(0).move(1, p1, window).commit();
- QQuickTouchUtils::flush(window);
- }
- QCOMPARE(pinchHandler->active(), true);
- QLineF line(p0, p1);
- const qreal startLength = line.length();
-
- p1+=pd;
- pinchSequence.stationary(0).move(1, p1, window).commit();
- QQuickTouchUtils::flush(window);
- line.setP2(p1);
- qreal scale = line.length() / startLength;
- QVERIFY(qFloatDistance(root->property("scale").toReal(), scale) < 10);
- QVERIFY(qFloatDistance(blackRect->scale(), scale) < 10);
-
- p1+=pd;
- pinchSequence.stationary(0).move(1, p1, window).commit();
- QQuickTouchUtils::flush(window);
+ QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(&window, touchscreen.get());
+ pinchSequence.press(0, p0, &window).commit();
+ QQuickTouchUtils::flush(&window);
+ // In order for the stationary point to remember its previous position,
+ // we have to reuse the same pinchSequence object. Otherwise if we let it
+ // be destroyed and then start a new sequence, point 0 will default to being
+ // stationary at 0, 0, and pinchHandler will filter out that touchpoint because
+ // it is outside its bounds.
+ pinchSequence.stationary(0).press(1, p1, &window).commit();
+ QQuickTouchUtils::flush(&window);
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
+ QCOMPARE(grabChangedSpy.size(), 1); // passive grab
+
+ QPoint pd(10, 10);
+ // move one point until PinchHandler activates
+ for (int pi = 0; pi < 10 && !pinchHandler->active(); ++pi) {
+ p1 += pd;
+ pinchSequence.stationary(0).move(1, p1, &window).commit();
+ QQuickTouchUtils::flush(&window);
+ }
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
+ QCOMPARE(pinchHandler->active(), true);
+ // grabs occur when the handler becomes active; at that time, QQuickHandlerPoint.sceneGrabPosition should be correct
+ QVERIFY(pinchHandler->firstPoint().sceneGrabPosition() != QPointF());
+ QVERIFY(pinchHandler->lastPoint().sceneGrabPosition() != QPointF());
+ QCOMPARE(pinchHandler->firstPoint().sceneGrabPosition(), pinchHandler->firstPoint().scenePosition());
+ QCOMPARE(pinchHandler->lastPoint().sceneGrabPosition(), pinchHandler->lastPoint().scenePosition());
+ // first point got a passive grab; both points got exclusive grabs
+ QCOMPARE(grabChangedSpy.size(), 3);
+ QLineF line(p0, p1);
+ const qreal startLength = line.length();
+
+ // move the same point even further and observe the change in scale
+ for (int i = 0; i < 2; ++i) {
+ qreal lastScale = pinchHandler->activeScale();
+ p1 += pd;
+ pinchSequence.stationary(0).move(1, p1, &window).commit();
+ QQuickTouchUtils::flush(&window);
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
line.setP2(p1);
- scale = line.length() / startLength;
-
- QVERIFY(qFloatDistance(root->property("scale").toReal(), scale) < 10);
- QVERIFY(qFloatDistance(blackRect->scale(), scale) < 10);
-
- QPointF expectedCentroid = p0 + (p1 - p0)/2;
+ qreal expectedScale = line.length() / startLength;
+ 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);
+ 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);
+ QPointF expectedCentroid = p0 + (p1 - p0) / 2;
QCOMPARE(pinchHandler->centroid().scenePosition(), expectedCentroid);
}
- // scale beyond bound
- p1 += QPoint(20, 20);
- {
- QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
- pinchSequence.stationary(0).move(1, p1, window).commit();
- QQuickTouchUtils::flush(window);
- QCOMPARE(blackRect->scale(), qreal(4)); // qquickpinchhandler does not manipulate scale property
- pinchSequence.release(0, p0, window).release(1, p1, window).commit();
- QQuickTouchUtils::flush(window);
+ qreal lastScale = pinchHandler->persistentScale();
+ pinchSequence.release(0, p0, &window).release(1, p1, &window).commit();
+ QQuickTouchUtils::flush(&window);
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
+ // scale property is persistent after release
+ QCOMPARE(pinchHandler->persistentScale(), lastScale);
+ QCOMPARE(pinchHandler->scaleAxis()->persistentValue(), lastScale);
+ QCOMPARE(pinchHandler->scaleAxis()->activeValue(), 1);
+
+ // pinch a second time: scale picks up where we left off
+ p0 = QPoint(80, 80);
+ p1 = QPoint(100, 100);
+ pinchSequence.press(0, p0, &window).press(1, p1, &window).commit();
+ // move one point until PinchHandler activates
+ for (int pi = 0; pi < 10 && !pinchHandler->active(); ++pi) {
+ p1 += pd;
+ pinchSequence.stationary(0).move(1, p1, &window).commit();
+ QQuickTouchUtils::flush(&window);
}
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
+ QCOMPARE(pinchHandler->active(), true);
+ QCOMPARE(pinchHandler->persistentScale(), lastScale); // just activated, not scaling further yet
+ QCOMPARE(pinchHandler->scaleAxis()->persistentValue(), lastScale);
+ QCOMPARE(pinchHandler->scaleAxis()->activeValue(), 1);
+ for (int i = 0; i < 2; ++i) {
+ lastScale = pinchHandler->persistentScale();
+ p1 += pd;
+ pinchSequence.stationary(0).move(1, p1, &window).commit();
+ QQuickTouchUtils::flush(&window);
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
+ QCOMPARE_GT(pinchHandler->persistentScale(), lastScale);
+ 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);
+ 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);
+ }
+
+ // scale beyond maximumScale
+ lastScale = pinchHandler->activeScale();
+ p1 = QPoint(310, 310);
+ 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);
+ pinchSequence.release(0, p0, &window).release(1, p1, &window).commit();
+ QQuickTouchUtils::flush(&window);
QCOMPARE(pinchHandler->active(), false);
}
void tst_QQuickPinchHandler::scaleThreeFingers()
{
- QQuickView *window = createView();
+ QQuickView *window = QQuickViewTestUtils::createView();
QScopedPointer<QQuickView> scope(window);
window->setSource(testFileUrl("threeFingers.qml"));
window->show();
@@ -300,7 +385,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.get());
pinchSequence.press(0, p0, window).commit();
QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
@@ -322,9 +407,17 @@ void tst_QQuickPinchHandler::scaleThreeFingers()
QCOMPARE(pinchHandler->active(), true);
// scale we got was 1.1729088738267854364, but keep some slack
- QVERIFY(withinBounds(1.163, root->property("scale").toReal(), 1.183));
+ qCDebug(lcPointerTests) << "pinch scale" << pinchHandler->persistentScale() << "expected 1.173";
+ QVERIFY(withinBounds(1.163, pinchHandler->persistentScale(), 1.183));
// should not rotate
- QCOMPARE(root->property("rotation").toReal(), 0.);
+ QCOMPARE(root->rotation(), 0);
+ // rotation should be 0, but could be something tiny
+ qCDebug(lcPointerTests) << "pinch scale expected zero:" << pinchHandler->activeRotation()
+ << pinchHandler->rotationAxis()->activeValue()
+ << pinchHandler->rotationAxis()->persistentValue();
+ QCOMPARE_LE(qAbs(pinchHandler->activeRotation()), 0.001);
+ QCOMPARE(pinchHandler->rotationAxis()->activeValue(), pinchHandler->activeRotation());
+ QCOMPARE(pinchHandler->rotationAxis()->persistentValue(), 0);
for (int i = 0; i < 5;++i) {
p0 += QPoint(-4, -4);
@@ -334,10 +427,10 @@ void tst_QQuickPinchHandler::scaleThreeFingers()
QQuickTouchUtils::flush(window);
}
// scale we got was 1.4613, but keep some slack
- QVERIFY(withinBounds(1.361, root->property("scale").toReal(), 1.561));
+ QVERIFY(withinBounds(1.361, pinchHandler->persistentScale(), 1.561));
// since points were moved symetrically around the y axis, centroid should remain at x:150
- QCOMPARE(root->property("centroid").value<QQuickHandlerPoint>().scenePosition().x(), 150); // blackrect is at 50,50
+ QCOMPARE(pinchHandler->centroid().scenePosition().x(), 150); // blackrect is at 50,50
// scale beyond bound, we should reach the maximumScale
p0 += QPoint(-40, -40);
@@ -346,16 +439,243 @@ void tst_QQuickPinchHandler::scaleThreeFingers()
pinchSequence.move(0, p0,window).move(1, p1,window).move(2, p2,window).commit();
QQuickTouchUtils::flush(window);
- QCOMPARE(root->property("scale").toReal(), 2.);
+ QCOMPARE(pinchHandler->persistentScale(), 2);
+ QCOMPARE(pinchHandler->scaleAxis()->persistentValue(), 2);
+ QCOMPARE(pinchHandler->scaleAxis()->activeValue(), 2);
pinchSequence.release(0, p0, window).release(1, p1, window).release(2, p2, window).commit();
QQuickTouchUtils::flush(window);
}
QCOMPARE(pinchHandler->active(), false);
}
+void tst_QQuickPinchHandler::scaleNativeGesture_data()
+{
+ QTest::addColumn<QString>("qmlfile");
+ QTest::addColumn<qreal>("scale");
+
+ QTest::newRow("just pinch") << "pinchproperties.qml" << 1.1;
+ QTest::newRow("pinch & drag") << "pinchAndDrag.qml" << 1.1;
+ QTest::newRow("bigger than limit") << "pinchproperties.qml" << 5.0;
+ QTest::newRow("smaller than limit") << "pinchproperties.qml" << 0.25;
+}
+
+void tst_QQuickPinchHandler::scaleNativeGesture()
+{
+ QFETCH(QString, qmlfile);
+ QFETCH(qreal, scale);
+
+ QQuickView *window = QQuickViewTestUtils::createView();
+ QScopedPointer<QQuickView> scope(window);
+ window->setSource(testFileUrl(qmlfile));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(window->rootObject() != nullptr);
+ qApp->processEvents();
+
+ QQuickPinchHandler *pinchHandler = window->rootObject()->findChild<QQuickPinchHandler*>("pinchHandler");
+ QVERIFY(pinchHandler != nullptr);
+ QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
+ QVERIFY(root != nullptr);
+ QQuickItem *target = window->rootObject()->findChild<QQuickItem*>("blackrect");
+ QVERIFY(target != nullptr);
+
+ QPointF targetPos = target->position();
+ ulong ts = 1;
+
+ // first pinch: scale it
+ const qreal expectedScale = qBound(qreal(0.5), scale, qreal(4));
+ QPointF pinchPos(75, 75);
+ QPointF pinchLocalPos = target->mapFromScene(pinchPos);
+ // target position is adjusted in QQuickItemPrivate::adjustedPosForTransform()
+ // 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++, touchpad.get(),
+ Qt::BeginNativeGesture, pinchPos, pinchPos);
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
+ QWindowSystemInterface::handleGestureEventWithRealValue(window, ts++, touchpad.get(),
+ Qt::ZoomNativeGesture, scale - 1, pinchPos, pinchPos);
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
+ QTRY_COMPARE(target->scale(), expectedScale);
+ QCOMPARE(pinchHandler->active(), true);
+ qCDebug(lcPointerTests) << "centroid: local" << pinchHandler->centroid().position()
+ << "scene" << pinchHandler->centroid().scenePosition();
+ QCOMPARE(pinchHandler->centroid().position().toPoint(), pinchLocalPos.toPoint());
+ QCOMPARE(pinchHandler->centroid().scenePosition().toPoint(), pinchPos.toPoint());
+ QVERIFY(qAbs(target->position().x() - expectedPos.x()) < 0.001);
+ QVERIFY(qAbs(target->position().y() - expectedPos.y()) < 0.001);
+ QCOMPARE(pinchHandler->persistentScale(), expectedScale);
+ QCOMPARE(pinchHandler->activeScale(), scale);
+ QCOMPARE(pinchHandler->scaleAxis()->activeValue(), scale);
+ QCOMPARE(pinchHandler->activeTranslation(), QPointF());
+ QCOMPARE(pinchHandler->activeRotation(), 0);
+ QCOMPARE(pinchHandler->rotationAxis()->persistentValue(), 0);
+ QCOMPARE(pinchHandler->rotationAxis()->activeValue(), 0);
+ QWindowSystemInterface::handleGestureEvent(window, ts++, touchpad.get(),
+ Qt::EndNativeGesture, pinchPos, pinchPos);
+ QTRY_COMPARE(pinchHandler->active(), false);
+ QCOMPARE(target->scale(), expectedScale);
+ QCOMPARE(pinchHandler->persistentScale(), expectedScale);
+ QCOMPARE(pinchHandler->activeScale(), 1);
+ QCOMPARE(pinchHandler->scaleAxis()->activeValue(), 1);
+ QCOMPARE(pinchHandler->activeTranslation(), QPointF());
+ QCOMPARE(pinchHandler->activeRotation(), 0);
+ QCOMPARE(pinchHandler->rotationAxis()->persistentValue(), 0);
+ QCOMPARE(pinchHandler->rotationAxis()->activeValue(), 0);
+
+ // second pinch at a different position: scale it back to original size again
+ // but remove the limits first, so that we can scale arbitrarily
+ pinchHandler->scaleAxis()->setMaximum(qInf());
+ pinchHandler->scaleAxis()->setMinimum(-qInf());
+ const qreal reverseScale = (1 / expectedScale);
+ pinchPos = QPointF(110, 110);
+ pinchLocalPos = target->mapFromScene(pinchPos);
+ QWindowSystemInterface::handleGestureEvent(window, ts++, touchpad.get(),
+ Qt::BeginNativeGesture, pinchPos, pinchPos);
+ QWindowSystemInterface::handleGestureEventWithRealValue(window, ts++, touchpad.get(),
+ Qt::ZoomNativeGesture, reverseScale - 1, pinchPos, pinchPos);
+ QTRY_COMPARE(target->scale(), 1);
+ QCOMPARE(pinchHandler->active(), true);
+ qCDebug(lcPointerTests) << "centroid: local" << pinchHandler->centroid().position()
+ << "scene" << pinchHandler->centroid().scenePosition();
+ QCOMPARE(pinchHandler->centroid().position().toPoint(), pinchLocalPos.toPoint());
+ QCOMPARE(pinchHandler->centroid().scenePosition().toPoint(), pinchPos.toPoint());
+ QCOMPARE(pinchHandler->persistentScale(), 1);
+ QCOMPARE(pinchHandler->activeScale(), reverseScale);
+ QCOMPARE(pinchHandler->scaleAxis()->activeValue(), reverseScale);
+ QWindowSystemInterface::handleGestureEvent(window, ts++, touchpad.get(),
+ Qt::EndNativeGesture, pinchPos, pinchPos);
+ QTRY_COMPARE(pinchHandler->active(), false);
+ QCOMPARE(target->scale(), 1);
+ QCOMPARE(pinchHandler->persistentScale(), 1);
+ QCOMPARE(pinchHandler->activeScale(), 1);
+ QCOMPARE(pinchHandler->scaleAxis()->activeValue(), 1);
+}
+
+void tst_QQuickPinchHandler::cumulativeNativeGestures_data()
+{
+ QTest::addColumn<const QPointingDevice*>("device");
+ QTest::addColumn<Qt::NativeGestureType>("gesture");
+ QTest::addColumn<qreal>("value");
+ QTest::addColumn<QList<QPoint>>("expectedTargetTranslations");
+
+ const auto *touchpadDevice = touchpad.get();
+ const auto *mouse = QPointingDevice::primaryPointingDevice();
+
+ QTest::newRow("touchpad: rotate") << touchpadDevice << Qt::RotateNativeGesture << 5.0
+ << QList<QPoint>{{-2, 2}, {-5, 4}, {-7, 6}, {-10, 7}};
+ QTest::newRow("touchpad: scale") << touchpadDevice << Qt::ZoomNativeGesture << 0.1
+ << 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
+ << QList<QPoint>{{-2, 2}, {-5, 4}, {-7, 6}, {-10, 7}};
+ QTest::newRow("mouse: scale") << mouse << Qt::ZoomNativeGesture << 0.1
+ << QList<QPoint>{{3, 3}, {5, 5}, {8, 8}, {12, 12}};
+ } else {
+ qCWarning(lcPointerTests) << "skipping mouse tests: primary device is not a mouse" << mouse;
+ }
+}
+
+void tst_QQuickPinchHandler::cumulativeNativeGestures()
+{
+ QFETCH(const QPointingDevice*, device);
+ QFETCH(Qt::NativeGestureType, gesture);
+ QFETCH(qreal, value);
+ QFETCH(QList<QPoint>, expectedTargetTranslations);
+
+ QCOMPARE(expectedTargetTranslations.size(), 4);
+
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("pinchproperties.qml")));
+ QVERIFY(window.rootObject() != nullptr);
+ qApp->processEvents();
+
+ QQuickItem *root = qobject_cast<QQuickItem*>(window.rootObject());
+ QVERIFY(root != nullptr);
+ QQuickPinchHandler *pinchHandler = root->findChild<QQuickPinchHandler*>("pinchHandler");
+ QVERIFY(pinchHandler != nullptr);
+ QQuickItem *target = root->findChild<QQuickItem*>("blackrect");
+ QVERIFY(target != nullptr);
+ QCOMPARE(pinchHandler->target(), target);
+
+ ulong ts = 1;
+ qreal expectedScale = 1;
+ qreal expectedRotation = 0;
+ QPointF pinchPos(75, 75);
+ const QPointF initialTargetPos(target->position());
+ QWindowSystemInterface::handleGestureEvent(&window, ts++, device,
+ Qt::BeginNativeGesture, pinchPos, pinchPos);
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
+ for (int i = 1; i <= 4; ++i) {
+ QWindowSystemInterface::handleGestureEventWithRealValue(&window, ts++, device,
+ gesture, value, pinchPos, pinchPos);
+ qApp->processEvents();
+ switch (gesture) {
+ case Qt::ZoomNativeGesture:
+ expectedScale = qBound(qreal(0.5), qPow(1 + value, i), qreal(4));
+ break;
+ case Qt::RotateNativeGesture:
+ expectedRotation = qBound(qreal(0), value * i, qreal(90));
+ break;
+ default:
+ break; // PinchHandler doesn't react to the others
+ }
+
+ qCDebug(lcPointerTests) << i << gesture << "with value" << value
+ << ": scale" << target->scale() << "expected" << expectedScale
+ << ": rotation" << target->rotation() << "expected" << expectedRotation;
+ if (lcPointerTests().isDebugEnabled()) QTest::qWait(500);
+ QCOMPARE(target->scale(), expectedScale);
+ QCOMPARE(target->rotation(), expectedRotation);
+ QCOMPARE(pinchHandler->persistentScale(), expectedScale);
+ QCOMPARE(pinchHandler->activeScale(), expectedScale);
+ QCOMPARE(pinchHandler->scaleAxis()->persistentValue(), expectedScale);
+ QCOMPARE(pinchHandler->scaleAxis()->activeValue(), expectedScale);
+ QCOMPARE(pinchHandler->persistentRotation(), expectedRotation);
+ QCOMPARE(pinchHandler->activeRotation(), expectedRotation);
+ QCOMPARE(pinchHandler->rotationAxis()->persistentValue(), expectedRotation);
+ QCOMPARE(pinchHandler->rotationAxis()->activeValue(), expectedRotation);
+ // The target gets transformed around the gesture position, for which
+ // QQuickItemPrivate::adjustedPosForTransform() computes its new position to compensate.
+ QPointF delta = target->position() - initialTargetPos;
+ 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));
+ // 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());
+ // The target only moves to compensate for scale and rotation changes, and that's
+ // not reflected in PinchHandler.persistentTranslation.
+ QCOMPARE(pinchHandler->persistentTranslation(), QPointF());
+ }
+ QCOMPARE(pinchHandler->active(), true);
+ qCDebug(lcPointerTests) << "centroid: local" << pinchHandler->centroid().position()
+ << "scene" << pinchHandler->centroid().scenePosition();
+ QCOMPARE(pinchHandler->persistentScale(), expectedScale);
+ QCOMPARE(pinchHandler->activeScale(), expectedScale);
+ QCOMPARE(pinchHandler->scaleAxis()->activeValue(), expectedScale);
+ QWindowSystemInterface::handleGestureEvent(&window, ts++, device,
+ Qt::EndNativeGesture, pinchPos, pinchPos);
+ QTRY_COMPARE(pinchHandler->active(), false);
+ QCOMPARE(target->scale(), expectedScale);
+ QCOMPARE(target->rotation(), expectedRotation);
+ QCOMPARE(pinchHandler->persistentScale(), expectedScale);
+ QCOMPARE(pinchHandler->activeScale(), 1);
+ QCOMPARE(pinchHandler->scaleAxis()->persistentValue(), expectedScale);
+ QCOMPARE(pinchHandler->scaleAxis()->activeValue(), 1);
+ QCOMPARE(pinchHandler->persistentRotation(), expectedRotation);
+ QCOMPARE(pinchHandler->activeRotation(), 0);
+ QCOMPARE(pinchHandler->rotationAxis()->persistentValue(), expectedRotation);
+ QCOMPARE(pinchHandler->rotationAxis()->activeValue(), 0);
+ QCOMPARE(pinchHandler->activeTranslation(), QPointF());
+ QCOMPARE(pinchHandler->persistentTranslation(), QPointF());
+}
+
void tst_QQuickPinchHandler::pan()
{
- QQuickView *window = createView();
+ QQuickView *window = QQuickViewTestUtils::createView();
QScopedPointer<QQuickView> scope(window);
window->setSource(testFileUrl("pinchproperties.qml"));
window->show();
@@ -365,6 +685,7 @@ void tst_QQuickPinchHandler::pan()
QQuickPinchHandler *pinchHandler = window->rootObject()->findChild<QQuickPinchHandler*>("pinchHandler");
QVERIFY(pinchHandler != nullptr);
+ QSignalSpy translationChangedSpy(pinchHandler, &QQuickPinchHandler::translationChanged);
QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
QVERIFY(root != nullptr);
@@ -377,7 +698,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.get());
pinchSequence.press(0, p0, window).commit();
QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
@@ -385,7 +706,7 @@ void tst_QQuickPinchHandler::pan()
pinchSequence.stationary(0).press(1, p1, window).commit();
QQuickTouchUtils::flush(window);
QVERIFY(!root->property("pinchActive").toBool());
- QCOMPARE(root->property("scale").toReal(), -1.0);
+ QCOMPARE(root->property("pinchScale").toReal(), -1.0);
p0 += QPoint(dragThreshold, 0);
p1 += QPoint(dragThreshold, 0);
@@ -393,7 +714,7 @@ void tst_QQuickPinchHandler::pan()
QQuickTouchUtils::flush(window);
// movement < dragThreshold: pinchHandler not yet active
QVERIFY(!root->property("pinchActive").toBool());
- QCOMPARE(root->property("scale").toReal(), -1.0);
+ QCOMPARE(root->property("pinchScale").toReal(), -1.0);
// just above the dragThreshold: pinchHandler starts
p0 += QPoint(1, 0);
@@ -401,7 +722,7 @@ void tst_QQuickPinchHandler::pan()
pinchSequence.move(0, p0, window).move(1, p1, window).commit();
QQuickTouchUtils::flush(window);
QCOMPARE(pinchHandler->active(), true);
- QCOMPARE(root->property("scale").toReal(), 1.0);
+ QCOMPARE(root->property("pinchScale").toReal(), 1.0);
// Calculation of the center point is tricky at first:
// center point of the two touch points in item coordinates:
@@ -413,6 +734,8 @@ void tst_QQuickPinchHandler::pan()
// blackrect starts at 50,50
QCOMPARE(blackRect->x(), 50.0);
QCOMPARE(blackRect->y(), 50.0);
+ QCOMPARE(translationChangedSpy.size(), 1);
+ QCOMPARE(translationChangedSpy.first().first().value<QVector2D>(), QVector2D(0, 0));
p0 += QPoint(10, 0);
p1 += QPoint(10, 0);
@@ -421,6 +744,8 @@ void tst_QQuickPinchHandler::pan()
QCOMPARE(pinchHandler->centroid().scenePosition(), QPointF(90 + dragThreshold + 11, 90));
QCOMPARE(blackRect->x(), 60.0);
QCOMPARE(blackRect->y(), 50.0);
+ QCOMPARE(translationChangedSpy.size(), 2);
+ QCOMPARE(translationChangedSpy.last().first().value<QVector2D>(), QVector2D(10, 0));
p0 += QPoint(0, 10);
p1 += QPoint(0, 10);
@@ -429,6 +754,8 @@ void tst_QQuickPinchHandler::pan()
QCOMPARE(pinchHandler->centroid().scenePosition(), QPointF(90 + dragThreshold + 11, 90 + 10));
QCOMPARE(blackRect->x(), 60.0);
QCOMPARE(blackRect->y(), 60.0);
+ QCOMPARE(translationChangedSpy.size(), 3);
+ QCOMPARE(translationChangedSpy.last().first().value<QVector2D>(), QVector2D(0, 10));
p0 += QPoint(10, 10);
p1 += QPoint(10, 10);
@@ -438,18 +765,22 @@ void tst_QQuickPinchHandler::pan()
QCOMPARE(pinchHandler->centroid().scenePosition(), QPointF(90 + dragThreshold + 21, 90 + 20));
QCOMPARE(blackRect->x(), 70.0);
QCOMPARE(blackRect->y(), 70.0);
+ QCOMPARE(translationChangedSpy.size(), 4);
+ QCOMPARE(translationChangedSpy.last().first().value<QVector2D>(), QVector2D(10, 10));
}
// 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.get()).move(0, p0, window).move(1, p1, window);
QQuickTouchUtils::flush(window);
QCOMPARE(blackRect->x(), 140.0);
QCOMPARE(blackRect->y(), 170.0);
+ QCOMPARE(translationChangedSpy.size(), 5);
+ QCOMPARE(translationChangedSpy.last().first().value<QVector2D>(), QVector2D(100, 100));
- QTest::touchEvent(window, device).release(0, p0, window).release(1, p1, window);
+ QTest::touchEvent(window, touchscreen.get()).release(0, p0, window).release(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(!root->property("pinchActive").toBool());
}
@@ -467,7 +798,7 @@ void tst_QQuickPinchHandler::dragAxesEnabled_data()
void tst_QQuickPinchHandler::dragAxesEnabled()
{
- QQuickView *window = createView();
+ QQuickView *window = QQuickViewTestUtils::createView();
QScopedPointer<QQuickView> scope(window);
window->setSource(testFileUrl("pinchproperties.qml"));
window->show();
@@ -489,7 +820,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.get());
pinchSequence.press(0, p0, window).press(1, p1, window).commit();
QQuickTouchUtils::flush(window);
@@ -526,7 +857,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.get()).release(0, p0, window).release(1, p1, window);
QQuickTouchUtils::flush(window);
}
@@ -534,7 +865,7 @@ void tst_QQuickPinchHandler::dragAxesEnabled()
void tst_QQuickPinchHandler::retouch()
{
const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
- QQuickView *window = createView();
+ QQuickView *window = QQuickViewTestUtils::createView();
QScopedPointer<QQuickView> scope(window);
window->setSource(testFileUrl("pinchproperties.qml"));
window->show();
@@ -555,7 +886,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.get());
pinchSequence.press(0, p0, window).commit();
QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
@@ -568,7 +899,7 @@ void tst_QQuickPinchHandler::retouch()
pinchSequence.move(0, p0,window).move(1, p1,window).commit();
QQuickTouchUtils::flush(window);
- QCOMPARE(root->property("scale").toReal(), 1.0);
+ QCOMPARE(root->property("pinchScale").toReal(), 1.0);
QCOMPARE(pinchHandler->active(), true);
p0 -= delta;
@@ -579,8 +910,8 @@ void tst_QQuickPinchHandler::retouch()
QCOMPARE(pinchHandler->active(), true);
// accept some slack
- QVERIFY(withinBounds(1.4, root->property("scale").toReal(), 1.6));
- QCOMPARE(pinchHandler->centroid().position(), QPointF(40, 40)); // blackrect is at 50,50
+ QVERIFY(withinBounds(1.4, root->property("pinchScale").toReal(), 1.6));
+ QCOMPARE(pinchHandler->centroid().position().toPoint(), QPoint(40, 40)); // blackrect is at 50,50
QVERIFY(withinBounds(1.4, blackRect->scale(), 1.6));
QCOMPARE(root->property("activeCount").toInt(), 1);
@@ -617,7 +948,7 @@ void tst_QQuickPinchHandler::retouch()
void tst_QQuickPinchHandler::cancel()
{
const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
- QQuickView *window = createView();
+ QQuickView *window = QQuickViewTestUtils::createView();
QScopedPointer<QQuickView> scope(window);
window->setSource(testFileUrl("pinchproperties.qml"));
window->show();
@@ -638,7 +969,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.get());
pinchSequence.press(0, p0, window).commit();
QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
@@ -654,7 +985,7 @@ void tst_QQuickPinchHandler::cancel()
pinchSequence.move(0, p0,window).move(1, p1,window).commit();
QQuickTouchUtils::flush(window);
- QCOMPARE(root->property("scale").toReal(), 1.0);
+ QCOMPARE(root->property("pinchScale").toReal(), 1.0);
QCOMPARE(pinchHandler->active(), true);
p0 -= delta;
@@ -662,18 +993,18 @@ void tst_QQuickPinchHandler::cancel()
pinchSequence.move(0, p0,window).move(1, p1,window).commit();
QQuickTouchUtils::flush(window);
- QVERIFY(withinBounds(1.4, root->property("scale").toReal(), 1.6));
- QCOMPARE(pinchHandler->centroid().position(), QPointF(40, 40)); // blackrect is at 50,50
+ QVERIFY(withinBounds(1.4, root->property("pinchScale").toReal(), 1.6));
+ QCOMPARE(pinchHandler->centroid().position().toPoint(), QPoint(40, 40)); // blackrect is at 50,50
QVERIFY(withinBounds(1.4, blackRect->scale(), 1.6));
QSKIP("cancel is not supported atm");
- QTouchEvent cancelEvent(QEvent::TouchCancel, device);
+ QTouchEvent cancelEvent(QEvent::TouchCancel, touchscreen.get());
QCoreApplication::sendEvent(window, &cancelEvent);
QQuickTouchUtils::flush(window);
- QCOMPARE(root->property("scale").toReal(), 1.0);
- QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50
+ QCOMPARE(root->property("pinchScale").toReal(), 1.0);
+ QCOMPARE(root->property("center").toPoint(), QPoint(40, 40)); // blackrect is at 50,50
QCOMPARE(blackRect->scale(), 1.0);
QVERIFY(!root->property("pinchActive").toBool());
}
@@ -710,7 +1041,7 @@ void tst_QQuickPinchHandler::transformedpinchHandler()
QFETCH(QPoint, p1);
QFETCH(bool, shouldPinch);
- QQuickView *view = createView();
+ QQuickView *view = QQuickViewTestUtils::createView();
QScopedPointer<QQuickView> scope(view);
view->setSource(testFileUrl("transformedPinchHandler.qml"));
view->show();
@@ -724,7 +1055,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.get());
// start pinchHandler
pinchSequence.press(0, p0, view).commit();
QQuickTouchUtils::flush(view);
@@ -749,14 +1080,6 @@ void tst_QQuickPinchHandler::transformedpinchHandler()
}
}
-QQuickView *tst_QQuickPinchHandler::createView()
-{
- QQuickView *window = new QQuickView(0);
- window->setGeometry(0,0,240,320);
-
- return window;
-}
-
QTEST_MAIN(tst_QQuickPinchHandler)
#include "tst_qquickpinchhandler.moc"
diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/CMakeLists.txt b/tests/auto/quick/pointerhandlers/qquickpointerhandler/CMakeLists.txt
index 9dc541a845..e15b802814 100644
--- a/tests/auto/quick/pointerhandlers/qquickpointerhandler/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/CMakeLists.txt
@@ -1,9 +1,18 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# Generated from qquickpointerhandler.pro.
#####################################################################
## tst_qquickpointerhandler Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickpointerhandler 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_qquickpointerhandler
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_qquickpointerhandler.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_qquickpointerhandler
qt_internal_extend_target(tst_qquickpointerhandler CONDITION ANDROID OR IOS
DEFINES
- QT_QMLTEST_DATADIR=\\\":/data\\\"
+ QT_QMLTEST_DATADIR=":/data"
)
qt_internal_extend_target(tst_qquickpointerhandler 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/pointerhandlers/qquickpointerhandler/data/clip.qml b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/clip.qml
new file mode 100644
index 0000000000..7bc3907c8c
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/clip.qml
@@ -0,0 +1,36 @@
+import QtQuick
+import Qt.test 1.0
+
+Item {
+ width: 200
+ height: 200
+
+ Rectangle {
+ id: circle
+ y: 0
+ width: 100
+ height: width
+ radius: width/2
+ color: "#3e1"
+ clip: true
+
+ // Rectangle contains() is not affected by its 'radius' property
+ containmentMask: QtObject {
+ property alias radius: circle.radius
+ function contains(point: point) : bool {
+ return (Math.pow(point.x - radius, 2) + Math.pow(point.y - radius, 2)) < Math.pow(radius, 2)
+ }
+ }
+ EventHandler {
+ objectName: "circle eventHandler"
+ }
+ Rectangle {
+ width: circle.width/2
+ height: width
+ color: "red"
+ EventHandler {
+ objectName: "eventHandler"
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/grabberSceneChange.qml b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/grabberSceneChange.qml
new file mode 100644
index 0000000000..7bc6028bc2
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/grabberSceneChange.qml
@@ -0,0 +1,78 @@
+import QtQuick
+
+Window {
+ id: root
+ visible: true
+ objectName: "root"
+ width: 320
+ height: 480
+
+ property bool useTimer : false
+ property int grabChangedCounter : 0
+
+ Item {
+ id: back
+ anchors.fill: parent
+
+ Rectangle {
+ id: background
+ anchors.fill: parent
+ color: "blue"
+ }
+
+ Rectangle {
+ id: container
+ objectName: "container"
+ anchors.fill: parent
+ anchors.margins: 50
+ z: 2
+
+ Rectangle {
+ id: likeButton
+ color: "gray"
+ anchors.centerIn: parent
+ width: 200
+ height: 200
+
+ DragHandler {
+ id: handler
+ objectName: "dragHandler"
+ grabPermissions: PointerHandler.CanTakeOverFromItems
+ onGrabChanged: {
+ ++grabChangedCounter
+ }
+ }
+ }
+ }
+
+ Timer {
+ id: reparentTimer
+ running: false
+ interval: 100
+ repeat: false
+ onTriggered: {
+ container.parent = null
+ }
+ }
+
+ Rectangle {
+ id: likeButton2
+ color: "yellow"
+ anchors.centerIn: parent
+ width: 100
+ height: 100
+ z: 3
+
+ MultiPointTouchArea {
+ id: press
+ anchors.fill: parent
+ onPressed: {
+ if (useTimer)
+ reparentTimer.running = true
+ else
+ container.parent = null
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/itemOnly.qml b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/itemOnly.qml
new file mode 100644
index 0000000000..70b4655160
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/itemOnly.qml
@@ -0,0 +1,24 @@
+import QtQuick 2.8
+import Qt.test 1.0
+
+Item {
+ id: root
+ objectName: "root Item"
+ width: 320
+ height: 480
+
+ Rectangle {
+ objectName: "eventItem's bounds"
+ anchors.fill: eventItem
+ color: "lightsteelblue"
+ }
+
+ EventItem {
+ id: eventItem
+ objectName: "eventItem1"
+ x: 5
+ y: 5
+ height: 30
+ width: 30
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/reparenting.qml b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/reparenting.qml
new file mode 100644
index 0000000000..7553bc63cc
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/reparenting.qml
@@ -0,0 +1,40 @@
+import QtQuick
+import Qt.test
+
+Item {
+ id: root
+ objectName: "root Item"
+ width: 320
+ height: 480
+
+ Rectangle {
+ id: top
+ objectName: "top"
+ width: parent.width - 12
+ height: parent.height / 2 - 9
+ x: 6; y: 6
+ color: "teal"
+ border.width: 3
+ border.color: handler.parent == top ? "brown" : "transparent"
+ EventHandler {
+ id: handler
+ objectName: "eventHandler"
+ }
+ }
+
+ Rectangle {
+ id: bottom
+ objectName: "bottom"
+ width: parent.width - 12
+ height: parent.height / 2 - 9
+ x: 6; y: parent.height / 2 + 3
+ color: "darkolivegreen"
+ border.width: 3
+ border.color: handler.parent == bottom ? "brown" : "transparent"
+ }
+
+ Timer {
+ interval: 1000; running: true; repeat: true
+ onTriggered: handler.parent = (handler.parent == top ? bottom : top)
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp
index 6b0f574178..1120cb54c2 100644
--- a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module 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) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -33,10 +8,13 @@
#include <QtGui/private/qpointingdevice_p.h>
#include <QtQuick/private/qquickpointerhandler_p.h>
#include <QtQuick/qquickitem.h>
+#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/qquickview.h>
+#include <QtQml/private/qqmlglobal_p.h> // qmlobject_cast
-#include "../../../shared/util.h"
-#include "../../shared/viewtestutil.h"
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtQuickTestUtils/private/viewtestutils_p.h>
+#include <QQmlComponent>
Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
@@ -103,45 +81,45 @@ public:
return (accept && (state != QEventPoint::State::Released)) ? (int)QPointingDevice::GrabExclusive : (int)NoGrab;
}
- void touchEvent(QTouchEvent *event)
+ void touchEvent(QTouchEvent *event) override
{
qCDebug(lcPointerTests) << event << "will accept?" << acceptTouch;
for (auto &tp : event->points())
eventList.append(Event(Event::TouchDestination, event->type(), tp.state(), grabTransition(acceptTouch, tp.state()), tp.position(), tp.scenePosition()));
event->setAccepted(acceptTouch);
}
- void mousePressEvent(QMouseEvent *event)
+ void mousePressEvent(QMouseEvent *event) override
{
qCDebug(lcPointerTests) << event << "will accept?" << acceptMouse;
eventList.append(Event(Event::MouseDestination, event->type(), QEventPoint::State::Pressed, grabTransition(acceptMouse, QEventPoint::State::Pressed), event->position().toPoint(), event->scenePosition()));
event->setAccepted(acceptMouse);
}
- void mouseMoveEvent(QMouseEvent *event)
+ void mouseMoveEvent(QMouseEvent *event) override
{
qCDebug(lcPointerTests) << event << "will accept?" << acceptMouse;
eventList.append(Event(Event::MouseDestination, event->type(), QEventPoint::State::Updated, grabTransition(acceptMouse, QEventPoint::State::Updated), event->position().toPoint(), event->scenePosition()));
event->setAccepted(acceptMouse);
}
- void mouseReleaseEvent(QMouseEvent *event)
+ void mouseReleaseEvent(QMouseEvent *event) override
{
qCDebug(lcPointerTests) << event << "will accept?" << acceptMouse;
eventList.append(Event(Event::MouseDestination, event->type(), QEventPoint::State::Released, grabTransition(acceptMouse, QEventPoint::State::Released), event->position().toPoint(), event->scenePosition()));
event->setAccepted(acceptMouse);
}
- void mouseDoubleClickEvent(QMouseEvent *event)
+ void mouseDoubleClickEvent(QMouseEvent *event) override
{
qCDebug(lcPointerTests) << event << "will accept?" << acceptMouse;
eventList.append(Event(Event::MouseDestination, event->type(), QEventPoint::State::Pressed, grabTransition(acceptMouse, QEventPoint::State::Pressed), event->position().toPoint(), event->scenePosition()));
event->setAccepted(acceptMouse);
}
- void mouseUngrabEvent()
+ void mouseUngrabEvent() override
{
qCDebug(lcPointerTests);
eventList.append(Event(Event::MouseDestination, QEvent::UngrabMouse, QEventPoint::State::Released, QPointingDevice::UngrabExclusive, QPoint(0,0), QPoint(0,0)));
}
- bool event(QEvent *event)
+ bool event(QEvent *event) override
{
qCDebug(lcPointerTests) << event;
return QQuickItem::event(event);
@@ -154,7 +132,7 @@ public:
bool acceptTouch;
bool filterTouch; // when used as event filter
- bool eventFilter(QObject *o, QEvent *event)
+ bool eventFilter(QObject *o, QEvent *event) override
{
qCDebug(lcPointerTests) << event << o;
if (event->type() == QEvent::TouchBegin ||
@@ -184,7 +162,11 @@ public:
class EventHandler : public QQuickPointerHandler
{
+ Q_OBJECT
public:
+ EventHandler(QQuickItem *parent = nullptr) :
+ QQuickPointerHandler(parent) {}
+
void handlePointerEventImpl(QPointerEvent *event) override
{
QQuickPointerHandler::handlePointerEventImpl(event);
@@ -233,7 +215,8 @@ class tst_PointerHandlers : public QQmlDataTest
Q_OBJECT
public:
tst_PointerHandlers()
- : touchDevice(QTest::createTouchDevice())
+ : QQmlDataTest(QT_QMLTEST_DATADIR)
+ , touchDevice(QTest::createTouchDevice())
{}
private slots:
@@ -247,9 +230,14 @@ private slots:
void dynamicCreation();
void handlerInWindow();
void dynamicCreationInWindow();
+ void cppConstruction();
+ void reparenting();
+ void grabberSceneChange_data();
+ void grabberSceneChange();
+ void clip();
protected:
- bool eventFilter(QObject *, QEvent *event)
+ bool eventFilter(QObject *, QEvent *event) override
{
QEventPoint::State tpState;
switch (event->type()) {
@@ -284,8 +272,8 @@ void tst_PointerHandlers::createView(QScopedPointer<QQuickView> &window, const c
// window->setGeometry(0,0,240,320);
window->setSource(testFileUrl(fileName));
QTRY_COMPARE(window->status(), QQuickView::Ready);
- QQuickViewTestUtil::centerOnScreen(window.data());
- QQuickViewTestUtil::moveMouseAway(window.data());
+ QQuickViewTestUtils::centerOnScreen(window.data());
+ QQuickViewTestUtils::moveMouseAway(window.data());
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
@@ -335,11 +323,11 @@ void tst_PointerHandlers::touchEventDelivery()
QTest::touchEvent(window, touchDevice).move(0, p1, window);
QQuickTouchUtils::flush(window);
qCDebug(lcPointerTests) << "events after touch move" << eventItem1->eventList;
- QCOMPARE(eventItem1->eventList.size(), 2); // no grabs -> no updates
+ QCOMPARE(eventItem1->eventList.size(), 3); // no grabs -> only the handler gets the update
QTest::touchEvent(window, touchDevice).release(0, p1, window);
QQuickTouchUtils::flush(window);
qCDebug(lcPointerTests) << "events after touch release" << eventItem1->eventList;
- QCOMPARE(eventItem1->eventList.size(), 3);
+ QCOMPARE(eventItem1->eventList.size(), 4);
QCOMPARE_EVENT(eventItem1->eventList.size() - 1, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Released, NoGrab);
eventItem1->eventList.clear();
@@ -390,12 +378,12 @@ void tst_PointerHandlers::touchEventDelivery()
QTest::touchEvent(window, touchDevice).move(0, p1, window);
QQuickTouchUtils::flush(window);
qCDebug(lcPointerTests) << "events after touch move" << eventItem1->eventList;
- QCOMPARE(eventItem1->eventList.size(), 2);
+ QCOMPARE(eventItem1->eventList.size(), 3);
QTest::touchEvent(window, touchDevice).release(0, p1, window);
QQuickTouchUtils::flush(window);
qCDebug(lcPointerTests) << "events after touch release" << eventItem1->eventList;
- QCOMPARE(eventItem1->eventList.size(), 3);
- QCOMPARE_EVENT(2, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Released, NoGrab);
+ QCOMPARE(eventItem1->eventList.size(), 4);
+ QCOMPARE_EVENT(3, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Released, NoGrab);
eventItem1->eventList.clear();
// wait to avoid getting a double click event
@@ -417,11 +405,11 @@ void tst_PointerHandlers::touchEventDelivery()
QTest::touchEvent(window, touchDevice).move(0, p1, window);
QQuickTouchUtils::flush(window);
qCDebug(lcPointerTests) << "events after touch move" << eventItem1->eventList;
- QCOMPARE(eventItem1->eventList.size(), 2);
+ QCOMPARE(eventItem1->eventList.size(), 3);
QTest::touchEvent(window, touchDevice).release(0, p1, window);
QQuickTouchUtils::flush(window);
qCDebug(lcPointerTests) << "events after touch release" << eventItem1->eventList;
- QCOMPARE(eventItem1->eventList.size(), 3);
+ QCOMPARE(eventItem1->eventList.size(), 4);
eventItem1->eventList.clear();
// wait to avoid getting a double click event
@@ -485,18 +473,24 @@ void tst_PointerHandlers::mouseEventDelivery()
EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
QVERIFY(eventItem1);
+ EventHandler *handler = window->rootObject()->findChild<EventHandler*>("eventHandler");
+ QVERIFY(handler);
+ QCOMPARE(handler->parentItem(), eventItem1);
+ QCOMPARE(handler->target(), eventItem1);
+ QVERIFY(QQuickItemPrivate::get(eventItem1)->extra->resourcesList.contains(handler));
+
// Do not accept anything
QPoint p1 = QPoint(20, 20);
QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
qCDebug(lcPointerTests) << "events after mouse press" << eventItem1->eventList;
- QCOMPARE(eventItem1->eventList.size(), 2);
+ QCOMPARE(eventItem1->eventList.size(), 3); // handler: hover; handler: press; item: press
p1 += QPoint(10, 0);
QTest::mouseMove(window, p1);
qCDebug(lcPointerTests) << "events after mouse move" << eventItem1->eventList;
- QCOMPARE(eventItem1->eventList.size(), 2);
+ QCOMPARE(eventItem1->eventList.size(), 4); // handler: hover
QTest::mouseRelease(window, Qt::LeftButton);
qCDebug(lcPointerTests) << "events after mouse release" << eventItem1->eventList;
- QCOMPARE(eventItem1->eventList.size(), 2);
+ QCOMPARE(eventItem1->eventList.size(), 4);
eventItem1->eventList.clear();
// wait to avoid getting a double click event
@@ -509,9 +503,9 @@ void tst_PointerHandlers::mouseEventDelivery()
p1 = QPoint(20, 20);
QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
qCDebug(lcPointerTests) << "events after mouse press" << eventItem1->eventList;
- QCOMPARE(eventItem1->eventList.size(), 2);
- QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Pressed, NoGrab);
- QCOMPARE_EVENT(1, Event::MouseDestination, QEvent::MouseButtonPress, QEventPoint::State::Pressed, QPointingDevice::GrabExclusive);
+ QCOMPARE(eventItem1->eventList.size(), 3);
+ QCOMPARE_EVENT(1, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Pressed, NoGrab);
+ QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseButtonPress, QEventPoint::State::Pressed, QPointingDevice::GrabExclusive);
QCOMPARE(window->mouseGrabberItem(), eventItem1);
QPointF localPos = eventItem1->mapFromScene(p1);
@@ -524,11 +518,11 @@ void tst_PointerHandlers::mouseEventDelivery()
p1 += QPoint(10, 0);
QTest::mouseMove(window, p1);
qCDebug(lcPointerTests) << "events after mouse move" << eventItem1->eventList;
- QCOMPARE(eventItem1->eventList.size(), 4);
- QCOMPARE_EVENT(3, Event::MouseDestination, QEvent::MouseMove, QEventPoint::State::Updated, QPointingDevice::GrabExclusive);
+ QCOMPARE(eventItem1->eventList.size(), 5);
+ QCOMPARE_EVENT(4, Event::MouseDestination, QEvent::MouseMove, QEventPoint::State::Updated, QPointingDevice::GrabExclusive);
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
qCDebug(lcPointerTests) << "events after mouse release" << eventItem1->eventList;
- QCOMPARE(eventItem1->eventList.size(), 7);
+ QCOMPARE(eventItem1->eventList.size(), 8);
QCOMPARE_EVENT(eventItem1->eventList.size() - 2, Event::MouseDestination, QEvent::MouseButtonRelease, QEventPoint::State::Released, NoGrab);
QCOMPARE_EVENT(eventItem1->eventList.size() - 1, Event::MouseDestination, QEvent::UngrabMouse, QEventPoint::State::Released, QPointingDevice::UngrabExclusive);
eventItem1->eventList.clear();
@@ -631,12 +625,14 @@ void tst_PointerHandlers::dynamicCreation()
QCOMPARE(handler->parentItem(), eventItem1);
QCOMPARE(handler->target(), eventItem1);
+ QVERIFY(QQuickItemPrivate::get(eventItem1)->extra->resourcesList.contains(handler));
QPoint p1(20, 20);
QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
- QTRY_COMPARE(eventItem1->eventList.size(), 2);
- QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Pressed, NoGrab);
- QCOMPARE_EVENT(1, Event::MouseDestination, QEvent::MouseButtonPress, QEventPoint::State::Pressed, NoGrab);
+ QTRY_COMPARE(eventItem1->eventList.size(), 3);
+ QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Updated, NoGrab);
+ QCOMPARE_EVENT(1, Event::HandlerDestination, QEvent::Pointer, QEventPoint::State::Pressed, NoGrab);
+ QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseButtonPress, QEventPoint::State::Pressed, NoGrab);
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
}
@@ -688,6 +684,181 @@ void tst_PointerHandlers::dynamicCreationInWindow()
QTRY_COMPARE(handler->releaseEventCount, 1);
}
+void tst_PointerHandlers::cppConstruction()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "itemOnly.qml");
+ QQuickView * window = windowPtr.data();
+
+ EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
+ QVERIFY(eventItem1);
+ QQuickItemPrivate *eventItemPriv = QQuickItemPrivate::get(eventItem1);
+ // tell the handler to grab on press
+ eventItem1->grabPointer = true;
+
+ EventHandler handler(eventItem1);
+ QCOMPARE(handler.parentItem(), eventItem1);
+ QCOMPARE(handler.target(), eventItem1);
+ QCOMPARE(eventItemPriv->extra->pointerHandlers.first(), &handler);
+ QVERIFY(eventItemPriv->extra->resourcesList.contains(&handler));
+
+ // the handler and then eventItem1 sees each event
+ QPoint p1 = QPoint(20, 20);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QCOMPARE(handler.pressEventCount, 1);
+ qCDebug(lcPointerTests) << "events after mouse press" << eventItem1->eventList;
+ QCOMPARE(eventItem1->eventList.size(), 3);
+ QTest::mouseRelease(window, Qt::LeftButton);
+ QCOMPARE(handler.releaseEventCount, 1);
+ qCDebug(lcPointerTests) << "events after mouse release" << eventItem1->eventList;
+ QCOMPARE(eventItem1->eventList.size(), 7);
+
+ // wait to avoid getting a double click event
+ QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
+}
+
+void tst_PointerHandlers::reparenting()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "reparenting.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *topItem = window->rootObject()->findChild<QQuickItem*>("top");
+ QVERIFY(topItem);
+ QQuickItem *bottomItem = window->rootObject()->findChild<QQuickItem*>("bottom");
+ QVERIFY(bottomItem);
+ EventHandler *handler = window->rootObject()->findChild<EventHandler*>("eventHandler");
+ QVERIFY(handler);
+ topItem->setAcceptedMouseButtons(Qt::RightButton);
+
+ for (int i = 1; i < 5; ++i) {
+ QQuickItem *expectedParentItem = (i % 2 ? topItem : bottomItem);
+ QQuickItem *unexpectedParentItem = (i % 2 ? bottomItem : topItem);
+ qCDebug(lcPointerTests) << "initial parent" << handler->parentItem() << "waiting for" << expectedParentItem;
+ QTRY_COMPARE(handler->parentItem(), expectedParentItem);
+ QCOMPARE(handler->target(), expectedParentItem);
+ QVERIFY(QQuickItemPrivate::get(expectedParentItem)->extra.isAllocated());
+ QVERIFY(QQuickItemPrivate::get(expectedParentItem)->extra->resourcesList.contains(handler));
+ if (QQuickItemPrivate::get(unexpectedParentItem)->extra.isAllocated())
+ QVERIFY(!QQuickItemPrivate::get(unexpectedParentItem)->extra->resourcesList.contains(handler));
+ QCOMPARE(expectedParentItem->acceptedMouseButtons(), Qt::AllButtons);
+ QCOMPARE(unexpectedParentItem->acceptedMouseButtons(), unexpectedParentItem == topItem ? Qt::RightButton : Qt::NoButton);
+
+ QPoint pt = expectedParentItem->mapToScene(expectedParentItem->boundingRect().center()).toPoint();
+ qCDebug(lcPointerTests) << "click @" << pt;
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, pt);
+ QTRY_COMPARE(handler->pressEventCount, i);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, pt);
+ QTRY_COMPARE(handler->releaseEventCount, i);
+ }
+}
+
+/*!
+ Verify that removing an item that has a grabbing handler from the scene
+ does not result in crashes in our event dispatching code. The item's window()
+ pointer will be nullptr, so the handler must have released the grab, or never
+ gotten the grab, depending on when the item gets removed.
+
+ See QTBUG-114475.
+*/
+void tst_PointerHandlers::grabberSceneChange_data()
+{
+ QTest::addColumn<bool>("useTimer");
+ QTest::addColumn<int>("grabChangedCount");
+
+ QTest::addRow("Immediately") << false << 0;
+ QTest::addRow("Delayed") << true << 2;
+}
+
+void tst_PointerHandlers::grabberSceneChange()
+{
+ QFETCH(const bool, useTimer);
+ QFETCH(const int, grabChangedCount);
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("grabberSceneChange.qml"));
+ QQuickWindow *window = qobject_cast<QQuickWindow*>(component.create());
+ QScopedPointer<QQuickWindow> cleanup(window);
+ QVERIFY(window);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ window->setProperty("useTimer", useTimer);
+
+ QQuickItem *container = window->findChild<QQuickItem *>("container");
+
+ QPoint p1 = QPoint(window->width() / 2, window->height() / 2);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ // The container gets removed from this window, either immediately on
+ // press, or through a timer.
+ QTRY_COMPARE(container->parentItem(), nullptr);
+
+ QEXPECT_FAIL("Delayed",
+ "PointerHandlers don't release their grab when item is removed", Continue);
+ QCOMPARE(window->property("grabChangedCounter").toInt(), grabChangedCount);
+
+ // this should not crash
+ QTest::mouseMove(window, p1 + QPoint(5, 5));
+}
+
+void tst_PointerHandlers::clip()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "clip.qml");
+ QQuickView * window = windowPtr.data();
+ QVERIFY(window);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ EventHandler *handler = window->contentItem()->findChild<EventHandler*>("eventHandler");
+ EventHandler *circleHandler = window->contentItem()->findChild<EventHandler*>("circle eventHandler");
+
+ QCOMPARE(handler->pressEventCount, 0);
+ QCOMPARE(circleHandler->pressEventCount, 0);
+ QCOMPARE(handler->releaseEventCount, 0);
+ QCOMPARE(circleHandler->releaseEventCount, 0);
+
+ const QPoint rectPt = QPoint(1, 1);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, rectPt);
+ QCOMPARE(handler->pressEventCount, 1);
+ QCOMPARE(circleHandler->pressEventCount, 0);
+
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, rectPt);
+ QCOMPARE(handler->releaseEventCount, 1);
+ QCOMPARE(circleHandler->releaseEventCount, 0);
+
+
+ handler->pressEventCount = 0;
+ circleHandler->pressEventCount = 0;
+ handler->releaseEventCount = 0;
+ circleHandler->releaseEventCount = 0;
+
+ const QPoint rectAndCirclePt = QPoint(49 ,49);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, rectAndCirclePt);
+ QCOMPARE(handler->pressEventCount, 1);
+ QCOMPARE(circleHandler->pressEventCount, 1);
+
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, rectAndCirclePt);
+ QCOMPARE(handler->releaseEventCount, 1);
+ QCOMPARE(circleHandler->releaseEventCount, 1);
+
+
+ handler->pressEventCount = 0;
+ circleHandler->pressEventCount = 0;
+ handler->releaseEventCount = 0;
+ circleHandler->releaseEventCount = 0;
+
+ const QPoint circlePt = QPoint(51 ,51);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, circlePt);
+ QCOMPARE(handler->pressEventCount, 0);
+ QCOMPARE(circleHandler->pressEventCount, 1);
+
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, circlePt);
+ QCOMPARE(handler->releaseEventCount, 0);
+ QCOMPARE(circleHandler->releaseEventCount, 1);
+}
+
QTEST_MAIN(tst_PointerHandlers)
#include "tst_qquickpointerhandler.moc"
diff --git a/tests/auto/quick/pointerhandlers/qquickpointhandler/BLACKLIST b/tests/auto/quick/pointerhandlers/qquickpointhandler/BLACKLIST
index f4d271c230..5d6a59e1dd 100644
--- a/tests/auto/quick/pointerhandlers/qquickpointhandler/BLACKLIST
+++ b/tests/auto/quick/pointerhandlers/qquickpointhandler/BLACKLIST
@@ -1,2 +1,4 @@
[tabletStylus]
macos ci
+qnx
+android # QTBUG-103068
diff --git a/tests/auto/quick/pointerhandlers/qquickpointhandler/CMakeLists.txt b/tests/auto/quick/pointerhandlers/qquickpointhandler/CMakeLists.txt
index 507bc7549b..aa73218361 100644
--- a/tests/auto/quick/pointerhandlers/qquickpointhandler/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/qquickpointhandler/CMakeLists.txt
@@ -1,9 +1,18 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# Generated from qquickpointhandler.pro.
#####################################################################
## tst_qquickpointhandler Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickpointhandler 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_qquickpointhandler
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_qquickpointhandler.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}
)
@@ -38,10 +40,10 @@ qt_internal_add_test(tst_qquickpointhandler
qt_internal_extend_target(tst_qquickpointhandler CONDITION ANDROID OR IOS
DEFINES
- QT_QMLTEST_DATADIR=\\\":/data\\\"
+ QT_QMLTEST_DATADIR=":/data"
)
qt_internal_extend_target(tst_qquickpointhandler 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/pointerhandlers/qquickpointhandler/data/multiPointTracker.qml b/tests/auto/quick/pointerhandlers/qquickpointhandler/data/multiPointTracker.qml
index 3f50d7c761..616d526592 100644
--- a/tests/auto/quick/pointerhandlers/qquickpointhandler/data/multiPointTracker.qml
+++ b/tests/auto/quick/pointerhandlers/qquickpointhandler/data/multiPointTracker.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 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) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/qquickpointhandler/data/pointTracker.qml b/tests/auto/quick/pointerhandlers/qquickpointhandler/data/pointTracker.qml
index 674bbda850..2de03703e8 100644
--- a/tests/auto/quick/pointerhandlers/qquickpointhandler/data/pointTracker.qml
+++ b/tests/auto/quick/pointerhandlers/qquickpointhandler/data/pointTracker.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 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) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp
index a2415fedd7..e1641c282e 100644
--- a/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module 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) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -33,13 +8,17 @@
#include <QtQuick/private/qquickpointhandler_p.h>
#include <qpa/qwindowsysteminterface.h>
+#include <private/qhighdpiscaling_p.h>
#include <private/qquickwindow_p.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlproperty.h>
-#include "../../../shared/util.h"
-#include "../../shared/viewtestutil.h"
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtQuickTestUtils/private/viewtestutils_p.h>
+#include <QtQuickTestUtils/private/visualtestutils_p.h>
+
+#include <QtCore/qpointer.h>
Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
@@ -48,7 +27,8 @@ class tst_PointHandler : public QQmlDataTest
Q_OBJECT
public:
tst_PointHandler()
- : touchDevice(QTest::createTouchDevice())
+ : QQmlDataTest(QT_QMLTEST_DATADIR)
+ , touchDevice(QTest::createTouchDevice())
{}
private slots:
@@ -59,6 +39,7 @@ private slots:
void simultaneousMultiTouch();
void pressedMultipleButtons_data();
void pressedMultipleButtons();
+ void ignoreSystemSynthMouse();
private:
void createView(QScopedPointer<QQuickView> &window, const char *fileName);
@@ -70,8 +51,8 @@ void tst_PointHandler::createView(QScopedPointer<QQuickView> &window, const char
window.reset(new QQuickView);
window->setSource(testFileUrl(fileName));
QTRY_COMPARE(window->status(), QQuickView::Ready);
- QQuickViewTestUtil::centerOnScreen(window.data());
- QQuickViewTestUtil::moveMouseAway(window.data());
+ QQuickVisualTestUtils::centerOnScreen(window.data());
+ QQuickVisualTestUtils::moveMouseAway(window.data());
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
@@ -104,20 +85,20 @@ void tst_PointHandler::singleTouch()
QTest::touchEvent(window, touchDevice).press(1, point, window);
QQuickTouchUtils::flush(window);
QTRY_COMPARE(handler->active(), true);
- QCOMPARE(activeSpy.count(), 1);
- QCOMPARE(pointSpy.count(), 1);
+ QCOMPARE(activeSpy.size(), 1);
+ QCOMPARE(pointSpy.size(), 1);
QCOMPARE(handler->point().position().toPoint(), point);
QCOMPARE(handler->point().scenePosition().toPoint(), point);
QCOMPARE(handler->point().pressedButtons(), Qt::NoButton);
QCOMPARE(handler->translation(), QVector2D());
- QCOMPARE(translationSpy.count(), 1);
+ QCOMPARE(translationSpy.size(), 1);
point += QPoint(10, 10);
QTest::touchEvent(window, touchDevice).move(1, point, window);
QQuickTouchUtils::flush(window);
QCOMPARE(handler->active(), true);
- QCOMPARE(activeSpy.count(), 1);
- QCOMPARE(pointSpy.count(), 2);
+ QCOMPARE(activeSpy.size(), 1);
+ QCOMPARE(pointSpy.size(), 2);
QCOMPARE(handler->point().position().toPoint(), point);
QCOMPARE(handler->point().scenePosition().toPoint(), point);
QCOMPARE(handler->point().pressPosition().toPoint(), QPoint(100, 100));
@@ -126,15 +107,15 @@ void tst_PointHandler::singleTouch()
QVERIFY(handler->point().velocity().x() > 0);
QVERIFY(handler->point().velocity().y() > 0);
QCOMPARE(handler->translation(), QVector2D(10, 10));
- QCOMPARE(translationSpy.count(), 2);
+ QCOMPARE(translationSpy.size(), 2);
QTest::touchEvent(window, touchDevice).release(1, point, window);
QQuickTouchUtils::flush(window);
QTRY_COMPARE(handler->active(), false);
- QCOMPARE(activeSpy.count(), 2);
- QCOMPARE(pointSpy.count(), 3);
+ QCOMPARE(activeSpy.size(), 2);
+ QCOMPARE(pointSpy.size(), 3);
QCOMPARE(handler->translation(), QVector2D());
- QCOMPARE(translationSpy.count(), 3);
+ QCOMPARE(translationSpy.size(), 3);
}
void tst_PointHandler::tabletStylus()
@@ -146,54 +127,59 @@ void tst_PointHandler::tabletStylus()
QQuickPointHandler *handler = window->rootObject()->findChild<QQuickPointHandler *>("pointHandler");
QVERIFY(handler);
handler->setAcceptedDevices(QInputDevice::DeviceType::Stylus);
+ // avoid generating a double click
+ QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
QSignalSpy activeSpy(handler, SIGNAL(activeChanged()));
QSignalSpy pointSpy(handler, SIGNAL(pointChanged()));
QSignalSpy translationSpy(handler, SIGNAL(translationChanged()));
QPoint point(100,100);
+ QPoint pointLocalDPI = QHighDpi::fromNativeLocalPosition(point, window);
const qint64 stylusId = 1234567890;
QWindowSystemInterface::handleTabletEvent(window, point, window->mapToGlobal(point),
int(QInputDevice::DeviceType::Stylus), int(QPointingDevice::PointerType::Pen), Qt::LeftButton, 0.5, 25, 35, 0.6, 12.3, 3, stylusId, Qt::NoModifier);
QTRY_COMPARE(handler->active(), true);
- QCOMPARE(activeSpy.count(), 1);
- QCOMPARE(pointSpy.count(), 1);
- QCOMPARE(handler->point().position().toPoint(), point);
- QCOMPARE(handler->point().scenePosition().toPoint(), point);
+ QCOMPARE(activeSpy.size(), 1);
+ QCOMPARE(pointSpy.size(), 1);
+ QCOMPARE(handler->point().position().toPoint(), pointLocalDPI);
+ QCOMPARE(handler->point().scenePosition().toPoint(), pointLocalDPI);
QCOMPARE(handler->point().pressedButtons(), Qt::LeftButton);
QCOMPARE(handler->point().pressure(), 0.5);
QCOMPARE(handler->point().rotation(), 12.3);
QCOMPARE(handler->point().uniqueId().numericId(), stylusId);
QCOMPARE(handler->translation(), QVector2D());
- QCOMPARE(translationSpy.count(), 1);
+ QCOMPARE(translationSpy.size(), 1);
- point += QPoint(10, 10);
+ QPoint delta(10, 10);
+ QPoint deltaLocalDPI = QHighDpi::fromNativeLocalPosition(delta, window);
+ point += delta;
QWindowSystemInterface::handleTabletEvent(window, point, window->mapToGlobal(point),
int(QInputDevice::DeviceType::Stylus), int(QPointingDevice::PointerType::Pen), Qt::LeftButton, 0.45, 23, 33, 0.57, 15.6, 3, stylusId, Qt::NoModifier);
- QTRY_COMPARE(pointSpy.count(), 2);
+ QTRY_COMPARE(pointSpy.size(), 2);
QCOMPARE(handler->active(), true);
- QCOMPARE(activeSpy.count(), 1);
- QCOMPARE(handler->point().position().toPoint(), point);
- QCOMPARE(handler->point().scenePosition().toPoint(), point);
- QCOMPARE(handler->point().pressPosition().toPoint(), QPoint(100, 100));
- QCOMPARE(handler->point().scenePressPosition().toPoint(), QPoint(100, 100));
+ QCOMPARE(activeSpy.size(), 1);
+ QCOMPARE(handler->point().position().toPoint(), pointLocalDPI + deltaLocalDPI);
+ QCOMPARE(handler->point().scenePosition().toPoint(), pointLocalDPI + deltaLocalDPI);
+ QCOMPARE(handler->point().pressPosition().toPoint(), pointLocalDPI);
+ QCOMPARE(handler->point().scenePressPosition().toPoint(), pointLocalDPI);
QCOMPARE(handler->point().pressedButtons(), Qt::LeftButton);
QCOMPARE(handler->point().pressure(), 0.45);
QCOMPARE(handler->point().rotation(), 15.6);
QCOMPARE(handler->point().uniqueId().numericId(), stylusId);
- QVERIFY(handler->point().velocity().x() > 0);
- QVERIFY(handler->point().velocity().y() > 0);
- QCOMPARE(handler->translation(), QVector2D(10, 10));
- QCOMPARE(translationSpy.count(), 2);
+ QCOMPARE_GT(handler->point().velocity().x(), 0);
+ QCOMPARE_GT(handler->point().velocity().y(), 0);
+ QCOMPARE(handler->translation(), QVector2D(deltaLocalDPI));
+ QCOMPARE(translationSpy.size(), 2);
QWindowSystemInterface::handleTabletEvent(window, point, window->mapToGlobal(point),
int(QInputDevice::DeviceType::Stylus), int(QPointingDevice::PointerType::Pen), Qt::NoButton, 0, 0, 0, 0, 0, 0, stylusId, Qt::NoModifier);
QTRY_COMPARE(handler->active(), false);
- QCOMPARE(activeSpy.count(), 2);
- QCOMPARE(pointSpy.count(), 3);
+ QCOMPARE(activeSpy.size(), 2);
+ QCOMPARE(pointSpy.size(), 3);
QCOMPARE(handler->translation(), QVector2D());
- QCOMPARE(translationSpy.count(), 3);
+ QCOMPARE(translationSpy.size(), 3);
}
void tst_PointHandler::simultaneousMultiTouch()
@@ -202,7 +188,7 @@ void tst_PointHandler::simultaneousMultiTouch()
createView(windowPtr, "multiPointTracker.qml");
QQuickView * window = windowPtr.data();
QList<QQuickPointHandler *> handlers = window->rootObject()->findChildren<QQuickPointHandler *>();
- QCOMPARE(handlers.count(), 3);
+ QCOMPARE(handlers.size(), 3);
QVector<QSignalSpy*> activeSpies;
QVector<QSignalSpy*> pointSpies;
@@ -221,8 +207,8 @@ void tst_PointHandler::simultaneousMultiTouch()
int i = 0;
for (auto h : handlers) {
QTRY_COMPARE(h->active(), true);
- QCOMPARE(activeSpies[i]->count(), 1);
- QCOMPARE(pointSpies[i]->count(), 1);
+ QCOMPARE(activeSpies[i]->size(), 1);
+ QCOMPARE(pointSpies[i]->size(), 1);
int chosenPointIndex = points.indexOf(h->point().position().toPoint());
QVERIFY(chosenPointIndex != -1);
// Verify that each handler chose a unique point
@@ -232,7 +218,7 @@ void tst_PointHandler::simultaneousMultiTouch()
QCOMPARE(h->point().scenePosition().toPoint(), point);
QCOMPARE(h->point().pressedButtons(), Qt::NoButton);
QCOMPARE(h->translation(), QVector2D());
- QCOMPARE(translationSpies[i]->count(), 1);
+ QCOMPARE(translationSpies[i]->size(), 1);
++i;
}
@@ -243,8 +229,8 @@ void tst_PointHandler::simultaneousMultiTouch()
i = 0;
for (auto h : handlers) {
QCOMPARE(h->active(), true);
- QCOMPARE(activeSpies[i]->count(), 1);
- QCOMPARE(pointSpies[i]->count(), 2);
+ QCOMPARE(activeSpies[i]->size(), 1);
+ QCOMPARE(pointSpies[i]->size(), 2);
QCOMPARE(h->point().position().toPoint(), points[pointIndexPerHandler[i]]);
QCOMPARE(h->point().scenePosition().toPoint(), points[pointIndexPerHandler[i]]);
QCOMPARE(h->point().pressPosition().toPoint(), pressPoints[pointIndexPerHandler[i]]);
@@ -253,7 +239,7 @@ void tst_PointHandler::simultaneousMultiTouch()
QVERIFY(h->point().velocity().x() > 0);
QVERIFY(h->point().velocity().y() > 0);
QCOMPARE(h->translation(), QVector2D(10 + 10 * pointIndexPerHandler[i], 10 + 10 * pointIndexPerHandler[i] % 2));
- QCOMPARE(translationSpies[i]->count(), 2);
+ QCOMPARE(translationSpies[i]->size(), 2);
++i;
}
@@ -262,10 +248,10 @@ void tst_PointHandler::simultaneousMultiTouch()
i = 0;
for (auto h : handlers) {
QTRY_COMPARE(h->active(), false);
- QCOMPARE(activeSpies[i]->count(), 2);
- QCOMPARE(pointSpies[i]->count(), 3);
+ QCOMPARE(activeSpies[i]->size(), 2);
+ QCOMPARE(pointSpies[i]->size(), 3);
QCOMPARE(h->translation(), QVector2D());
- QCOMPARE(translationSpies[i]->count(), 3);
+ QCOMPARE(translationSpies[i]->size(), 3);
++i;
}
@@ -379,7 +365,7 @@ void tst_PointHandler::pressedMultipleButtons()
QPoint point(100,100);
- for (int i = 0; i < buttons.count(); ++i) {
+ for (int i = 0; i < buttons.size(); ++i) {
int btns = int(buttons.at(i));
int release = 0;
if (i > 0) {
@@ -399,8 +385,91 @@ void tst_PointHandler::pressedMultipleButtons()
QTest::mousePress(windowPtr.data(), Qt::NoButton, Qt::NoModifier, point);
QCOMPARE(handler->active(), false);
- QCOMPARE(activeSpy.count(), activeChangeCount);
- QCOMPARE(pointSpy.count(), changeCount);
+ QCOMPARE(activeSpy.size(), activeChangeCount);
+ QCOMPARE(pointSpy.size(), changeCount);
+}
+
+void tst_PointHandler::ignoreSystemSynthMouse() // QTBUG-104890
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("pointTracker.qml")));
+ QQuickPointHandler *handler = window.rootObject()->findChild<QQuickPointHandler *>();
+ QVERIFY(handler);
+ auto devPriv = QPointingDevicePrivate::get(touchDevice);
+ QSignalSpy activeSpy(handler, SIGNAL(activeChanged()));
+ QSignalSpy pointSpy(handler, SIGNAL(pointChanged()));
+
+ // touch press
+ QPoint point(100,100);
+ QTest::touchEvent(&window, touchDevice).press(0, point, &window);
+ QQuickTouchUtils::flush(&window);
+
+ // touch move
+ point += QPoint(10, 10);
+ QTest::touchEvent(&window, touchDevice).move(0, point, &window);
+ QQuickTouchUtils::flush(&window);
+ QCOMPARE(handler->active(), true);
+ QCOMPARE(activeSpy.size(), 1);
+ QCOMPARE(pointSpy.size(), 2);
+ QVERIFY(devPriv->queryPointById(0)->passiveGrabbers.contains(handler));
+
+ // Windows begins to synthesize mouse events in parallel with the touch event stream: move to touchpoint position, then press
+ {
+ QMouseEvent move(QEvent::MouseMove, point, point, window.mapToGlobal(point),
+ Qt::NoButton, Qt::NoButton, Qt::NoModifier, Qt::MouseEventSynthesizedBySystem, touchDevice);
+ move.setTimestamp(235); // slightly after the last touch event
+ QGuiApplication::sendEvent(&window, &move);
+ }
+ QCOMPARE(handler->active(), true);
+ QCOMPARE(activeSpy.size(), 1);
+ QCOMPARE(pointSpy.size(), 2);
+ QVERIFY(devPriv->queryPointById(0)->passiveGrabbers.contains(handler));
+ {
+ QMouseEvent press(QEvent::MouseButtonPress, point, point, window.mapToGlobal(point),
+ Qt::LeftButton, Qt::LeftButton, Qt::NoModifier, Qt::MouseEventSynthesizedBySystem, touchDevice);
+ press.setTimestamp(235);
+ QGuiApplication::sendEvent(&window, &press);
+ }
+ QCOMPARE(handler->active(), true);
+ QCOMPARE(activeSpy.size(), 1);
+ QCOMPARE(pointSpy.size(), 2);
+ QVERIFY(devPriv->queryPointById(0)->passiveGrabbers.contains(handler));
+
+ // another touch move
+ point += QPoint(10, 10);
+ QTest::touchEvent(&window, touchDevice).move(0, point, &window);
+ QQuickTouchUtils::flush(&window);
+ QCOMPARE(handler->active(), true);
+ QCOMPARE(activeSpy.size(), 1);
+ QCOMPARE(pointSpy.size(), 3);
+ QCOMPARE(handler->point().position().toPoint(), point);
+ QCOMPARE(handler->point().scenePosition().toPoint(), point);
+ QCOMPARE(handler->point().pressPosition().toPoint(), QPoint(100, 100));
+ QCOMPARE(handler->point().scenePressPosition().toPoint(), QPoint(100, 100));
+ QVERIFY(devPriv->queryPointById(0)->passiveGrabbers.contains(handler));
+
+ // another fake mouse move
+ {
+ QMouseEvent move(QEvent::MouseMove, point, point, window.mapToGlobal(point),
+ Qt::LeftButton, Qt::LeftButton, Qt::NoModifier, Qt::MouseEventSynthesizedBySystem, touchDevice);
+ move.setTimestamp(240);
+ QGuiApplication::sendEvent(&window, &move);
+ }
+ QCOMPARE(handler->active(), true);
+ QCOMPARE(activeSpy.size(), 1);
+ QCOMPARE(pointSpy.size(), 3);
+ QCOMPARE(handler->point().position().toPoint(), point);
+ QCOMPARE(handler->point().scenePosition().toPoint(), point);
+ QCOMPARE(handler->point().pressPosition().toPoint(), QPoint(100, 100));
+ QCOMPARE(handler->point().scenePressPosition().toPoint(), QPoint(100, 100));
+ QVERIFY(devPriv->queryPointById(0)->passiveGrabbers.contains(handler));
+
+ // end with released state
+ QTest::touchEvent(&window, touchDevice).release(0, point, &window);
+ QMouseEvent release(QEvent::MouseButtonRelease, point, point, window.mapToGlobal(point),
+ Qt::LeftButton, Qt::LeftButton, Qt::NoModifier, Qt::MouseEventSynthesizedBySystem);
+ release.setTimestamp(280);
+ QGuiApplication::sendEvent(&window, &release);
}
QTEST_MAIN(tst_PointHandler)
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/BLACKLIST b/tests/auto/quick/pointerhandlers/qquicktaphandler/BLACKLIST
new file mode 100644
index 0000000000..1559014480
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/BLACKLIST
@@ -0,0 +1,3 @@
+# QTBUG-103072
+[gesturePolicyDragWithinBounds]
+android
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/CMakeLists.txt b/tests/auto/quick/pointerhandlers/qquicktaphandler/CMakeLists.txt
index babe276519..94834e04c6 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/CMakeLists.txt
@@ -1,9 +1,18 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# Generated from qquicktaphandler.pro.
#####################################################################
## 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}
@@ -12,21 +21,14 @@ list(APPEND test_data ${test_data_glob})
qt_internal_add_test(tst_qquicktaphandler
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_qquicktaphandler.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_qquicktaphandler
qt_internal_extend_target(tst_qquicktaphandler CONDITION ANDROID OR IOS
DEFINES
- QT_QMLTEST_DATADIR=\\\":/data\\\"
+ QT_QMLTEST_DATADIR=":/data"
)
qt_internal_extend_target(tst_qquicktaphandler 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/pointerhandlers/qquicktaphandler/data/Button.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml
index 800c25c77d..fc1e623902 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
@@ -35,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" }
@@ -50,11 +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
- onTapped: {
+ onSingleTapped: console.log("Single tap")
+ onDoubleTapped: console.log("Double tap")
+ 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 158a02b7a6..9483a12d1c 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/FlashAnimation.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/FlashAnimation.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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) 2017 The Qt Company Ltd.
+// 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 4a8b8e1375..b36fcdef08 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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) 2017 The Qt Company Ltd.
+// 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 821b8073e9..04fbbc176b 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
@@ -34,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
new file mode 100644
index 0000000000..5f60ef879e
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/dragReleaseMenu.qml
@@ -0,0 +1,64 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ width: 480
+ height: 480
+ property alias feedbackText: feedback.text
+
+ Rectangle {
+ id: rect
+ anchors.fill: parent; anchors.margins: 40
+ color: tapHandler.active ? "lightgrey" : "darkgrey"
+
+ TapHandler {
+ id: tapHandler
+ gesturePolicy: TapHandler.DragWithinBounds
+ onPressedChanged: if (pressed) {
+ menu.x = point.position.x - menu.width / 2
+ menu.y = point.position.y - menu.height / 2
+ } else {
+ if (menu.highlightedMenuItem !== "")
+ feedback.text = menu.highlightedMenuItem
+ }
+ onCanceled: feedback.text = "canceled"
+ }
+
+ Column {
+ id: menu
+ visible: tapHandler.pressed
+ opacity: Math.min(1, tapHandler.timeHeld)
+ property string highlightedMenuItem: ""
+ Repeater {
+ model: [ "top", "middle", "bottom" ]
+ delegate: Rectangle {
+ property bool highlighted: tapHandler.pressed &&
+ contains(mapFromItem(rect, tapHandler.point.position))
+ onHighlightedChanged: {
+ if (highlighted)
+ menu.highlightedMenuItem = menuItemText.text
+ else if (menu.highlightedMenuItem === menuItemText.text)
+ menu.highlightedMenuItem = ""
+ }
+ width: 100
+ height: 20
+ color: highlighted ? "lightsteelblue" : "aliceblue"
+ Text {
+ id: menuItemText
+ anchors.centerIn: parent
+ text: modelData
+ }
+ }
+ }
+ }
+
+ Text {
+ id: feedback
+ x: 6; y: 6
+ textFormat: Text.MarkdownText
+ text: "hold for context menu"
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nested.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nested.qml
new file mode 100644
index 0000000000..c0f0b10bf4
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nested.qml
@@ -0,0 +1,35 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+import QtQuick 2.12
+
+Item {
+ width: 300
+ height: 200
+ property var taps: []
+
+ Rectangle {
+ x: 25
+ y: 25
+ width: 200
+ height: 100
+ color: "salmon"
+
+ TapHandler {
+ objectName: "parentTapHandler"
+ onTapped: taps.push(objectName)
+ }
+
+ Rectangle {
+ x: 25
+ y: 25
+ width: 200
+ height: 100
+ color: "lightsteelblue"
+
+ TapHandler {
+ objectName: "childTapHandler"
+ onTapped: taps.push(objectName)
+ }
+ }
+ }
+}
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 aea01c154c..85f5c87b39 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 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) 2018 The Qt Company Ltd.
+// 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
new file mode 100644
index 0000000000..026be48f83
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/simpleTapHandler.qml
@@ -0,0 +1,14 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick 2.12
+
+Item {
+ id: root
+ width: 100
+ height: 100
+ property int tapCount: 0
+ TapHandler {
+ onTapped: { ++root.tapCount }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/tapHandlersOverlapped.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/tapHandlersOverlapped.qml
deleted file mode 100644
index 8d2e36d921..0000000000
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/tapHandlersOverlapped.qml
+++ /dev/null
@@ -1,60 +0,0 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
-import QtQuick 2.12
-
-Item {
- width: 300
- height: 200
- property var taps: []
-
- Rectangle {
- x: 25
- y: 25
- width: 200
- height: 100
- color: "salmon"
-
- TapHandler {
- objectName: "parentTapHandler"
- onTapped: taps.push(objectName)
- }
-
- Rectangle {
- x: 25
- y: 25
- width: 200
- height: 100
- color: "lightsteelblue"
-
- TapHandler {
- objectName: "childTapHandler"
- onTapped: taps.push(objectName)
- }
- }
- }
-}
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
index 8457488cd9..1dab0836cd 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module 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) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -41,8 +16,8 @@
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlproperty.h>
-#include "../../../shared/util.h"
-#include "../../shared/viewtestutil.h"
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtQuickTestUtils/private/viewtestutils_p.h>
Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
@@ -51,6 +26,7 @@ class tst_TapHandler : public QQmlDataTest
Q_OBJECT
public:
tst_TapHandler()
+ : QQmlDataTest(QT_QMLTEST_DATADIR)
{}
private slots:
@@ -63,33 +39,68 @@ private slots:
void mouseGesturePolicyWithinBounds();
void touchGesturePolicyReleaseWithinBounds();
void mouseGesturePolicyReleaseWithinBounds();
+ void gesturePolicyDragWithinBounds_data();
+ void gesturePolicyDragWithinBounds();
void touchMultiTap();
+ void mouseMultiTap_data();
void mouseMultiTap();
- void touchLongPress();
- void mouseLongPress();
+ void mouseMultiTapLeftRight_data();
+ void mouseMultiTapLeftRight();
+ void singleTapDoubleTap_data();
+ void singleTapDoubleTap();
+ void longPress_data();
+ void longPress();
void buttonsMultiTouch();
void componentUserBehavioralOverride();
void rightLongPressIgnoreWheel();
void negativeZStackingOrder();
+ void nonTopLevelParentWindow();
+ void nestedDoubleTap_data();
+ void nestedDoubleTap();
+ void nestedAndSiblingPropagation_data();
+ void nestedAndSiblingPropagation();
private:
- void createView(QScopedPointer<QQuickView> &window, const char *fileName);
- QPointingDevice *touchDevice = QTest::createTouchDevice();
+ void createView(QScopedPointer<QQuickView> &window, const char *fileName,
+ QWindow *parent = nullptr);
+ QPointingDevice *touchDevice = QTest::createTouchDevice(); // TODO const after fixing QTBUG-107864
+ void mouseEvent(QEvent::Type type, Qt::MouseButton button, const QPoint &point,
+ QWindow *targetWindow, QWindow *mapToWindow);
};
-void tst_TapHandler::createView(QScopedPointer<QQuickView> &window, const char *fileName)
+void tst_TapHandler::createView(QScopedPointer<QQuickView> &window, const char *fileName,
+ QWindow *parent)
{
- window.reset(new QQuickView);
+ window.reset(new QQuickView(parent));
+ if (parent) {
+ parent->show();
+ QVERIFY(QTest::qWaitForWindowActive(parent));
+ }
+
window->setSource(testFileUrl(fileName));
QTRY_COMPARE(window->status(), QQuickView::Ready);
- QQuickViewTestUtil::centerOnScreen(window.data());
- QQuickViewTestUtil::moveMouseAway(window.data());
+ QQuickViewTestUtils::centerOnScreen(window.data());
+ QQuickViewTestUtils::moveMouseAway(window.data());
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
QVERIFY(window->rootObject() != nullptr);
}
+void tst_TapHandler::mouseEvent(QEvent::Type type, Qt::MouseButton button, const QPoint &point,
+ QWindow *targetWindow, QWindow *mapToWindow)
+{
+ QVERIFY(targetWindow);
+ QVERIFY(mapToWindow);
+ auto buttons = button;
+ if (type == QEvent::MouseButtonRelease) {
+ buttons = Qt::NoButton;
+ }
+ QMouseEvent me(type, point, mapToWindow->mapToGlobal(point), button, buttons,
+ Qt::KeyboardModifiers(), QPointingDevice::primaryPointingDevice());
+ QVERIFY(qApp->notify(targetWindow, &me));
+}
+
void tst_TapHandler::initTestCase()
{
// This test assumes that we don't get synthesized mouse events from QGuiApplication
@@ -123,7 +134,7 @@ void tst_TapHandler::touchGesturePolicyDragThreshold()
QTest::touchEvent(window, touchDevice).release(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!buttonDragThreshold->property("pressed").toBool());
- QCOMPARE(dragThresholdTappedSpy.count(), 1);
+ QCOMPARE(dragThresholdTappedSpy.size(), 1);
QCOMPARE(buttonDragThreshold->property("tappedPosition").toPoint(), p1);
QCOMPARE(tapHandler->point().position(), QPointF());
@@ -144,7 +155,7 @@ void tst_TapHandler::touchGesturePolicyDragThreshold()
QTest::touchEvent(window, touchDevice).release(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(!buttonDragThreshold->property("pressed").toBool());
- QCOMPARE(dragThresholdTappedSpy.count(), 0);
+ QCOMPARE(dragThresholdTappedSpy.size(), 0);
}
void tst_TapHandler::mouseGesturePolicyDragThreshold()
@@ -169,7 +180,7 @@ void tst_TapHandler::mouseGesturePolicyDragThreshold()
QVERIFY(buttonDragThreshold->property("pressed").toBool());
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
QTRY_VERIFY(!buttonDragThreshold->property("pressed").toBool());
- QTRY_COMPARE(dragThresholdTappedSpy.count(), 1);
+ QTRY_COMPARE(dragThresholdTappedSpy.size(), 1);
QCOMPARE(buttonDragThreshold->property("tappedPosition").toPoint(), p1);
QCOMPARE(tapHandler->point().position(), QPointF());
@@ -186,7 +197,7 @@ void tst_TapHandler::mouseGesturePolicyDragThreshold()
QTRY_VERIFY(!buttonDragThreshold->property("pressed").toBool());
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
QVERIFY(!buttonDragThreshold->property("pressed").toBool());
- QCOMPARE(dragThresholdTappedSpy.count(), 0);
+ QCOMPARE(dragThresholdTappedSpy.size(), 0);
}
void tst_TapHandler::touchMouseGesturePolicyDragThreshold()
@@ -206,8 +217,8 @@ void tst_TapHandler::touchMouseGesturePolicyDragThreshold()
QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
QTRY_VERIFY(buttonDragThreshold->property("pressed").toBool());
QTest::mouseMove(window, p2);
- QTRY_COMPARE(canceledSpy.count(), 1);
- QCOMPARE(tappedSpy.count(), 0);
+ QTRY_COMPARE(canceledSpy.size(), 1);
+ QCOMPARE(tappedSpy.size(), 0);
QCOMPARE(buttonDragThreshold->property("pressed").toBool(), false);
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p2);
@@ -218,7 +229,7 @@ void tst_TapHandler::touchMouseGesturePolicyDragThreshold()
QTest::touchEvent(window, touchDevice).release(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!buttonDragThreshold->property("pressed").toBool());
- QCOMPARE(tappedSpy.count(), 1);
+ QCOMPARE(tappedSpy.size(), 1);
// Press touch, drag it outside the button, release
QTest::touchEvent(window, touchDevice).press(1, p1, window);
@@ -229,16 +240,16 @@ void tst_TapHandler::touchMouseGesturePolicyDragThreshold()
QTRY_COMPARE(buttonDragThreshold->property("pressed").toBool(), false);
QTest::touchEvent(window, touchDevice).release(1, p2, window);
QQuickTouchUtils::flush(window);
- QTRY_COMPARE(canceledSpy.count(), 2);
- QCOMPARE(tappedSpy.count(), 1); // didn't increase
+ QTRY_COMPARE(canceledSpy.size(), 2);
+ QCOMPARE(tappedSpy.size(), 1); // didn't increase
QCOMPARE(buttonDragThreshold->property("pressed").toBool(), false);
// Press and release mouse, verify that it still works
QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
QTRY_VERIFY(buttonDragThreshold->property("pressed").toBool());
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
- QTRY_COMPARE(tappedSpy.count(), 2);
- QCOMPARE(canceledSpy.count(), 2); // didn't increase
+ QTRY_COMPARE(tappedSpy.size(), 2);
+ QCOMPARE(canceledSpy.size(), 2); // didn't increase
QCOMPARE(buttonDragThreshold->property("pressed").toBool(), false);
}
@@ -264,7 +275,7 @@ void tst_TapHandler::touchGesturePolicyWithinBounds()
QTest::touchEvent(window, touchDevice).release(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!buttonWithinBounds->property("pressed").toBool());
- QCOMPARE(withinBoundsTappedSpy.count(), 1);
+ QCOMPARE(withinBoundsTappedSpy.size(), 1);
// WithinBounds button is no longer pressed if touchpoint leaves bounds
withinBoundsTappedSpy.clear();
@@ -279,7 +290,7 @@ void tst_TapHandler::touchGesturePolicyWithinBounds()
QTest::touchEvent(window, touchDevice).release(1, p1, window);
QQuickTouchUtils::flush(window);
QVERIFY(!buttonWithinBounds->property("pressed").toBool());
- QCOMPARE(withinBoundsTappedSpy.count(), 0);
+ QCOMPARE(withinBoundsTappedSpy.size(), 0);
}
void tst_TapHandler::mouseGesturePolicyWithinBounds()
@@ -301,7 +312,7 @@ void tst_TapHandler::mouseGesturePolicyWithinBounds()
QVERIFY(buttonWithinBounds->property("pressed").toBool());
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
QTRY_VERIFY(!buttonWithinBounds->property("pressed").toBool());
- QCOMPARE(withinBoundsTappedSpy.count(), 1);
+ QCOMPARE(withinBoundsTappedSpy.size(), 1);
// WithinBounds button is no longer pressed if touchpoint leaves bounds
withinBoundsTappedSpy.clear();
@@ -313,7 +324,7 @@ void tst_TapHandler::mouseGesturePolicyWithinBounds()
QTRY_VERIFY(!buttonWithinBounds->property("pressed").toBool());
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
QVERIFY(!buttonWithinBounds->property("pressed").toBool());
- QCOMPARE(withinBoundsTappedSpy.count(), 0);
+ QCOMPARE(withinBoundsTappedSpy.size(), 0);
}
void tst_TapHandler::touchGesturePolicyReleaseWithinBounds()
@@ -347,7 +358,7 @@ void tst_TapHandler::touchGesturePolicyReleaseWithinBounds()
QTest::touchEvent(window, touchDevice).release(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!buttonReleaseWithinBounds->property("pressed").toBool());
- QCOMPARE(releaseWithinBoundsTappedSpy.count(), 1);
+ QCOMPARE(releaseWithinBoundsTappedSpy.size(), 1);
// ReleaseWithinBounds button does not emit tapped if released out of bounds
releaseWithinBoundsTappedSpy.clear();
@@ -362,7 +373,7 @@ void tst_TapHandler::touchGesturePolicyReleaseWithinBounds()
QTest::touchEvent(window, touchDevice).release(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!buttonReleaseWithinBounds->property("pressed").toBool());
- QCOMPARE(releaseWithinBoundsTappedSpy.count(), 0);
+ QCOMPARE(releaseWithinBoundsTappedSpy.size(), 0);
}
void tst_TapHandler::mouseGesturePolicyReleaseWithinBounds()
@@ -391,7 +402,7 @@ void tst_TapHandler::mouseGesturePolicyReleaseWithinBounds()
QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
QTRY_VERIFY(!buttonReleaseWithinBounds->property("pressed").toBool());
- QCOMPARE(releaseWithinBoundsTappedSpy.count(), 1);
+ QCOMPARE(releaseWithinBoundsTappedSpy.size(), 1);
// ReleaseWithinBounds button does not emit tapped if released out of bounds
releaseWithinBoundsTappedSpy.clear();
@@ -403,7 +414,52 @@ void tst_TapHandler::mouseGesturePolicyReleaseWithinBounds()
QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
QTRY_VERIFY(!buttonReleaseWithinBounds->property("pressed").toBool());
- QCOMPARE(releaseWithinBoundsTappedSpy.count(), 0);
+ QCOMPARE(releaseWithinBoundsTappedSpy.size(), 0);
+}
+
+void tst_TapHandler::gesturePolicyDragWithinBounds_data()
+{
+ QTest::addColumn<const QPointingDevice *>("device");
+ QTest::addColumn<QPoint>("dragStart");
+ QTest::addColumn<QPoint>("dragDistance");
+ QTest::addColumn<QString>("expectedFeedback");
+
+ const QPointingDevice *constTouchDevice = touchDevice;
+
+ QTest::newRow("mouse: click") << QPointingDevice::primaryPointingDevice() << QPoint(200, 200) << QPoint(0, 0) << "middle";
+ QTest::newRow("touch: tap") << constTouchDevice << QPoint(200, 200) << QPoint(0, 0) << "middle";
+ QTest::newRow("mouse: drag up") << QPointingDevice::primaryPointingDevice() << QPoint(200, 200) << QPoint(0, -20) << "top";
+ QTest::newRow("touch: drag up") << constTouchDevice << QPoint(200, 200) << QPoint(0, -20) << "top";
+ QTest::newRow("mouse: drag out to cancel") << QPointingDevice::primaryPointingDevice() << QPoint(435, 200) << QPoint(10, 0) << "canceled";
+ QTest::newRow("touch: drag out to cancel") << constTouchDevice << QPoint(435, 200) << QPoint(10, 0) << "canceled";
+}
+
+void tst_TapHandler::gesturePolicyDragWithinBounds()
+{
+ QFETCH(const QPointingDevice *, device);
+ QFETCH(QPoint, dragStart);
+ QFETCH(QPoint, dragDistance);
+ QFETCH(QString, expectedFeedback);
+ const bool expectedCanceled = expectedFeedback == "canceled";
+
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("dragReleaseMenu.qml")));
+ QQuickTapHandler *tapHandler = window.rootObject()->findChild<QQuickTapHandler*>();
+ QVERIFY(tapHandler);
+ QSignalSpy canceledSpy(tapHandler, &QQuickTapHandler::canceled);
+
+ QQuickTest::pointerPress(device, &window, 0, dragStart);
+ QTRY_VERIFY(tapHandler->isPressed());
+ QQuickTest::pointerMove(device, &window, 0, dragStart + dragDistance);
+ if (expectedCanceled)
+ QTRY_COMPARE(tapHandler->timeHeld(), -1);
+ else
+ QTRY_VERIFY(tapHandler->timeHeld() > 0.1);
+ QQuickTest::pointerRelease(device, &window, 0, dragStart + dragDistance);
+
+ QCOMPARE(window.rootObject()->property("feedbackText"), expectedFeedback);
+ if (expectedCanceled)
+ QCOMPARE(canceledSpy.size(), 1);
}
void tst_TapHandler::touchMultiTap()
@@ -425,7 +481,7 @@ void tst_TapHandler::touchMultiTap()
QTest::touchEvent(window, touchDevice).release(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!button->property("pressed").toBool());
- QCOMPARE(tappedSpy.count(), 1);
+ QCOMPARE(tappedSpy.size(), 1);
// Tap again in exactly the same place (not likely with touch in the real world)
QTest::touchEvent(window, touchDevice).press(1, p1, window);
@@ -434,7 +490,7 @@ void tst_TapHandler::touchMultiTap()
QTest::touchEvent(window, touchDevice).release(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!button->property("pressed").toBool());
- QCOMPARE(tappedSpy.count(), 2);
+ QCOMPARE(tappedSpy.size(), 2);
// Tap a third time, nearby
p1 += QPoint(dragThreshold, dragThreshold);
@@ -444,7 +500,7 @@ void tst_TapHandler::touchMultiTap()
QTest::touchEvent(window, touchDevice).release(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!button->property("pressed").toBool());
- QCOMPARE(tappedSpy.count(), 3);
+ QCOMPARE(tappedSpy.size(), 3);
// Tap a fourth time, drifting farther away
p1 += QPoint(dragThreshold, dragThreshold);
@@ -454,11 +510,52 @@ void tst_TapHandler::touchMultiTap()
QTest::touchEvent(window, touchDevice).release(1, p1, window);
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!button->property("pressed").toBool());
- QCOMPARE(tappedSpy.count(), 4);
+ 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()
+{
+ QTest::addColumn<QQuickTapHandler::ExclusiveSignals>("exclusiveSignals");
+ QTest::addColumn<int>("expectedSingleTaps");
+ QTest::addColumn<int>("expectedSingleTapsAfterMovingAway");
+ QTest::addColumn<int>("expectedSingleTapsAfterWaiting");
+ QTest::addColumn<int>("expectedDoubleTaps");
+
+ QTest::newRow("NotExclusive") << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::NotExclusive)
+ << 1 << 2 << 3 << 1;
+ QTest::newRow("SingleTap") << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::SingleTap)
+ << 1 << 2 << 3 << 0;
+ QTest::newRow("DoubleTap") << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::DoubleTap)
+ << 0 << 0 << 0 << 1;
+ QTest::newRow("SingleTap|DoubleTap") << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::SingleTap | QQuickTapHandler::DoubleTap)
+ << 0 << 0 << 0 << 0;
}
void tst_TapHandler::mouseMultiTap()
{
+ QFETCH(QQuickTapHandler::ExclusiveSignals, exclusiveSignals);
+ QFETCH(int, expectedSingleTaps);
+ QFETCH(int, expectedSingleTapsAfterMovingAway);
+ QFETCH(int, expectedSingleTapsAfterWaiting);
+ QFETCH(int, expectedDoubleTaps);
+
const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
QScopedPointer<QQuickView> windowPtr;
createView(windowPtr, "buttons.qml");
@@ -466,110 +563,409 @@ void tst_TapHandler::mouseMultiTap()
QQuickItem *button = window->rootObject()->findChild<QQuickItem*>("DragThreshold");
QVERIFY(button);
+ QQuickTapHandler *tapHandler = button->findChild<QQuickTapHandler*>();
+ QVERIFY(tapHandler);
+ tapHandler->setExclusiveSignals(exclusiveSignals);
QSignalSpy tappedSpy(button, SIGNAL(tapped()));
+ QSignalSpy singleTapSpy(tapHandler, &QQuickTapHandler::singleTapped);
+ QSignalSpy doubleTapSpy(tapHandler, &QQuickTapHandler::doubleTapped);
- // Tap once
+ // Click once
QPoint p1 = button->mapToScene(QPointF(2, 2)).toPoint();
- QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
- QTRY_VERIFY(button->property("pressed").toBool());
- QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
- QTRY_VERIFY(!button->property("pressed").toBool());
- QCOMPARE(tappedSpy.count(), 1);
-
- // Tap again in exactly the same place (not likely with touch in the real world)
- QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
QTRY_VERIFY(button->property("pressed").toBool());
- QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
QTRY_VERIFY(!button->property("pressed").toBool());
- QCOMPARE(tappedSpy.count(), 2);
-
- // Tap a third time, nearby
+ QCOMPARE(tappedSpy.size(), 1);
+ // If exclusiveSignals == SingleTap | DoubleTap:
+ // This would be a single-click if we waited longer than the double-click interval,
+ // but it's too early for the signal at this moment; and we're going to click again.
+ // If exclusiveSignals == DoubleTap: singleTapped() won't happen.
+ // Otherwise: we got singleTapped() immediately.
+ QCOMPARE(singleTapSpy.size(), expectedSingleTaps);
+ QCOMPARE(tapHandler->timeHeld(), -1);
+
+ // Click again in exactly the same place
+ QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
+ QCOMPARE(tappedSpy.size(), 2);
+ QCOMPARE(singleTapSpy.size(), expectedSingleTaps);
+ QCOMPARE(doubleTapSpy.size(), expectedDoubleTaps);
+
+ // Click a third time, nearby: that'll be a triple-click
+ p1 += QPoint(1, 1);
+ QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
+ QCOMPARE(tappedSpy.size(), 3);
+ QCOMPARE(singleTapSpy.size(), expectedSingleTaps);
+ QCOMPARE(doubleTapSpy.size(), expectedDoubleTaps);
+ QCOMPARE(tapHandler->tapCount(), 3);
+
+ // Click a fourth time, drifting farther away: treated as a separate click, regardless of timing
p1 += QPoint(dragThreshold, dragThreshold);
- QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
- QTRY_VERIFY(button->property("pressed").toBool());
- QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
- QTRY_VERIFY(!button->property("pressed").toBool());
- QCOMPARE(tappedSpy.count(), 3);
+ QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, p1); // default delay to prevent double-click
+ QCOMPARE(tappedSpy.size(), 4);
+ QCOMPARE(tapHandler->tapCount(), 1);
+ QTRY_COMPARE(singleTapSpy.size(), expectedSingleTapsAfterMovingAway);
+
+ // Click a fifth time later on at the same place: treated as a separate click
+ QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QCOMPARE(tappedSpy.size(), 5);
+ QCOMPARE(tapHandler->tapCount(), 1);
+ QCOMPARE(singleTapSpy.size(), expectedSingleTapsAfterWaiting);
+}
- // Tap a fourth time, drifting farther away
- p1 += QPoint(dragThreshold, dragThreshold);
- QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
- QTRY_VERIFY(button->property("pressed").toBool());
- QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
- QTRY_VERIFY(!button->property("pressed").toBool());
- QCOMPARE(tappedSpy.count(), 4);
+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::touchLongPress()
+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*>("DragThreshold");
+ QQuickTapHandler *tapHandler = button->findChild<QQuickTapHandler*>();
QVERIFY(tapHandler);
+ tapHandler->setExclusiveSignals(exclusiveSignals);
+ tapHandler->setAcceptedButtons(Qt::LeftButton | Qt::RightButton);
QSignalSpy tappedSpy(button, SIGNAL(tapped()));
- QSignalSpy longPressThresholdChangedSpy(tapHandler, SIGNAL(longPressThresholdChanged()));
- QSignalSpy timeHeldSpy(tapHandler, SIGNAL(timeHeldChanged()));
- QSignalSpy longPressedSpy(tapHandler, SIGNAL(longPressed()));
+ QSignalSpy singleTapSpy(tapHandler, &QQuickTapHandler::singleTapped);
+ QSignalSpy doubleTapSpy(tapHandler, &QQuickTapHandler::doubleTapped);
- // Reduce the threshold so that we can get a long press quickly
- tapHandler->setLongPressThreshold(0.5);
- QCOMPARE(longPressThresholdChangedSpy.count(), 1);
+ // 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);
- // 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.count(), 1);
- timeHeldSpy.wait(); // the longer we hold it, the more this will occur
- qDebug() << "held" << tapHandler->timeHeld() << "secs; timeHeld updated" << timeHeldSpy.count() << "times";
- QVERIFY(timeHeldSpy.count() > 0);
- QVERIFY(tapHandler->timeHeld() > 0.4); // Should be > 0.5 but slow CI and timer granularity can interfere
+ // 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);
- // 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.count(), 0);
+ 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");
+ QTest::addColumn<QQuickTapHandler::ExclusiveSignals>("exclusiveSignals");
+ QTest::addColumn<int>("expectedEndingSingleTapCount");
+ QTest::addColumn<int>("expectedDoubleTapCount");
+
+ QTest::newRow("mouse:NotExclusive")
+ << QPointingDevice::DeviceType::Mouse
+ << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::NotExclusive)
+ << 1 << 1;
+ QTest::newRow("mouse:SingleTap")
+ << QPointingDevice::DeviceType::Mouse
+ << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::SingleTap)
+ << 1 << 0;
+ QTest::newRow("mouse:DoubleTap")
+ << QPointingDevice::DeviceType::Mouse
+ << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::DoubleTap)
+ << 0 << 1;
+ QTest::newRow("mouse:SingleTap|DoubleTap")
+ << QPointingDevice::DeviceType::Mouse
+ << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::SingleTap | QQuickTapHandler::DoubleTap)
+ << 0 << 1;
+ QTest::newRow("touch:NotExclusive")
+ << QPointingDevice::DeviceType::TouchScreen
+ << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::NotExclusive)
+ << 1 << 1;
+ QTest::newRow("touch:SingleTap")
+ << QPointingDevice::DeviceType::TouchScreen
+ << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::SingleTap)
+ << 1 << 0;
+ QTest::newRow("touch:DoubleTap")
+ << QPointingDevice::DeviceType::TouchScreen
+ << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::DoubleTap)
+ << 0 << 1;
+ QTest::newRow("touch:SingleTap|DoubleTap")
+ << QPointingDevice::DeviceType::TouchScreen
+ << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::SingleTap | QQuickTapHandler::DoubleTap)
+ << 0 << 1;
}
-void tst_TapHandler::mouseLongPress()
+void tst_TapHandler::singleTapDoubleTap()
{
+ QFETCH(QPointingDevice::DeviceType, deviceType);
+ QFETCH(QQuickTapHandler::ExclusiveSignals, exclusiveSignals);
+ QFETCH(int, expectedEndingSingleTapCount);
+ QFETCH(int, expectedDoubleTapCount);
+
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*>("DragThreshold");
+ QQuickTapHandler *tapHandler = button->findChild<QQuickTapHandler*>();
+ QVERIFY(tapHandler);
+ tapHandler->setExclusiveSignals(exclusiveSignals);
+ QSignalSpy tappedSpy(tapHandler, &QQuickTapHandler::tapped);
+ QSignalSpy singleTapSpy(tapHandler, &QQuickTapHandler::singleTapped);
+ QSignalSpy doubleTapSpy(tapHandler, &QQuickTapHandler::doubleTapped);
+
+ 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, 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);
+ break;
+ default:
+ break;
+ }
+ };
+
+ // tap once
+ const QPoint p1 = button->mapToScene(QPointF(2, 2)).toPoint();
+ tap(p1);
+ QCOMPARE(tappedSpy.size(), 1);
+ QCOMPARE(doubleTapSpy.size(), 0);
+
+ // tap again immediately afterwards
+ tap(p1);
+ QTRY_COMPARE(doubleTapSpy.size(), expectedDoubleTapCount);
+ QCOMPARE(tappedSpy.size(), 2);
+ QCOMPARE(singleTapSpy.size(), expectedEndingSingleTapCount);
+
+ // wait past the double-tap interval, then do it again
+ const auto delay = qApp->styleHints()->mouseDoubleClickInterval() + 10;
+ tappedSpy.clear();
+ singleTapSpy.clear();
+ doubleTapSpy.clear();
+
+ // tap once with delay
+ tap(p1, delay);
+ QCOMPARE(tappedSpy.size(), 1);
+ QCOMPARE(doubleTapSpy.size(), 0);
+
+ // tap again immediately afterwards
+ tap(p1);
+ QTRY_COMPARE(doubleTapSpy.size(), expectedDoubleTapCount);
+ QCOMPARE(tappedSpy.size(), 2);
+ QCOMPARE(singleTapSpy.size(), expectedEndingSingleTapCount);
+}
+
+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");
+
+ 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::longPress()
+{
+ QFETCH(const QPointingDevice *, device);
+ QFETCH(QString, buttonName);
+ QFETCH(qreal, longPressThreshold);
+ QFETCH(QPoint, releaseOffset);
+ QFETCH(bool, expectLongPress);
+ QFETCH(bool, expectTapped);
+
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("buttons.qml")));
+
+ QQuickItem *button = window.rootObject()->findChild<QQuickItem*>(buttonName);
+ QVERIFY(button);
+ 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.count(), 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.count(), 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.count() << "times";
- QVERIFY(timeHeldSpy.count() > 0);
- QVERIFY(tapHandler->timeHeld() > 0.4); // Should be > 0.5 but slow CI and timer granularity can interfere
+ qDebug() << "held" << tapHandler->timeHeld() << "secs; timeHeld updated" << timeHeldSpy.size() << "times";
+ 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.count(), 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()
@@ -631,11 +1027,11 @@ void tst_TapHandler::buttonsMultiTouch()
touchSeq.stationary(2).stationary(3).release(1, p1, window).commit();
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!buttonDragThreshold->property("pressed").toBool());
- QCOMPARE(dragThresholdTappedSpy.count(), 1);
+ QCOMPARE(dragThresholdTappedSpy.size(), 1);
QVERIFY(buttonWithinBounds->property("pressed").toBool());
- QCOMPARE(withinBoundsTappedSpy.count(), 0);
+ QCOMPARE(withinBoundsTappedSpy.size(), 0);
QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
- QCOMPARE(releaseWithinBoundsTappedSpy.count(), 0);
+ QCOMPARE(releaseWithinBoundsTappedSpy.size(), 0);
touchSeq.stationary(2).stationary(3).press(1, p1, window).commit();
QQuickTouchUtils::flush(window);
QTRY_VERIFY(buttonDragThreshold->property("pressed").toBool());
@@ -646,11 +1042,11 @@ void tst_TapHandler::buttonsMultiTouch()
touchSeq.stationary(1).stationary(3).release(2, p2, window).commit();
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!buttonWithinBounds->property("pressed").toBool());
- QCOMPARE(withinBoundsTappedSpy.count(), 1);
+ QCOMPARE(withinBoundsTappedSpy.size(), 1);
QVERIFY(buttonDragThreshold->property("pressed").toBool());
- QCOMPARE(dragThresholdTappedSpy.count(), 1);
+ QCOMPARE(dragThresholdTappedSpy.size(), 1);
QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
- QCOMPARE(releaseWithinBoundsTappedSpy.count(), 0);
+ QCOMPARE(releaseWithinBoundsTappedSpy.size(), 0);
touchSeq.stationary(1).stationary(3).press(2, p2, window).commit();
QQuickTouchUtils::flush(window);
QVERIFY(buttonDragThreshold->property("pressed").toBool());
@@ -660,11 +1056,11 @@ void tst_TapHandler::buttonsMultiTouch()
// can release bottom button and press again: others stay pressed the whole time
touchSeq.stationary(1).stationary(2).release(3, p3, window).commit();
QQuickTouchUtils::flush(window);
- QCOMPARE(releaseWithinBoundsTappedSpy.count(), 1);
+ QCOMPARE(releaseWithinBoundsTappedSpy.size(), 1);
QVERIFY(buttonWithinBounds->property("pressed").toBool());
- QCOMPARE(withinBoundsTappedSpy.count(), 1);
+ QCOMPARE(withinBoundsTappedSpy.size(), 1);
QVERIFY(!buttonReleaseWithinBounds->property("pressed").toBool());
- QCOMPARE(dragThresholdTappedSpy.count(), 1);
+ QCOMPARE(dragThresholdTappedSpy.size(), 1);
touchSeq.stationary(1).stationary(2).press(3, p3, window).commit();
QQuickTouchUtils::flush(window);
QTRY_VERIFY(buttonDragThreshold->property("pressed").toBool());
@@ -685,26 +1081,26 @@ 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()));
// Press
QPoint p1 = button->mapToScene(button->clipRect().center()).toPoint();
QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
- QTRY_COMPARE(userPressedChangedSpy.count(), 1);
- QCOMPARE(innerPressedChangedSpy.count(), 0);
- QCOMPARE(innerGrabChangedSpy.count(), 0);
- QCOMPARE(userGrabChangedSpy.count(), 1);
+ QTRY_COMPARE(userPressedChangedSpy.size(), 1);
+ QCOMPARE(innerPressedChangedSpy.size(), 0);
+ QCOMPARE(innerGrabChangedSpy.size(), 0);
+ QCOMPARE(userGrabChangedSpy.size(), 1);
// Release
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
- QTRY_COMPARE(userPressedChangedSpy.count(), 2);
- QCOMPARE(innerPressedChangedSpy.count(), 0);
- QCOMPARE(tappedSpy.count(), 1); // only because the override handler makes that happen
- QCOMPARE(innerGrabChangedSpy.count(), 0);
- QCOMPARE(userGrabChangedSpy.count(), 2);
+ QTRY_COMPARE(userPressedChangedSpy.size(), 2);
+ QCOMPARE(innerPressedChangedSpy.size(), 0);
+ QCOMPARE(tappedSpy.size(), 1); // only because the override handler makes that happen
+ QCOMPARE(innerGrabChangedSpy.size(), 0);
+ QCOMPARE(userGrabChangedSpy.size(), 2);
}
void tst_TapHandler::rightLongPressIgnoreWheel()
@@ -715,8 +1111,8 @@ void tst_TapHandler::rightLongPressIgnoreWheel()
QQuickTapHandler *tap = window->rootObject()->findChild<QQuickTapHandler*>();
QVERIFY(tap);
- QSignalSpy tappedSpy(tap, SIGNAL(tapped(QEventPoint *)));
- QSignalSpy longPressedSpy(tap, SIGNAL(longPressed()));
+ QSignalSpy tappedSpy(tap, &QQuickTapHandler::tapped);
+ QSignalSpy longPressedSpy(tap, &QQuickTapHandler::longPressed);
QPoint p1(100, 100);
// Mouse wheel with ScrollBegin phase (because as soon as two fingers are touching
@@ -735,20 +1131,20 @@ void tst_TapHandler::rightLongPressIgnoreWheel()
QWheelEvent wheelEvent(p1, p1, QPoint(0, 0), QPoint(0, 0),
Qt::NoButton, Qt::NoModifier, Qt::ScrollEnd, false, Qt::MouseEventNotSynthesized);
QGuiApplication::sendEvent(window, &wheelEvent);
- QTRY_COMPARE(longPressedSpy.count(), 1);
+ QTRY_COMPARE(longPressedSpy.size(), 1);
QCOMPARE(tap->isPressed(), true);
- QCOMPARE(tappedSpy.count(), 0);
+ QCOMPARE(tappedSpy.size(), 0);
// Release
QTest::mouseRelease(window, Qt::RightButton, Qt::NoModifier, p1, 500);
QTRY_COMPARE(tap->isPressed(), false);
- QCOMPARE(tappedSpy.count(), 0);
+ QCOMPARE(tappedSpy.size(), 0);
}
void tst_TapHandler::negativeZStackingOrder() // QTBUG-83114
{
QScopedPointer<QQuickView> windowPtr;
- createView(windowPtr, "tapHandlersOverlapped.qml");
+ createView(windowPtr, "nested.qml");
QQuickView *window = windowPtr.data();
QQuickItem *root = window->rootObject();
@@ -760,8 +1156,8 @@ void tst_TapHandler::negativeZStackingOrder() // QTBUG-83114
QSignalSpy clickSpyChild(childTapHandler, &QQuickTapHandler::tapped);
QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(150, 100));
- QCOMPARE(clickSpyChild.count(), 1);
- QCOMPARE(clickSpyParent.count(), 1);
+ QCOMPARE(clickSpyChild.size(), 1);
+ QCOMPARE(clickSpyParent.size(), 1);
auto order = root->property("taps").toList();
QVERIFY(order.at(0) == "childTapHandler");
QVERIFY(order.at(1) == "parentTapHandler");
@@ -770,13 +1166,129 @@ void tst_TapHandler::negativeZStackingOrder() // QTBUG-83114
childTapHandler->parentItem()->setZ(-1);
root->setProperty("taps", QVariantList());
QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(150, 100));
- QCOMPARE(clickSpyChild.count(), 2);
- QCOMPARE(clickSpyParent.count(), 2);
+ QCOMPARE(clickSpyChild.size(), 2);
+ QCOMPARE(clickSpyParent.size(), 2);
order = root->property("taps").toList();
QVERIFY(order.at(0) == "parentTapHandler");
QVERIFY(order.at(1) == "childTapHandler");
}
+void tst_TapHandler::nonTopLevelParentWindow() // QTBUG-91716
+{
+ QScopedPointer<QQuickWindow> parentWindowPtr(new QQuickWindow);
+ auto parentWindow = parentWindowPtr.get();
+ parentWindow->setGeometry(400, 400, 250, 250);
+
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "simpleTapHandler.qml", parentWindow);
+ auto window = windowPtr.get();
+ window->setGeometry(10, 10, 100, 100);
+
+ QQuickItem *root = window->rootObject();
+
+ auto p1 = QPoint(20, 20);
+ mouseEvent(QEvent::MouseButtonPress, Qt::LeftButton, p1, window, parentWindow);
+ mouseEvent(QEvent::MouseButtonRelease, Qt::LeftButton, p1, window, parentWindow);
+
+ QCOMPARE(root->property("tapCount").toInt(), 1);
+
+ QTest::touchEvent(window, touchDevice).press(0, p1, parentWindow).commit();
+ QTest::touchEvent(window, touchDevice).release(0, p1, parentWindow).commit();
+
+ QCOMPARE(root->property("tapCount").toInt(), 2);
+}
+
+void tst_TapHandler::nestedDoubleTap_data()
+{
+ QTest::addColumn<QQuickTapHandler::GesturePolicy>("childGesturePolicy");
+
+ QTest::newRow("DragThreshold") << QQuickTapHandler::GesturePolicy::DragThreshold;
+ QTest::newRow("WithinBounds") << QQuickTapHandler::GesturePolicy::WithinBounds;
+ QTest::newRow("ReleaseWithinBounds") << QQuickTapHandler::GesturePolicy::ReleaseWithinBounds;
+ QTest::newRow("DragWithinBounds") << QQuickTapHandler::GesturePolicy::DragWithinBounds;
+}
+
+void tst_TapHandler::nestedDoubleTap() // QTBUG-102625
+{
+ QFETCH(QQuickTapHandler::GesturePolicy, childGesturePolicy);
+
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("nested.qml")));
+ QQuickItem *root = window.rootObject();
+ QQuickTapHandler *parentTapHandler = root->findChild<QQuickTapHandler*>("parentTapHandler");
+ QVERIFY(parentTapHandler);
+ QSignalSpy parentSpy(parentTapHandler, &QQuickTapHandler::doubleTapped);
+ QQuickTapHandler *childTapHandler = root->findChild<QQuickTapHandler*>("childTapHandler");
+ QVERIFY(childTapHandler);
+ QSignalSpy childSpy(childTapHandler, &QQuickTapHandler::doubleTapped);
+ childTapHandler->setGesturePolicy(childGesturePolicy);
+
+ QTest::mouseDClick(&window, Qt::LeftButton, Qt::NoModifier, QPoint(150, 100));
+
+ QCOMPARE(childSpy.size(), 1);
+ // If the child gets by with a passive grab, both handlers see tap and double-tap.
+ // If the child takes an exclusive grab and stops event propagation, the parent doesn't see them.
+ QCOMPARE(parentSpy.size(),
+ childGesturePolicy == QQuickTapHandler::GesturePolicy::DragThreshold ? 1 : 0);
+ QCOMPARE(root->property("taps").toList().size(),
+ 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"
diff --git a/tests/auto/quick/pointerhandlers/qquickwheelhandler/CMakeLists.txt b/tests/auto/quick/pointerhandlers/qquickwheelhandler/CMakeLists.txt
index 588fd8f2e2..d50181dfe4 100644
--- a/tests/auto/quick/pointerhandlers/qquickwheelhandler/CMakeLists.txt
+++ b/tests/auto/quick/pointerhandlers/qquickwheelhandler/CMakeLists.txt
@@ -1,9 +1,18 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# Generated from qquickwheelhandler.pro.
#####################################################################
## tst_qquickwheelhandler Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickwheelhandler 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_qquickwheelhandler
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_qquickwheelhandler.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}
)
@@ -38,10 +40,10 @@ qt_internal_add_test(tst_qquickwheelhandler
qt_internal_extend_target(tst_qquickwheelhandler CONDITION ANDROID OR IOS
DEFINES
- QT_QMLTEST_DATADIR=\\\":/data\\\"
+ QT_QMLTEST_DATADIR=":/data"
)
qt_internal_extend_target(tst_qquickwheelhandler 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/pointerhandlers/qquickwheelhandler/data/nested.qml b/tests/auto/quick/pointerhandlers/qquickwheelhandler/data/nested.qml
index 49e44f2b1f..9c43df46da 100644
--- a/tests/auto/quick/pointerhandlers/qquickwheelhandler/data/nested.qml
+++ b/tests/auto/quick/pointerhandlers/qquickwheelhandler/data/nested.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.14
diff --git a/tests/auto/quick/pointerhandlers/qquickwheelhandler/data/rectWheel.qml b/tests/auto/quick/pointerhandlers/qquickwheelhandler/data/rectWheel.qml
index d4875d5313..ca6053ebcf 100644
--- a/tests/auto/quick/pointerhandlers/qquickwheelhandler/data/rectWheel.qml
+++ b/tests/auto/quick/pointerhandlers/qquickwheelhandler/data/rectWheel.qml
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.14
@@ -39,7 +14,23 @@ Rectangle {
}
}
+ Rectangle {
+ color: "red"
+ width: 6; height: 6; radius: 3
+ x: wheelHandler.point.position.x - radius
+ y: wheelHandler.point.position.y - radius
+ }
+
+ Text {
+ anchors.centerIn: parent
+ anchors.verticalCenterOffset: 20
+ color: "white"
+ font.pixelSize: 18
+ text: parent.x.toFixed(2) + ", " + parent.y.toFixed(2)
+ }
+
WheelHandler {
+ id: wheelHandler
activeTimeout: 0.5
}
}
diff --git a/tests/auto/quick/pointerhandlers/qquickwheelhandler/tst_qquickwheelhandler.cpp b/tests/auto/quick/pointerhandlers/qquickwheelhandler/tst_qquickwheelhandler.cpp
index 2abf2ea8c3..c88b1af2ea 100644
--- a/tests/auto/quick/pointerhandlers/qquickwheelhandler/tst_qquickwheelhandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickwheelhandler/tst_qquickwheelhandler.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
@@ -34,8 +9,8 @@
#include <QtQuick/private/qquickrectangle_p.h>
#include <QtQuick/qquickview.h>
#include <QtQml/qqmlcontext.h>
-#include "../../../shared/util.h"
-#include "../../shared/viewtestutil.h"
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtQuickTestUtils/private/viewtestutils_p.h>
Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
@@ -43,13 +18,15 @@ class tst_QQuickWheelHandler: public QQmlDataTest
{
Q_OBJECT
public:
- tst_QQuickWheelHandler() { }
+ tst_QQuickWheelHandler() : QQmlDataTest(QT_QMLTEST_DATADIR) { }
private slots:
void singleHandler_data();
void singleHandler();
void nestedHandler_data();
void nestedHandler();
+ void blocking_data();
+ void blocking();
private:
void sendWheelEvent(QQuickView &window, QPoint pos, QPoint angleDelta,
@@ -188,13 +165,13 @@ void tst_QQuickWheelHandler::singleHandler()
sendWheelEvent(window, eventPos, eventAngleDelta, eventPixelDelta, eventModifiers, Qt::NoScrollPhase, eventInverted);
}
QCOMPARE(rect->position().toPoint(), expectedPosition);
- QCOMPARE(activeChangedSpy.count(), 1);
+ QCOMPARE(activeChangedSpy.size(), 1);
QCOMPARE(handler->active(), true);
QCOMPARE(rect->scale(), expectedScale);
QCOMPARE(rect->rotation(), expectedRotation);
if (!eventPhases) {
QTRY_COMPARE(handler->active(), false);
- QCOMPARE(activeChangedSpy.count(), 2);
+ QCOMPARE(activeChangedSpy.size(), 2);
}
// restore by rotating backwards
@@ -204,7 +181,7 @@ void tst_QQuickWheelHandler::singleHandler()
} else {
sendWheelEvent(window, eventPos, eventAngleDelta * -1, eventPixelDelta * -1, eventModifiers, Qt::NoScrollPhase, eventInverted);
}
- QCOMPARE(activeChangedSpy.count(), eventPhases ? 2 : 3);
+ QCOMPARE(activeChangedSpy.size(), eventPhases ? 2 : 3);
QCOMPARE(handler->active(), !eventPhases);
QCOMPARE(rect->position().toPoint(), QPoint(0, 0));
QCOMPARE(rect->scale(), 1);
@@ -329,16 +306,61 @@ void tst_QQuickWheelHandler::nestedHandler()
QCOMPARE(innerRect->scale(), innerScale);
QCOMPARE(innerRect->rotation(), innerRotation);
QCOMPARE(outerRect->position().toPoint(), outerPosition);
- QCOMPARE(outerActiveChangedSpy.count(), 1);
+ QCOMPARE(outerActiveChangedSpy.size(), 1);
QCOMPARE(outerHandler->active(), true);
QCOMPARE(outerRect->scale(), outerScale);
QCOMPARE(outerRect->rotation(), outerRotation);
if (!eventPhases) {
QTRY_COMPARE(outerHandler->active(), false);
- QCOMPARE(outerActiveChangedSpy.count(), 2);
+ QCOMPARE(outerActiveChangedSpy.size(), 2);
}
}
+void tst_QQuickWheelHandler::blocking_data()
+{
+ // handler properties
+ QTest::addColumn<bool>("blocking");
+
+ // move the item
+ QTest::newRow("default: blocking") << true;
+ QTest::newRow("nonblocking") << false;
+}
+
+void tst_QQuickWheelHandler::blocking()
+{
+ QFETCH(bool, blocking);
+
+ QQuickView window;
+ QByteArray errorMessage;
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("nested.qml"), true, &errorMessage), errorMessage.constData());
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ QQuickItem *outerRect = window.rootObject();
+ QVERIFY(outerRect != nullptr);
+ QQuickWheelHandler *outerHandler = outerRect->findChild<QQuickWheelHandler*>("outerWheelHandler");
+ QVERIFY(outerHandler != nullptr);
+ QQuickWheelHandler *innerHandler = outerRect->findChild<QQuickWheelHandler*>("innerWheelHandler");
+ QVERIFY(innerHandler != nullptr);
+ QQuickItem *innerRect = innerHandler->parentItem();
+ QVERIFY(innerRect != nullptr);
+ QPoint eventPos = innerRect->mapToScene(innerRect->boundingRect().center()).toPoint();
+
+ QCOMPARE(innerHandler->isBlocking(), true); // default property value
+ innerHandler->setBlocking(blocking);
+ QSignalSpy innerActiveChangedSpy(innerHandler, SIGNAL(activeChanged()));
+ QSignalSpy outerActiveChangedSpy(outerHandler, SIGNAL(activeChanged()));
+
+ qreal innerPosWas = innerRect->position().x();
+ qreal outerPosWas = outerRect->position().x();
+
+ sendWheelEvent(window, eventPos, {0, 120}, {0, 0}, Qt::NoModifier, Qt::NoScrollPhase, false);
+ QTRY_COMPARE(innerActiveChangedSpy.size(), 2);
+ QCOMPARE(innerRect->position().x(), innerPosWas + 15);
+ QCOMPARE(outerActiveChangedSpy.size(), blocking ? 0 : 2);
+ QCOMPARE(outerRect->position().x(), outerPosWas + (blocking ? 0 : 15));
+}
+
QTEST_MAIN(tst_QQuickWheelHandler)
#include "tst_qquickwheelhandler.moc"