diff options
-rw-r--r-- | src/quicktemplates2/qquickscrollbar.cpp | 52 | ||||
-rw-r--r-- | src/quicktemplates2/qquickscrollbar_p.h | 2 | ||||
-rw-r--r-- | src/quicktemplates2/qquickscrollbar_p_p.h | 1 | ||||
-rw-r--r-- | tests/auto/controls/data/tst_scrollbar.qml | 201 |
4 files changed, 256 insertions, 0 deletions
diff --git a/src/quicktemplates2/qquickscrollbar.cpp b/src/quicktemplates2/qquickscrollbar.cpp index cb5c0001..844bba3a 100644 --- a/src/quicktemplates2/qquickscrollbar.cpp +++ b/src/quicktemplates2/qquickscrollbar.cpp @@ -165,6 +165,7 @@ QQuickScrollBarPrivate::QQuickScrollBarPrivate() moving(false), interactive(true), explicitInteractive(false), + touchId(-1), orientation(Qt::Vertical), snapMode(QQuickScrollBar::NoSnap), policy(QQuickScrollBar::AsNeeded) @@ -268,6 +269,7 @@ void QQuickScrollBarPrivate::handleRelease(const QPointF &point) pos = snapPosition(pos); q->setPosition(pos); offset = 0.0; + touchId = -1; q->setPressed(false); } @@ -275,6 +277,7 @@ void QQuickScrollBarPrivate::handleUngrab() { Q_Q(QQuickScrollBar); offset = 0.0; + touchId = -1; q->setPressed(false); } @@ -616,6 +619,55 @@ void QQuickScrollBar::mouseUngrabEvent() d->handleUngrab(); } +void QQuickScrollBar::touchEvent(QTouchEvent *event) +{ + Q_D(QQuickScrollBar); + switch (event->type()) { + case QEvent::TouchBegin: + if (d->touchId == -1) { + const QTouchEvent::TouchPoint point = event->touchPoints().first(); + d->touchId = point.id(); + d->handlePress(point.pos()); + } else { + event->ignore(); + } + break; + + case QEvent::TouchUpdate: + for (const QTouchEvent::TouchPoint &point : event->touchPoints()) { + if (point.id() != d->touchId) + continue; + + d->handleMove(point.pos()); + } + break; + + case QEvent::TouchEnd: + for (const QTouchEvent::TouchPoint &point : event->touchPoints()) { + if (point.id() != d->touchId) + continue; + + d->handleRelease(point.pos()); + } + break; + + case QEvent::TouchCancel: + d->handleUngrab(); + break; + + default: + QQuickControl::touchEvent(event); + break; + } +} + +void QQuickScrollBar::touchUngrabEvent() +{ + Q_D(QQuickScrollBar); + QQuickControl::touchUngrabEvent(); + d->handleUngrab(); +} + #if QT_CONFIG(quicktemplates2_hover) void QQuickScrollBar::hoverChange() { diff --git a/src/quicktemplates2/qquickscrollbar_p.h b/src/quicktemplates2/qquickscrollbar_p.h index 1b18c4ad..7bf8a9d3 100644 --- a/src/quicktemplates2/qquickscrollbar_p.h +++ b/src/quicktemplates2/qquickscrollbar_p.h @@ -134,6 +134,8 @@ protected: void mouseMoveEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void mouseUngrabEvent() override; + void touchEvent(QTouchEvent *event) override; + void touchUngrabEvent() override; #if QT_CONFIG(quicktemplates2_hover) void hoverChange() override; diff --git a/src/quicktemplates2/qquickscrollbar_p_p.h b/src/quicktemplates2/qquickscrollbar_p_p.h index cbbef2c8..409b952b 100644 --- a/src/quicktemplates2/qquickscrollbar_p_p.h +++ b/src/quicktemplates2/qquickscrollbar_p_p.h @@ -88,6 +88,7 @@ public: bool moving; bool interactive; bool explicitInteractive; + int touchId; Qt::Orientation orientation; QQuickScrollBar::SnapMode snapMode; QQuickScrollBar::Policy policy; diff --git a/tests/auto/controls/data/tst_scrollbar.qml b/tests/auto/controls/data/tst_scrollbar.qml index 97fb5bc1..b27e92cb 100644 --- a/tests/auto/controls/data/tst_scrollbar.qml +++ b/tests/auto/controls/data/tst_scrollbar.qml @@ -241,6 +241,147 @@ TestCase { compare(control.position, 0.25) } + function test_touch_data() { + return [ + { tag: "horizontal", properties: { visible: true, orientation: Qt.Horizontal, width: testCase.width } }, + { tag: "vertical", properties: { visible: true, orientation: Qt.Vertical, height: testCase.height } } + ] + } + + function test_touch(data) { + var control = createTemporaryObject(scrollBar, testCase, data.properties) + verify(control) + + var pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"}) + verify(pressedSpy.valid) + + var touch = touchEvent(control) + + touch.press(0, control, 0, 0).commit() + compare(pressedSpy.count, 1) + compare(control.pressed, true) + compare(control.position, 0.0) + + touch.move(0, control, -control.width, -control.height).commit() + compare(pressedSpy.count, 1) + compare(control.pressed, true) + compare(control.position, 0.0) + + touch.move(0, control, control.width * 0.5, control.height * 0.5).commit() + compare(pressedSpy.count, 1) + compare(control.pressed, true) + verify(control.position, 0.5) + + touch.release(0, control, control.width * 0.5, control.height * 0.5).commit() + compare(pressedSpy.count, 2) + compare(control.pressed, false) + compare(control.position, 0.5) + + touch.press(0, control, control.width, control.height).commit() + compare(pressedSpy.count, 3) + compare(control.pressed, true) + compare(control.position, 0.5) + + touch.move(0, control, control.width * 2, control.height * 2).commit() + compare(pressedSpy.count, 3) + compare(control.pressed, true) + compare(control.position, 1.0) + + touch.move(0, control, control.width * 0.75, control.height * 0.75).commit() + compare(pressedSpy.count, 3) + compare(control.pressed, true) + compare(control.position, 0.75) + + touch.release(0, control, control.width * 0.25, control.height * 0.25).commit() + compare(pressedSpy.count, 4) + compare(control.pressed, false) + compare(control.position, 0.25) + } + + function test_multiTouch() { + var control1 = createTemporaryObject(scrollBar, testCase) + verify(control1) + + var pressedCount1 = 0 + var movedCount1 = 0 + + var pressedSpy1 = signalSpy.createObject(control1, {target: control1, signalName: "pressedChanged"}) + verify(pressedSpy1.valid) + + var positionSpy1 = signalSpy.createObject(control1, {target: control1, signalName: "positionChanged"}) + verify(positionSpy1.valid) + + var touch = touchEvent(control1) + touch.press(0, control1, 0, 0).commit().move(0, control1, control1.width, control1.height).commit() + + compare(pressedSpy1.count, ++pressedCount1) + compare(positionSpy1.count, ++movedCount1) + compare(control1.pressed, true) + compare(control1.position, 1.0) + + // second touch point on the same control is ignored + touch.stationary(0).press(1, control1, 0, 0).commit() + touch.stationary(0).move(1, control1).commit() + touch.stationary(0).release(1).commit() + + compare(pressedSpy1.count, pressedCount1) + compare(positionSpy1.count, movedCount1) + compare(control1.pressed, true) + compare(control1.position, 1.0) + + var control2 = createTemporaryObject(scrollBar, testCase, {y: control1.height}) + verify(control2) + waitForRendering(control2) + + var pressedCount2 = 0 + var movedCount2 = 0 + + var pressedSpy2 = signalSpy.createObject(control2, {target: control2, signalName: "pressedChanged"}) + verify(pressedSpy2.valid) + + var positionSpy2 = signalSpy.createObject(control2, {target: control2, signalName: "positionChanged"}) + verify(positionSpy2.valid) + + // press the second scrollbar + touch.stationary(0).press(2, control2, 0, 0).commit() + + compare(pressedSpy2.count, ++pressedCount2) + compare(positionSpy2.count, movedCount2) + compare(control2.pressed, true) + compare(control2.position, 0.0) + + compare(pressedSpy1.count, pressedCount1) + compare(positionSpy1.count, movedCount1) + compare(control1.pressed, true) + compare(control1.position, 1.0) + + // move both scrollbars + touch.move(0, control1).move(2, control2).commit() + + compare(pressedSpy2.count, pressedCount2) + compare(positionSpy2.count, ++movedCount2) + compare(control2.pressed, true) + compare(control2.position, 0.5) + + compare(pressedSpy1.count, pressedCount1) + compare(positionSpy1.count, ++movedCount1) + compare(control1.pressed, true) + compare(control1.position, 0.5) + + // release both scrollbars + touch.release(0, control1).release(2, control2).commit() + + compare(pressedSpy2.count, ++pressedCount2) + compare(positionSpy2.count, movedCount2) + compare(control2.pressed, false) + compare(control2.position, 0.5) + + compare(pressedSpy1.count, ++pressedCount1) + compare(positionSpy1.count, movedCount1) + compare(control1.pressed, false) + compare(control1.position, 0.5) + } + function test_increase_decrease_data() { return [ { tag: "increase:active", increase: true, active: true }, @@ -426,6 +567,66 @@ TestCase { mouseRelease(control, control.width - 1, 0) } + function test_snapMode_touch_data() { + return test_snapMode_data() + } + + function test_snapMode_touch(data) { + var control = createTemporaryObject(scrollBar, testCase, {snapMode: data.snapMode, orientation: Qt.Horizontal, stepSize: data.stepSize, size: data.size, width: data.width}) + verify(control) + + function snappedPosition(pos) { + var effectiveStep = control.stepSize * (1.0 - control.size) + return Math.round(pos / effectiveStep) * effectiveStep + } + + function boundPosition(pos) { + return Math.max(0, Math.min(pos, 1.0 - control.size)) + } + + var touch = touchEvent(control) + + touch.press(0, control, 0, 0).commit() + compare(control.position, 0) + + touch.move(0, control, control.width * 0.3, 0).commit() + var expectedMovePos = 0.3 + if (control.snapMode === ScrollBar.SnapAlways) { + expectedMovePos = snappedPosition(expectedMovePos) + verify(expectedMovePos !== 0.3) + } + compare(control.position, expectedMovePos) + + touch.release(0, control, control.width * 0.75, 0).commit() + var expectedReleasePos = 0.75 + if (control.snapMode !== ScrollBar.NoSnap) { + expectedReleasePos = snappedPosition(expectedReleasePos) + verify(expectedReleasePos !== 0.75) + } + compare(control.position, expectedReleasePos) + + control.position = 0 + touch.press(0, control, 0, 0).commit() + + var steps = 0 + var prevPos = 0 + + for (var x = 0; x < control.width; ++x) { + touch.move(0, control, x, 0).commit() + expectedMovePos = boundPosition(x / control.width) + if (control.snapMode === ScrollBar.SnapAlways) + expectedMovePos = snappedPosition(expectedMovePos) + compare(control.position, expectedMovePos) + + if (control.position !== prevPos) + ++steps + prevPos = control.position + } + compare(steps, data.steps) + + touch.release(0, control, control.width - 1).commit() + } + function test_interactive_data() { return [ { tag: "true", interactive: true }, |