aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/handlers
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/handlers')
-rw-r--r--src/quick/handlers/qquickdraghandler.cpp11
-rw-r--r--src/quick/handlers/qquickmultipointhandler.cpp16
-rw-r--r--src/quick/handlers/qquickpinchhandler.cpp24
-rw-r--r--src/quick/handlers/qquickpointerhandler.cpp43
-rw-r--r--src/quick/handlers/qquicktaphandler.cpp15
-rw-r--r--src/quick/handlers/qquickwheelhandler.cpp2
6 files changed, 79 insertions, 32 deletions
diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp
index 980481303f..9471ef7660 100644
--- a/src/quick/handlers/qquickdraghandler.cpp
+++ b/src/quick/handlers/qquickdraghandler.cpp
@@ -182,7 +182,13 @@ void QQuickDragHandler::onActiveChanged()
bool QQuickDragHandler::wantsPointerEvent(QPointerEvent *event)
{
if (!QQuickMultiPointHandler::wantsPointerEvent(event))
- return false;
+ /* Do handle other events than we would normally care about
+ while we are still doing a drag; otherwise we would suddenly
+ become inactive when a wheel event arrives during dragging.
+ This extra condition needs to be kept in sync with
+ handlePointerEventImpl */
+ if (!active())
+ return false;
#if QT_CONFIG(gestures)
if (event->type() == QEvent::NativeGesture)
@@ -194,6 +200,9 @@ bool QQuickDragHandler::wantsPointerEvent(QPointerEvent *event)
void QQuickDragHandler::handlePointerEventImpl(QPointerEvent *event)
{
+ if (active() && !QQuickMultiPointHandler::wantsPointerEvent(event))
+ return; // see QQuickDragHandler::wantsPointerEvent; we don't want to handle those events
+
QQuickMultiPointHandler::handlePointerEventImpl(event);
event->setAccepted(true);
diff --git a/src/quick/handlers/qquickmultipointhandler.cpp b/src/quick/handlers/qquickmultipointhandler.cpp
index 97cb958aa6..6f66d0e426 100644
--- a/src/quick/handlers/qquickmultipointhandler.cpp
+++ b/src/quick/handlers/qquickmultipointhandler.cpp
@@ -145,7 +145,7 @@ void QQuickMultiPointHandler::onActiveChanged()
}
}
-void QQuickMultiPointHandler::onGrabChanged(QQuickPointerHandler *, QPointingDevice::GrabTransition transition, QPointerEvent *, QEventPoint &)
+void QQuickMultiPointHandler::onGrabChanged(QQuickPointerHandler *grabber, QPointingDevice::GrabTransition transition, QPointerEvent *event, QEventPoint &point)
{
Q_D(QQuickMultiPointHandler);
// If another handler or item takes over this set of points, assume it has
@@ -154,6 +154,20 @@ void QQuickMultiPointHandler::onGrabChanged(QQuickPointerHandler *, QPointingDev
// (e.g. between DragHandler and PinchHandler).
if (transition == QPointingDevice::UngrabExclusive || transition == QPointingDevice::CancelGrabExclusive)
d->currentPoints.clear();
+ if (grabber != this)
+ return;
+ switch (transition) {
+ case QPointingDevice::GrabExclusive:
+ case QPointingDevice::GrabPassive:
+ case QPointingDevice::UngrabPassive:
+ case QPointingDevice::UngrabExclusive:
+ case QPointingDevice::CancelGrabPassive:
+ case QPointingDevice::CancelGrabExclusive:
+ QQuickPointerHandler::onGrabChanged(grabber, transition, event, point);
+ break;
+ case QPointingDevice::OverrideGrabPassive:
+ return; // don't emit
+ }
}
QVector<QEventPoint> QQuickMultiPointHandler::eligiblePoints(QPointerEvent *event)
diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp
index fffcc2f848..68b5f2faed 100644
--- a/src/quick/handlers/qquickpinchhandler.cpp
+++ b/src/quick/handlers/qquickpinchhandler.cpp
@@ -85,7 +85,14 @@ Q_LOGGING_CATEGORY(lcPinchHandler, "qt.quick.handler.pinch")
\image touchpoints-pinchhandler.png
- \sa PinchArea
+ \note The pinch begins when the number of fingers pressed is between
+ \l {MultiPointHandler::minimumPointCount}{minimumPointCount} and
+ \l {MultiPointHandler::maximumPointCount}{maximumPointCount}, inclusive.
+ Until then, PinchHandler tracks the positions of any pressed fingers,
+ but if it's a disallowed number, it does not scale or rotate
+ its \l target, and the \l active property remains \c false.
+
+ \sa PinchArea, QPointerEvent::pointCount()
*/
QQuickPinchHandler::QQuickPinchHandler(QQuickItem *parent)
@@ -209,19 +216,12 @@ bool QQuickPinchHandler::wantsPointerEvent(QPointerEvent *event)
*/
/*!
- \qmlproperty int QtQuick::PinchHandler::minimumTouchPoints
-
- The pinch begins when this number of fingers are pressed.
- Until then, PinchHandler tracks the positions of any pressed fingers,
- but if it's an insufficient number, it does not scale or rotate
- its \l target, and the \l active property will remain false.
-*/
-
-/*!
\qmlproperty bool QtQuick::PinchHandler::active
- This property is true when all the constraints (epecially \l minimumTouchPoints)
- are satisfied and the \l target, if any, is being manipulated.
+ This property is \c true when all the constraints (epecially
+ \l {MultiPointHandler::minimumPointCount}{minimumPointCount} and
+ \l {MultiPointHandler::maximumPointCount}{maximumPointCount}) are satisfied
+ and the \l target, if any, is being manipulated.
*/
void QQuickPinchHandler::onActiveChanged()
diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp
index 11c29ee812..12b064a79b 100644
--- a/src/quick/handlers/qquickpointerhandler.cpp
+++ b/src/quick/handlers/qquickpointerhandler.cpp
@@ -302,7 +302,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 +339,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 +351,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() &&
+ (QQuickWindowPrivate::isMouseEvent(event) || isTouchMouse)) ||
+ (existingItemGrabber->keepTouchGrab() && QQuickWindowPrivate::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 +370,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();
+ }
}
}
}
@@ -394,7 +407,8 @@ bool QQuickPointerHandler::approveGrabTransition(QPointerEvent *event, const QEv
}
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;
}
@@ -516,8 +530,11 @@ bool QQuickPointerHandler::parentContains(const QPointF &scenePosition) const
{
if (QQuickItem *par = parentItem()) {
if (par->window()) {
+ QRect windowGeometry = par->window()->geometry();
+ if (!par->window()->isTopLevel())
+ windowGeometry = QRect(QWindowPrivate::get(par->window())->globalPosition(), par->window()->size());
QPoint screenPosition = par->window()->mapToGlobal(scenePosition.toPoint());
- if (!par->window()->geometry().contains(screenPosition))
+ if (!windowGeometry.contains(screenPosition))
return false;
}
QPointF p = par->mapFromScene(scenePosition);
diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp
index 0a7cc7e075..6c6d491f3c 100644
--- a/src/quick/handlers/qquicktaphandler.cpp
+++ b/src/quick/handlers/qquicktaphandler.cpp
@@ -77,6 +77,8 @@ int QQuickTapHandler::m_touchMultiTapDistanceSquared(-1);
button in order to cancel the click. For this use case, set the
\l gesturePolicy to \c TapHandler.ReleaseWithinBounds.
+ \snippet pointerHandlers/tapHandlerButton.qml 0
+
For multi-tap gestures (double-tap, triple-tap etc.), the distance moved
must not exceed QStyleHints::mouseDoubleClickDistance() with mouse and
QStyleHints::touchDoubleTapDistance() with touch, and the time between
@@ -214,6 +216,8 @@ void QQuickTapHandler::timerEvent(QTimerEvent *event)
If the spatial constraint is violated, \l pressed transitions immediately
from true to false, regardless of the time held.
+ The \c gesturePolicy also affects grab behavior as described below.
+
\value TapHandler.DragThreshold
(the default value) The event point must not move significantly.
If the mouse, finger or stylus moves past the system-wide drag
@@ -222,11 +226,13 @@ void QQuickTapHandler::timerEvent(QTimerEvent *event)
can be useful whenever TapHandler needs to cooperate with other
input handlers (for example \l DragHandler) or event-handling Items
(for example QtQuick Controls), because in this case TapHandler
- will not take the exclusive grab, but merely a passive grab.
+ will not take the exclusive grab, but merely a
+ \l {QPointerEvent::addPassiveGrabber()}{passive grab}.
\value TapHandler.WithinBounds
If the event point leaves the bounds of the \c parent Item, the tap
- gesture is canceled. The TapHandler will take the exclusive grab on
+ gesture is canceled. The TapHandler will take the
+ \l {QPointerEvent::setExclusiveGrabber}{exclusive grab} on
press, but will release the grab as soon as the boundary constraint
is no longer satisfied.
@@ -237,8 +243,9 @@ void QQuickTapHandler::timerEvent(QTimerEvent *event)
typical behavior for button widgets: you can cancel a click by
dragging outside the button, and you can also change your mind by
dragging back inside the button before release. Note that it's
- necessary for TapHandler take the exclusive grab on press and retain
- it until release in order to detect this gesture.
+ necessary for TapHandler to take the
+ \l {QPointerEvent::setExclusiveGrabber}{exclusive grab} on press
+ and retain it until release in order to detect this gesture.
*/
void QQuickTapHandler::setGesturePolicy(QQuickTapHandler::GesturePolicy gesturePolicy)
{
diff --git a/src/quick/handlers/qquickwheelhandler.cpp b/src/quick/handlers/qquickwheelhandler.cpp
index 7045f10d8e..51cb72032b 100644
--- a/src/quick/handlers/qquickwheelhandler.cpp
+++ b/src/quick/handlers/qquickwheelhandler.cpp
@@ -502,7 +502,7 @@ void QQuickWheelHandler::timerEvent(QTimerEvent *event)
}
/*!
- \qmlsignal QtQuick::WheelHandler::wheel(PointerScrollEvent event)
+ \qmlsignal QtQuick::WheelHandler::wheel(WheelEvent event)
This signal is emitted every time this handler receives an \a event
of type \l QWheelEvent: that is, every time the wheel is moved or the