diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2016-11-29 14:50:05 +0100 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2017-02-10 13:04:47 +0000 |
commit | 50aaca40fe09a3ab6c927f7a550b2e97cf332a9c (patch) | |
tree | 9353a10e848499b14ff8ae0254cbfde67dbce721 /src | |
parent | 02f430462b4e9256b6ae021e3d415c0d2180404d (diff) |
start making explicit exclusive or passive grabs
Change-Id: I4a6e3c72d69e893fec2e39f4faab24af6d00c7e0
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/quick/handlers/qquickdraghandler.cpp | 5 | ||||
-rw-r--r-- | src/quick/handlers/qquickdraghandler_p.h | 2 | ||||
-rw-r--r-- | src/quick/handlers/qquickmultipointerhandler.cpp | 2 | ||||
-rw-r--r-- | src/quick/handlers/qquickpointerhandler.cpp | 34 | ||||
-rw-r--r-- | src/quick/handlers/qquickpointerhandler_p.h | 6 | ||||
-rw-r--r-- | src/quick/handlers/qquickpointersinglehandler.cpp | 8 | ||||
-rw-r--r-- | src/quick/handlers/qquicktaphandler.cpp | 3 | ||||
-rw-r--r-- | src/quick/items/qquickevents.cpp | 109 | ||||
-rw-r--r-- | src/quick/items/qquickevents_p_p.h | 15 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 6 |
10 files changed, 138 insertions, 52 deletions
diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp index 6caee6be13..9575f7ede9 100644 --- a/src/quick/handlers/qquickdraghandler.cpp +++ b/src/quick/handlers/qquickdraghandler.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQuick module of the Qt Toolkit. @@ -80,6 +80,7 @@ void QQuickDragHandler::handleEventPoint(QQuickEventPoint *point) case QQuickEventPoint::Pressed: if (target() && target()->parentItem()) m_startPos = target()->parentItem()->mapToScene(target()->position()); + setPassiveGrab(point); break; case QQuickEventPoint::Updated: { QPointF delta = point->scenePos() - point->scenePressPos(); @@ -96,7 +97,7 @@ void QQuickDragHandler::handleEventPoint(QQuickEventPoint *point) } } else if ((m_xAxis.enabled() && QQuickWindowPrivate::dragOverThreshold(delta.x(), Qt::XAxis, point)) || (m_yAxis.enabled() && QQuickWindowPrivate::dragOverThreshold(delta.y(), Qt::YAxis, point))) { - setGrab(point, true); + setExclusiveGrab(point); } } break; default: diff --git a/src/quick/handlers/qquickdraghandler_p.h b/src/quick/handlers/qquickdraghandler_p.h index 69fa297b3c..6250615091 100644 --- a/src/quick/handlers/qquickdraghandler_p.h +++ b/src/quick/handlers/qquickdraghandler_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQuick module of the Qt Toolkit. diff --git a/src/quick/handlers/qquickmultipointerhandler.cpp b/src/quick/handlers/qquickmultipointerhandler.cpp index d3b986bcce..4b931641a2 100644 --- a/src/quick/handlers/qquickmultipointerhandler.cpp +++ b/src/quick/handlers/qquickmultipointerhandler.cpp @@ -213,7 +213,7 @@ void QQuickMultiPointerHandler::acceptPoints(const QVector<QQuickEventPoint *> & void QQuickMultiPointerHandler::grabPoints(QVector<QQuickEventPoint *> points) { for (QQuickEventPoint* point : points) - setGrab(point, true); + setExclusiveGrab(point); } QT_END_NAMESPACE diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp index 0398863ba3..c91fb2de88 100644 --- a/src/quick/handlers/qquickpointerhandler.cpp +++ b/src/quick/handlers/qquickpointerhandler.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQuick module of the Qt Toolkit. @@ -42,6 +42,7 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcPointerHandlerDispatch, "qt.quick.handler.dispatch") +Q_LOGGING_CATEGORY(lcPointerHandlerActive, "qt.quick.handler.active") /*! \qmltype PointerHandler @@ -73,22 +74,42 @@ QQuickPointerHandler::~QQuickPointerHandler() } } -void QQuickPointerHandler::setGrab(QQuickEventPoint *point, bool grab) +void QQuickPointerHandler::setPassiveGrab(QQuickEventPoint *point, bool grab) +{ + if (grab) { + point->setGrabberPointerHandler(this, false); + emit grabChanged(point); + } else if (point->grabberPointerHandler() == this) { + // TODO should giving up passive grab imply giving up exclusive grab too? + // we're being inconsistent here: check whether the exclusive grabber is this, + // then say that the passive grab was canceled. + point->cancelPassiveGrab(this); + emit grabChanged(point); + } +} + +void QQuickPointerHandler::setExclusiveGrab(QQuickEventPoint *point, bool grab) { QQuickPointerHandler *oldGrabber = point->grabberPointerHandler(); if (grab && oldGrabber != this) { if (oldGrabber) oldGrabber->handleGrabCancel(point); - point->setGrabberPointerHandler(this); + point->setGrabberPointerHandler(this, true); onGrabChanged(point); - emit grabChanged(point); +// emit grabChanged(point); // TODO maybe } else if (!grab && oldGrabber == this) { - point->setGrabberPointerHandler(nullptr); + point->setGrabberPointerHandler(nullptr, true); onGrabChanged(point); - emit grabChanged(point); +// emit grabChanged(point); // TODO maybe } } +void QQuickPointerHandler::cancelAllGrabs(QQuickEventPoint *point) +{ + point->cancelAllGrabs(this); + emit grabChanged(point); +} + QPointF QQuickPointerHandler::eventPos(const QQuickEventPoint *point) const { return (target() ? target()->mapFromScene(point->scenePos()) : point->scenePos()); @@ -164,6 +185,7 @@ bool QQuickPointerHandler::wantsPointerEvent(QQuickPointerEvent *event) void QQuickPointerHandler::setActive(bool active) { if (m_active != active) { + qCDebug(lcPointerHandlerActive) << this << m_active << "->" << active; m_active = active; onActiveChanged(); emit activeChanged(); diff --git a/src/quick/handlers/qquickpointerhandler_p.h b/src/quick/handlers/qquickpointerhandler_p.h index 85f1096410..526a60262b 100644 --- a/src/quick/handlers/qquickpointerhandler_p.h +++ b/src/quick/handlers/qquickpointerhandler_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQuick module of the Qt Toolkit. @@ -99,7 +99,9 @@ protected: void setActive(bool active); virtual void onActiveChanged() { } virtual void onGrabChanged(QQuickEventPoint *) { } - void setGrab(QQuickEventPoint *point, bool grab); + void setPassiveGrab(QQuickEventPoint *point, bool grab = true); + void setExclusiveGrab(QQuickEventPoint *point, bool grab = true); + void cancelAllGrabs(QQuickEventPoint *point); virtual void handleGrabCancel(QQuickEventPoint *point); QPointF eventPos(const QQuickEventPoint *point) const; bool parentContains(const QQuickEventPoint *point) const; diff --git a/src/quick/handlers/qquickpointersinglehandler.cpp b/src/quick/handlers/qquickpointersinglehandler.cpp index aeaa9d8309..41c9e1f322 100644 --- a/src/quick/handlers/qquickpointersinglehandler.cpp +++ b/src/quick/handlers/qquickpointersinglehandler.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQuick module of the Qt Toolkit. @@ -70,8 +70,8 @@ bool QQuickPointerSingleHandler::wantsPointerEvent(QQuickPointerEvent *event) if (wantsEventPoint(point)) { point->setAccepted(); return true; - } else if (point->grabber() == this) { - point->cancelGrab(); + } else { + point->cancelAllGrabs(this); } } else { qCWarning(DBG_TOUCH_TARGET) << this << "pointId" << m_pointId @@ -125,7 +125,7 @@ void QQuickPointerSingleHandler::handlePointerEventImpl(QQuickPointerEvent *even emit pointIdChanged(); break; case QQuickEventPoint::Released: - setGrab(currentPoint, false); + setExclusiveGrab(currentPoint, false); reset(); break; default: diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp index 51a496001c..5065e87e8e 100644 --- a/src/quick/handlers/qquicktaphandler.cpp +++ b/src/quick/handlers/qquicktaphandler.cpp @@ -253,8 +253,7 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QQuickEventPoint *poi m_longPressTimer.stop(); m_holdTimer.invalidate(); } - if (m_gesturePolicy != DragThreshold) - setGrab(point, press); + setPassiveGrab(point, press); if (!cancel && !press && point->timeHeld() < longPressThreshold()) { // Assuming here that pointerEvent()->timestamp() is in ms. qreal ts = point->pointerEvent()->timestamp() / 1000.0; diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index d7b5fe79de..eb4a6636f2 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQuick module of the Qt Toolkit. @@ -519,9 +519,9 @@ void QQuickEventPoint::reset(Qt::TouchPointState state, const QPointF &scenePos, { m_scenePos = scenePos; if (m_pointId != pointId) { - if (m_grabber) { - qWarning() << m_grabber << "failed to ungrab previous point" << m_pointId; - cancelGrab(); + if (m_exclusiveGrabber) { + qWarning() << m_exclusiveGrabber << "failed to ungrab previous point" << m_pointId; + cancelExclusiveGrab(); } m_pointId = pointId; } @@ -552,34 +552,34 @@ void QQuickEventPoint::invalidate() QObject *QQuickEventPoint::grabber() const { - return m_grabber.data(); + return m_exclusiveGrabber.data(); } void QQuickEventPoint::setGrabber(QObject *grabber) { if (QQuickPointerHandler *phGrabber = qmlobject_cast<QQuickPointerHandler *>(grabber)) - setGrabberPointerHandler(phGrabber); + setGrabberPointerHandler(phGrabber, true); else setGrabberItem(static_cast<QQuickItem *>(grabber)); } QQuickItem *QQuickEventPoint::grabberItem() const { - return (m_grabberIsHandler ? nullptr : static_cast<QQuickItem *>(m_grabber.data())); + return (m_grabberIsHandler ? nullptr : static_cast<QQuickItem *>(m_exclusiveGrabber.data())); } void QQuickEventPoint::setGrabberItem(QQuickItem *grabber) { - if (grabber != m_grabber.data()) { + if (grabber != m_exclusiveGrabber.data()) { if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) { auto device = static_cast<const QQuickPointerEvent *>(parent())->device(); static const QMetaEnum stateMetaEnum = metaObject()->enumerator(metaObject()->indexOfEnumerator("State")); QString deviceName = (device ? device->name() : QLatin1String("null device")); deviceName.resize(16, ' '); // shorten, and align in case of sequential output qCDebug(lcPointerGrab) << deviceName << "point" << hex << m_pointId << stateMetaEnum.valueToKey(state()) - << ": grab" << m_grabber << "->" << grabber; + << ": grab" << m_exclusiveGrabber << "->" << grabber; } - m_grabber = QPointer<QObject>(grabber); + m_exclusiveGrabber = QPointer<QObject>(grabber); m_grabberIsHandler = false; m_sceneGrabPos = m_scenePos; } @@ -587,35 +587,76 @@ void QQuickEventPoint::setGrabberItem(QQuickItem *grabber) QQuickPointerHandler *QQuickEventPoint::grabberPointerHandler() const { - return (m_grabberIsHandler ? static_cast<QQuickPointerHandler *>(m_grabber.data()) : nullptr); + return (m_grabberIsHandler ? static_cast<QQuickPointerHandler *>(m_exclusiveGrabber.data()) : nullptr); } -void QQuickEventPoint::setGrabberPointerHandler(QQuickPointerHandler *grabber) +void QQuickEventPoint::setGrabberPointerHandler(QQuickPointerHandler *grabber, bool exclusive) { - if (grabber != m_grabber.data()) { - if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) { - auto device = static_cast<const QQuickPointerEvent *>(parent())->device(); - static const QMetaEnum stateMetaEnum = metaObject()->enumerator(metaObject()->indexOfEnumerator("State")); - QString deviceName = (device ? device->name() : QLatin1String("null device")); - deviceName.resize(16, ' '); // shorten, and align in case of sequential output + if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) { + auto device = static_cast<const QQuickPointerEvent *>(parent())->device(); + static const QMetaEnum stateMetaEnum = metaObject()->enumerator(metaObject()->indexOfEnumerator("State")); + QString deviceName = (device ? device->name() : QLatin1String("null device")); + deviceName.resize(16, ' '); // shorten, and align in case of sequential output + if (exclusive) { + if (m_exclusiveGrabber != grabber) + qCDebug(lcPointerGrab) << deviceName << "point" << hex << m_pointId << stateMetaEnum.valueToKey(state()) + << ": grab (exclusive)" << m_exclusiveGrabber << "->" << grabber; + } else { qCDebug(lcPointerGrab) << deviceName << "point" << hex << m_pointId << stateMetaEnum.valueToKey(state()) - << ": grab" << m_grabber << "->" << grabber; + << ": grab (passive)" << grabber; } - m_grabber = QPointer<QObject>(grabber); - m_grabberIsHandler = true; - m_sceneGrabPos = m_scenePos; + } + if (exclusive) { + if (grabber != m_exclusiveGrabber.data()) { + m_exclusiveGrabber = QPointer<QObject>(grabber); + m_grabberIsHandler = true; + m_sceneGrabPos = m_scenePos; + m_passiveGrabbers.removeAll(QPointer<QQuickPointerHandler>(grabber)); + } + } else { + if (!grabber) { + qDebug() << "can't set passive grabber to null"; + return; + } + auto ptr = QPointer<QQuickPointerHandler>(grabber); + if (!m_passiveGrabbers.contains(ptr)) + m_passiveGrabbers.append(ptr); } } -void QQuickEventPoint::cancelGrab() +void QQuickEventPoint::cancelExclusiveGrab() { - if (m_grabber.isNull()) { + if (m_exclusiveGrabber.isNull()) { qWarning("cancelGrab: no grabber"); return; } + if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) { + // TODO somehow avoid duplicating this code from setGrabberPointerHandler + auto device = static_cast<const QQuickPointerEvent *>(parent())->device(); + static const QMetaEnum stateMetaEnum = metaObject()->enumerator(metaObject()->indexOfEnumerator("State")); + QString deviceName = (device ? device->name() : QLatin1String("null device")); + deviceName.resize(16, ' '); // shorten, and align in case of sequential output + qCDebug(lcPointerGrab) << deviceName << "point" << hex << m_pointId << stateMetaEnum.valueToKey(state()) + << ": grab (exclusive)" << m_exclusiveGrabber << "-> nullptr"; + } if (auto handler = grabberPointerHandler()) handler->handleGrabCancel(this); - m_grabber.clear(); + m_exclusiveGrabber.clear(); +} + +void QQuickEventPoint::cancelPassiveGrab(QQuickPointerHandler *handler) +{ + if (m_passiveGrabbers.removeOne(QPointer<QQuickPointerHandler>(handler))) + handler->handleGrabCancel(this); +} + +void QQuickEventPoint::cancelAllGrabs(QQuickPointerHandler *handler) +{ + if (m_exclusiveGrabber == handler) { + handler->handleGrabCancel(this); + m_exclusiveGrabber.clear(); + } + cancelPassiveGrab(handler); } void QQuickEventPoint::setAccepted(bool accepted) @@ -738,6 +779,7 @@ QQuickPointerEvent *QQuickPointerMouseEvent::reset(QEvent *event) switch (ev->type()) { case QEvent::MouseButtonPress: case QEvent::MouseButtonDblClick: + m_mousePoint->clearPassiveGrabbers(); state = Qt::TouchPointPressed; break; case QEvent::MouseButtonRelease: @@ -779,13 +821,19 @@ QQuickPointerEvent *QQuickPointerTouchEvent::reset(QEvent *event) // Make sure the grabbers are right from one event to the next QVector<QObject*> grabbers; + QVector<QVector <QPointer <QQuickPointerHandler> > > passiveGrabberses; + passiveGrabberses.reserve(newPointCount); // 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) { QObject *grabber = nullptr; - if (auto point = pointById(tps.at(i).id())) + QVector <QPointer <QQuickPointerHandler> > passiveGrabbers; + if (auto point = pointById(tps.at(i).id())) { grabber = point->grabber(); + passiveGrabbers = point->passiveGrabbers(); + } grabbers.append(grabber); + passiveGrabberses.append(passiveGrabbers); } for (int i = 0; i < newPointCount; ++i) { @@ -795,8 +843,10 @@ QQuickPointerEvent *QQuickPointerTouchEvent::reset(QEvent *event) if (grabbers.at(i)) qWarning() << "TouchPointPressed without previous release event" << point; point->setGrabberItem(nullptr); + point->clearPassiveGrabbers(); } else { point->setGrabber(grabbers.at(i)); + point->setPassiveGrabbers(passiveGrabberses.at(i)); } } m_pointCount = newPointCount; @@ -822,7 +872,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), + : QObject(parent), m_pointId(0), m_exclusiveGrabber(nullptr), m_timestamp(0), m_pressTimestamp(0), m_state(QQuickEventPoint::Released), m_valid(false), m_accept(false), m_grabberIsHandler(false) { Q_UNUSED(m_reserved); @@ -859,6 +909,7 @@ QVector<QObject *> QQuickPointerMouseEvent::grabbers() const void QQuickPointerMouseEvent::clearGrabbers() const { m_mousePoint->setGrabberItem(nullptr); + m_mousePoint->clearPassiveGrabbers(); } bool QQuickPointerMouseEvent::hasGrabber(const QQuickPointerHandler *handler) const @@ -904,8 +955,10 @@ QVector<QObject *> QQuickPointerTouchEvent::grabbers() const } void QQuickPointerTouchEvent::clearGrabbers() const { - for (auto point: m_touchPoints) + for (auto point: m_touchPoints) { point->setGrabber(nullptr); + point->clearPassiveGrabbers(); + } } bool QQuickPointerTouchEvent::hasGrabber(const QQuickPointerHandler *handler) const diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h index 1751e366b2..5386eacad9 100644 --- a/src/quick/items/qquickevents_p_p.h +++ b/src/quick/items/qquickevents_p_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQuick module of the Qt Toolkit. @@ -302,9 +302,15 @@ public: void setGrabberItem(QQuickItem *grabber); QQuickPointerHandler *grabberPointerHandler() const; - void setGrabberPointerHandler(QQuickPointerHandler *grabber); + void setGrabberPointerHandler(QQuickPointerHandler *grabber, bool exclusive = false); - Q_INVOKABLE void cancelGrab(); + Q_INVOKABLE void cancelExclusiveGrab(); + Q_INVOKABLE void cancelPassiveGrab(QQuickPointerHandler *handler); + void cancelAllGrabs(QQuickPointerHandler *handler); + + QVector<QPointer <QQuickPointerHandler> > passiveGrabbers() const { return m_passiveGrabbers; } + void setPassiveGrabbers(const QVector<QPointer <QQuickPointerHandler> > &grabbers) { m_passiveGrabbers = grabbers; } + void clearPassiveGrabbers() { m_passiveGrabbers.clear(); } private: QVector2D estimatedVelocity() const; @@ -316,7 +322,8 @@ private: QPointF m_sceneGrabPos; QVector2D m_velocity; quint64 m_pointId; - QPointer<QObject> m_grabber; + QPointer<QObject> m_exclusiveGrabber; + QVector<QPointer <QQuickPointerHandler> > m_passiveGrabbers; ulong m_timestamp; ulong m_pressTimestamp; State m_state; diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index fc53420cdd..457d59ea39 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1680,8 +1680,10 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven auto handler = point->grabberPointerHandler(); pointerEvent->localize(handler->parentItem()); handler->handlePointerEvent(pointerEvent); - if (mouseIsReleased) - point->setGrabberPointerHandler(nullptr); + if (mouseIsReleased) { + point->setGrabberPointerHandler(nullptr, true); + point->clearPassiveGrabbers(); + } } } else { bool delivered = false; |