From 1fdbbb49d9f2d2bb62e151a29e5615031af6606a Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 19 Aug 2020 22:45:17 +0200 Subject: Calculate velocity in QMutEventPoint::setTimestamp() with Kalman filter This functionality was only in Qt Quick in Qt 5. Now we move it up to QtGui so that every QEventPoint will have a valid velocity() before being delivered anywhere. [ChangeLog][QtGui][QPointerEvent] Every QEventPoint should now carry a valid velocity(): if the operating system doesn't provide it, Qt will calculate it, using a simple Kalman filter to provide a weighted average over time. Fixes: QTBUG-33891 Change-Id: I40352f717f0ad6edd87cf71ef55e955a591eeea1 Reviewed-by: Volker Hilsheimer --- .../gui/kernel/qmouseevent/tst_qmouseevent.cpp | 56 +++++++++++++++++++++- .../gui/kernel/qtouchevent/tst_qtouchevent.cpp | 46 ++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp b/tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp index 660539d706..865785a108 100644 --- a/tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp +++ b/tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -51,11 +51,17 @@ public: int mouseReleaseButton; int mouseReleaseButtons; int mouseReleaseModifiers; + ulong timestamp; ulong pressTimestamp; + ulong lastTimestamp; + QVector2D velocity; protected: void mousePressEvent(QMouseEvent *e) override { const auto &firstPoint = e->point(0); + qCDebug(lcTests) << e << firstPoint; + timestamp = firstPoint.timestamp(); + lastTimestamp = firstPoint.lastTimestamp(); if (e->type() == QEvent::MouseButtonPress) { auto firstPoint = e->points().first(); QCOMPARE(e->exclusiveGrabber(firstPoint), nullptr); @@ -77,12 +83,23 @@ protected: if (grabPassive) e->addPassiveGrabber(firstPoint, this); } + void mouseMoveEvent(QMouseEvent *e) override + { + qCDebug(lcTests) << e << e->points().first(); + timestamp = e->points().first().timestamp(); + lastTimestamp = e->points().first().lastTimestamp(); + velocity = e->points().first().velocity(); + } void mouseReleaseEvent(QMouseEvent *e) override { + qCDebug(lcTests) << e << e->points().first(); QWindow::mouseReleaseEvent(e); mouseReleaseButton = e->button(); mouseReleaseButtons = e->buttons(); mouseReleaseModifiers = e->modifiers(); + timestamp = e->points().first().timestamp(); + lastTimestamp = e->points().first().lastTimestamp(); + velocity = e->points().first().velocity(); mouseReleaseEventRecieved = true; e->accept(); } @@ -104,6 +121,7 @@ private slots: void checkMouseReleaseEvent(); void grabbers_data(); void grabbers(); + void velocity(); private: MouseEventWidget* testMouseWidget; @@ -279,5 +297,41 @@ void tst_QMouseEvent::grabbers() QCOMPARE(firstEPD->passiveGrabbers.count(), 0); } +void tst_QMouseEvent::velocity() +{ + testMouseWidget->grabExclusive = true; + auto devPriv = QPointingDevicePrivate::get(const_cast(QPointingDevice::primaryPointingDevice())); + devPriv->activePoints.clear(); + + qCDebug(lcTests) << "sending mouse press event"; + QPoint pos(10, 10); + QTest::mousePress(testMouseWidget, Qt::LeftButton, Qt::KeyboardModifiers(), pos); + QCOMPARE(devPriv->activePoints.count(), 1); + QVERIFY(devPriv->activePoints.count() <= 2); + const auto &firstPoint = devPriv->pointById(0)->eventPoint; + QVERIFY(firstPoint.timestamp() > 0); + QCOMPARE(firstPoint.state(), QEventPoint::State::Pressed); + + ulong timestamp = firstPoint.timestamp(); + for (int i = 1; i < 4; ++i) { + qCDebug(lcTests) << "sending mouse move event" << i; + pos += {10, 10}; + QTest::mouseMove(testMouseWidget, pos, 1); + qApp->processEvents(); + qCDebug(lcTests) << firstPoint; + // currently we expect it to be updated in-place in devPriv->activePoints + QVERIFY(firstPoint.timestamp() > timestamp); + QVERIFY(testMouseWidget->timestamp > testMouseWidget->lastTimestamp); + QCOMPARE(testMouseWidget->timestamp, firstPoint.timestamp()); + timestamp = firstPoint.timestamp(); + QVERIFY(testMouseWidget->velocity.x() > 0); + QVERIFY(testMouseWidget->velocity.y() > 0); + } + QTest::mouseRelease(testMouseWidget, Qt::LeftButton, Qt::KeyboardModifiers(), pos, 1); + qCDebug(lcTests) << firstPoint; + QVERIFY(testMouseWidget->velocity.x() > 0); + QVERIFY(testMouseWidget->velocity.y() > 0); +} + QTEST_MAIN(tst_QMouseEvent) #include "tst_qmouseevent.moc" diff --git a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp index 4a5843bb13..38e58c9cc0 100644 --- a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp +++ b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp @@ -215,10 +215,16 @@ struct GrabberWindow : public QWindow { bool grabExclusive = false; bool grabPassive = false; + QVector2D velocity; + ulong timestamp; + ulong lastTimestamp; void touchEvent(QTouchEvent *ev) override { qCDebug(lcTests) << ev; const auto &firstPoint = ev->point(0); + velocity = firstPoint.velocity(); + timestamp = firstPoint.timestamp(); + lastTimestamp = firstPoint.lastTimestamp(); switch (ev->type()) { case QEvent::TouchBegin: { QCOMPARE(ev->exclusiveGrabber(firstPoint), nullptr); @@ -264,6 +270,7 @@ private slots: void testMultiDevice(); void grabbers_data(); void grabbers(); + void velocity(); private: QPointingDevice *touchScreenDevice; @@ -1942,6 +1949,45 @@ void tst_QTouchEvent::grabbers() QTRY_COMPARE(devPriv->activePoints.count(), 0); } +void tst_QTouchEvent::velocity() +{ + GrabberWindow w; + w.grabExclusive = true; + w.setGeometry(100, 100, 100, 100); + w.show(); + QVERIFY(QTest::qWaitForWindowExposed(&w)); + + auto devPriv = QPointingDevicePrivate::get(touchScreenDevice); + devPriv->activePoints.clear(); + QPoint pos(10, 10); + QTest::touchEvent(&w, touchScreenDevice).press(0, pos, &w); + QCOMPARE(devPriv->activePoints.count(), 1); + const auto &firstPoint = devPriv->pointById(0)->eventPoint; + qCDebug(lcTests) << "persistent active point after press" << firstPoint; + QCOMPARE(firstPoint.velocity(), QVector2D()); + + QCOMPARE(firstPoint.pressTimestamp(), firstPoint.timestamp()); + QVERIFY(firstPoint.timestamp() > 0); + QCOMPARE(firstPoint.state(), QEventPoint::State::Pressed); + + ulong timestamp = firstPoint.timestamp(); + for (int i = 1; i < 4; ++i) { + qCDebug(lcTests) << "sending touch move event" << i; + pos += {10, 10}; + QTest::touchEvent(&w, touchScreenDevice).move(0, pos, &w); + qCDebug(lcTests) << firstPoint; + QVERIFY(firstPoint.timestamp() > timestamp); + QVERIFY(w.timestamp > w.lastTimestamp); + QCOMPARE(w.timestamp, firstPoint.timestamp()); + timestamp = firstPoint.timestamp(); + QVERIFY(w.velocity.x() > 0); + QVERIFY(w.velocity.y() > 0); + } + QTest::touchEvent(&w, touchScreenDevice).release(0, pos, &w); + QVERIFY(w.velocity.x() > 0); + QVERIFY(w.velocity.y() > 0); +} + QTEST_MAIN(tst_QTouchEvent) #include "tst_qtouchevent.moc" -- cgit v1.2.3