diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2016-08-08 17:09:15 +0200 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2016-08-23 20:49:05 +0000 |
commit | 8a06075f48ad352acfc70111682e7decf8fedb33 (patch) | |
tree | 1d241486b9eced82f0a7c15cd815fc6e10674dbf /src | |
parent | a0cb20c08db13003f7b8adc2f02fdcadf96fb8d1 (diff) |
QQuickEventPoint::grabber: allow grabbing either an item or a handler
QQuickPointerHandler and QQuickItem have only QObject in common.
Change-Id: I8fb68cc1779f42049db1e0eb5ff60019a1c674d3
Reviewed-by: Jan Arve Sæther <jan-arve.saether@theqtcompany.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/quick/handlers/qquickpointerhandler.cpp | 7 | ||||
-rw-r--r-- | src/quick/items/qquickevents.cpp | 56 | ||||
-rw-r--r-- | src/quick/items/qquickevents_p_p.h | 24 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 69 | ||||
-rw-r--r-- | src/quick/items/qquickwindow_p.h | 2 |
5 files changed, 101 insertions, 57 deletions
diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp index 293eae914e..038e7f2571 100644 --- a/src/quick/handlers/qquickpointerhandler.cpp +++ b/src/quick/handlers/qquickpointerhandler.cpp @@ -64,11 +64,10 @@ QQuickPointerHandler::QQuickPointerHandler(QObject *parent) void QQuickPointerHandler::setGrab(QQuickEventPoint *point, bool grab) { - // TODO eventually the handler itself should be the grabber, instead of the target Item if (grab) - point->setGrabber(m_target); - else if (point->grabber() == m_target) - point->setGrabber(nullptr); + point->setPointerHandlerGrabber(this); + else if (point->pointerHandlerGrabber() == this) + point->setPointerHandlerGrabber(nullptr); } QPointF QQuickPointerHandler::eventPos(const QQuickEventPoint *point) const diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index 7e84d27836..e8f333f953 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -40,12 +40,14 @@ #include "qquickevents_p_p.h" #include <QtGui/private/qguiapplication_p.h> #include <QtQuick/private/qquickitem_p.h> +#include <QtQuick/private/qquickpointerhandler_p.h> #include <QtQuick/private/qquickwindow_p.h> #include <private/qdebug_p.h> QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcPointerEvents, "qt.quick.pointer.events") +Q_DECLARE_LOGGING_CATEGORY(lcPointerHandlerDispatch) /*! \qmltype KeyEvent @@ -525,14 +527,40 @@ void QQuickEventPoint::reset(Qt::TouchPointState state, QPointF scenePos, quint6 m_velocity = velocity; } -QQuickItem *QQuickEventPoint::grabber() const +QObject *QQuickEventPoint::grabber() const { return m_grabber.data(); } -void QQuickEventPoint::setGrabber(QQuickItem *grabber) +void QQuickEventPoint::setGrabber(QObject *grabber) { - m_grabber = QPointer<QQuickItem>(grabber); + qCDebug(lcPointerHandlerDispatch) << this << grabber; + m_grabber = QPointer<QObject>(grabber); + m_grabberIsHandler = (qmlobject_cast<QQuickPointerHandler *>(grabber) != nullptr); +} + +QQuickItem *QQuickEventPoint::itemGrabber() const +{ + return (m_grabberIsHandler ? nullptr : static_cast<QQuickItem *>(m_grabber.data())); +} + +void QQuickEventPoint::setItemGrabber(QQuickItem *grabber) +{ + qCDebug(lcPointerHandlerDispatch) << this << grabber; + m_grabber = QPointer<QObject>(grabber); + m_grabberIsHandler = false; +} + +QQuickPointerHandler *QQuickEventPoint::pointerHandlerGrabber() const +{ + return (m_grabberIsHandler ? static_cast<QQuickPointerHandler *>(m_grabber.data()) : nullptr); +} + +void QQuickEventPoint::setPointerHandlerGrabber(QQuickPointerHandler *grabber) +{ + qCDebug(lcPointerHandlerDispatch) << this << grabber; + m_grabber = QPointer<QObject>(grabber); + m_grabberIsHandler = true; } void QQuickEventPoint::setAccepted(bool accepted) @@ -620,11 +648,11 @@ QQuickPointerEvent *QQuickPointerTouchEvent::reset(QEvent *event) m_touchPoints.insert(i, new QQuickEventTouchPoint(this)); // Make sure the grabbers are right from one event to the next - QVector<QQuickItem*> grabbers; + QVector<QObject*> grabbers; // Copy all grabbers, because the order of points might have changed in the event. // The ID is all that we can rely on (release might remove the first point etc). for (int i = 0; i < newPointCount; ++i) { - QQuickItem *grabber = nullptr; + QObject *grabber = nullptr; if (auto point = pointById(tps.at(i).id())) grabber = point->grabber(); grabbers.append(grabber); @@ -636,7 +664,7 @@ QQuickPointerEvent *QQuickPointerTouchEvent::reset(QEvent *event) if (point->state() == QQuickEventPoint::Pressed) { if (grabbers.at(i)) qWarning() << "TouchPointPressed without previous release event" << point; - point->setGrabber(nullptr); + point->setItemGrabber(nullptr); } else { point->setGrabber(grabbers.at(i)); } @@ -659,7 +687,7 @@ QQuickEventPoint *QQuickPointerTouchEvent::point(int i) const { QQuickEventPoint::QQuickEventPoint(QQuickPointerEvent *parent) : QObject(parent), m_pointId(0), m_grabber(nullptr), m_timestamp(0), m_pressTimestamp(0), - m_state(QQuickEventPoint::Released), m_valid(false), m_accept(false) + m_state(QQuickEventPoint::Released), m_valid(false), m_accept(false), m_grabberIsHandler(false) { Q_UNUSED(m_reserved); } @@ -680,16 +708,16 @@ QMouseEvent *QQuickPointerMouseEvent::asMouseEvent(const QPointF &localPos) cons return event; } -QVector<QQuickItem *> QQuickPointerMouseEvent::grabbers() const +QVector<QObject *> QQuickPointerMouseEvent::grabbers() const { - QVector<QQuickItem *> result; - if (QQuickItem *grabber = m_mousePoint->grabber()) + QVector<QObject *> result; + if (QObject *grabber = m_mousePoint->grabber()) result << grabber; return result; } void QQuickPointerMouseEvent::clearGrabbers() const { - m_mousePoint->setGrabber(nullptr); + m_mousePoint->setItemGrabber(nullptr); } bool QQuickPointerMouseEvent::isPressEvent() const @@ -707,12 +735,12 @@ bool QQuickPointerTouchEvent::allPointsAccepted() const { return true; } -QVector<QQuickItem *> QQuickPointerTouchEvent::grabbers() const +QVector<QObject *> QQuickPointerTouchEvent::grabbers() const { - QVector<QQuickItem *> result; + QVector<QObject *> result; for (int i = 0; i < m_pointCount; ++i) { auto point = m_touchPoints.at(i); - if (QQuickItem *grabber = point->grabber()) { + if (QObject *grabber = point->grabber()) { if (!result.contains(grabber)) result << grabber; } diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h index c64478e856..b954c8a4ec 100644 --- a/src/quick/items/qquickevents_p_p.h +++ b/src/quick/items/qquickevents_p_p.h @@ -68,6 +68,7 @@ class QQuickPointerEvent; class QQuickPointerMouseEvent; class QQuickPointerTabletEvent; class QQuickPointerTouchEvent; +class QQuickPointerHandler; class QQuickKeyEvent : public QObject { @@ -255,7 +256,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickEventPoint : public QObject Q_PROPERTY(quint64 pointId READ pointId) Q_PROPERTY(qreal timeHeld READ timeHeld) Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted) - Q_PROPERTY(QQuickItem *grabber READ grabber WRITE setGrabber) + Q_PROPERTY(QObject *grabber READ grabber WRITE setGrabber) public: enum State { @@ -282,20 +283,27 @@ public: qreal timeHeld() const { return (m_timestamp - m_pressTimestamp) / 1000.0; } bool isAccepted() const { return m_accept; } void setAccepted(bool accepted = true); - QQuickItem *grabber() const; - void setGrabber(QQuickItem *grabber); + QObject *grabber() const; + void setGrabber(QObject *grabber); + + QQuickItem *itemGrabber() const; + void setItemGrabber(QQuickItem *grabber); + + QQuickPointerHandler *pointerHandlerGrabber() const; + void setPointerHandlerGrabber(QQuickPointerHandler *grabber); private: QPointF m_scenePos; QVector2D m_velocity; quint64 m_pointId; - QPointer<QQuickItem> m_grabber; + QPointer<QObject> m_grabber; ulong m_timestamp; ulong m_pressTimestamp; State m_state; bool m_valid : 1; bool m_accept : 1; - int m_reserved : 30; + bool m_grabberIsHandler : 1; + int m_reserved : 29; Q_DISABLE_COPY(QQuickEventPoint) }; @@ -368,7 +376,7 @@ 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<QQuickItem *> grabbers() const = 0; + virtual QVector<QObject *> grabbers() const = 0; virtual void clearGrabbers() const = 0; ulong timestamp() const { return m_event->timestamp(); } @@ -397,7 +405,7 @@ public: QQuickEventPoint *point(int i) const override; QQuickEventPoint *pointById(quint64 pointId) const override; bool allPointsAccepted() const override; - QVector<QQuickItem *> grabbers() const override; + QVector<QObject *> grabbers() const override; void clearGrabbers() const override; QMouseEvent *asMouseEvent(const QPointF& localPos) const; @@ -427,7 +435,7 @@ public: QQuickEventPoint *pointById(quint64 pointId) const override; const QTouchEvent::TouchPoint *touchPointById(int pointId) const; bool allPointsAccepted() const override; - QVector<QQuickItem *> grabbers() const override; + QVector<QObject *> grabbers() const override; void clearGrabbers() const override; QMouseEvent *syntheticMouseEvent(int pointID, QQuickItem *relativeTo) const; diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index fc6bfc43a4..b2727f113e 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -46,6 +46,7 @@ #include "qquickevents_p_p.h" #include <private/qquickdrag_p.h> +#include <private/qquickpointerhandler_p.h> #include <QtQuick/private/qsgrenderer_p.h> #include <QtQuick/private/qsgtexture_p.h> @@ -656,7 +657,7 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve if (!q->mouseGrabberItem()) item->grabMouse(); auto pointerEventPoint = pointerEvent->pointById(p.id()); - pointerEventPoint->setGrabber(item); + pointerEventPoint->setItemGrabber(item); if (checkIfDoubleClicked(event->timestamp())) { QScopedPointer<QMouseEvent> mouseDoubleClick(touchToMouseEvent(QEvent::MouseButtonDblClick, p, event, item, false)); @@ -740,14 +741,14 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber) QQuickPointerEvent *event = QQuickPointerDevice::genericMouseDevice()->pointerEvent(); Q_ASSERT(event->pointCount() == 1); - event->point(0)->setGrabber(grabber); + event->point(0)->setItemGrabber(grabber); if (grabber && touchMouseId != -1 && touchMouseDevice) { // update the touch item for mouse touch id to the new grabber qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << touchMouseId << "->" << q->mouseGrabberItem(); auto point = touchMouseDevice->pointerEvent()->pointById(touchMouseId); if (point) - point->setGrabber(grabber); + point->setItemGrabber(grabber); } if (oldGrabber) { @@ -758,10 +759,10 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber) } } -void QQuickWindowPrivate::grabTouchPoints(QQuickItem *grabber, const QVector<int> &ids) +void QQuickWindowPrivate::grabTouchPoints(QObject *grabber, const QVector<int> &ids) { Q_Q(QQuickWindow); - QSet<QQuickItem*> ungrab; + QSet<QObject*> ungrab; for (int i = 0; i < ids.count(); ++i) { // FIXME: deprecate this function, we need a device const auto touchDevices = QQuickPointerDevice::touchDevices(); @@ -769,7 +770,7 @@ void QQuickWindowPrivate::grabTouchPoints(QQuickItem *grabber, const QVector<int auto point = device->pointerEvent()->pointById(ids.at(i)); if (!point) continue; - QQuickItem *oldGrabber = point->grabber(); + QObject *oldGrabber = point->grabber(); if (oldGrabber == grabber) continue; @@ -784,8 +785,10 @@ void QQuickWindowPrivate::grabTouchPoints(QQuickItem *grabber, const QVector<int setMouseGrabber(nullptr); } } - for (QQuickItem *oldGrabber : qAsConst(ungrab)) - oldGrabber->touchUngrabEvent(); + for (QObject *oldGrabber : qAsConst(ungrab)) + if (QQuickItem *item = qmlobject_cast<QQuickItem *>(oldGrabber)) + item->touchUngrabEvent(); + // TODO else if the old grabber was a PointerHandler, notify it somehow? } void QQuickWindowPrivate::removeGrabber(QQuickItem *grabber, bool mouse, bool touch) @@ -797,7 +800,7 @@ void QQuickWindowPrivate::removeGrabber(QQuickItem *grabber, bool mouse, bool to auto pointerEvent = device->pointerEvent(); for (int i = 0; i < pointerEvent->pointCount(); ++i) { if (pointerEvent->point(i)->grabber() == grabber) { - pointerEvent->point(i)->setGrabber(nullptr); + pointerEvent->point(i)->setItemGrabber(nullptr); // FIXME send ungrab event only once grabber->touchUngrabEvent(); } @@ -1466,7 +1469,7 @@ QQuickItem *QQuickWindow::mouseGrabberItem() const { QQuickPointerEvent *event = QQuickPointerDevice::genericMouseDevice()->pointerEvent(); Q_ASSERT(event->pointCount()); - return event->point(0)->grabber(); + return event->point(0)->itemGrabber(); } @@ -1609,7 +1612,13 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven Q_Q(QQuickWindow); auto point = pointerEvent->point(0); lastMousePosition = point->scenePos(); - QQuickItem *grabber = point->grabber(); + + if (point->pointerHandlerGrabber()) { + point->pointerHandlerGrabber()->handlePointerEvent(pointerEvent); + return; + } + + QQuickItem *grabber = point->itemGrabber(); if (grabber) { // if the update consists of changing button state, then don't accept it // unless the button is one in which the item is interested @@ -1620,12 +1629,6 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven return; } - // Let the Item's handlers (if any) have the event first. - QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(grabber); - itemPrivate->handlePointerEvent(pointerEvent); - if (pointerEvent->allPointsAccepted()) - return; - // send update QPointF localPos = grabber->mapFromScene(lastMousePosition); auto me = pointerEvent->asMouseEvent(localPos); @@ -1845,10 +1848,14 @@ 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<QQuickItem *> grabbers = pointerEvent->grabbers(); - - for (QQuickItem *grabber: qAsConst(grabbers)) { - q->sendEvent(grabber, event); + QVector<QObject *> grabbers = pointerEvent->grabbers(); + + for (QObject *grabber: qAsConst(grabbers)) { + if (QQuickItem *grabberItem = qmlobject_cast<QQuickItem *>(grabber)) + q->sendEvent(grabberItem, event); + else //if (QQuickPointerHandler *grabberHandler = qmlobject_cast<QQuickPointerHandler *>(grabber)) +// grabberHandler->handlePointerEvent() + qWarning("unexpected: can't deliver touch cancel to a PointerHandler (yet?)"); } touchMouseId = -1; touchMouseDevice = nullptr; @@ -1986,8 +1993,6 @@ void QQuickWindow::mouseReleaseEvent(QMouseEvent *event) void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event) { - Q_Q(QQuickWindow); - if (event->source() == Qt::MouseEventSynthesizedBySystem) { event->accept(); return; @@ -2020,7 +2025,7 @@ void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event) updateCursor(event->windowPos()); #endif - if (!q->mouseGrabberItem()) { + if (!QQuickPointerDevice::genericMouseDevice()->pointerEvent()->point(0)->grabber()) { QPointF last = lastMousePosition.isNull() ? event->windowPos() : lastMousePosition; lastMousePosition = event->windowPos(); @@ -2188,7 +2193,7 @@ void QQuickWindowPrivate::deliverTouchEvent(QQuickPointerTouchEvent *event) if (point->state() == QQuickEventPoint::Released) { int id = point->pointId(); qCDebug(DBG_TOUCH_TARGET) << "TP" << id << "released"; - point->setGrabber(nullptr); + point->setItemGrabber(nullptr); if (id == touchMouseId) { touchMouseId = -1; touchMouseDevice = nullptr; @@ -2208,8 +2213,12 @@ void QQuickWindowPrivate::deliverTouchEvent(QQuickPointerTouchEvent *event) bool QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *event, QSet<QQuickItem *> *hasFiltered) { const auto grabbers = event->grabbers(); - for (auto grabber : grabbers) - deliverMatchingPointsToItem(grabber, event, hasFiltered); + for (auto grabber : grabbers) { + if (QQuickItem *grabberItem = qmlobject_cast<QQuickItem *>(grabber)) + deliverMatchingPointsToItem(grabberItem, event, hasFiltered); + else if (QQuickPointerHandler *grabberHandler = qmlobject_cast<QQuickPointerHandler *>(grabber)) + deliverMatchingPointsToItem(grabberHandler->target(), event, hasFiltered); + } return false; } @@ -2310,7 +2319,7 @@ bool QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo auto pointerEventPoint = event->pointById(point.id()); pointerEventPoint->setAccepted(); if (point.state() == Qt::TouchPointPressed) - pointerEventPoint->setGrabber(item); + pointerEventPoint->setItemGrabber(item); } } else { // But if the event was not accepted then we know this item @@ -2319,7 +2328,7 @@ bool QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo if (point.state() == Qt::TouchPointPressed) { if (event->pointById(point.id())->grabber() == item) { qCDebug(DBG_TOUCH_TARGET) << "TP" << point.id() << "disassociated"; - event->pointById(point.id())->setGrabber(nullptr); + event->pointById(point.id())->setItemGrabber(nullptr); } } } @@ -2558,7 +2567,7 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem qCDebug(DBG_TOUCH_TARGET) << "TP" << tp.id() << "->" << target; touchMouseId = tp.id(); touchMouseDevice = event->device(); - touchMouseDevice->pointerEvent()->pointById(tp.id())->setGrabber(target); + touchMouseDevice->pointerEvent()->pointById(tp.id())->setItemGrabber(target); target->grabMouse(); } filtered = true; diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 3328eb65c4..a2a53fd2ce 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -141,7 +141,7 @@ public: bool deliverTouchAsMouse(QQuickItem *item, QQuickPointerEvent *pointerEvent); void translateTouchEvent(QTouchEvent *touchEvent); void setMouseGrabber(QQuickItem *grabber); - void grabTouchPoints(QQuickItem *grabber, const QVector<int> &ids); + void grabTouchPoints(QObject *grabber, const QVector<int> &ids); void removeGrabber(QQuickItem *grabber, bool mouse = true, bool touch = true); static QMouseEvent *cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos = 0); void deliverMouseEvent(QQuickPointerMouseEvent *pointerEvent); |