diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2018-07-03 17:31:12 +0200 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2018-07-12 20:22:39 +0000 |
commit | 090cfda4ed0be536f023e38713296565ea9c7623 (patch) | |
tree | cdd31aee525202e58fa5fadf0a1e185a50b9df3e /tests/auto/quick/pointerhandlers | |
parent | 424cfef3cc3c140df51905713fa3849562bc494d (diff) |
tst_FlickableInterop: test both usages of DragHandler in a Slider
When there's a DragHandler on one Item and a TapHandler on another,
we have more trouble with Flickable stealing the grab. We need a
test to ensure that this problem doesn't reappear after fixing.
Task-number: QTBUG-64846
Change-Id: Ia3bc3b7c9654f09aa96ad70968d82b566686e030
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
Diffstat (limited to 'tests/auto/quick/pointerhandlers')
-rw-r--r-- | tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml | 123 | ||||
-rw-r--r-- | tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml (renamed from tests/auto/quick/pointerhandlers/flickableinterop/data/Slider.qml) | 16 | ||||
-rw-r--r-- | tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml | 13 | ||||
-rw-r--r-- | tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp | 75 |
4 files changed, 195 insertions, 32 deletions
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml new file mode 100644 index 0000000000..485c6ce914 --- /dev/null +++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick 2.8 +import Qt.labs.handlers 1.0 + +Item { + id: root + property int value: 50 + property int maximumValue: 99 + property alias label: label.text + property alias tapEnabled: tap.enabled + property alias pressed: tap.pressed + signal tapped + + DragHandler { + id: dragHandler + objectName: root.objectName + " DragHandler" + target: knob + xAxis.enabled: false + yAxis.minimum: slot.y + yAxis.maximum: slot.height + slot.y - knob.height + } + + Rectangle { + id: slot + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.margins: 10 + anchors.topMargin: 30 + anchors.bottomMargin: 30 + anchors.horizontalCenter: parent.horizontalCenter + width: 10 + color: "black" + radius: width / 2 + smooth: true + } + + Rectangle { + id: glow + anchors.fill: knob + anchors.margins: -5 + anchors.leftMargin: -2 + anchors.horizontalCenterOffset: 1 + radius: 5 + color: "#4400FFFF" + opacity: tap.pressed || tapFlash.running ? 1 : 0 + FlashAnimation on visible { + id: tapFlash + } + } + Rectangle { + id: knob + objectName: "Slider Knob" + width: parent.width - 2 + height: 20 + radius: 5 + color: "darkgray" + border.color: "black" + property bool programmatic: false + property real multiplier: root.maximumValue / (dragHandler.yAxis.maximum - dragHandler.yAxis.minimum) + onYChanged: if (!programmatic) root.value = root.maximumValue - (knob.y - dragHandler.yAxis.minimum) * multiplier + transformOrigin: Item.Center + function setValue(value) { knob.y = dragHandler.yAxis.maximum - value / knob.multiplier } + TapHandler { + id: tap + objectName: root.objectName + " TapHandler" + gesturePolicy: TapHandler.DragThreshold + onTapped: { + tapFlash.start() + root.tapped + } + } + } + + Text { + color: "red" + anchors.top: slot.bottom + anchors.horizontalCenter: parent.horizontalCenter + text: root.value + } + + Text { + id: label + font.pointSize: 9 + color: "red" + anchors.bottom: slot.top + anchors.bottomMargin: 5 + anchors.horizontalCenter: parent.horizontalCenter + verticalAlignment: Text.AlignBottom + } + + Component.onCompleted: { + knob.programmatic = true + knob.setValue(root.value) + knob.programmatic = false + } +} diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/Slider.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml index f6acd53615..7f6535651c 100644 --- a/tests/auto/quick/pointerhandlers/flickableinterop/data/Slider.qml +++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** 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. @@ -80,14 +80,14 @@ Item { function setValue(value) { knob.y = dragHandler.yAxis.maximum - value / knob.multiplier } DragHandler { id: dragHandler - objectName: label.text + " DragHandler" + objectName: root.objectName + " DragHandler" xAxis.enabled: false yAxis.minimum: slot.y yAxis.maximum: slot.height + slot.y - knob.height } TapHandler { id: tap - objectName: label.text + " TapHandler" + objectName: root.objectName + " TapHandler" gesturePolicy: TapHandler.DragThreshold onTapped: { tapFlash.start() @@ -97,20 +97,20 @@ Item { } Text { - font.pointSize: 16 color: "red" - anchors.bottom: parent.bottom + anchors.top: slot.bottom anchors.horizontalCenter: parent.horizontalCenter text: root.value } Text { id: label - font.pointSize: 12 + font.pointSize: 9 color: "red" - anchors.top: parent.top - anchors.topMargin: 5 + anchors.bottom: slot.top + anchors.bottomMargin: 5 anchors.horizontalCenter: parent.horizontalCenter + verticalAlignment: Text.AlignBottom } Component.onCompleted: { diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml index 3bdc564a47..8adec58621 100644 --- a/tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml +++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml @@ -46,10 +46,15 @@ Rectangle { Row { spacing: 6 - Slider { - label: "DH Slider" - objectName: "Slider" - value: 49; width: 100; height: 400 + KnobDragSlider { + label: "Slider with\nDH on knob" + objectName: "knobSlider" + value: 49; width: 120; height: 400 + } + GrooveDragSlider { + label: "Slider with\nDH on root" + objectName: "grooveSlider" + value: 49; width: 120; height: 400 } Column { spacing: 6 diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp index 73d9b0b464..6aa2eaa3cb 100644 --- a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp +++ b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp @@ -69,6 +69,7 @@ private slots: void mouseDragFlickableBehindButton(); void touchDragSlider(); void touchDragFlickableBehindSlider(); + void mouseDragSlider_data(); void mouseDragSlider(); void mouseDragFlickableBehindSlider(); void touchDragFlickableBehindItemWithHandlers_data(); @@ -293,7 +294,7 @@ void tst_FlickableInterop::touchDragSlider() createView(windowPtr, "flickableWithHandlers.qml"); QQuickView * window = windowPtr.data(); - QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("Slider"); + QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("knobSlider"); QVERIFY(slider); QQuickDragHandler *drag = slider->findChild<QQuickDragHandler*>(); QVERIFY(drag); @@ -339,6 +340,26 @@ void tst_FlickableInterop::touchDragSlider() QCOMPARE(translationChangedSpy.count(), 1); } +void tst_FlickableInterop::mouseDragSlider_data() +{ + QTest::addColumn<QString>("nameOfSliderToDrag"); + QTest::addColumn<QPoint>("pressPositionRelativeToKnob"); + QTest::addColumn<QPoint>("dragDirection"); // a unit vector + QTest::addColumn<bool>("expectedTapHandlerPressed"); + QTest::addColumn<bool>("expectedDragHandlerActive"); + QTest::addColumn<bool>("expectedFlickableMoving"); + + QTest::newRow("drag down on knob of knobSlider") << "knobSlider" << QPoint(0, 0) << QPoint(0, 1) << true << true << false; + QTest::newRow("drag sideways on knob of knobSlider") << "knobSlider" << QPoint(0, 0) << QPoint(1, 0) << true << false << true; + QTest::newRow("drag down on groove of knobSlider") << "knobSlider" << QPoint(0, 20) << QPoint(0, 1) << false << false << true; + QTest::newRow("drag sideways on groove of knobSlider") << "knobSlider" << QPoint(0, 20) << QPoint(1, 0) << false << false << true; + + QTest::newRow("drag down on knob of grooveSlider") << "grooveSlider" << QPoint(0, 0) << QPoint(0, 1) << true << true << false; + QTest::newRow("drag sideways on knob of grooveSlider") << "grooveSlider" << QPoint(0, 0) << QPoint(1, 0) << true << false << true; + QTest::newRow("drag down on groove of grooveSlider") << "grooveSlider" << QPoint(0, 20) << QPoint(0, 1) << false << true << false; + QTest::newRow("drag sideways on groove of grooveSlider") << "grooveSlider" << QPoint(0, 20) << QPoint(1, 0) << false << false << true; +} + void tst_FlickableInterop::mouseDragSlider() { const int dragThreshold = QGuiApplication::styleHints()->startDragDistance(); @@ -346,7 +367,14 @@ void tst_FlickableInterop::mouseDragSlider() createView(windowPtr, "flickableWithHandlers.qml"); QQuickView * window = windowPtr.data(); - QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("Slider"); + QFETCH(QString, nameOfSliderToDrag); + QFETCH(QPoint, pressPositionRelativeToKnob); + QFETCH(QPoint, dragDirection); // a unit vector + QFETCH(bool, expectedTapHandlerPressed); + QFETCH(bool, expectedDragHandlerActive); + QFETCH(bool, expectedFlickableMoving); + + QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>(nameOfSliderToDrag); QVERIFY(slider); QQuickDragHandler *drag = slider->findChild<QQuickDragHandler*>(); QVERIFY(drag); @@ -357,33 +385,40 @@ void tst_FlickableInterop::mouseDragSlider() QSignalSpy tappedSpy(knob->parent(), SIGNAL(tapped())); QSignalSpy translationChangedSpy(drag, SIGNAL(translationChanged())); - // Drag the slider in the allowed (vertical) direction + // Drag the slider tappedSpy.clear(); - QPoint p1 = knob->mapToScene(knob->clipRect().center()).toPoint(); + QPoint p1 = knob->mapToScene(knob->clipRect().center()).toPoint() + pressPositionRelativeToKnob; QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1); - QTRY_VERIFY(slider->property("pressed").toBool()); - p1 += QPoint(0, dragThreshold); + QTRY_COMPARE(slider->property("pressed").toBool(), expectedTapHandlerPressed); + p1 += QPoint(dragThreshold * dragDirection.x(), dragThreshold * dragDirection.y()); QTest::mouseMove(window, p1); - QVERIFY(slider->property("pressed").toBool()); + QCOMPARE(drag->active(), false); + QCOMPARE(slider->property("pressed").toBool(), expectedTapHandlerPressed); QCOMPARE(slider->property("value").toInt(), 49); - p1 += QPoint(0, 1); + p1 += dragDirection; // one more pixel QTest::mouseMove(window, p1); - p1 += QPoint(0, 10); + QCOMPARE(drag->active(), expectedDragHandlerActive); + // drag farther, to make sure the knob gets adjusted significantly + p1 += QPoint(10 * dragDirection.x(), 10 * dragDirection.y()); QTest::mouseMove(window, p1); - QVERIFY(slider->property("value").toInt() < 49); - QVERIFY(!flickable->isMoving()); - QVERIFY(!slider->property("pressed").toBool()); + if (expectedDragHandlerActive && dragDirection.y() > 0) + QVERIFY(slider->property("value").toInt() < 49); + // by now, Flickable will have stolen the grab, if it decided that it wanted to during filtering of the last event + QCOMPARE(flickable->isMoving(), expectedFlickableMoving); + QCOMPARE(slider->property("pressed").toBool(), false); - // Now that the DragHandler is active, the Flickable will not steal the grab + // If 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::mouseMove(window, p1); - QVERIFY(!flickable->isMoving()); + if (expectedDragHandlerActive) { + p1 += QPoint(dragThreshold * 2, 0); + QTest::mouseMove(window, p1); + QCOMPARE(flickable->isMoving(), false); + } // Release, and do not expect the tapped signal QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1); QCOMPARE(tappedSpy.count(), 0); - QCOMPARE(translationChangedSpy.count(), 1); + QCOMPARE(translationChangedSpy.count(), expectedDragHandlerActive ? 1 : 0); } void tst_FlickableInterop::touchDragFlickableBehindSlider() @@ -393,7 +428,7 @@ void tst_FlickableInterop::touchDragFlickableBehindSlider() createView(windowPtr, "flickableWithHandlers.qml"); QQuickView * window = windowPtr.data(); - QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("Slider"); + QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("knobSlider"); QVERIFY(slider); QQuickDragHandler *drag = slider->findChild<QQuickDragHandler*>(); QVERIFY(drag); @@ -439,7 +474,7 @@ void tst_FlickableInterop::mouseDragFlickableBehindSlider() createView(windowPtr, "flickableWithHandlers.qml"); QQuickView * window = windowPtr.data(); - QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("Slider"); + QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("knobSlider"); QVERIFY(slider); QQuickDragHandler *drag = slider->findChild<QQuickDragHandler*>(); QVERIFY(drag); @@ -568,7 +603,7 @@ void tst_FlickableInterop::touchDragSliderAndFlickable() createView(windowPtr, "flickableWithHandlers.qml"); QQuickView * window = windowPtr.data(); - QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("Slider"); + QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("knobSlider"); QVERIFY(slider); QQuickDragHandler *drag = slider->findChild<QQuickDragHandler*>(); QVERIFY(drag); |