QGuiAppPrivate::processMouseEvent: don't assume eventpoint didn't move
During delivery of a pointer event, another type might be synthesized from it; and we are not yet "done" with all access to the original event until the delivery of the synthesized event is completed. Further, there could be a nested event loop if exec() is called on a dialog. If QPointingDevicePrivate::pointById() causes activePoints to grow (for example if we handle a fresh incoming touch event in the nested event loop), reallocation could cause the persistentPoint reference near the top of processMouseEvent() to be dangling by the time we get to the bottom; so we need to call queryPointById() again to be sure to get the persistent QEventPoint that is actually used in the current mouse event to ungrab. Fixes: QTBUG-97157 Pick-to: 6.2 6.3 Change-Id: Ib3b90eef5db691675b03474fd75981e972d11d2d Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
parent
26a0638222
commit
bd71fb2514
@ -2173,13 +2173,12 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
|
||||
QPointF localPoint = e->localPos;
|
||||
bool doubleClick = false;
|
||||
auto persistentEPD = devPriv->pointById(0);
|
||||
const auto &persistentPoint = persistentEPD->eventPoint;
|
||||
|
||||
if (mouseMove) {
|
||||
QGuiApplicationPrivate::lastCursorPosition = globalPoint;
|
||||
const auto doubleClickDistance = (e->device && e->device->type() == QInputDevice::DeviceType::Mouse ?
|
||||
mouseDoubleClickDistance : touchDoubleTapDistance);
|
||||
const auto pressPos = persistentPoint.globalPressPosition();
|
||||
const auto pressPos = persistentEPD->eventPoint.globalPressPosition();
|
||||
if (qAbs(globalPoint.x() - pressPos.x()) > doubleClickDistance ||
|
||||
qAbs(globalPoint.y() - pressPos.y()) > doubleClickDistance)
|
||||
mousePressButton = Qt::NoButton;
|
||||
@ -2187,7 +2186,8 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
|
||||
mouse_buttons = e->buttons;
|
||||
if (mousePress) {
|
||||
ulong doubleClickInterval = static_cast<ulong>(QGuiApplication::styleHints()->mouseDoubleClickInterval());
|
||||
doubleClick = e->timestamp - persistentPoint.pressTimestamp() < doubleClickInterval && button == mousePressButton;
|
||||
doubleClick = e->timestamp - persistentEPD->eventPoint.pressTimestamp()
|
||||
< doubleClickInterval && button == mousePressButton;
|
||||
mousePressButton = button;
|
||||
}
|
||||
}
|
||||
@ -2231,9 +2231,11 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
|
||||
#endif
|
||||
|
||||
QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, e->buttons, e->modifiers, e->source, device);
|
||||
Q_ASSERT(devPriv->pointById(0) == persistentEPD); // we don't expect reallocation in QPlatformCursor::pointerEvenmt()
|
||||
// restore globalLastPosition to avoid invalidating the velocity calculations,
|
||||
// because the QPlatformCursor mouse event above was in native coordinates
|
||||
QMutableEventPoint::setGlobalLastPosition(persistentEPD->eventPoint, lastGlobalPosition);
|
||||
persistentEPD = nullptr; // incoming and synth events can cause reallocation during delivery, so don't use this again
|
||||
// ev now contains a detached copy of the QEventPoint from QPointingDevicePrivate::activePoints
|
||||
ev.setTimestamp(e->timestamp);
|
||||
if (window->d_func()->blockedByModalWindow && !qApp->d_func()->popupActive()) {
|
||||
@ -2290,8 +2292,10 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
|
||||
}
|
||||
}
|
||||
if (type == QEvent::MouseButtonRelease && e->buttons == Qt::NoButton) {
|
||||
ev.setExclusiveGrabber(persistentPoint, nullptr);
|
||||
ev.clearPassiveGrabbers(persistentPoint);
|
||||
if (auto *persistentEPD = devPriv->queryPointById(0)) {
|
||||
ev.setExclusiveGrabber(persistentEPD->eventPoint, nullptr);
|
||||
ev.clearPassiveGrabbers(persistentEPD->eventPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user