xcb: Delete touch points without target windows
When XCB_INPUT_TOUCH_BEGIN closes a popup, we then receive XCB_INPUT_TOUCH_END, and cannot find a target window (because it's destroyed). If we don't deliver it, we need to at least clear the stored point from QPointingDevicePrivate::activePoints. Then when we deliver the next touch press, m_fakeMouseSourcePointId also needs to be reset. It's now even more paramount that autotests (and real-world touchscreens) must never omit any active touchpoint from a touch event. If a point doesn't move, it must be included in the QTouchEvent, with Stationary state. If not, QGuiApp::processTouchEvent() could generate multiple TouchBegin events in a row, which gets other bits of logic confused, here and there. Fixes: QTBUG-94557 Fixes: QTBUG-98519 Fixes: QTBUG-102751 Fixes: QTBUG-103706 Pick-to: 6.2 6.3 5.15 Change-Id: Ia95e410a2bb8bc7784aa5d296fac2b89e53a9f55 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
parent
9af1f3557a
commit
efc02f9cc3
@ -2984,7 +2984,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
|
||||
QEvent::Type mouseEventType = QEvent::MouseMove;
|
||||
Qt::MouseButton button = Qt::NoButton;
|
||||
Qt::MouseButtons buttons = Qt::LeftButton;
|
||||
if (eventType == QEvent::TouchBegin && m_fakeMouseSourcePointId < 0) {
|
||||
if (eventType == QEvent::TouchBegin || m_fakeMouseSourcePointId < 0) {
|
||||
m_fakeMouseSourcePointId = touchEvent.point(0).id();
|
||||
qCDebug(lcPtrDispatch) << "synthesizing mouse events from touchpoint" << m_fakeMouseSourcePointId;
|
||||
}
|
||||
|
@ -748,8 +748,12 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
|
||||
event->event_type, xiDeviceEvent->sequence, xiDeviceEvent->detail,
|
||||
fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y),
|
||||
fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event);
|
||||
if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event))
|
||||
if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) {
|
||||
xi2ProcessTouch(xiDeviceEvent, platformWindow);
|
||||
} else { // When the window cannot be matched, delete it from touchPoints
|
||||
if (TouchDeviceData *dev = touchDeviceForId(xiDeviceEvent->sourceid))
|
||||
dev->touchPoints.remove((xiDeviceEvent->detail % INT_MAX));
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (xiEnterEvent && eventListener) {
|
||||
|
@ -1157,14 +1157,18 @@ void tst_QWindow::touchToMouseTranslation()
|
||||
QVERIFY(QTest::qWaitForWindowExposed(&window));
|
||||
|
||||
QList<QWindowSystemInterface::TouchPoint> points;
|
||||
QWindowSystemInterface::TouchPoint tp1, tp2;
|
||||
QWindowSystemInterface::TouchPoint tp1, tp2, tp3;
|
||||
const QRectF pressArea(101, 102, 4, 4);
|
||||
const QRectF pressArea1(107, 110, 4, 4);
|
||||
const QRectF moveArea(105, 108, 4, 4);
|
||||
tp1.id = 1;
|
||||
tp1.state = QEventPoint::State::Pressed;
|
||||
tp1.area = QHighDpi::toNativePixels(pressArea, &window);
|
||||
tp2.id = 2;
|
||||
tp2.state = QEventPoint::State::Pressed;
|
||||
tp3.id = 3;
|
||||
tp3.state = QEventPoint::State::Pressed;
|
||||
tp3.area = QHighDpi::toNativePixels(pressArea1, &window);
|
||||
points << tp1 << tp2;
|
||||
QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points);
|
||||
// Now an update but with changed list order. The mouse event should still
|
||||
@ -1246,6 +1250,40 @@ void tst_QWindow::touchToMouseTranslation()
|
||||
QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points);
|
||||
QCoreApplication::processEvents();
|
||||
QTRY_COMPARE(window.mouseReleaseButton, 1);
|
||||
|
||||
points.clear();
|
||||
points.append(tp1);
|
||||
points[0].state = QEventPoint::State::Pressed;
|
||||
QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points);
|
||||
QCoreApplication::processEvents();
|
||||
points.clear();
|
||||
points.append(tp2);
|
||||
points[0].state = QEventPoint::State::Pressed;
|
||||
QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points);
|
||||
QCoreApplication::processEvents();
|
||||
points.clear();
|
||||
points.append(tp3);
|
||||
points[0].state = QEventPoint::State::Pressed;
|
||||
QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points);
|
||||
QCoreApplication::processEvents();
|
||||
QTRY_COMPARE(window.mousePressButton, 1);
|
||||
|
||||
points.clear();
|
||||
points.append(tp2);
|
||||
points[0].state = QEventPoint::State::Released;
|
||||
QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points);
|
||||
QCoreApplication::processEvents();
|
||||
points.clear();
|
||||
points.append(tp3);
|
||||
points[0].state = QEventPoint::State::Released;
|
||||
QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points);
|
||||
QCoreApplication::processEvents();
|
||||
points.clear();
|
||||
points.append(tp1);
|
||||
points[0].state = QEventPoint::State::Released;
|
||||
QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points);
|
||||
QCoreApplication::processEvents();
|
||||
QTRY_COMPARE(window.mouseReleaseButton, 1);
|
||||
}
|
||||
|
||||
void tst_QWindow::touchToMouseTranslationForDevices()
|
||||
|
@ -269,7 +269,7 @@ void tst_QGestureRecognizer::swipeGesture()
|
||||
|
||||
// Press point #3
|
||||
points.append(points.last() + fingerDistance);
|
||||
swipeSequence.press(points.size() - 1, points.last(), &widget);
|
||||
swipeSequence.stationary(0).stationary(1).press(points.size() - 1, points.last(), &widget);
|
||||
swipeSequence.commit();
|
||||
Q_ASSERT(points.size() == swipePoints);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user