diff options
author | Jan Arve Sæther <jan-arve.saether@qt.io> | 2021-08-17 10:01:18 +0200 |
---|---|---|
committer | Jan Arve Sæther <jan-arve.saether@qt.io> | 2021-08-26 07:03:17 +0200 |
commit | 3c896d3a3c158f7d01340229d6d98b8e077b9f46 (patch) | |
tree | 9c77b90e24b7656caae401df5d65e5241a5c574f /tests/auto/quick/qquicklistview/tst_qquicklistview.cpp | |
parent | 5a6d15d2ad7c8c9edd2b194d1ed78e45872c6d18 (diff) |
Fix regression in ListView/Flickable event delivery
The regression was introduced with 2acb31641fc9c34d24ac29232cdfec
The problem was that when we entered
QQuickListViewPrivate::wantsPointerEvent(), the event was not localized
to the QQuickFlickable when mouse filtering was done.
Therefore, since the code assumed that the localPos was local to the
Flickable, it always ended up assuming that the point was within the
bounds of the header/footer.
Fixes: QTBUG-89409
Change-Id: Ib595e61b7995241b58e3051da09139e1e1f13cba
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
(cherry picked from commit b2e4f09bfa2c42af562f6741c0a0246a53028f0a)
Diffstat (limited to 'tests/auto/quick/qquicklistview/tst_qquicklistview.cpp')
-rw-r--r-- | tests/auto/quick/qquicklistview/tst_qquicklistview.cpp | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index a7aefbe432..d3deb513d0 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -299,6 +299,8 @@ private slots: void requiredObjectListModel(); void clickHeaderAndFooterWhenClip(); void animatedDelegate(); + void dragDelegateWithMouseArea(); + void dragDelegateWithMouseArea_data(); private: template <class T> void items(const QUrl &source); @@ -10109,6 +10111,95 @@ void tst_QQuickListView::animatedDelegate() } } +static void dragListView(QWindow *window, QPoint *startPos, const QPoint &delta) +{ + auto drag_helper = [&](QWindow *window, QPoint *startPos, const QPoint &d) { + QPoint pos = *startPos; + const int dragDistance = d.manhattanLength(); + const QPoint unitVector(qBound(-1, d.x(), 1), qBound(-1, d.y(), 1)); + for (int i = 0; i < dragDistance; ++i) { + QTest::mouseMove(window, pos); + pos += unitVector; + } + // Move to the final position + pos = *startPos + d; + QTest::mouseMove(window, pos); + *startPos = pos; + }; + + if (delta.manhattanLength() == 0) + return; + const int dragThreshold = QGuiApplication::styleHints()->startDragDistance(); + const QPoint unitVector(qBound(-1, delta.x(), 1), qBound(-1, delta.y(), 1)); + // go just beyond the drag theshold + drag_helper(window, startPos, unitVector * (dragThreshold + 1)); + drag_helper(window, startPos, unitVector); + + // next drag will actually scroll the listview + drag_helper(window, startPos, delta); +} + +void tst_QQuickListView::dragDelegateWithMouseArea() +{ + QFETCH(QQuickItemView::LayoutDirection, layoutDirection); + + QScopedPointer<QQuickView> window(createView()); + QVERIFY(window); + window->setSource(testFileUrl("delegateWithMouseArea2.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + + QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list"); + QVERIFY(listview != nullptr); + + const bool horizontal = layoutDirection < QQuickItemView::VerticalTopToBottom; + listview->setOrientation(horizontal ? QQuickListView::Horizontal : QQuickListView::Vertical); + + if (horizontal) + listview->setLayoutDirection(static_cast<Qt::LayoutDirection>(layoutDirection)); + else + listview->setVerticalLayoutDirection(static_cast<QQuickItemView::VerticalLayoutDirection>(layoutDirection)); + + QVERIFY(QQuickTest::qWaitForItemPolished(listview)); + + auto contentPosition = [&](QQuickListView *listview) { + return (listview->orientation() == QQuickListView::Horizontal ? listview->contentX(): listview->contentY()); + }; + + qreal expectedContentPosition = contentPosition(listview); + QPoint startPos = (QPointF(listview->width(), listview->height())/2).toPoint(); + QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, startPos, 200); + + QPoint dragDelta(0, -10); + + if (layoutDirection == QQuickItemView::RightToLeft || layoutDirection == QQuickItemView::VerticalBottomToTop) + dragDelta = -dragDelta; + expectedContentPosition -= dragDelta.y(); + if (horizontal) + dragDelta = dragDelta.transposed(); + + dragListView(window.data(), &startPos, dragDelta); + + QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, startPos, 200); // Wait 200 ms before we release to avoid trigger a flick + + // wait for the "fixup" animation to finish + QVERIFY(QTest::qWaitFor([&]() + { return !listview->isMoving();} + )); + + QCOMPARE(contentPosition(listview), expectedContentPosition); +} + +void tst_QQuickListView::dragDelegateWithMouseArea_data() +{ + QTest::addColumn<QQuickItemView::LayoutDirection>("layoutDirection"); + + for (int layDir = QQuickItemView::LeftToRight; layDir <= (int)QQuickItemView::VerticalBottomToTop; layDir++) { + const char *enumValueName = QMetaEnum::fromType<QQuickItemView::LayoutDirection>().valueToKey(layDir); + QTest::newRow(enumValueName) << static_cast<QQuickItemView::LayoutDirection>(layDir); + } +} + QTEST_MAIN(tst_QQuickListView) #include "tst_qquicklistview.moc" |