From 40330b8f0a717098982d1f54f34a18a8262b1f55 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 19 Apr 2021 16:00:35 +0200 Subject: [PATCH] Add grabber context pointers In Qt Quick we now need to keep track of which QQDeliveryAgent is responsible when a point is grabbed, either passively or exclusively. When we re-deliver to that grabber, we need to do it via the same agent, so that the same scene transform is used, and the grabber will see the event in the correct coordinate system. It's easier to track this mapping here instead of in a separate map in Qt Quick. Pick-to: 6.1 Task-number: QTBUG-92944 Change-Id: I69f769c694d0da24885cdf4087e5032022bff629 Reviewed-by: Volker Hilsheimer --- src/gui/kernel/qevent.cpp | 2 +- src/gui/kernel/qpointingdevice.cpp | 21 +++++++++++-------- src/gui/kernel/qpointingdevice_p.h | 4 +++- .../kernel/qmouseevent/tst_qmouseevent.cpp | 2 +- .../kernel/qtouchevent/tst_qtouchevent.cpp | 2 +- 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 7e5e7ac7032..d856ebfc3ec 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -401,7 +401,7 @@ QList > QPointerEvent::passiveGrabbers(const QEventPoint &poin qWarning() << "point is not in activePoints" << point; return {}; } - return persistentPoint->passiveGrabbers; + return persistentPoint->passiveGrabbers.keys(); } /*! diff --git a/src/gui/kernel/qpointingdevice.cpp b/src/gui/kernel/qpointingdevice.cpp index 176a5fedf46..c9b91b7cba0 100644 --- a/src/gui/kernel/qpointingdevice.cpp +++ b/src/gui/kernel/qpointingdevice.cpp @@ -508,6 +508,8 @@ void QPointingDevicePrivate::setExclusiveGrabber(const QPointerEvent *event, con QMutableEventPoint::from(persistentPoint->eventPoint).setGlobalGrabPosition(point.globalPosition()); if (exclusiveGrabber) emit q->grabChanged(exclusiveGrabber, QPointingDevice::GrabExclusive, event, point); + else + persistentPoint->exclusiveGrabberContext.clear(); } /*! @@ -540,7 +542,7 @@ bool QPointingDevicePrivate::addPassiveGrabber(const QPointerEvent *event, const qCDebug(lcPointerGrab) << name << "point" << point.id() << point.state() << ": grab (passive)" << grabber; } - persistentPoint->passiveGrabbers << grabber; + persistentPoint->passiveGrabbers.insert(grabber, {}); emit q->grabChanged(grabber, QPointingDevice::GrabPassive, event, point); return true; } @@ -553,14 +555,14 @@ bool QPointingDevicePrivate::removePassiveGrabber(const QPointerEvent *event, co qWarning() << "point is not in activePoints" << point; return false; } - int i = persistentPoint->passiveGrabbers.indexOf(grabber); - if (i >= 0) { + auto pgit = persistentPoint->passiveGrabbers.find(grabber); + if (pgit != persistentPoint->passiveGrabbers.end()) { if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) { qCDebug(lcPointerGrab) << name << "point" << point.id() << point.state() << ": removing passive grabber" << grabber; } emit q->grabChanged(grabber, QPointingDevice::UngrabPassive, event, point); - persistentPoint->passiveGrabbers.removeAt(i); + persistentPoint->passiveGrabbers.erase(pgit); return true; } return false; @@ -578,9 +580,9 @@ void QPointingDevicePrivate::clearPassiveGrabbers(const QPointerEvent *event, co return; if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) { qCDebug(lcPointerGrab) << name << "point" << point.id() << point.state() - << ": clearing" << persistentPoint->passiveGrabbers; + << ": clearing" << persistentPoint->passiveGrabbers.keys(); } - for (auto g : persistentPoint->passiveGrabbers) + for (auto g : persistentPoint->passiveGrabbers.keys()) emit q->grabChanged(g, QPointingDevice::UngrabPassive, event, point); persistentPoint->passiveGrabbers.clear(); } @@ -606,15 +608,16 @@ void QPointingDevicePrivate::removeGrabber(QObject *grabber, bool cancel) << "@" << epd.eventPoint.scenePosition() << ": grab" << grabber << "-> nullptr"; epd.exclusiveGrabber.clear(); + epd.exclusiveGrabberContext.clear(); emit q->grabChanged(grabber, cancel ? QPointingDevice::CancelGrabExclusive : QPointingDevice::UngrabExclusive, nullptr, epd.eventPoint); } - int pi = epd.passiveGrabbers.indexOf(grabber); - if (pi >= 0) { + auto pgit = epd.passiveGrabbers.find(grabber); + if (pgit != epd.passiveGrabbers.end()) { qCDebug(lcPointerGrab) << name << "point" << epd.eventPoint.id() << epd.eventPoint.state() << ": removing passive grabber" << grabber; - epd.passiveGrabbers.removeAt(pi); + epd.passiveGrabbers.erase(pgit); emit q->grabChanged(grabber, cancel ? QPointingDevice::CancelGrabPassive : QPointingDevice::UngrabPassive, nullptr, epd.eventPoint); diff --git a/src/gui/kernel/qpointingdevice_p.h b/src/gui/kernel/qpointingdevice_p.h index 04823a3e86b..d67dedf9e19 100644 --- a/src/gui/kernel/qpointingdevice_p.h +++ b/src/gui/kernel/qpointingdevice_p.h @@ -85,10 +85,12 @@ public: /*! \internal This struct (stored in activePoints) holds persistent state between event deliveries. */ + using PassiveGrabbersMap = QFlatMap, QPointer>; struct EventPointData { QEventPoint eventPoint; QPointer exclusiveGrabber; - QList > passiveGrabbers; + QPointer exclusiveGrabberContext; // extra info about where the grab happened + PassiveGrabbersMap passiveGrabbers; // key: passive grabber; value: context (where the grab happened) }; EventPointData *queryPointById(int id) const; EventPointData *pointById(int id) const; diff --git a/tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp b/tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp index d5174e09421..cdf11ec54ac 100644 --- a/tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp +++ b/tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp @@ -290,7 +290,7 @@ void tst_QMouseEvent::grabbers() QCOMPARE(firstEPD->exclusiveGrabber, grabExclusive ? testMouseWidget : nullptr); QCOMPARE(firstEPD->passiveGrabbers.count(), grabPassive ? 1 : 0); if (grabPassive) - QCOMPARE(firstEPD->passiveGrabbers.first(), testMouseWidget); + QCOMPARE(firstEPD->passiveGrabbers.keys().first(), testMouseWidget); // Ensure that grabbers are forgotten after release delivery QTest::mouseRelease(testMouseWidget, Qt::LeftButton, Qt::KeyboardModifiers(), {10, 10}); diff --git a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp index 28c33e82265..fa3f495c236 100644 --- a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp +++ b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp @@ -1949,7 +1949,7 @@ void tst_QTouchEvent::grabbers() QCOMPARE(devPriv->pointById(0)->exclusiveGrabber, grabExclusive ? &w : nullptr); QCOMPARE(devPriv->pointById(0)->passiveGrabbers.count(), grabPassive ? 1 : 0); if (grabPassive) - QCOMPARE(devPriv->pointById(0)->passiveGrabbers.first(), &w); + QCOMPARE(devPriv->pointById(0)->passiveGrabbers.keys().first(), &w); // Ensure that eventpoints are forgotten after release delivery points.first().state = QEventPoint::State::Released;