diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp index 20711819d3..e36e8cffed 100644 --- a/src/quick/handlers/qquicktaphandler.cpp +++ b/src/quick/handlers/qquicktaphandler.cpp @@ -13,7 +13,7 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcTapHandler, "qt.quick.handler.tap") -qreal QQuickTapHandler::m_multiTapInterval(0.0); +quint64 QQuickTapHandler::m_multiTapInterval(0); // single tap distance is the same as the drag threshold int QQuickTapHandler::m_mouseMultiClickDistanceSquared(-1); int QQuickTapHandler::m_touchMultiTapDistanceSquared(-1); @@ -57,7 +57,7 @@ QQuickTapHandler::QQuickTapHandler(QQuickItem *parent) : QQuickSinglePointHandler(parent) { if (m_mouseMultiClickDistanceSquared < 0) { - m_multiTapInterval = qApp->styleHints()->mouseDoubleClickInterval() / 1000.0; + m_multiTapInterval = qApp->styleHints()->mouseDoubleClickInterval(); m_mouseMultiClickDistanceSquared = qApp->styleHints()->mouseDoubleClickDistance(); m_mouseMultiClickDistanceSquared *= m_mouseMultiClickDistanceSquared; m_touchMultiTapDistanceSquared = qApp->styleHints()->touchDoubleTapDistance(); @@ -355,16 +355,6 @@ 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(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 @@ -376,8 +366,8 @@ 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. - const qreal ts = event->timestamp() / 1000.0; - const qreal interval = ts - m_lastTapTimestamp; + const quint64 ts = event->timestamp(); + const quint64 interval = ts - m_lastTapTimestamp; const auto distanceSquared = QVector2D(point.scenePosition() - m_lastTapPos).lengthSquared(); const auto singleTapReleasedButton = event->isSinglePointEvent() ? static_cast(event)->button() : Qt::NoButton; if ((interval < m_multiTapInterval && distanceSquared < @@ -387,6 +377,7 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QPointerEvent *event, ++m_tapCount; } else { m_singleTapReleasedButton = singleTapReleasedButton; + m_singleTapReleasedPoint = point; m_tapCount = 1; } qCDebug(lcTapHandler) << objectName() << "tapped" << m_tapCount << "times; interval since last:" << interval @@ -394,11 +385,29 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QPointerEvent *event, auto button = event->isSinglePointEvent() ? static_cast(event)->button() : Qt::NoButton; emit tapped(point, button); emit tapCountChanged(); - if (m_tapCount == 1 && !m_exclusiveSignals.testFlag(DoubleTap)) - emit singleTapped(point, button); - else if (m_tapCount == 2 && !m_exclusiveSignals.testFlag(SingleTap)) { - emit doubleTapped(point, button); + switch (m_exclusiveSignals) { + case NotExclusive: + if (m_tapCount == 1) + emit singleTapped(point, button); + else if (m_tapCount == 2) + emit doubleTapped(point, button); + break; + case SingleTap: + if (m_tapCount == 1) + emit singleTapped(point, button); + break; + case DoubleTap: + if (m_tapCount == 2) + emit doubleTapped(point, button); + break; + case (SingleTap | DoubleTap): + if (m_tapCount == 1) { + qCDebug(lcTapHandler) << objectName() << "waiting to emit singleTapped:" << m_multiTapInterval << "ms"; + m_doubleTapTimer.start(m_multiTapInterval, this); + } } + qCDebug(lcTapHandler) << objectName() << "tap" << m_tapCount << "after" << event->timestamp() - m_lastTapTimestamp << "ms"; + m_lastTapTimestamp = ts; m_lastTapPos = point.scenePosition(); } else { diff --git a/src/quick/handlers/qquicktaphandler_p.h b/src/quick/handlers/qquicktaphandler_p.h index 0a9707e17e..be8aa83032 100644 --- a/src/quick/handlers/qquicktaphandler_p.h +++ b/src/quick/handlers/qquicktaphandler_p.h @@ -98,7 +98,7 @@ private: private: QPointF m_lastTapPos; - qreal m_lastTapTimestamp = 0; + quint64 m_lastTapTimestamp = 0; QElapsedTimer m_holdTimer; QBasicTimer m_longPressTimer; QBasicTimer m_doubleTapTimer; @@ -110,7 +110,7 @@ private: ExclusiveSignals m_exclusiveSignals = NotExclusive; bool m_pressed = false; - static qreal m_multiTapInterval; + static quint64 m_multiTapInterval; static int m_mouseMultiClickDistanceSquared; static int m_touchMultiTapDistanceSquared; }; diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp index 8f4cc56698..65b40c08a3 100644 --- a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp @@ -715,12 +715,13 @@ void tst_TapHandler::singleTapDoubleTap() QSignalSpy singleTapSpy(tapHandler, &QQuickTapHandler::singleTapped); QSignalSpy doubleTapSpy(tapHandler, &QQuickTapHandler::doubleTapped); - auto tap = [window, tapHandler, deviceType, this](const QPoint &p1) { + auto tap = [window, tapHandler, deviceType, this](const QPoint &p1, int delay = 10) { switch (static_cast(deviceType)) { case QPointingDevice::DeviceType::Mouse: - QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, p1, 10); + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, p1, delay); break; case QPointingDevice::DeviceType::TouchScreen: + QTest::qWait(delay); QTest::touchEvent(window, touchDevice).press(0, p1, window); QTRY_VERIFY(tapHandler->isPressed()); QTest::touchEvent(window, touchDevice).release(0, p1, window); @@ -741,6 +742,23 @@ void tst_TapHandler::singleTapDoubleTap() QTRY_COMPARE(doubleTapSpy.size(), expectedDoubleTapCount); QCOMPARE(tappedSpy.size(), 2); QCOMPARE(singleTapSpy.size(), expectedEndingSingleTapCount); + + // wait past the double-tap interval, then do it again + const auto delay = qApp->styleHints()->mouseDoubleClickInterval() + 10; + tappedSpy.clear(); + singleTapSpy.clear(); + doubleTapSpy.clear(); + + // tap once with delay + tap(p1, delay); + 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()