aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ-P Nurmi <jpnurmi@qt.io>2017-01-03 16:05:46 +0100
committerJ-P Nurmi <jpnurmi@qt.io>2017-01-03 18:26:08 +0000
commit28a9f66ea4910657b98cd4db548d84b298cf844e (patch)
treea397993c9cf1cf1ac0000d47e37c26228cb653b8
parent0b290018b52bc15534bedebe39f183e74eaee24e (diff)
QQuickDial: handle touch events
In comparison to handling synthesized mouse events, handling touch events has the advantage that it gives multi-touch support. That is, it is possible to move multiple dials at the same time, each handling its own touch point. Change-Id: Icabd971147f291fa4df00c6215c847d7976fda5f Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
-rw-r--r--src/quicktemplates2/qquickdial.cpp62
-rw-r--r--src/quicktemplates2/qquickdial_p.h2
-rw-r--r--tests/auto/controls/data/tst_dial.qml128
3 files changed, 191 insertions, 1 deletions
diff --git a/src/quicktemplates2/qquickdial.cpp b/src/quicktemplates2/qquickdial.cpp
index bd59f057..3f37a73b 100644
--- a/src/quicktemplates2/qquickdial.cpp
+++ b/src/quicktemplates2/qquickdial.cpp
@@ -96,6 +96,7 @@ class QQuickDialPrivate : public QQuickControlPrivate
public:
QQuickDialPrivate() :
+ touchId(-1),
from(0),
to(1),
value(0),
@@ -122,6 +123,7 @@ public:
void handleRelease(const QPointF &point);
void handleUngrab();
+ int touchId;
qreal from;
qreal to;
qreal value;
@@ -241,12 +243,14 @@ void QQuickDialPrivate::handleRelease(const QPointF &point)
q->setPressed(false);
pressPoint = QPointF();
+ touchId = -1;
}
void QQuickDialPrivate::handleUngrab()
{
Q_Q(QQuickDial);
pressPoint = QPointF();
+ touchId = -1;
q->setPressed(false);
}
@@ -685,6 +689,64 @@ void QQuickDial::mouseUngrabEvent()
d->handleUngrab();
}
+void QQuickDial::touchEvent(QTouchEvent *event)
+{
+ Q_D(QQuickDial);
+ 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;
+
+ if (!keepMouseGrab()) {
+ bool overXDragThreshold = QQuickWindowPrivate::dragOverThreshold(point.pos().x() - d->pressPoint.x(), Qt::XAxis, &point);
+ setKeepMouseGrab(overXDragThreshold);
+
+ if (!overXDragThreshold) {
+ bool overYDragThreshold = QQuickWindowPrivate::dragOverThreshold(point.pos().y() - d->pressPoint.y(), Qt::YAxis, &point);
+ setKeepMouseGrab(overYDragThreshold);
+ }
+ }
+ 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 QQuickDial::touchUngrabEvent()
+{
+ Q_D(QQuickDial);
+ QQuickControl::touchUngrabEvent();
+ d->handleUngrab();
+}
+
void QQuickDial::wheelEvent(QWheelEvent *event)
{
Q_D(QQuickDial);
diff --git a/src/quicktemplates2/qquickdial_p.h b/src/quicktemplates2/qquickdial_p.h
index cfaf1f32..efb43165 100644
--- a/src/quicktemplates2/qquickdial_p.h
+++ b/src/quicktemplates2/qquickdial_p.h
@@ -138,6 +138,8 @@ protected:
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseUngrabEvent() override;
+ void touchEvent(QTouchEvent *event) override;
+ void touchUngrabEvent() override;
void wheelEvent(QWheelEvent *event) override;
void mirrorChange() override;
diff --git a/tests/auto/controls/data/tst_dial.qml b/tests/auto/controls/data/tst_dial.qml
index 599bd03b..fb33892e 100644
--- a/tests/auto/controls/data/tst_dial.qml
+++ b/tests/auto/controls/data/tst_dial.qml
@@ -165,6 +165,15 @@ TestCase {
mouseRelease(dial, dial.width / 2, dial.height / 2);
verify(!dial.pressed);
compare(pressSpy.count, 2);
+
+ var touch = touchEvent(dial);
+ touch.press(0).commit();
+ verify(dial.pressed);
+ compare(pressSpy.count, 3);
+
+ touch.release(0).commit();
+ verify(!dial.pressed);
+ compare(pressSpy.count, 4);
}
SignalSpy {
@@ -272,6 +281,90 @@ TestCase {
verify(dial.position > positionAtPress);
}
+ function test_touch() {
+ var dial = createTemporaryObject(dialComponent, testCase);
+ verify(dial);
+
+ var touch = touchEvent(dial);
+
+ // Ensure that dragging from bottom left to bottom right doesn't work.
+ var yPos = dial.height * 0.75;
+ touch.press(0, dial, dial.width * 0.25, yPos).commit();
+ var positionAtPress = dial.position;
+ touch.move(0, dial, dial.width * 0.5, yPos).commit();
+ compare(dial.position, positionAtPress);
+ touch.move(0, dial, dial.width * 0.75, yPos).commit();
+ compare(dial.position, positionAtPress);
+ touch.release(0, dial, dial.width * 0.75, yPos).commit();
+ compare(dial.position, positionAtPress);
+
+ // Try the same thing, but a bit higher.
+ yPos = dial.height * 0.6;
+ touch.press(0, dial, dial.width * 0.25, yPos).commit();
+ positionAtPress = dial.position;
+ touch.move(0, dial, dial.width * 0.5, yPos).commit();
+ compare(dial.position, positionAtPress);
+ touch.move(0, dial, dial.width * 0.75, yPos).commit();
+ compare(dial.position, positionAtPress);
+ touch.release(0, dial, dial.width * 0.75, yPos).commit();
+ compare(dial.position, positionAtPress);
+
+ // Going from below the center of the dial to above it should work (once it gets above the center).
+ touch.press(0, dial, dial.width * 0.25, dial.height * 0.75).commit();
+ positionAtPress = dial.position;
+ touch.move(0, dial, dial.width * 0.5, dial.height * 0.6).commit();
+ compare(dial.position, positionAtPress);
+ touch.move(0, dial, dial.width * 0.75, dial.height * 0.4).commit();
+ verify(dial.position > positionAtPress);
+ touch.release(0, dial, dial.width * 0.75, dial.height * 0.3).commit();
+ verify(dial.position > positionAtPress);
+ }
+
+ function test_multiTouch() {
+ var dial1 = createTemporaryObject(dialComponent, testCase);
+ verify(dial1);
+
+ var touch = touchEvent(dial1);
+ touch.press(0, dial1).commit().move(0, dial1, dial1.width / 4, dial1.height / 4).commit();
+ compare(dial1.pressed, true);
+ verify(dial1.position > 0.0);
+
+ var pos1Before = dial1.position;
+
+ // second touch point on the same control is ignored
+ touch.stationary(0).press(1, dial1, 0, 0).commit()
+ touch.stationary(0).move(1, dial1).commit()
+ touch.stationary(0).release(1).commit()
+ compare(dial1.pressed, true);
+ compare(dial1.position, pos1Before);
+
+ var dial2 = createTemporaryObject(dialComponent, testCase, {y: dial1.height});
+ verify(dial2);
+ waitForRendering(dial2);
+
+ // press the second dial
+ touch.stationary(0).press(2, dial2, 0, 0).commit();
+ compare(dial2.pressed, true);
+ compare(dial2.position, 0.0);
+
+ pos1Before = dial1.position;
+ var pos2Before = dial2.position;
+
+ // move both dials
+ touch.move(0, dial1).move(2, dial2, dial2.width / 4, dial2.height / 4).commit();
+ compare(dial1.pressed, true);
+ verify(dial1.position !== pos1Before);
+ compare(dial2.pressed, true);
+ verify(dial2.position !== pos2Before);
+
+ // release both dials
+ touch.release(0, dial1).release(2, dial2).commit();
+ compare(dial1.pressed, false);
+ compare(dial1.value, dial1.position);
+ compare(dial2.pressed, false);
+ compare(dial2.value, dial2.position);
+ }
+
property Component focusTest: Component {
FocusScope {
signal receivedKeyPress
@@ -376,7 +469,11 @@ TestCase {
]
}
- function test_snapMode(data) {
+ function test_snapMode_mouse_data() {
+ return test_snapMode_data()
+ }
+
+ function test_snapMode_mouse(data) {
var dial = createTemporaryObject(dialComponent, testCase);
verify(dial);
@@ -400,6 +497,35 @@ TestCase {
fuzzyCompare(dial.position, data.positions[2], fuzz);
}
+ function test_snapMode_touch_data() {
+ return test_snapMode_data()
+ }
+
+ function test_snapMode_touch(data) {
+ var dial = createTemporaryObject(dialComponent, testCase);
+ verify(dial);
+
+ dial.snapMode = data.snapMode;
+ dial.from = data.from;
+ dial.to = data.to;
+ dial.stepSize = 0.2;
+
+ var fuzz = 0.05;
+
+ var touch = touchEvent(dial);
+ touch.press(0, dial, dial.width * 0.25, dial.height * 0.75).commit()
+ compare(dial.value, data.values[0]);
+ compare(dial.position, data.positions[0]);
+
+ touch.move(0, dial, dial.width * 0.5, dial.height * 0.25).commit();
+ fuzzyCompare(dial.value, data.values[1], fuzz);
+ fuzzyCompare(dial.position, data.positions[1], fuzz);
+
+ touch.release(0, dial, dial.width * 0.5, dial.height * 0.25).commit();
+ fuzzyCompare(dial.value, data.values[2], fuzz);
+ fuzzyCompare(dial.position, data.positions[2], fuzz);
+ }
+
function test_wheel_data() {
return [
{ tag: "horizontal", orientation: Qt.Horizontal, dx: 120, dy: 0 },