Fix TapHandler signals in combination with exclusiveSignals
TapHandler does not emit any singleTapped or doubleTapped signals after emitting it once, if exclusiveSignals is set to `SingleTap | DoubleTap`. This change corrects the behavior by resetting m_tapCount properly. Fixes: QTBUG-111800 Pick-to: 6.5 Change-Id: Ice7af2f41c2f30448004033d8330e733abe44110 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
This commit is contained in:
parent
07aaa7c1b6
commit
951ab9f3c0
|
@ -13,7 +13,7 @@ QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(lcTapHandler, "qt.quick.handler.tap")
|
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
|
// single tap distance is the same as the drag threshold
|
||||||
int QQuickTapHandler::m_mouseMultiClickDistanceSquared(-1);
|
int QQuickTapHandler::m_mouseMultiClickDistanceSquared(-1);
|
||||||
int QQuickTapHandler::m_touchMultiTapDistanceSquared(-1);
|
int QQuickTapHandler::m_touchMultiTapDistanceSquared(-1);
|
||||||
|
@ -57,7 +57,7 @@ QQuickTapHandler::QQuickTapHandler(QQuickItem *parent)
|
||||||
: QQuickSinglePointHandler(parent)
|
: QQuickSinglePointHandler(parent)
|
||||||
{
|
{
|
||||||
if (m_mouseMultiClickDistanceSquared < 0) {
|
if (m_mouseMultiClickDistanceSquared < 0) {
|
||||||
m_multiTapInterval = qApp->styleHints()->mouseDoubleClickInterval() / 1000.0;
|
m_multiTapInterval = qApp->styleHints()->mouseDoubleClickInterval();
|
||||||
m_mouseMultiClickDistanceSquared = qApp->styleHints()->mouseDoubleClickDistance();
|
m_mouseMultiClickDistanceSquared = qApp->styleHints()->mouseDoubleClickDistance();
|
||||||
m_mouseMultiClickDistanceSquared *= m_mouseMultiClickDistanceSquared;
|
m_mouseMultiClickDistanceSquared *= m_mouseMultiClickDistanceSquared;
|
||||||
m_touchMultiTapDistanceSquared = qApp->styleHints()->touchDoubleTapDistance();
|
m_touchMultiTapDistanceSquared = qApp->styleHints()->touchDoubleTapDistance();
|
||||||
|
@ -355,16 +355,6 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QPointerEvent *event,
|
||||||
} else {
|
} else {
|
||||||
m_longPressTimer.stop();
|
m_longPressTimer.stop();
|
||||||
m_holdTimer.invalidate();
|
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) {
|
if (press) {
|
||||||
// on press, grab before emitting changed signals
|
// 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 (!cancel && !press && parentContains(point)) {
|
||||||
if (point.timeHeld() < longPressThreshold()) {
|
if (point.timeHeld() < longPressThreshold()) {
|
||||||
// Assuming here that pointerEvent()->timestamp() is in ms.
|
// Assuming here that pointerEvent()->timestamp() is in ms.
|
||||||
const qreal ts = event->timestamp() / 1000.0;
|
const quint64 ts = event->timestamp();
|
||||||
const qreal interval = ts - m_lastTapTimestamp;
|
const quint64 interval = ts - m_lastTapTimestamp;
|
||||||
const auto distanceSquared = QVector2D(point.scenePosition() - m_lastTapPos).lengthSquared();
|
const auto distanceSquared = QVector2D(point.scenePosition() - m_lastTapPos).lengthSquared();
|
||||||
const auto singleTapReleasedButton = event->isSinglePointEvent() ? static_cast<QSinglePointEvent *>(event)->button() : Qt::NoButton;
|
const auto singleTapReleasedButton = event->isSinglePointEvent() ? static_cast<QSinglePointEvent *>(event)->button() : Qt::NoButton;
|
||||||
if ((interval < m_multiTapInterval && distanceSquared <
|
if ((interval < m_multiTapInterval && distanceSquared <
|
||||||
|
@ -387,6 +377,7 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QPointerEvent *event,
|
||||||
++m_tapCount;
|
++m_tapCount;
|
||||||
} else {
|
} else {
|
||||||
m_singleTapReleasedButton = singleTapReleasedButton;
|
m_singleTapReleasedButton = singleTapReleasedButton;
|
||||||
|
m_singleTapReleasedPoint = point;
|
||||||
m_tapCount = 1;
|
m_tapCount = 1;
|
||||||
}
|
}
|
||||||
qCDebug(lcTapHandler) << objectName() << "tapped" << m_tapCount << "times; interval since last:" << interval
|
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<QSinglePointEvent *>(event)->button() : Qt::NoButton;
|
auto button = event->isSinglePointEvent() ? static_cast<QSinglePointEvent *>(event)->button() : Qt::NoButton;
|
||||||
emit tapped(point, button);
|
emit tapped(point, button);
|
||||||
emit tapCountChanged();
|
emit tapCountChanged();
|
||||||
if (m_tapCount == 1 && !m_exclusiveSignals.testFlag(DoubleTap))
|
switch (m_exclusiveSignals) {
|
||||||
emit singleTapped(point, button);
|
case NotExclusive:
|
||||||
else if (m_tapCount == 2 && !m_exclusiveSignals.testFlag(SingleTap)) {
|
if (m_tapCount == 1)
|
||||||
emit doubleTapped(point, button);
|
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_lastTapTimestamp = ts;
|
||||||
m_lastTapPos = point.scenePosition();
|
m_lastTapPos = point.scenePosition();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -98,7 +98,7 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPointF m_lastTapPos;
|
QPointF m_lastTapPos;
|
||||||
qreal m_lastTapTimestamp = 0;
|
quint64 m_lastTapTimestamp = 0;
|
||||||
QElapsedTimer m_holdTimer;
|
QElapsedTimer m_holdTimer;
|
||||||
QBasicTimer m_longPressTimer;
|
QBasicTimer m_longPressTimer;
|
||||||
QBasicTimer m_doubleTapTimer;
|
QBasicTimer m_doubleTapTimer;
|
||||||
|
@ -110,7 +110,7 @@ private:
|
||||||
ExclusiveSignals m_exclusiveSignals = NotExclusive;
|
ExclusiveSignals m_exclusiveSignals = NotExclusive;
|
||||||
bool m_pressed = false;
|
bool m_pressed = false;
|
||||||
|
|
||||||
static qreal m_multiTapInterval;
|
static quint64 m_multiTapInterval;
|
||||||
static int m_mouseMultiClickDistanceSquared;
|
static int m_mouseMultiClickDistanceSquared;
|
||||||
static int m_touchMultiTapDistanceSquared;
|
static int m_touchMultiTapDistanceSquared;
|
||||||
};
|
};
|
||||||
|
|
|
@ -715,12 +715,13 @@ void tst_TapHandler::singleTapDoubleTap()
|
||||||
QSignalSpy singleTapSpy(tapHandler, &QQuickTapHandler::singleTapped);
|
QSignalSpy singleTapSpy(tapHandler, &QQuickTapHandler::singleTapped);
|
||||||
QSignalSpy doubleTapSpy(tapHandler, &QQuickTapHandler::doubleTapped);
|
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<QPointingDevice::DeviceType>(deviceType)) {
|
switch (static_cast<QPointingDevice::DeviceType>(deviceType)) {
|
||||||
case QPointingDevice::DeviceType::Mouse:
|
case QPointingDevice::DeviceType::Mouse:
|
||||||
QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, p1, 10);
|
QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, p1, delay);
|
||||||
break;
|
break;
|
||||||
case QPointingDevice::DeviceType::TouchScreen:
|
case QPointingDevice::DeviceType::TouchScreen:
|
||||||
|
QTest::qWait(delay);
|
||||||
QTest::touchEvent(window, touchDevice).press(0, p1, window);
|
QTest::touchEvent(window, touchDevice).press(0, p1, window);
|
||||||
QTRY_VERIFY(tapHandler->isPressed());
|
QTRY_VERIFY(tapHandler->isPressed());
|
||||||
QTest::touchEvent(window, touchDevice).release(0, p1, window);
|
QTest::touchEvent(window, touchDevice).release(0, p1, window);
|
||||||
|
@ -741,6 +742,23 @@ void tst_TapHandler::singleTapDoubleTap()
|
||||||
QTRY_COMPARE(doubleTapSpy.size(), expectedDoubleTapCount);
|
QTRY_COMPARE(doubleTapSpy.size(), expectedDoubleTapCount);
|
||||||
QCOMPARE(tappedSpy.size(), 2);
|
QCOMPARE(tappedSpy.size(), 2);
|
||||||
QCOMPARE(singleTapSpy.size(), expectedEndingSingleTapCount);
|
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()
|
void tst_TapHandler::touchLongPress()
|
||||||
|
|
Loading…
Reference in New Issue