Clear only one device from g_pointIdMap when all points released
The new test tst_QTouchEvent::touchOnMultipleTouchscreens() needs the touchpoint IDs to be predictable, but another test currently has a QEXPECT_FAIL; without release events, g_pointIdMap continued to hold the touchpoints that were there when the test failed. So it's necessary to add QWindowSystemInterfacePrivate::clearPointIdMap() to be able to call it in the test cleanup function. Fixes: QTBUG-73830 Change-Id: Ia6a70d028be95cd2b6676db6363ec408c0b116bc Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
This commit is contained in:
parent
7e60858cbc
commit
1500d2283e
@ -695,13 +695,29 @@ QList<QTouchEvent::TouchPoint>
|
||||
}
|
||||
|
||||
if (states == Qt::TouchPointReleased) {
|
||||
g_nextPointId = 1;
|
||||
g_pointIdMap->clear();
|
||||
// All points on deviceId have been released.
|
||||
// Remove all points associated with that device from g_pointIdMap.
|
||||
// (On other devices, some touchpoints might still be pressed.
|
||||
// But this function is only called with points from one device at a time.)
|
||||
for (auto it = g_pointIdMap->begin(); it != g_pointIdMap->end();) {
|
||||
if (it.key() >> 32 == quint64(deviceId))
|
||||
it = g_pointIdMap->erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
if (g_pointIdMap->isEmpty())
|
||||
g_nextPointId = 1;
|
||||
}
|
||||
|
||||
return touchPoints;
|
||||
}
|
||||
|
||||
void QWindowSystemInterfacePrivate::clearPointIdMap()
|
||||
{
|
||||
g_pointIdMap->clear();
|
||||
g_nextPointId = 1;
|
||||
}
|
||||
|
||||
QList<QWindowSystemInterface::TouchPoint>
|
||||
QWindowSystemInterfacePrivate::toNativeTouchPoints(const QList<QTouchEvent::TouchPoint>& pointList,
|
||||
const QWindow *window)
|
||||
|
@ -537,6 +537,7 @@ public:
|
||||
static QList<QWindowSystemInterface::TouchPoint>
|
||||
toNativeTouchPoints(const QList<QTouchEvent::TouchPoint>& pointList,
|
||||
const QWindow *window);
|
||||
static void clearPointIdMap();
|
||||
|
||||
static void installWindowSystemEventHandler(QWindowSystemEventHandler *handler);
|
||||
static void removeWindowSystemEventhandler(QWindowSystemEventHandler *handler);
|
||||
|
@ -204,6 +204,7 @@ private slots:
|
||||
void basicRawEventTranslationOfIds();
|
||||
void multiPointRawEventTranslationOnTouchScreen();
|
||||
void multiPointRawEventTranslationOnTouchPad();
|
||||
void touchOnMultipleTouchscreens();
|
||||
void deleteInEventHandler();
|
||||
void deleteInRawEventTranslation();
|
||||
void crashInQGraphicsSceneAfterNotHandlingTouchBegin();
|
||||
@ -213,11 +214,13 @@ private slots:
|
||||
|
||||
private:
|
||||
QTouchDevice *touchScreenDevice;
|
||||
QTouchDevice *secondaryTouchScreenDevice;
|
||||
QTouchDevice *touchPadDevice;
|
||||
};
|
||||
|
||||
tst_QTouchEvent::tst_QTouchEvent()
|
||||
: touchScreenDevice(QTest::createTouchDevice())
|
||||
, secondaryTouchScreenDevice(QTest::createTouchDevice())
|
||||
, touchPadDevice(QTest::createTouchDevice(QTouchDevice::TouchPad))
|
||||
{
|
||||
}
|
||||
@ -225,6 +228,7 @@ tst_QTouchEvent::tst_QTouchEvent()
|
||||
void tst_QTouchEvent::cleanup()
|
||||
{
|
||||
QVERIFY(QGuiApplication::topLevelWindows().isEmpty());
|
||||
QWindowSystemInterfacePrivate::clearPointIdMap();
|
||||
}
|
||||
|
||||
void tst_QTouchEvent::qPointerUniqueId()
|
||||
@ -951,6 +955,157 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QTouchEvent::touchOnMultipleTouchscreens()
|
||||
{
|
||||
tst_QTouchEventWidget touchWidget;
|
||||
touchWidget.setWindowTitle(QTest::currentTestFunction());
|
||||
touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
|
||||
touchWidget.setGeometry(100, 100, 400, 300);
|
||||
touchWidget.show();
|
||||
QVERIFY(QTest::qWaitForWindowExposed(&touchWidget));
|
||||
QWindow *window = touchWidget.windowHandle();
|
||||
|
||||
QPointF pos = touchWidget.rect().center();
|
||||
QPointF screenPos = touchWidget.mapToGlobal(pos.toPoint());
|
||||
QPointF delta(10, 10);
|
||||
QRectF screenGeometry = QApplication::desktop()->screenGeometry(&touchWidget);
|
||||
|
||||
QVector<QTouchEvent::TouchPoint> rawTouchPoints(3);
|
||||
rawTouchPoints[0].setId(0);
|
||||
rawTouchPoints[1].setId(10);
|
||||
rawTouchPoints[2].setId(11);
|
||||
|
||||
// this should be translated to a TouchBegin
|
||||
rawTouchPoints[0].setState(Qt::TouchPointPressed);
|
||||
rawTouchPoints[0].setScreenPos(screenPos);
|
||||
rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
|
||||
rawTouchPoints[0].setRawScreenPositions({{12, 34}, {56, 78}});
|
||||
ulong timestamp = 1234;
|
||||
QList<QWindowSystemInterface::TouchPoint> nativeTouchPoints =
|
||||
QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QTouchEvent::TouchPoint>() << rawTouchPoints[0], window);
|
||||
QWindowSystemInterface::handleTouchEvent(window, timestamp, touchScreenDevice, nativeTouchPoints);
|
||||
QCoreApplication::processEvents();
|
||||
QVERIFY(touchWidget.seenTouchBegin);
|
||||
QVERIFY(!touchWidget.seenTouchUpdate);
|
||||
QVERIFY(!touchWidget.seenTouchEnd);
|
||||
QCOMPARE(touchWidget.touchBeginPoints.count(), 1);
|
||||
QCOMPARE(touchWidget.timestamp, timestamp);
|
||||
QTouchEvent::TouchPoint touchBeginPoint = touchWidget.touchBeginPoints.first();
|
||||
const int touchPointId = (QTouchDevicePrivate::get(touchScreenDevice)->id << 24) + 1;
|
||||
const int secTouchPointId = (QTouchDevicePrivate::get(secondaryTouchScreenDevice)->id << 24) + 2;
|
||||
QCOMPARE(touchBeginPoint.id(), touchPointId);
|
||||
QCOMPARE(touchBeginPoint.state(), rawTouchPoints[0].state());
|
||||
QCOMPARE(touchBeginPoint.pos(), pos);
|
||||
|
||||
// press a point on secondaryTouchScreenDevice
|
||||
touchWidget.seenTouchBegin = false;
|
||||
rawTouchPoints[1].setState(Qt::TouchPointPressed);
|
||||
rawTouchPoints[1].setScreenPos(screenPos);
|
||||
rawTouchPoints[1].setNormalizedPos(normalized(rawTouchPoints[1].pos(), screenGeometry));
|
||||
rawTouchPoints[1].setRawScreenPositions({{90, 100}, {110, 120}});
|
||||
nativeTouchPoints =
|
||||
QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QTouchEvent::TouchPoint>() << rawTouchPoints[1], window);
|
||||
QWindowSystemInterface::handleTouchEvent(window, ++timestamp, secondaryTouchScreenDevice, nativeTouchPoints);
|
||||
QCoreApplication::processEvents();
|
||||
QVERIFY(!touchWidget.seenTouchEnd);
|
||||
QCOMPARE(touchWidget.touchBeginPoints.count(), 1);
|
||||
QCOMPARE(touchWidget.timestamp, timestamp);
|
||||
touchBeginPoint = touchWidget.touchBeginPoints[0];
|
||||
QCOMPARE(touchBeginPoint.id(), (QTouchDevicePrivate::get(secondaryTouchScreenDevice)->id << 24) + 2);
|
||||
QCOMPARE(touchBeginPoint.state(), rawTouchPoints[1].state());
|
||||
QCOMPARE(touchBeginPoint.pos(), pos);
|
||||
|
||||
// press another point on secondaryTouchScreenDevice
|
||||
touchWidget.seenTouchBegin = false;
|
||||
rawTouchPoints[2].setState(Qt::TouchPointPressed);
|
||||
rawTouchPoints[2].setScreenPos(screenPos);
|
||||
rawTouchPoints[2].setNormalizedPos(normalized(rawTouchPoints[2].pos(), screenGeometry));
|
||||
rawTouchPoints[2].setRawScreenPositions({{130, 140}, {150, 160}});
|
||||
nativeTouchPoints =
|
||||
QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QTouchEvent::TouchPoint>() << rawTouchPoints[2], window);
|
||||
QWindowSystemInterface::handleTouchEvent(window, ++timestamp, secondaryTouchScreenDevice, nativeTouchPoints);
|
||||
QCoreApplication::processEvents();
|
||||
QVERIFY(!touchWidget.seenTouchEnd);
|
||||
QCOMPARE(touchWidget.touchBeginPoints.count(), 1);
|
||||
QCOMPARE(touchWidget.timestamp, timestamp);
|
||||
touchBeginPoint = touchWidget.touchBeginPoints[0];
|
||||
QCOMPARE(touchBeginPoint.id(), (QTouchDevicePrivate::get(secondaryTouchScreenDevice)->id << 24) + 3);
|
||||
QCOMPARE(touchBeginPoint.state(), rawTouchPoints[2].state());
|
||||
QCOMPARE(touchBeginPoint.pos(), pos);
|
||||
|
||||
// moving the first point should translate to TouchUpdate
|
||||
rawTouchPoints[0].setState(Qt::TouchPointMoved);
|
||||
rawTouchPoints[0].setScreenPos(screenPos + delta);
|
||||
rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
|
||||
nativeTouchPoints =
|
||||
QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QTouchEvent::TouchPoint>() << rawTouchPoints[0], window);
|
||||
QWindowSystemInterface::handleTouchEvent(window, ++timestamp, touchScreenDevice, nativeTouchPoints);
|
||||
QCoreApplication::processEvents();
|
||||
QVERIFY(touchWidget.seenTouchBegin);
|
||||
QVERIFY(touchWidget.seenTouchUpdate);
|
||||
QVERIFY(!touchWidget.seenTouchEnd);
|
||||
QCOMPARE(touchWidget.touchUpdatePoints.count(), 1);
|
||||
QTouchEvent::TouchPoint touchUpdatePoint = touchWidget.touchUpdatePoints.first();
|
||||
QCOMPARE(touchUpdatePoint.id(), touchPointId);
|
||||
QCOMPARE(touchUpdatePoint.state(), rawTouchPoints[0].state());
|
||||
QCOMPARE(touchUpdatePoint.pos(), pos + delta);
|
||||
|
||||
// releasing the first point translates to TouchEnd
|
||||
rawTouchPoints[0].setState(Qt::TouchPointReleased);
|
||||
rawTouchPoints[0].setScreenPos(screenPos + delta + delta);
|
||||
rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
|
||||
nativeTouchPoints =
|
||||
QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QTouchEvent::TouchPoint>() << rawTouchPoints[0], window);
|
||||
QWindowSystemInterface::handleTouchEvent(window, ++timestamp, touchScreenDevice, nativeTouchPoints);
|
||||
QCoreApplication::processEvents();
|
||||
QVERIFY(touchWidget.seenTouchBegin);
|
||||
QVERIFY(touchWidget.seenTouchUpdate);
|
||||
QVERIFY(touchWidget.seenTouchEnd);
|
||||
QCOMPARE(touchWidget.touchEndPoints.count(), 1);
|
||||
QTouchEvent::TouchPoint touchEndPoint = touchWidget.touchEndPoints.first();
|
||||
QCOMPARE(touchEndPoint.id(), touchPointId);
|
||||
QCOMPARE(touchEndPoint.state(), rawTouchPoints[0].state());
|
||||
QCOMPARE(touchEndPoint.pos(), pos + delta + delta);
|
||||
|
||||
// Widgets don't normally handle this case: if a TouchEnd was seen before, then
|
||||
// WA_WState_AcceptedTouchBeginEvent will be false, and
|
||||
// QApplicationPrivate::translateRawTouchEvent will ignore touch events that aren't TouchBegin.
|
||||
// So we have to set it true. It _did_ in fact accept the touch begin from the secondary device,
|
||||
// but it also got a TouchEnd from the primary device in the meantime.
|
||||
touchWidget.setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, true);
|
||||
|
||||
// Releasing one point on the secondary touchscreen does not yet generate TouchEnd.
|
||||
touchWidget.seenTouchEnd = false;
|
||||
touchWidget.touchEndPoints.clear();
|
||||
rawTouchPoints[1].setState(Qt::TouchPointReleased);
|
||||
rawTouchPoints[2].setState(Qt::TouchPointStationary);
|
||||
nativeTouchPoints =
|
||||
QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QTouchEvent::TouchPoint>() << rawTouchPoints[1] << rawTouchPoints[2], window);
|
||||
QWindowSystemInterface::handleTouchEvent(window, ++timestamp, secondaryTouchScreenDevice, nativeTouchPoints);
|
||||
QCoreApplication::processEvents();
|
||||
QVERIFY(touchWidget.seenTouchBegin);
|
||||
QVERIFY(touchWidget.seenTouchUpdate);
|
||||
QVERIFY(!touchWidget.seenTouchEnd);
|
||||
QCOMPARE(touchWidget.touchUpdatePoints.count(), 2);
|
||||
QCOMPARE(touchWidget.touchUpdatePoints[0].id(), secTouchPointId);
|
||||
QCOMPARE(touchWidget.touchUpdatePoints[1].id(), secTouchPointId + 1);
|
||||
|
||||
// releasing the last point on the secondary touchscreen translates to TouchEnd
|
||||
touchWidget.seenTouchEnd = false;
|
||||
rawTouchPoints[2].setState(Qt::TouchPointReleased);
|
||||
nativeTouchPoints =
|
||||
QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QTouchEvent::TouchPoint>() << rawTouchPoints[2], window);
|
||||
QWindowSystemInterface::handleTouchEvent(window, ++timestamp, secondaryTouchScreenDevice, nativeTouchPoints);
|
||||
QCoreApplication::processEvents();
|
||||
QVERIFY(touchWidget.seenTouchBegin);
|
||||
QVERIFY(touchWidget.seenTouchUpdate);
|
||||
QVERIFY(touchWidget.seenTouchEnd);
|
||||
QCOMPARE(touchWidget.touchEndPoints.count(), 1);
|
||||
touchEndPoint = touchWidget.touchEndPoints.first();
|
||||
QCOMPARE(touchEndPoint.id(), secTouchPointId + 1);
|
||||
QCOMPARE(touchEndPoint.state(), rawTouchPoints[2].state());
|
||||
}
|
||||
|
||||
void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad()
|
||||
{
|
||||
tst_QTouchEventWidget touchWidget;
|
||||
|
Loading…
x
Reference in New Issue
Block a user