Add TapHandler.exclusiveSignals to enable single/double tap exclusivity
If exclusiveSignals == NotExclusive (the default), behavior remains as it was: singleTapped() and doubleTapped() are emitted as the taps occur, so it's not very useful to react on singleTapped() if you mean to distinguish these two cases. If exclusiveSignals == SingleTap, the doubleTapped signal will not be emitted at all, and therefore singleTapped can be emitted immediately and unambiguously. If exclusiveSignals == DoubleTap, the singleTapped signal will not be emitted at all, and therefore doubleTapped can be emitted immediately and unambiguously. If exclusiveSignals == SingleTap | DoubleTap, we must wait qApp->styleHints()->mouseDoubleClickInterval() milliseconds after a tap is detected before emitting either signal, so that they are distinct and can be used to drive behavior that should not occur in other cases. A triple-tap will not trigger either signal. [ChangeLog][QtQuick][Event Handlers] TapHandler.exclusiveSignals now lets you make the singleTapped and doubleTapped signals exclusive. Task-number: QTBUG-65088 Fixes: QTBUG-107264 Change-Id: Ifb2c4b72759246c64b3bfa2f776c28266806b985 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Oliver Eftevaag <oliver.eftevaag@qt.io>
This commit is contained in:
parent
e3343eb83f
commit
d3f2c6ac42
|
@ -11,6 +11,7 @@ Rectangle {
|
|||
property alias hovered: hoverHandler.hovered
|
||||
property alias gesturePolicy: tap.gesturePolicy
|
||||
property alias margin: tap.margin
|
||||
property alias exclusiveSignals: tap.exclusiveSignals
|
||||
signal tapped
|
||||
|
||||
implicitHeight: Math.max(Screen.pixelDensity * 7, label.implicitHeight * 2)
|
||||
|
@ -29,7 +30,7 @@ Rectangle {
|
|||
id: tap
|
||||
margin: 10 // the user can tap a little beyond the edges
|
||||
objectName: label.text + " Tap"
|
||||
onTapped: {
|
||||
onSingleTapped: {
|
||||
tapFlash.start()
|
||||
root.tapped()
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ Item {
|
|||
text: "Launch Missile"
|
||||
Layout.fillWidth: true
|
||||
gesturePolicy: TapHandler.ReleaseWithinBounds
|
||||
exclusiveSignals: TapHandler.SingleTap
|
||||
onTapped: missileEmitter.burst(1)
|
||||
Text {
|
||||
anchors { top: parent.bottom; horizontalCenter: parent.horizontalCenter }
|
||||
|
|
|
@ -179,6 +179,14 @@ void QQuickTapHandler::timerEvent(QTimerEvent *event)
|
|||
m_longPressTimer.stop();
|
||||
qCDebug(lcTapHandler) << objectName() << "longPressed";
|
||||
emit longPressed();
|
||||
} else if (event->timerId() == m_doubleTapTimer.timerId()) {
|
||||
m_doubleTapTimer.stop();
|
||||
qCDebug(lcTapHandler) << objectName() << "double-tap timer expired; taps:" << m_tapCount;
|
||||
Q_ASSERT(m_exclusiveSignals == (SingleTap | DoubleTap));
|
||||
if (m_tapCount == 1)
|
||||
emit singleTapped(m_singleTapReleasedPoint, m_singleTapReleasedButton);
|
||||
else if (m_tapCount == 2)
|
||||
emit doubleTapped(m_singleTapReleasedPoint, m_singleTapReleasedButton);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,6 +255,38 @@ void QQuickTapHandler::setGesturePolicy(QQuickTapHandler::GesturePolicy gestureP
|
|||
emit gesturePolicyChanged();
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlproperty enumeration QtQuick::TapHandler::exclusiveSignals
|
||||
\since 6.5
|
||||
|
||||
Determines the exclusivity of the singleTapped() and doubleTapped() signals.
|
||||
|
||||
\value NotExclusive (the default) singleTapped() and doubleTapped() are
|
||||
emitted immediately when the user taps once or twice, respectively.
|
||||
|
||||
\value SingleTap singleTapped() is emitted immediately when the user taps
|
||||
once, and doubleTapped() is never emitted.
|
||||
|
||||
\value DoubleTap doubleTapped() is emitted immediately when the user taps
|
||||
twice, and singleTapped() is never emitted.
|
||||
|
||||
\value (SingleTap | DoubleTap) Both signals are delayed until
|
||||
QStyleHints::mouseDoubleClickInterval(), such that either singleTapped()
|
||||
or doubleTapped() can be emitted, but not both. But if 3 or more taps
|
||||
occur within \c mouseDoubleClickInterval, neither signal is emitted.
|
||||
|
||||
\note The remaining signals such as tapped() and tapCountChanged() are
|
||||
always emitted immediately, regardless of this property.
|
||||
*/
|
||||
void QQuickTapHandler::setExclusiveSignals(QQuickTapHandler::ExclusiveSignals exc)
|
||||
{
|
||||
if (m_exclusiveSignals == exc)
|
||||
return;
|
||||
|
||||
m_exclusiveSignals = exc;
|
||||
emit exclusiveSignalsChanged();
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlproperty bool QtQuick::TapHandler::pressed
|
||||
\readonly
|
||||
|
@ -270,6 +310,16 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QPointerEvent *event,
|
|||
} else {
|
||||
m_longPressTimer.stop();
|
||||
m_holdTimer.invalidate();
|
||||
if (m_exclusiveSignals == (SingleTap | DoubleTap)) {
|
||||
if (m_tapCount == 0) {
|
||||
m_singleTapReleasedPoint = point;
|
||||
m_singleTapReleasedButton = event->isSinglePointEvent() ? static_cast<QSinglePointEvent *>(event)->button() : Qt::NoButton;
|
||||
qCDebug(lcTapHandler) << objectName() << "waiting to emit singleTapped:" << qApp->styleHints()->mouseDoubleClickInterval() << "ms";
|
||||
m_doubleTapTimer.start(qApp->styleHints()->mouseDoubleClickInterval(), this);
|
||||
} else if (m_doubleTapTimer.isActive()) {
|
||||
qCDebug(lcTapHandler) << objectName() << "tap" << (m_tapCount + 1) << "after" << event->timestamp() / 1000.0 - m_lastTapTimestamp << "sec";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (press) {
|
||||
// on press, grab before emitting changed signals
|
||||
|
@ -281,22 +331,25 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QPointerEvent *event,
|
|||
if (!cancel && !press && parentContains(point)) {
|
||||
if (point.timeHeld() < longPressThreshold()) {
|
||||
// Assuming here that pointerEvent()->timestamp() is in ms.
|
||||
qreal ts = event->timestamp() / 1000.0;
|
||||
if (ts - m_lastTapTimestamp < m_multiTapInterval &&
|
||||
QVector2D(point.scenePosition() - m_lastTapPos).lengthSquared() <
|
||||
const qreal ts = event->timestamp() / 1000.0;
|
||||
const qreal interval = ts - m_lastTapTimestamp;
|
||||
const auto distanceSquared = QVector2D(point.scenePosition() - m_lastTapPos).lengthSquared();
|
||||
if (interval < m_multiTapInterval && distanceSquared <
|
||||
(event->device()->type() == QInputDevice::DeviceType::Mouse ?
|
||||
m_mouseMultiClickDistanceSquared : m_touchMultiTapDistanceSquared))
|
||||
++m_tapCount;
|
||||
else
|
||||
m_tapCount = 1;
|
||||
qCDebug(lcTapHandler) << objectName() << "tapped" << m_tapCount << "times";
|
||||
qCDebug(lcTapHandler) << objectName() << "tapped" << m_tapCount << "times; interval since last:" << interval
|
||||
<< "sec; distance since last:" << qSqrt(distanceSquared);
|
||||
auto button = event->isSinglePointEvent() ? static_cast<QSinglePointEvent *>(event)->button() : Qt::NoButton;
|
||||
emit tapped(point, button);
|
||||
emit tapCountChanged();
|
||||
if (m_tapCount == 1)
|
||||
if (m_tapCount == 1 && !m_exclusiveSignals.testFlag(DoubleTap))
|
||||
emit singleTapped(point, button);
|
||||
else if (m_tapCount == 2)
|
||||
else if (m_tapCount == 2 && !m_exclusiveSignals.testFlag(SingleTap)) {
|
||||
emit doubleTapped(point, button);
|
||||
}
|
||||
m_lastTapTimestamp = ts;
|
||||
m_lastTapPos = point.scenePosition();
|
||||
} else {
|
||||
|
|
|
@ -30,6 +30,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTapHandler : public QQuickSinglePointHandler
|
|||
Q_PROPERTY(qreal timeHeld READ timeHeld NOTIFY timeHeldChanged)
|
||||
Q_PROPERTY(qreal longPressThreshold READ longPressThreshold WRITE setLongPressThreshold NOTIFY longPressThresholdChanged)
|
||||
Q_PROPERTY(GesturePolicy gesturePolicy READ gesturePolicy WRITE setGesturePolicy NOTIFY gesturePolicyChanged)
|
||||
Q_PROPERTY(QQuickTapHandler::ExclusiveSignals exclusiveSignals READ exclusiveSignals WRITE setExclusiveSignals NOTIFY exclusiveSignalsChanged REVISION(6, 5))
|
||||
|
||||
QML_NAMED_ELEMENT(TapHandler)
|
||||
QML_ADDED_IN_VERSION(2, 12)
|
||||
|
@ -43,6 +44,14 @@ public:
|
|||
};
|
||||
Q_ENUM(GesturePolicy)
|
||||
|
||||
enum ExclusiveSignal {
|
||||
NotExclusive = 0,
|
||||
SingleTap = 1 << 1,
|
||||
DoubleTap = 1 << 2
|
||||
};
|
||||
Q_DECLARE_FLAGS(ExclusiveSignals, ExclusiveSignal)
|
||||
Q_FLAG(ExclusiveSignal)
|
||||
|
||||
explicit QQuickTapHandler(QQuickItem *parent = nullptr);
|
||||
|
||||
bool isPressed() const { return m_pressed; }
|
||||
|
@ -56,12 +65,16 @@ public:
|
|||
GesturePolicy gesturePolicy() const { return m_gesturePolicy; }
|
||||
void setGesturePolicy(GesturePolicy gesturePolicy);
|
||||
|
||||
QQuickTapHandler::ExclusiveSignals exclusiveSignals() const { return m_exclusiveSignals; }
|
||||
void setExclusiveSignals(QQuickTapHandler::ExclusiveSignals newexclusiveSignals);
|
||||
|
||||
Q_SIGNALS:
|
||||
void pressedChanged();
|
||||
void tapCountChanged();
|
||||
void timeHeldChanged();
|
||||
void longPressThresholdChanged();
|
||||
void gesturePolicyChanged();
|
||||
Q_REVISION(6, 5) void exclusiveSignalsChanged();
|
||||
// the second argument (Qt::MouseButton) was added in 6.2: avoid name clashes with IDs by not naming it for now
|
||||
void tapped(QEventPoint eventPoint, Qt::MouseButton /* button */);
|
||||
void singleTapped(QEventPoint eventPoint, Qt::MouseButton /* button */);
|
||||
|
@ -86,9 +99,13 @@ private:
|
|||
qreal m_lastTapTimestamp = 0;
|
||||
QElapsedTimer m_holdTimer;
|
||||
QBasicTimer m_longPressTimer;
|
||||
QBasicTimer m_doubleTapTimer;
|
||||
QEventPoint m_singleTapReleasedPoint;
|
||||
Qt::MouseButton m_singleTapReleasedButton;
|
||||
int m_tapCount = 0;
|
||||
int m_longPressThreshold = -1;
|
||||
GesturePolicy m_gesturePolicy = GesturePolicy::DragThreshold;
|
||||
ExclusiveSignals m_exclusiveSignals = NotExclusive;
|
||||
bool m_pressed = false;
|
||||
|
||||
static qreal m_multiTapInterval;
|
||||
|
|
|
@ -26,7 +26,10 @@ Rectangle {
|
|||
id: tap
|
||||
objectName: label.text
|
||||
longPressThreshold: 100 // CI can be insanely slow, so don't demand a timely release to generate onTapped
|
||||
onSingleTapped: console.log("Single tap")
|
||||
onDoubleTapped: console.log("Double tap")
|
||||
onTapped: {
|
||||
console.log("Tapped")
|
||||
tapFlash.start()
|
||||
root.tappedPosition = point.scenePosition
|
||||
root.tapped()
|
||||
|
|
|
@ -42,7 +42,10 @@ private slots:
|
|||
void gesturePolicyDragWithinBounds_data();
|
||||
void gesturePolicyDragWithinBounds();
|
||||
void touchMultiTap();
|
||||
void mouseMultiTap_data();
|
||||
void mouseMultiTap();
|
||||
void singleTapDoubleTap_data();
|
||||
void singleTapDoubleTap();
|
||||
void touchLongPress();
|
||||
void mouseLongPress();
|
||||
void buttonsMultiTouch();
|
||||
|
@ -523,8 +526,32 @@ void tst_TapHandler::touchMultiTap()
|
|||
QCOMPARE(tappedSpy.size(), 4);
|
||||
}
|
||||
|
||||
void tst_TapHandler::mouseMultiTap_data()
|
||||
{
|
||||
QTest::addColumn<QQuickTapHandler::ExclusiveSignals>("exclusiveSignals");
|
||||
QTest::addColumn<int>("expectedSingleTaps");
|
||||
QTest::addColumn<int>("expectedSingleTapsAfterMovingAway");
|
||||
QTest::addColumn<int>("expectedSingleTapsAfterWaiting");
|
||||
QTest::addColumn<int>("expectedDoubleTaps");
|
||||
|
||||
QTest::newRow("NotExclusive") << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::NotExclusive)
|
||||
<< 1 << 2 << 3 << 1;
|
||||
QTest::newRow("SingleTap") << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::SingleTap)
|
||||
<< 1 << 2 << 3 << 0;
|
||||
QTest::newRow("DoubleTap") << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::DoubleTap)
|
||||
<< 0 << 0 << 0 << 1;
|
||||
QTest::newRow("SingleTap|DoubleTap") << QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::SingleTap | QQuickTapHandler::DoubleTap)
|
||||
<< 0 << 0 << 0 << 0;
|
||||
}
|
||||
|
||||
void tst_TapHandler::mouseMultiTap()
|
||||
{
|
||||
QFETCH(QQuickTapHandler::ExclusiveSignals, exclusiveSignals);
|
||||
QFETCH(int, expectedSingleTaps);
|
||||
QFETCH(int, expectedSingleTapsAfterMovingAway);
|
||||
QFETCH(int, expectedSingleTapsAfterWaiting);
|
||||
QFETCH(int, expectedDoubleTaps);
|
||||
|
||||
const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
|
||||
QScopedPointer<QQuickView> windowPtr;
|
||||
createView(windowPtr, "buttons.qml");
|
||||
|
@ -532,38 +559,143 @@ void tst_TapHandler::mouseMultiTap()
|
|||
|
||||
QQuickItem *button = window->rootObject()->findChild<QQuickItem*>("DragThreshold");
|
||||
QVERIFY(button);
|
||||
QQuickTapHandler *tapHandler = button->findChild<QQuickTapHandler*>();
|
||||
QVERIFY(tapHandler);
|
||||
tapHandler->setExclusiveSignals(exclusiveSignals);
|
||||
QSignalSpy tappedSpy(button, SIGNAL(tapped()));
|
||||
QSignalSpy singleTapSpy(tapHandler, &QQuickTapHandler::singleTapped);
|
||||
QSignalSpy doubleTapSpy(tapHandler, &QQuickTapHandler::doubleTapped);
|
||||
|
||||
// Tap once
|
||||
// Click once
|
||||
QPoint p1 = button->mapToScene(QPointF(2, 2)).toPoint();
|
||||
QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
|
||||
QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
|
||||
QTRY_VERIFY(button->property("pressed").toBool());
|
||||
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
|
||||
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
|
||||
QTRY_VERIFY(!button->property("pressed").toBool());
|
||||
QCOMPARE(tappedSpy.size(), 1);
|
||||
// If exclusiveSignals == SingleTap | DoubleTap:
|
||||
// This would be a single-click if we waited longer than the double-click interval,
|
||||
// but it's too early for the signal at this moment; and we're going to click again.
|
||||
// If exclusiveSignals == DoubleTap: singleTapped() won't happen.
|
||||
// Otherwise: we got singleTapped() immediately.
|
||||
QCOMPARE(singleTapSpy.size(), expectedSingleTaps);
|
||||
QCOMPARE(tapHandler->timeHeld(), -1);
|
||||
|
||||
// Tap again in exactly the same place (not likely with touch in the real world)
|
||||
QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
|
||||
QTRY_VERIFY(button->property("pressed").toBool());
|
||||
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
|
||||
QTRY_VERIFY(!button->property("pressed").toBool());
|
||||
// Click again in exactly the same place
|
||||
QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
|
||||
QCOMPARE(tappedSpy.size(), 2);
|
||||
QCOMPARE(singleTapSpy.size(), expectedSingleTaps);
|
||||
QCOMPARE(doubleTapSpy.size(), expectedDoubleTaps);
|
||||
|
||||
// Tap a third time, nearby
|
||||
p1 += QPoint(dragThreshold, dragThreshold);
|
||||
QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
|
||||
QTRY_VERIFY(button->property("pressed").toBool());
|
||||
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
|
||||
QTRY_VERIFY(!button->property("pressed").toBool());
|
||||
// Click a third time, nearby: that'll be a triple-click
|
||||
p1 += QPoint(1, 1);
|
||||
QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
|
||||
QCOMPARE(tappedSpy.size(), 3);
|
||||
QCOMPARE(singleTapSpy.size(), expectedSingleTaps);
|
||||
QCOMPARE(doubleTapSpy.size(), expectedDoubleTaps);
|
||||
QCOMPARE(tapHandler->tapCount(), 3);
|
||||
|
||||
// Tap a fourth time, drifting farther away
|
||||
// Click a fourth time, drifting farther away: treated as a separate click, regardless of timing
|
||||
p1 += QPoint(dragThreshold, dragThreshold);
|
||||
QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
|
||||
QTRY_VERIFY(button->property("pressed").toBool());
|
||||
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
|
||||
QTRY_VERIFY(!button->property("pressed").toBool());
|
||||
QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, p1); // default delay to prevent double-click
|
||||
QCOMPARE(tappedSpy.size(), 4);
|
||||
QCOMPARE(tapHandler->tapCount(), 1);
|
||||
QTRY_COMPARE(singleTapSpy.size(), expectedSingleTapsAfterMovingAway);
|
||||
|
||||
// Click a fifth time later on at the same place: treated as a separate click
|
||||
QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, p1);
|
||||
QCOMPARE(tappedSpy.size(), 5);
|
||||
QCOMPARE(tapHandler->tapCount(), 1);
|
||||
QCOMPARE(singleTapSpy.size(), expectedSingleTapsAfterWaiting);
|
||||
}
|
||||
|
||||
void tst_TapHandler::singleTapDoubleTap_data()
|
||||
{
|
||||
QTest::addColumn<QPointingDevice::DeviceType>("deviceType");
|
||||
QTest::addColumn<QQuickTapHandler::ExclusiveSignals>("exclusiveSignals");
|
||||
QTest::addColumn<int>("expectedEndingSingleTapCount");
|
||||
QTest::addColumn<int>("expectedDoubleTapCount");
|
||||
|
||||
QTest::newRow("mouse:NotExclusive")
|
||||
<< QPointingDevice::DeviceType::Mouse
|
||||
<< QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::NotExclusive)
|
||||
<< 1 << 1;
|
||||
QTest::newRow("mouse:SingleTap")
|
||||
<< QPointingDevice::DeviceType::Mouse
|
||||
<< QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::SingleTap)
|
||||
<< 1 << 0;
|
||||
QTest::newRow("mouse:DoubleTap")
|
||||
<< QPointingDevice::DeviceType::Mouse
|
||||
<< QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::DoubleTap)
|
||||
<< 0 << 1;
|
||||
QTest::newRow("mouse:SingleTap|DoubleTap")
|
||||
<< QPointingDevice::DeviceType::Mouse
|
||||
<< QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::SingleTap | QQuickTapHandler::DoubleTap)
|
||||
<< 0 << 1;
|
||||
QTest::newRow("touch:NotExclusive")
|
||||
<< QPointingDevice::DeviceType::TouchScreen
|
||||
<< QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::NotExclusive)
|
||||
<< 1 << 1;
|
||||
QTest::newRow("touch:SingleTap")
|
||||
<< QPointingDevice::DeviceType::TouchScreen
|
||||
<< QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::SingleTap)
|
||||
<< 1 << 0;
|
||||
QTest::newRow("touch:DoubleTap")
|
||||
<< QPointingDevice::DeviceType::TouchScreen
|
||||
<< QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::DoubleTap)
|
||||
<< 0 << 1;
|
||||
QTest::newRow("touch:SingleTap|DoubleTap")
|
||||
<< QPointingDevice::DeviceType::TouchScreen
|
||||
<< QQuickTapHandler::ExclusiveSignals(QQuickTapHandler::SingleTap | QQuickTapHandler::DoubleTap)
|
||||
<< 0 << 1;
|
||||
}
|
||||
|
||||
void tst_TapHandler::singleTapDoubleTap()
|
||||
{
|
||||
QFETCH(QPointingDevice::DeviceType, deviceType);
|
||||
QFETCH(QQuickTapHandler::ExclusiveSignals, exclusiveSignals);
|
||||
QFETCH(int, expectedEndingSingleTapCount);
|
||||
QFETCH(int, expectedDoubleTapCount);
|
||||
|
||||
QScopedPointer<QQuickView> windowPtr;
|
||||
createView(windowPtr, "buttons.qml");
|
||||
QQuickView * window = windowPtr.data();
|
||||
|
||||
QQuickItem *button = window->rootObject()->findChild<QQuickItem*>("DragThreshold");
|
||||
QVERIFY(button);
|
||||
QQuickTapHandler *tapHandler = button->findChild<QQuickTapHandler*>();
|
||||
QVERIFY(tapHandler);
|
||||
tapHandler->setExclusiveSignals(exclusiveSignals);
|
||||
QSignalSpy tappedSpy(tapHandler, &QQuickTapHandler::tapped);
|
||||
QSignalSpy singleTapSpy(tapHandler, &QQuickTapHandler::singleTapped);
|
||||
QSignalSpy doubleTapSpy(tapHandler, &QQuickTapHandler::doubleTapped);
|
||||
|
||||
auto tap = [window, tapHandler, deviceType, this](const QPoint &p1) {
|
||||
switch (static_cast<QPointingDevice::DeviceType>(deviceType)) {
|
||||
case QPointingDevice::DeviceType::Mouse:
|
||||
QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
|
||||
break;
|
||||
case QPointingDevice::DeviceType::TouchScreen:
|
||||
QTest::touchEvent(window, touchDevice).press(0, p1, window);
|
||||
QTRY_VERIFY(tapHandler->isPressed());
|
||||
QTest::touchEvent(window, touchDevice).release(0, p1, window);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// tap once
|
||||
const QPoint p1 = button->mapToScene(QPointF(2, 2)).toPoint();
|
||||
tap(p1);
|
||||
QCOMPARE(tappedSpy.size(), 1);
|
||||
QCOMPARE(doubleTapSpy.size(), 0);
|
||||
|
||||
// tap again immediately afterwards
|
||||
tap(p1);
|
||||
QTRY_COMPARE(doubleTapSpy.size(), expectedDoubleTapCount);
|
||||
QCOMPARE(tappedSpy.size(), 2);
|
||||
QCOMPARE(singleTapSpy.size(), expectedEndingSingleTapCount);
|
||||
}
|
||||
|
||||
void tst_TapHandler::touchLongPress()
|
||||
|
|
Loading…
Reference in New Issue