diff options
author | Jan Arve Sæther <jan-arve.saether@qt.io> | 2018-02-20 14:42:49 +0100 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2018-02-21 20:13:00 +0000 |
commit | e4bea7805a229d3625f110f844d908e2abe790b5 (patch) | |
tree | d6952df5ff40dfe8a4f7a675acaa86c903cf9b24 /tests | |
parent | 01cdc1798977ba6e53c2439fa45c14889685290a (diff) |
Fix draghandler to respect axis constraints
..while its (ancestor) coordinate system has changed during the drag.
For example, ensure that a DragHandler-based Slider keeps its knob centered.
If the Slider is used on a Flickable which you are flicking with a second
finger, then the coordinate system is changing underneath the Slider.
The problem was that DragHandler stored the initial drag position of the
target when the target item was pressed, and used that throughout the
whole drag operation. Unfortunately if the target item was inside a
Flickable that got flicked during a drag operation, that initial position
was not updated (and thus, incorrect).
Instead of storing the initial target position in scene coordinates, we
now store the position that got pressed in local target coordinates, and
ensure that in any further updates the touchpoint have the same local
position (by moving the target).
Task-number: QTBUG-64852
Change-Id: I25012d34d88f45c7eb9c711db0037d530cf10854
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp index c0b34f8246..f3513881cd 100644 --- a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp +++ b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp @@ -75,6 +75,7 @@ private slots: void touchDragFlickableBehindItemWithHandlers(); void mouseDragFlickableBehindItemWithHandlers_data(); void mouseDragFlickableBehindItemWithHandlers(); + void touchDragSliderAndFlickable(); private: void createView(QScopedPointer<QQuickView> &window, const char *fileName); @@ -560,6 +561,91 @@ void tst_FlickableInterop::mouseDragFlickableBehindItemWithHandlers() QCOMPARE(originP1, rect->mapToScene(rect->clipRect().center()).toPoint()); } +void tst_FlickableInterop::touchDragSliderAndFlickable() +{ + const int dragThreshold = QGuiApplication::styleHints()->startDragDistance(); + QScopedPointer<QQuickView> windowPtr; + createView(windowPtr, "flickableWithHandlers.qml"); + QQuickView * window = windowPtr.data(); + + QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("Slider"); + QVERIFY(slider); + QQuickDragHandler *drag = slider->findChild<QQuickDragHandler*>(); + QVERIFY(drag); + QQuickItem *knob = slider->findChild<QQuickItem*>("Slider Knob"); + QVERIFY(knob); + QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>(); + QVERIFY(flickable); + + // The knob is initially centered over the slider's "groove" + qreal initialXOffset = qAbs(knob->mapToScene(knob->clipRect().center()).x() - slider->mapToScene + (slider->clipRect().center()).x()); + QVERIFY(initialXOffset <= 1); + + // Drag the slider in the allowed (vertical) direction with one finger + QPoint p1 = knob->mapToScene(knob->clipRect().center()).toPoint(); + QTest::touchEvent(window, touchDevice).press(1, p1, window); + QQuickTouchUtils::flush(window); + p1 += QPoint(0, dragThreshold); + QTest::touchEvent(window, touchDevice).move(1, p1, window); + QQuickTouchUtils::flush(window); + p1 += QPoint(0, dragThreshold); + QTest::touchEvent(window, touchDevice).move(1, p1, window); + QQuickTouchUtils::flush(window); + p1 += QPoint(0, dragThreshold); + QTest::touchEvent(window, touchDevice).move(1, p1, window); + QQuickTouchUtils::flush(window); + QTRY_VERIFY(slider->property("value").toInt() < 49); + QVERIFY(!flickable->isMoving()); + + // Drag the Flickable with a second finger + QPoint p2(300,300); + QTest::touchEvent(window, touchDevice).stationary(1).press(2, p2, window); + QQuickTouchUtils::flush(window); + p1 += QPoint(-10, -10); + p2 += QPoint(dragThreshold, 0); + QTest::touchEvent(window, touchDevice).move(1, p1, window).stationary(2); + QQuickTouchUtils::flush(window); + p1 += QPoint(-10, -10); + p2 += QPoint(dragThreshold, 0); + QTest::touchEvent(window, touchDevice).stationary(1).move(2, p2, window); + QQuickTouchUtils::flush(window); + p1 += QPoint(-10, -10); + p2 += QPoint(dragThreshold, 0); + QTest::touchEvent(window, touchDevice).move(1, p1, window).stationary(2); + QQuickTouchUtils::flush(window); + p1 += QPoint(-10, -10); + p2 += QPoint(dragThreshold, 0); + QTest::touchEvent(window, touchDevice).stationary(1).move(2, p2, window); + QQuickTouchUtils::flush(window); + p1 += QPoint(-10, -10); + p2 += QPoint(dragThreshold, 0); + QTest::touchEvent(window, touchDevice).move(1, p1, window).stationary(2); + QQuickTouchUtils::flush(window); + p1 += QPoint(-10, -10); + p2 += QPoint(dragThreshold, 0); + QTest::touchEvent(window, touchDevice).stationary(1).move(2, p2, window); + QQuickTouchUtils::flush(window); + p1 += QPoint(-10, -10); + p2 += QPoint(dragThreshold, 0); + QTest::touchEvent(window, touchDevice).move(1, p1, window).stationary(2); + QQuickTouchUtils::flush(window); + p1 += QPoint(-10, -10); + p2 += QPoint(dragThreshold, 0); + QTest::touchEvent(window, touchDevice).stationary(1).move(2, p2, window); + QQuickTouchUtils::flush(window); + QTRY_VERIFY(flickable->isMoving()); + qreal knobSliderXOffset = qAbs(knob->mapToScene(knob->clipRect().center()).toPoint().x() - + slider->mapToScene(slider->clipRect().center()).toPoint().x()) - initialXOffset; + if (knobSliderXOffset > 1) + qDebug() << "knob has slipped out of groove by" << knobSliderXOffset << "pixels"; + // See if the knob is still centered over the slider's "groove" + QVERIFY(qAbs(knobSliderXOffset) <= 1); + + // Release + QTest::touchEvent(window, touchDevice).release(1, p1, window).release(2, p2, window); +} + QTEST_MAIN(tst_FlickableInterop) #include "tst_flickableinterop.moc" |