aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/handlers/qquickpointerhandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/handlers/qquickpointerhandler.cpp')
-rw-r--r--src/quick/handlers/qquickpointerhandler.cpp386
1 files changed, 283 insertions, 103 deletions
diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp
index f9ae620c75..a29c8ae2d3 100644
--- a/src/quick/handlers/qquickpointerhandler.cpp
+++ b/src/quick/handlers/qquickpointerhandler.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQuick module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qquickpointerhandler_p.h"
#include "qquickpointerhandler_p_p.h"
@@ -44,11 +8,14 @@
#include <QtQuick/private/qquickdeliveryagent_p_p.h>
#include <QtGui/private/qinputdevice_p.h>
+#include <QtCore/qpointer.h>
+
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcPointerHandlerDispatch, "qt.quick.handler.dispatch")
Q_LOGGING_CATEGORY(lcPointerHandlerGrab, "qt.quick.handler.grab")
Q_LOGGING_CATEGORY(lcPointerHandlerActive, "qt.quick.handler.active")
+Q_DECLARE_LOGGING_CATEGORY(lcHandlerParent)
/*!
\qmltype PointerHandler
@@ -62,14 +29,34 @@ Q_LOGGING_CATEGORY(lcPointerHandlerActive, "qt.quick.handler.active")
events from any kind of pointing device (touch, mouse or graphics tablet).
*/
+/*! \internal
+ So far we only offer public QML API for Pointer Handlers, but we expect
+ in some future version of Qt to have public C++ API as well. This will open
+ up the possibility to instantiate handlers in custom items (which we should
+ begin doing in Qt Quick Controls in the near future), and to subclass to make
+ custom handlers (as TableView is already doing).
+
+ To make a custom Pointer Handler, first try to choose the parent class
+ according to your needs. If the gesture that you want to recognize could
+ involve multiple touchpoints (even if it could start with only one point),
+ subclass QQuickMultiPointHandler. If you are sure that you never want to
+ handle more than one QEventPoint, subclass QQuickSinglePointHandler.
+*/
QQuickPointerHandler::QQuickPointerHandler(QQuickItem *parent)
- : QObject(*(new QQuickPointerHandlerPrivate), parent)
+ : QQuickPointerHandler(*(new QQuickPointerHandlerPrivate), parent)
{
}
QQuickPointerHandler::QQuickPointerHandler(QQuickPointerHandlerPrivate &dd, QQuickItem *parent)
: QObject(dd, parent)
{
+ // When a handler is created in QML, the given parent is null, and we
+ // depend on QQuickItemPrivate::data_append() later when it's added to an
+ // item's DefaultProperty data property. But when a handler is created in
+ // C++ with a parent item, data_append() won't be called, and the caller
+ // shouldn't have to worry about it either.
+ if (parent)
+ QQuickItemPrivate::get(parent)->addPointerHandler(this);
}
QQuickPointerHandler::~QQuickPointerHandler()
@@ -85,7 +72,7 @@ QQuickPointerHandler::~QQuickPointerHandler()
\qmlproperty real PointerHandler::margin
The margin beyond the bounds of the \l {PointerHandler::parent}{parent}
- item within which an event point can activate this handler. For example, on
+ item within which an \l eventPoint can activate this handler. For example, on
a PinchHandler where the \l {PointerHandler::target}{target} is also the
\c parent, it's useful to set this to a distance at least half the width
of a typical user's finger, so that if the \c parent has been scaled down
@@ -118,7 +105,7 @@ void QQuickPointerHandler::setMargin(qreal pointDistanceThreshold)
\qmlproperty int PointerHandler::dragThreshold
\since 5.15
- The distance in pixels that the user must drag an event point in order to
+ The distance in pixels that the user must drag an \l eventPoint in order to
have it treated as a drag gesture.
The default value depends on the platform and screen resolution.
@@ -210,9 +197,13 @@ void QQuickPointerHandler::setCursorShape(Qt::CursorShape shape)
return;
d->cursorShape = shape;
d->cursorSet = true;
- QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(parentItem());
- itemPriv->hasCursorHandler = true;
- itemPriv->setHasCursorInChild(true);
+ d->cursorDirty = true;
+ if (auto *parent = parentItem()) {
+ QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(parent);
+ itemPriv->hasCursorHandler = true;
+ itemPriv->setHasCursorInChild(true);
+ }
+
emit cursorShapeChanged();
}
@@ -223,9 +214,11 @@ void QQuickPointerHandler::resetCursorShape()
return;
d->cursorShape = Qt::ArrowCursor;
d->cursorSet = false;
- QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(parentItem());
- itemPriv->hasCursorHandler = false;
- itemPriv->setHasCursorInChild(itemPriv->hasCursor);
+ if (auto *parent = parentItem()) {
+ QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(parent);
+ itemPriv->hasCursorHandler = false;
+ itemPriv->setHasCursorInChild(itemPriv->hasCursor);
+ }
emit cursorShapeChanged();
}
@@ -241,8 +234,8 @@ bool QQuickPointerHandler::isCursorShapeExplicitlySet() const
The \a grabber (subject) will be the Input Handler whose state is changing,
or null if the state change regards an Item.
The \a transition (verb) tells what happened.
- The \a point (object) is the point that was grabbed or ungrabbed.
- EventPoint has the sole responsibility to call this function.
+ The \a point (object) is the \l eventPoint that was grabbed or ungrabbed.
+ QQuickDeliveryAgent calls this function.
The Input Handler must react in whatever way is appropriate, and must
emit the relevant signals (for the benefit of QML code).
A subclass is allowed to override this virtual function, but must always
@@ -302,7 +295,8 @@ void QQuickPointerHandler::onGrabChanged(QQuickPointerHandler *grabber, QPointin
*/
void QQuickPointerHandler::setPassiveGrab(QPointerEvent *event, const QEventPoint &point, bool grab)
{
- qCDebug(lcPointerHandlerGrab) << point << grab;
+ qCDebug(lcPointerHandlerGrab) << this << point << grab << "via"
+ << QQuickDeliveryAgentPrivate::currentOrItemDeliveryAgent(parentItem());
if (grab) {
event->addPassiveGrabber(point, this);
} else {
@@ -338,8 +332,8 @@ bool QQuickPointerHandler::approveGrabTransition(QPointerEvent *event, const QEv
{
Q_D(const QQuickPointerHandler);
bool allowed = false;
+ QObject* existingGrabber = event->exclusiveGrabber(point);
if (proposedGrabber == this) {
- QObject* existingGrabber = event->exclusiveGrabber(point);
allowed = (existingGrabber == nullptr) || ((d->grabPermissions & CanTakeOverFromAnything) == CanTakeOverFromAnything);
if (existingGrabber) {
if (QQuickPointerHandler *existingPhGrabber = qobject_cast<QQuickPointerHandler *>(event->exclusiveGrabber(point))) {
@@ -350,10 +344,17 @@ bool QQuickPointerHandler::approveGrabTransition(QPointerEvent *event, const QEv
existingPhGrabber->metaObject()->className() == metaObject()->className())
allowed = true;
} else if ((d->grabPermissions & CanTakeOverFromItems)) {
+ allowed = true;
QQuickItem * existingItemGrabber = qobject_cast<QQuickItem *>(event->exclusiveGrabber(point));
- if (existingItemGrabber && !((existingItemGrabber->keepMouseGrab() && QQuickWindowPrivate::isMouseEvent(event)) ||
- (existingItemGrabber->keepTouchGrab() && QQuickWindowPrivate::isTouchEvent(event)))) {
- allowed = true;
+ auto da = parentItem() ? QQuickItemPrivate::get(parentItem())->deliveryAgentPrivate()
+ : QQuickDeliveryAgentPrivate::currentEventDeliveryAgent ? static_cast<QQuickDeliveryAgentPrivate *>(
+ QQuickDeliveryAgentPrivate::get(QQuickDeliveryAgentPrivate::currentEventDeliveryAgent)) : nullptr;
+ const bool isTouchMouse = (da && da->isDeliveringTouchAsMouse());
+ if (existingItemGrabber &&
+ ((existingItemGrabber->keepMouseGrab() &&
+ (QQuickDeliveryAgentPrivate::isMouseEvent(event) || isTouchMouse)) ||
+ (existingItemGrabber->keepTouchGrab() && QQuickDeliveryAgentPrivate::isTouchEvent(event)))) {
+ allowed = false;
// If the handler wants to steal the exclusive grab from an Item, the Item can usually veto
// by having its keepMouseGrab flag set. But an exception is if that Item is a parent that
// normally filters events (such as a Flickable): it needs to be possible for e.g. a
@@ -362,15 +363,20 @@ bool QQuickPointerHandler::approveGrabTransition(QPointerEvent *event, const QEv
// at first and then expects to be able to steal the grab later on. It cannot respect
// Flickable's wishes in that case, because then it would never have a chance.
if (existingItemGrabber->keepMouseGrab() &&
- !(existingItemGrabber->filtersChildMouseEvents() && existingItemGrabber->isAncestorOf(parentItem()))) {
- auto da = QQuickItemPrivate::get(parentItem())->deliveryAgentPrivate();
+ existingItemGrabber->filtersChildMouseEvents() && existingItemGrabber->isAncestorOf(parentItem())) {
Q_ASSERT(da);
- if (da->isDeliveringTouchAsMouse() && point.id() == da->touchMouseId) {
- qCDebug(lcPointerHandlerGrab) << this << "wants to grab touchpoint" << point.id()
- << "but declines to steal grab from touch-mouse grabber with keepMouseGrab=true" << existingItemGrabber;
- allowed = false;
+ if (isTouchMouse && point.id() == da->touchMouseId) {
+ qCDebug(lcPointerHandlerGrab) << this << "steals touchpoint" << point.id()
+ << "despite parent touch-mouse grabber with keepMouseGrab=true" << existingItemGrabber;
+ allowed = true;
}
}
+ if (!allowed) {
+ qCDebug(lcPointerHandlerGrab) << this << "wants to grab point" << point.id()
+ << "but declines to steal from grabber" << existingItemGrabber
+ << "with keepMouseGrab=" << existingItemGrabber->keepMouseGrab()
+ << "keepTouchGrab=" << existingItemGrabber->keepTouchGrab();
+ }
}
}
}
@@ -388,13 +394,14 @@ bool QQuickPointerHandler::approveGrabTransition(QPointerEvent *event, const QEv
if (!allowed && (d->grabPermissions & ApprovesTakeOverByItems) && proposedGrabber->inherits("QQuickItem"))
allowed = true;
} else {
- if (!allowed && (d->grabPermissions & ApprovesCancellation))
+ if (d->grabPermissions & ApprovesCancellation)
allowed = true;
}
}
qCDebug(lcPointerHandlerGrab) << "point" << Qt::hex << point.id() << "permission" <<
QMetaEnum::fromType<GrabPermissions>().valueToKeys(grabPermissions()) <<
- ':' << this << (allowed ? "approved to" : "denied to") << proposedGrabber;
+ ':' << this << (allowed ? "approved from" : "denied from") <<
+ existingGrabber << "to" << proposedGrabber;
return allowed;
}
@@ -411,6 +418,8 @@ bool QQuickPointerHandler::approveGrabTransition(QPointerEvent *event, const QEv
This handler can take the exclusive grab from another handler of the same class.
\value PointerHandler.CanTakeOverFromHandlersOfDifferentType
This handler can take the exclusive grab from any kind of handler.
+ \value PointerHandler.CanTakeOverFromItems
+ This handler can take the exclusive grab from any type of Item.
\value PointerHandler.CanTakeOverFromAnything
This handler can take the exclusive grab from any type of Item or Handler.
\value PointerHandler.ApprovesTakeOverByHandlersOfSameType
@@ -422,7 +431,7 @@ bool QQuickPointerHandler::approveGrabTransition(QPointerEvent *event, const QEv
\value PointerHandler.ApprovesCancellation
This handler will allow its grab to be set to null.
\value PointerHandler.ApprovesTakeOverByAnything
- This handler gives permission for any any type of Item or Handler to take the grab.
+ This handler gives permission for any type of Item or Handler to take the grab.
The default is
\c {PointerHandler.CanTakeOverFromItems | PointerHandler.CanTakeOverFromHandlersOfDifferentType | PointerHandler.ApprovesTakeOverByAnything}
@@ -445,14 +454,35 @@ void QQuickPointerHandler::setGrabPermissions(GrabPermissions grabPermission)
emit grabPermissionChanged();
}
+/*!
+ Overridden only because QQmlParserStatus requires it.
+*/
void QQuickPointerHandler::classBegin()
{
}
+/*!
+ Overridden from QQmlParserStatus to ensure that parentItem() sets its
+ cursor if this handler's \l cursorShape property has been set.
+*/
void QQuickPointerHandler::componentComplete()
{
+ Q_D(const QQuickPointerHandler);
+ if (d->cursorSet) {
+ if (auto *parent = parentItem()) {
+ QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(parent);
+ itemPriv->hasCursorHandler = true;
+ itemPriv->setHasCursorInChild(true);
+ }
+ }
}
+/*! \internal
+ \deprecated You should handle the event during delivery by overriding
+ handlePointerEventImpl() or QQuickSinglePointHandler::handleEventPoint().
+ Therefore currentEvent() should not be needed. It is here only because
+ onActiveChanged() does not take the event as an argument.
+*/
QPointerEvent *QQuickPointerHandler::currentEvent()
{
Q_D(const QQuickPointerHandler);
@@ -507,17 +537,34 @@ QPointF QQuickPointerHandler::eventPos(const QEventPoint &point) const
return (target() ? target()->mapFromScene(point.scenePosition()) : point.scenePosition());
}
+/*!
+ Returns \c true if margin() > 0 and \a point is within the margin beyond
+ QQuickItem::boundingRect(), or else returns QQuickItem::contains()
+ QEventPoint::position() effectively (because parentContains(scenePosition)
+ calls QQuickItem::mapFromScene()).
+*/
bool QQuickPointerHandler::parentContains(const QEventPoint &point) const
{
return parentContains(point.scenePosition());
}
+/*!
+ Returns \c true if \a scenePosition is within the margin() beyond
+ QQuickItem::boundingRect() (if margin > 0), or parentItem() contains
+ \a scenePosition according to QQuickItem::contains(). (So if the \l margin
+ property is set, that overrides the bounds-check, and QQuickItem::contains()
+ is not called.) As a precheck, it's also required that the window contains
+ \a scenePosition mapped to global coordinates, if parentItem() is in a window.
+*/
bool QQuickPointerHandler::parentContains(const QPointF &scenePosition) const
{
if (QQuickItem *par = parentItem()) {
if (par->window()) {
- QPoint screenPosition = par->window()->mapToGlobal(scenePosition.toPoint());
- if (!par->window()->geometry().contains(screenPosition))
+ QRectF windowGeometry = par->window()->geometry();
+ if (!par->window()->isTopLevel())
+ windowGeometry = QRectF(QWindowPrivate::get(par->window())->globalPosition(), par->window()->size());
+ QPointF screenPosition = par->window()->mapToGlobal(scenePosition);
+ if (!windowGeometry.contains(screenPosition))
return false;
}
QPointF p = par->mapFromScene(scenePosition);
@@ -525,6 +572,10 @@ bool QQuickPointerHandler::parentContains(const QPointF &scenePosition) const
if (m > 0)
return p.x() >= -m && p.y() >= -m && p.x() <= par->width() + m && p.y() <= par->height() + m;
return par->contains(p);
+ } else if (parent() && parent()->inherits("QQuick3DModel")) {
+ // If the parent is from Qt Quick 3D, assume that
+ // bounds checking was already done, as part of picking.
+ return true;
}
return false;
}
@@ -548,13 +599,9 @@ void QQuickPointerHandler::setEnabled(bool enabled)
return;
d->enabled = enabled;
- emit enabledChanged();
-}
+ d->onEnabledChanged();
-bool QQuickPointerHandler::active() const
-{
- Q_D(const QQuickPointerHandler);
- return d->active;
+ emit enabledChanged();
}
/*!
@@ -568,6 +615,14 @@ bool QQuickPointerHandler::active() const
but manipulate another; or to \c null, to disable the default behavior
and do something else instead.
*/
+QQuickItem *QQuickPointerHandler::target() const
+{
+ Q_D(const QQuickPointerHandler);
+ if (!d->targetExplicitlySet)
+ return parentItem();
+ return d->target;
+}
+
void QQuickPointerHandler::setTarget(QQuickItem *target)
{
Q_D(QQuickPointerHandler);
@@ -581,17 +636,47 @@ void QQuickPointerHandler::setTarget(QQuickItem *target)
emit targetChanged();
}
+/*!
+ \qmlproperty Item QtQuick::PointerHandler::parent
+
+ The \l Item which is the scope of the handler; the Item in which it was
+ declared. The handler will handle events on behalf of this Item, which
+ means a pointer event is relevant if at least one of its
+ \l {eventPoint}{eventPoints} occurs within the Item's interior. Initially
+ \l [QML] {target} {target()} is the same, but it can be reassigned.
+
+ \sa {target}, QObject::parent()
+*/
+/*! \internal
+ We still haven't shipped official support for declaring handlers in
+ QtQuick3D.Model objects. Many prerequisites are in place for that, so we
+ should try to keep it working; but there are issues with getting
+ DragHandler to drag its target intuitively in 3D space, for example.
+ TapHandler would work well enough.
+
+ \note When a handler is declared in a \l [QtQuick3D] {Model}{QtQuick3D.Model}
+ object, the parent is not an Item, therefore this property is \c null.
+*/
QQuickItem *QQuickPointerHandler::parentItem() const
{
- return static_cast<QQuickItem *>(QObject::parent());
+ return qmlobject_cast<QQuickItem *>(QObject::parent());
}
-QQuickItem *QQuickPointerHandler::target() const
+void QQuickPointerHandler::setParentItem(QQuickItem *p)
{
- Q_D(const QQuickPointerHandler);
- if (!d->targetExplicitlySet)
- return parentItem();
- return d->target;
+ Q_D(QQuickPointerHandler);
+ if (QObject::parent() == p)
+ return;
+
+ qCDebug(lcHandlerParent) << "reparenting handler" << this << ":" << parent() << "->" << p;
+ auto *oldParent = static_cast<QQuickItem *>(QObject::parent());
+ if (oldParent)
+ QQuickItemPrivate::get(oldParent)->removePointerHandler(this);
+ setParent(p);
+ if (p)
+ QQuickItemPrivate::get(p)->addPointerHandler(this);
+ d->onParentChanged(oldParent, p);
+ emit parentChanged();
}
/*! \internal
@@ -616,27 +701,59 @@ bool QQuickPointerHandler::event(QEvent *e)
}
}
+/*! \internal
+ The entry point to handle the \a event: it's called from
+ QQuickItemPrivate::handlePointerEvent(), begins with wantsPointerEvent(),
+ and calls handlePointerEventImpl() if that returns \c true.
+*/
void QQuickPointerHandler::handlePointerEvent(QPointerEvent *event)
{
+ Q_D(QQuickPointerHandler);
bool wants = wantsPointerEvent(event);
qCDebug(lcPointerHandlerDispatch) << metaObject()->className() << objectName()
- << "on" << parentItem()->metaObject()->className() << parentItem()->objectName()
+ << "on" << parent()->metaObject()->className() << parent()->objectName()
<< (wants ? "WANTS" : "DECLINES") << event;
+ d->currentEvent = event;
if (wants) {
handlePointerEventImpl(event);
+ d->lastEventTime = event->timestamp();
} else {
- setActive(false);
+#if QT_CONFIG(gestures)
+ if (event->type() != QEvent::NativeGesture)
+#endif
+ setActive(false);
for (int i = 0; i < event->pointCount(); ++i) {
auto &pt = event->point(i);
- if (event->exclusiveGrabber(pt) == this && pt.state() != QEventPoint::Stationary) {
+ if (event->exclusiveGrabber(pt) == this && pt.state() != QEventPoint::Stationary)
event->setExclusiveGrabber(pt, nullptr);
- onGrabChanged(this, QPointingDevice::CancelGrabExclusive, event, pt);
- }
}
}
+ d->currentEvent = nullptr;
QQuickPointerHandlerPrivate::deviceDeliveryTargets(event->device()).append(this);
}
+/*!
+ It is the responsibility of this function to decide whether the \a event
+ could be relevant at all to this handler, as a preliminary check.
+
+ Returns \c true if this handler would like handlePointerEventImpl() to be called.
+ If it returns \c false, the handler will be deactivated: \c setActive(false)
+ will be called, and any remaining exclusive grab will be relinquished,
+ as a fail-safe.
+
+ If you override this function, you should call the immediate parent class
+ implementation (and return \c false if it returns \c false); that in turn
+ calls its parent class implementation, and so on.
+ QQuickSinglePointHandler::wantsPointerEvent() and
+ QQuickMultiPointHandler::wantsPointerEvent() call wantsEventPoint(), which
+ is also virtual. You usually can get the behavior you want by subclassing
+ the appropriate handler type, overriding
+ QQuickSinglePointHandler::handleEventPoint() or handlePointerEventImpl(),
+ and perhaps overriding wantsEventPoint() if needed.
+
+ \sa wantsEventPoint(), QQuickPointerDeviceHandler::wantsPointerEvent(),
+ QQuickMultiPointHandler::wantsPointerEvent(), QQuickSinglePointHandler::wantsPointerEvent()
+ */
bool QQuickPointerHandler::wantsPointerEvent(QPointerEvent *event)
{
Q_D(const QQuickPointerHandler);
@@ -644,6 +761,27 @@ bool QQuickPointerHandler::wantsPointerEvent(QPointerEvent *event)
return d->enabled;
}
+/*!
+ Returns \c true if the given \a point (as part of \a event) could be
+ relevant at all to this handler, as a preliminary check.
+
+ If you override this function, you should call the immediate parent class
+ implementation (and return \c false if it returns \c false); that in turn
+ calls its parent class implementation, and so on.
+
+ In particular, the bounds checking is done here: the base class
+ QQuickPointerHandler::wantsEventPoint() calls parentContains(point)
+ (which allows the flexibility promised by margin(), QQuickItem::contains()
+ and QQuickItem::containmentMask()). Pointer Handlers can receive
+ QEventPoints that are outside the parent item's bounds: this allows some
+ flexibility for dealing with multi-point gestures in which one or more
+ fingers have strayed outside the bounds, and yet the gesture is still
+ unambiguously intended for the target() item.
+
+ You should not generally react to the \a event or \a point here, but it's
+ ok to set state to remember what needs to be done in your overridden
+ handlePointerEventImpl() or QQuickSinglePointHandler::handleEventPoint().
+*/
bool QQuickPointerHandler::wantsEventPoint(const QPointerEvent *event, const QEventPoint &point)
{
Q_UNUSED(event);
@@ -658,12 +796,18 @@ bool QQuickPointerHandler::wantsEventPoint(const QPointerEvent *event, const QEv
\readonly
\qmlproperty bool QtQuick::PointerHandler::active
- This holds true whenever this Input Handler has taken sole responsibility
- for handing one or more EventPoints, by successfully taking an exclusive
- grab of those points. This means that it is keeping its properties
- up-to-date according to the movements of those Event Points and actively
+ This holds \c true whenever this Input Handler has taken sole responsibility
+ for handing one or more \l {eventPoint}{eventPoints}, by successfully taking an
+ exclusive grab of those points. This means that it is keeping its properties
+ up-to-date according to the movements of those eventPoints and actively
manipulating its \l target (if any).
*/
+bool QQuickPointerHandler::active() const
+{
+ Q_D(const QQuickPointerHandler);
+ return d->active;
+}
+
void QQuickPointerHandler::setActive(bool active)
{
Q_D(QQuickPointerHandler);
@@ -675,37 +819,50 @@ void QQuickPointerHandler::setActive(bool active)
}
}
+/*!
+ This function can be overridden to implement whatever behavior a specific
+ subclass is intended to have:
+ \list
+ \li Handle all the event's QPointerEvent::points() for which
+ wantsEventPoint() already returned \c true.
+ \li Call setPassiveGrab() setExclusiveGrab() or cancelAllGrabs() as
+ necessary.
+ \li Call QEvent::accept() to stop propagation, or ignore() to allow it
+ to keep going.
+ \endlist
+*/
void QQuickPointerHandler::handlePointerEventImpl(QPointerEvent *event)
{
- Q_D(QQuickPointerHandler);
- d->currentEvent = event;
+ Q_UNUSED(event);
}
/*!
- \readonly
- \qmlproperty Item QtQuick::PointerHandler::parent
-
- The \l Item which is the scope of the handler; the Item in which it was declared.
- The handler will handle events on behalf of this Item, which means a
- pointer event is relevant if at least one of its event points occurs within
- the Item's interior. Initially \l [QML] {target} {target()} is the same, but it
- can be reassigned.
-
- \sa {target}, QObject::parent()
-*/
-
-/*!
- \qmlsignal QtQuick::PointerHandler::grabChanged(GrabTransition transition, EventPoint point)
+ \qmlsignal QtQuick::PointerHandler::grabChanged(PointerDevice::GrabTransition transition, eventPoint point)
This signal is emitted when the grab has changed in some way which is
relevant to this handler.
The \a transition (verb) tells what happened.
The \a point (object) is the point that was grabbed or ungrabbed.
+
+ Valid values for \a transition are:
+
+ \value PointerDevice.GrabExclusive
+ This handler has taken primary responsibility for handling the \a point.
+ \value PointerDevice.UngrabExclusive
+ This handler has given up its previous exclusive grab.
+ \value PointerDevice.CancelGrabExclusive
+ This handler's exclusive grab has been taken over or cancelled.
+ \value PointerDevice.GrabPassive
+ This handler has acquired a passive grab, to monitor the \a point.
+ \value PointerDevice.UngrabPassive
+ This handler has given up its previous passive grab.
+ \value PointerDevice.CancelGrabPassive
+ This handler's previous passive grab has terminated abnormally.
*/
/*!
- \qmlsignal QtQuick::PointerHandler::canceled(EventPoint point)
+ \qmlsignal QtQuick::PointerHandler::canceled(eventPoint point)
If this handler has already grabbed the given \a point, this signal is
emitted when the grab is stolen by a different Pointer Handler or Item.
@@ -722,9 +879,17 @@ QQuickPointerHandlerPrivate::QQuickPointerHandlerPrivate()
, hadKeepMouseGrab(false)
, hadKeepTouchGrab(false)
, cursorSet(false)
+ , cursorDirty(false)
{
}
+/*! \internal
+ Returns \c true if the movement delta \a d in pixels along the \a axis
+ exceeds QQuickPointerHandler::dragThreshold() \e or QEventPoint::velocity()
+ exceeds QStyleHints::startDragVelocity().
+
+ \sa QQuickDeliveryAgentPrivate::dragOverThreshold()
+*/
template <typename TEventPoint>
bool QQuickPointerHandlerPrivate::dragOverThreshold(qreal d, Qt::Axis axis, const TEventPoint &p) const
{
@@ -739,6 +904,12 @@ bool QQuickPointerHandlerPrivate::dragOverThreshold(qreal d, Qt::Axis axis, cons
return overThreshold;
}
+/*!
+ Returns \c true if the movement \a delta in pixels exceeds
+ QQuickPointerHandler::dragThreshold().
+
+ \sa QQuickDeliveryAgentPrivate::dragOverThreshold()
+*/
bool QQuickPointerHandlerPrivate::dragOverThreshold(QVector2D delta) const
{
Q_Q(const QQuickPointerHandler);
@@ -746,6 +917,13 @@ bool QQuickPointerHandlerPrivate::dragOverThreshold(QVector2D delta) const
return qAbs(delta.x()) > threshold || qAbs(delta.y()) > threshold;
}
+/*!
+ Returns \c true if the movement delta of \a point in pixels
+ (calculated as QEventPoint::scenePosition() - QEventPoint::scenePressPosition())
+ exceeds QQuickPointerHandler::dragThreshold().
+
+ \sa QQuickDeliveryAgentPrivate::dragOverThreshold()
+*/
bool QQuickPointerHandlerPrivate::dragOverThreshold(const QEventPoint &point) const
{
QPointF delta = point.scenePosition() - point.scenePressPosition();
@@ -759,3 +937,5 @@ QVector<QObject *> &QQuickPointerHandlerPrivate::deviceDeliveryTargets(const QIn
}
QT_END_NAMESPACE
+
+#include "moc_qquickpointerhandler_p.cpp"