diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2017-02-13 15:18:43 +0100 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2017-02-20 13:55:33 +0000 |
commit | 8967a1b7b86306879a3113b290610b03727670ff (patch) | |
tree | 444521cfa170c04890745b66365123fcdd4eff3a /src | |
parent | e9a2155cfd76666043dee8c034708a0149f3e2e6 (diff) |
clarify further exclusive vs. passive grabs
Add documentation to the grab-related event and eventpoint methods.
Rename "grabber" functions which relate only to the exclusive grab,
in cases where it would otherwise be ambiguous.
And a few other documentation changes.
Change-Id: I1a203c8c06a19d4abdb000f08b387c38341ef476
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/quick/handlers/qquickpointersinglehandler.cpp | 4 | ||||
-rw-r--r-- | src/quick/items/qquickevents.cpp | 124 | ||||
-rw-r--r-- | src/quick/items/qquickevents_p_p.h | 22 | ||||
-rw-r--r-- | src/quick/items/qquickitem.cpp | 11 | ||||
-rw-r--r-- | src/quick/items/qquickitem_p.h | 2 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 24 |
6 files changed, 137 insertions, 50 deletions
diff --git a/src/quick/handlers/qquickpointersinglehandler.cpp b/src/quick/handlers/qquickpointersinglehandler.cpp index 41c9e1f322..c0c88f3852 100644 --- a/src/quick/handlers/qquickpointersinglehandler.cpp +++ b/src/quick/handlers/qquickpointersinglehandler.cpp @@ -83,7 +83,7 @@ bool QQuickPointerSingleHandler::wantsPointerEvent(QQuickPointerEvent *event) int c = event->pointCount(); for (int i = 0; i < c && !m_pointId; ++i) { QQuickEventPoint *p = event->point(i); - if (!p->grabber() && wantsEventPoint(p)) { + if (!p->exclusiveGrabber() && wantsEventPoint(p)) { m_pointId = p->pointId(); p->setAccepted(); } @@ -149,7 +149,7 @@ void QQuickPointerSingleHandler::handleGrabCancel(QQuickEventPoint *point) void QQuickPointerSingleHandler::onGrabChanged(QQuickEventPoint *point) { - bool grabbing = (point->grabber() == this); + bool grabbing = (point->exclusiveGrabber() == this); setActive(grabbing); if (grabbing) m_sceneGrabPos = point->sceneGrabPos(); diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index 0af19ff750..1843d2b656 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -566,12 +566,26 @@ void QQuickEventPoint::invalidate() m_pointId = 0; } -QObject *QQuickEventPoint::grabber() const +/*! + If this point has an exclusive grabber, returns a pointer to it; else + returns null, if there is no grabber. The grabber could be either + an Item or a PointerHandler. +*/ +QObject *QQuickEventPoint::exclusiveGrabber() const { return m_exclusiveGrabber.data(); } -void QQuickEventPoint::setGrabber(QObject *grabber) +/*! + Set the given Item or PointerHandler as the exclusive grabber of this point. + If there was already an exclusive grab, it will be canceled. If there + were passive grabbers, they will continue to lurk, but the exclusive grab + is a behavioral override of the passive grab as long as it remains. + If you already know whether the grabber is to be an Item or a PointerHandler, + you should instead call setGrabberItem() or setGrabberPointerHandler(), + because it is slightly more efficient. +*/ +void QQuickEventPoint::setExclusiveGrabber(QObject *grabber) { if (QQuickPointerHandler *phGrabber = qmlobject_cast<QQuickPointerHandler *>(grabber)) setGrabberPointerHandler(phGrabber, true); @@ -579,11 +593,22 @@ void QQuickEventPoint::setGrabber(QObject *grabber) setGrabberItem(static_cast<QQuickItem *>(grabber)); } +/*! + If the exclusive grabber of this point is an Item, returns a + pointer to that Item; else returns null, if there is no grabber or if + the grabber is a PointerHandler. +*/ QQuickItem *QQuickEventPoint::grabberItem() const { return (m_grabberIsHandler ? nullptr : static_cast<QQuickItem *>(m_exclusiveGrabber.data())); } +/*! + Set the given Item \a grabber as the exclusive grabber of this point. + If there was already an exclusive grab, it will be canceled. If there + were passive grabbers, they will continue to lurk, but the exclusive grab + is a behavioral override of the passive grab as long as it remains. +*/ void QQuickEventPoint::setGrabberItem(QQuickItem *grabber) { if (grabber != m_exclusiveGrabber.data()) { @@ -597,11 +622,21 @@ void QQuickEventPoint::setGrabberItem(QQuickItem *grabber) } } +/*! + If the exclusive grabber of this point is a PointerHandler, returns a + pointer to that handler; else returns null, if there is no grabber or if + the grabber is an Item. +*/ QQuickPointerHandler *QQuickEventPoint::grabberPointerHandler() const { return (m_grabberIsHandler ? static_cast<QQuickPointerHandler *>(m_exclusiveGrabber.data()) : nullptr); } +/*! + Set the given PointerHandler \a grabber as grabber of this point. If \a + exclusive is true, it will override any other grabs; if false, \a grabber + will be added to the list of passive grabbers of this point. +*/ void QQuickEventPoint::setGrabberPointerHandler(QQuickPointerHandler *grabber, bool exclusive) { if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) { @@ -633,6 +668,11 @@ void QQuickEventPoint::setGrabberPointerHandler(QQuickPointerHandler *grabber, b } } +/*! + If this point has an existing exclusive grabber (Item or PointerHandler), + inform the grabber that its grab is canceled, and remove it as grabber. + This normally happens when the grab is stolen by another Item. +*/ void QQuickEventPoint::cancelExclusiveGrab() { if (m_exclusiveGrabber.isNull()) { @@ -648,6 +688,11 @@ void QQuickEventPoint::cancelExclusiveGrab() m_exclusiveGrabber.clear(); } +/*! + If this point has the given \a handler as a passive grabber, + inform the grabber that its grab is canceled, and remove it as grabber. + This normally happens when another Item or PointerHandler does an exclusive grab. +*/ void QQuickEventPoint::cancelPassiveGrab(QQuickPointerHandler *handler) { if (m_passiveGrabbers.removeOne(QPointer<QQuickPointerHandler>(handler))) { @@ -659,6 +704,17 @@ void QQuickEventPoint::cancelPassiveGrab(QQuickPointerHandler *handler) } } +/*! + If the given \a handler is grabbing this point passively, exclusively + or both, cancel the grab and remove it as grabber. + This normally happens when the handler decides that the behavior of this + point can no longer satisfy the handler's behavioral constraints within + the remainder of the gesture which the user is performing: for example + the handler tries to detect a tap but a drag is occurring instead, or + it tries to detect a drag in one direction but the drag is going in + another direction. In such cases the handler no longer needs or wants + to be informed of any further movements of this point. +*/ void QQuickEventPoint::cancelAllGrabs(QQuickPointerHandler *handler) { if (m_exclusiveGrabber == handler) { @@ -668,6 +724,12 @@ void QQuickEventPoint::cancelAllGrabs(QQuickPointerHandler *handler) cancelPassiveGrab(handler); } +/*! + Set this point as \a accepted (true) or rejected (false). + Accepting a point is intended to stop event propagation. + It does not imply any kind of grab, passive or exclusive. + TODO explain further under what conditions propagation really does stop... +*/ void QQuickEventPoint::setAccepted(bool accepted) { if (m_accept != accepted) { @@ -707,11 +769,10 @@ Q_GLOBAL_STATIC(PointDataForPointIdMap, g_previousPointData) static const int PointVelocityAgeLimit = 500; // milliseconds /*! - * \interal - * \brief Estimates the velocity based on a weighted average of all previous velocities. - * The older the velocity is, the less significant it becomes for the estimate. - * \return - */ + \internal + Estimates the velocity based on a weighted average of all previous velocities. + The older the velocity is, the less significant it becomes for the estimate. +*/ QVector2D QQuickEventPoint::estimatedVelocity() const { PointVelocityData *prevPoint = g_previousPointData->value(m_pointId); @@ -838,7 +899,7 @@ QQuickPointerEvent *QQuickPointerTouchEvent::reset(QEvent *event) QObject *grabber = nullptr; QVector <QPointer <QQuickPointerHandler> > passiveGrabbers; if (auto point = pointById(tps.at(i).id())) { - grabber = point->grabber(); + grabber = point->exclusiveGrabber(); passiveGrabbers = point->passiveGrabbers(); } grabbers.append(grabber); @@ -854,7 +915,7 @@ QQuickPointerEvent *QQuickPointerTouchEvent::reset(QEvent *event) point->setGrabberItem(nullptr); point->clearPassiveGrabbers(); } else { - point->setGrabber(grabbers.at(i)); + point->setExclusiveGrabber(grabbers.at(i)); point->setPassiveGrabbers(passiveGrabberses.at(i)); } } @@ -902,7 +963,7 @@ bool QQuickPointerMouseEvent::allUpdatedPointsAccepted() const { bool QQuickPointerMouseEvent::allPointsGrabbed() const { - return m_mousePoint->grabber() != nullptr; + return m_mousePoint->exclusiveGrabber() != nullptr; } QMouseEvent *QQuickPointerMouseEvent::asMouseEvent(const QPointF &localPos) const @@ -912,22 +973,31 @@ QMouseEvent *QQuickPointerMouseEvent::asMouseEvent(const QPointF &localPos) cons return event; } -QVector<QObject *> QQuickPointerMouseEvent::grabbers() const +/*! + Returns the exclusive grabber of this event, if any, in a vector. +*/ +QVector<QObject *> QQuickPointerMouseEvent::exclusiveGrabbers() const { QVector<QObject *> result; - if (QObject *grabber = m_mousePoint->grabber()) + if (QObject *grabber = m_mousePoint->exclusiveGrabber()) result << grabber; return result; } +/*! + Remove all passive and exclusive grabbers of this event, without notifying. +*/ void QQuickPointerMouseEvent::clearGrabbers() const { m_mousePoint->setGrabberItem(nullptr); m_mousePoint->clearPassiveGrabbers(); } -bool QQuickPointerMouseEvent::hasGrabber(const QQuickPointerHandler *handler) const +/*! + Returns whether the given \a handler is the exclusive grabber of this event. +*/ +bool QQuickPointerMouseEvent::hasExclusiveGrabber(const QQuickPointerHandler *handler) const { - return m_mousePoint->grabber() == handler; + return m_mousePoint->exclusiveGrabber() == handler; } bool QQuickPointerMouseEvent::isPressEvent() const @@ -957,18 +1027,20 @@ bool QQuickPointerTouchEvent::allUpdatedPointsAccepted() const { bool QQuickPointerTouchEvent::allPointsGrabbed() const { for (int i = 0; i < m_pointCount; ++i) { - if (!m_touchPoints.at(i)->grabber()) + if (!m_touchPoints.at(i)->exclusiveGrabber()) return false; } return true; } -QVector<QObject *> QQuickPointerTouchEvent::grabbers() const +/*! + Returns the exclusive grabbers of all points in this event, if any, in a vector. +*/ +QVector<QObject *> QQuickPointerTouchEvent::exclusiveGrabbers() const { QVector<QObject *> result; for (int i = 0; i < m_pointCount; ++i) { - auto point = m_touchPoints.at(i); - if (QObject *grabber = point->grabber()) { + if (QObject *grabber = m_touchPoints.at(i)->exclusiveGrabber()) { if (!result.contains(grabber)) result << grabber; } @@ -976,17 +1048,25 @@ QVector<QObject *> QQuickPointerTouchEvent::grabbers() const return result; } +/*! + Remove all passive and exclusive grabbers of all touchpoints in this event, + without notifying. +*/ void QQuickPointerTouchEvent::clearGrabbers() const { for (auto point: m_touchPoints) { - point->setGrabber(nullptr); + point->setGrabberItem(nullptr); point->clearPassiveGrabbers(); } } -bool QQuickPointerTouchEvent::hasGrabber(const QQuickPointerHandler *handler) const +/*! + Returns whether the given \a handler is the exclusive grabber of any + touchpoint within this event. +*/ +bool QQuickPointerTouchEvent::hasExclusiveGrabber(const QQuickPointerHandler *handler) const { for (auto point: m_touchPoints) - if (point->grabber() == handler) + if (point->exclusiveGrabber() == handler) return true; return false; } @@ -1111,7 +1191,7 @@ QTouchEvent *QQuickPointerTouchEvent::touchEventForItem(QQuickItem *item, bool i auto p = m_touchPoints.at(i); if (p->isAccepted()) continue; - bool isGrabber = p->grabber() == item; + bool isGrabber = p->exclusiveGrabber() == item; bool isPressInside = p->state() == QQuickEventPoint::Pressed && item->contains(item->mapFromScene(p->scenePos())); if (!(isGrabber || isPressInside || isFiltering)) continue; diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h index d042f318e9..00da53eb48 100644 --- a/src/quick/items/qquickevents_p_p.h +++ b/src/quick/items/qquickevents_p_p.h @@ -263,7 +263,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickEventPoint : public QObject Q_PROPERTY(qreal timeHeld READ timeHeld) Q_PROPERTY(QVector2D velocity READ velocity) Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted) - Q_PROPERTY(QObject *grabber READ grabber WRITE setGrabber) + Q_PROPERTY(QObject *exclusiveGrabber READ exclusiveGrabber WRITE setExclusiveGrabber) public: enum State { @@ -295,14 +295,14 @@ public: bool isAccepted() const { return m_accept; } void setAccepted(bool accepted = true); bool isDraggedOverThreshold() const; - QObject *grabber() const; - void setGrabber(QObject *grabber); + QObject *exclusiveGrabber() const; + void setExclusiveGrabber(QObject *exclusiveGrabber); QQuickItem *grabberItem() const; - void setGrabberItem(QQuickItem *grabber); + void setGrabberItem(QQuickItem *exclusiveGrabber); QQuickPointerHandler *grabberPointerHandler() const; - void setGrabberPointerHandler(QQuickPointerHandler *grabber, bool exclusive = false); + void setGrabberPointerHandler(QQuickPointerHandler *exclusiveGrabber, bool exclusive = false); Q_INVOKABLE void cancelExclusiveGrab(); Q_INVOKABLE void cancelPassiveGrab(QQuickPointerHandler *handler); @@ -409,9 +409,9 @@ public: // helpers for C++ only (during event delivery) virtual int pointCount() const = 0; virtual QQuickEventPoint *point(int i) const = 0; virtual QQuickEventPoint *pointById(quint64 pointId) const = 0; - virtual QVector<QObject *> grabbers() const = 0; + virtual QVector<QObject *> exclusiveGrabbers() const = 0; virtual void clearGrabbers() const = 0; - virtual bool hasGrabber(const QQuickPointerHandler *handler) const = 0; + virtual bool hasExclusiveGrabber(const QQuickPointerHandler *handler) const = 0; ulong timestamp() const { return m_event->timestamp(); } @@ -442,9 +442,9 @@ public: bool allPointsAccepted() const override; bool allUpdatedPointsAccepted() const override; bool allPointsGrabbed() const override; - QVector<QObject *> grabbers() const override; + QVector<QObject *> exclusiveGrabbers() const override; void clearGrabbers() const override; - bool hasGrabber(const QQuickPointerHandler *handler) const override; + bool hasExclusiveGrabber(const QQuickPointerHandler *handler) const override; QMouseEvent *asMouseEvent(const QPointF& localPos) const; @@ -476,9 +476,9 @@ public: bool allPointsAccepted() const override; bool allUpdatedPointsAccepted() const override; bool allPointsGrabbed() const override; - QVector<QObject *> grabbers() const override; + QVector<QObject *> exclusiveGrabbers() const override; void clearGrabbers() const override; - bool hasGrabber(const QQuickPointerHandler *handler) const override; + bool hasExclusiveGrabber(const QQuickPointerHandler *handler) const override; QMouseEvent *syntheticMouseEvent(int pointID, QQuickItem *relativeTo) const; QTouchEvent *touchEventForItem(QQuickItem *item, bool isFiltering = false) const; diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 9b91b4bda4..7adf455ac6 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -5091,7 +5091,14 @@ void QQuickItemPrivate::deliverShortcutOverrideEvent(QKeyEvent *event) } } -bool QQuickItemPrivate::handlePointerEvent(QQuickPointerEvent *event, bool avoidGrabber) +/*! + \internal + Deliver the \a event to all PointerHandlers which are in the pre-determined + eventDeliveryTargets() vector. If \a avoidExclusiveGrabber is true, it skips + delivery to any handler which is the exclusive grabber of any point within this event + (because delivery to exclusive grabbers is handled separately). +*/ +bool QQuickItemPrivate::handlePointerEvent(QQuickPointerEvent *event, bool avoidExclusiveGrabber) { Q_Q(QQuickItem); bool delivered = false; @@ -5099,7 +5106,7 @@ bool QQuickItemPrivate::handlePointerEvent(QQuickPointerEvent *event, bool avoid if (extra.isAllocated()) { for (QQuickPointerHandler *handler : extra->pointerHandlers) { qCDebug(lcPointerHandlerDispatch) << " delivering" << event << "to" << handler << "on" << q; - if ((!avoidGrabber || !event->hasGrabber(handler)) && !eventDeliveryTargets.contains(handler)) { + if ((!avoidExclusiveGrabber || !event->hasExclusiveGrabber(handler)) && !eventDeliveryTargets.contains(handler)) { handler->handlePointerEvent(event); delivered = true; eventDeliveryTargets.append(handler); diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index b39c437da5..6ce6a233d6 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -563,7 +563,7 @@ public: #endif void deliverShortcutOverrideEvent(QKeyEvent *); - virtual bool handlePointerEvent(QQuickPointerEvent *, bool avoidGrabber = false); + virtual bool handlePointerEvent(QQuickPointerEvent *, bool avoidExclusiveGrabber = false); bool isTransparentForPositioner() const; void setTransparentForPositioner(bool trans); diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 669e521b7f..0cd9357b9a 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -790,7 +790,7 @@ void QQuickWindowPrivate::grabTouchPoints(QObject *grabber, const QVector<int> & auto point = touchMouseDevice->pointerEvent()->pointById(id); auto touchMouseGrabber = point->grabberItem(); if (touchMouseGrabber) { - point->setGrabber(nullptr); + point->setExclusiveGrabber(nullptr); touchMouseGrabber->mouseUngrabEvent(); ungrab.insert(touchMouseGrabber); touchMouseDevice = nullptr; @@ -804,11 +804,11 @@ void QQuickWindowPrivate::grabTouchPoints(QObject *grabber, const QVector<int> & auto point = device->pointerEvent()->pointById(id); if (!point) continue; - QObject *oldGrabber = point->grabber(); + QObject *oldGrabber = point->exclusiveGrabber(); if (oldGrabber == grabber) continue; - point->setGrabber(grabber); + point->setExclusiveGrabber(grabber); if (oldGrabber) ungrab.insert(oldGrabber); } @@ -827,7 +827,7 @@ void QQuickWindowPrivate::removeGrabber(QQuickItem *grabber, bool mouse, bool to for (auto device : touchDevices) { auto pointerEvent = device->pointerEvent(); for (int i = 0; i < pointerEvent->pointCount(); ++i) { - if (pointerEvent->point(i)->grabber() == grabber) { + if (pointerEvent->point(i)->exclusiveGrabber() == grabber) { pointerEvent->point(i)->setGrabberItem(nullptr); // FIXME send ungrab event only once grabber->touchUngrabEvent(); @@ -1658,7 +1658,7 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven auto point = pointerEvent->point(0); lastMousePosition = point->scenePos(); - if (point->grabber()) { + if (point->exclusiveGrabber()) { bool mouseIsReleased = (point->state() == QQuickEventPoint::Released && pointerEvent->buttons() == Qt::NoButton); if (auto grabber = point->grabberItem()) { if (sendFilteredPointerEvent(pointerEvent, grabber)) @@ -1721,7 +1721,7 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven if (itemPrivate->handlePointerEvent(pointerEvent, true)) // avoid re-delivering to grabbers delivered = true; } - if (point->grabber()) + if (point->exclusiveGrabber()) break; } } @@ -1929,7 +1929,7 @@ bool QQuickWindowPrivate::deliverTouchCancelEvent(QTouchEvent *event) // A TouchCancel event will typically not contain any points. // Deliver it to all items that have active touches. QQuickPointerEvent *pointerEvent = QQuickPointerDevice::touchDevice(event->device())->pointerEvent(); - QVector<QObject *> grabbers = pointerEvent->grabbers(); + QVector<QObject *> grabbers = pointerEvent->exclusiveGrabbers(); for (QObject *grabber: qAsConst(grabbers)) { if (QQuickItem *grabberItem = qmlobject_cast<QQuickItem *>(grabber)) @@ -2106,7 +2106,7 @@ void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event) updateCursor(event->windowPos()); #endif - if (!QQuickPointerDevice::genericMouseDevice()->pointerEvent()->point(0)->grabber()) { + if (!QQuickPointerDevice::genericMouseDevice()->pointerEvent()->point(0)->exclusiveGrabber()) { QPointF last = lastMousePosition.isNull() ? event->windowPos() : lastMousePosition; lastMousePosition = event->windowPos(); @@ -2283,8 +2283,8 @@ void QQuickWindowPrivate::deliverTouchEvent(QQuickPointerTouchEvent *event) } } - if (allReleased && !event->grabbers().isEmpty()) { - qWarning() << "No release received for some grabbers" << event->grabbers(); + if (allReleased && !event->exclusiveGrabbers().isEmpty()) { + qWarning() << "No release received for some grabbers" << event->exclusiveGrabbers(); event->clearGrabbers(); } } @@ -2292,7 +2292,7 @@ void QQuickWindowPrivate::deliverTouchEvent(QQuickPointerTouchEvent *event) // Deliver touch points to existing grabbers void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *event) { - const auto grabbers = event->grabbers(); + const auto grabbers = event->exclusiveGrabbers(); for (auto grabber : grabbers) { // The grabber is guaranteed to be either an item or a handler. QQuickItem *receiver = qmlobject_cast<QQuickItem *>(grabber); @@ -2467,7 +2467,7 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo // will not be interested in further updates for those touchpoint IDs either. for (auto point: qAsConst(touchEvent->touchPoints())) { if (point.state() == Qt::TouchPointPressed) { - if (ptEvent->pointById(point.id())->grabber() == item) { + if (ptEvent->pointById(point.id())->exclusiveGrabber() == item) { qCDebug(DBG_TOUCH_TARGET) << "TP" << hex << point.id() << "disassociated"; ptEvent->pointById(point.id())->setGrabberItem(nullptr); } |