diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2020-10-28 07:51:26 +0100 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2020-10-30 12:19:53 +0100 |
commit | 7b911a65d238d68177a69feb773b3c9d803f6ef4 (patch) | |
tree | b16a6954d72a91782992786c5296b7528da7cf45 /src/quick/items/qquickpincharea.cpp | |
parent | 0fa6091b1076bc3cc58303ff00d43efdad32b8ad (diff) |
Modernize event handling in PinchArea
Worrying about the window's touchmouse is really not a relevant concern
for a touch-only item; and grabs are done by grabbing the specific
points that the pincharea chooses to handle, not by grabbing the
touchmouse. We simply didn't have suitable API in Qt 5.
Also some drive-by fixes: better packing and initialization in
QQuickPinchAreaPrivate; and the stealMouse variable has only
been set, not checked, for a long time, so we can remove it.
Remove unimplemented handlePress() and handleRelease().
Change-Id: Ia76dc9b9974f663b13c4bb9dac32efe8ed7815c5
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/quick/items/qquickpincharea.cpp')
-rw-r--r-- | src/quick/items/qquickpincharea.cpp | 99 |
1 files changed, 53 insertions, 46 deletions
diff --git a/src/quick/items/qquickpincharea.cpp b/src/quick/items/qquickpincharea.cpp index 8de9071b21..8ed92de051 100644 --- a/src/quick/items/qquickpincharea.cpp +++ b/src/quick/items/qquickpincharea.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtSG module of the Qt Toolkit. @@ -337,25 +337,25 @@ void QQuickPinchArea::touchEvent(QTouchEvent *event) d->touchPoints.clear(); for (int i = 0; i < event->pointCount(); ++i) { auto &tp = event->point(i); - if (!(tp.state() & QEventPoint::State::Released)) { + if (tp.state() != QEventPoint::State::Released) { d->touchPoints << tp; tp.setAccepted(); } } - updatePinch(); + updatePinch(event, false); break; case QEvent::TouchEnd: - clearPinch(); + clearPinch(event); break; case QEvent::TouchCancel: - cancelPinch(); + cancelPinch(event); break; default: QQuickItem::touchEvent(event); } } -void QQuickPinchArea::clearPinch() +void QQuickPinchArea::clearPinch(QTouchEvent *event) { Q_D(QQuickPinchArea); @@ -380,15 +380,17 @@ void QQuickPinchArea::clearPinch() d->pinchActivated = false; d->initPinch = false; d->pinchRejected = false; - d->stealMouse = false; d->id1 = -1; - QQuickWindow *win = window(); - if (win && win->mouseGrabberItem() == this) - ungrabMouse(); - setKeepMouseGrab(false); + if (event) { + for (const auto &point : event->points()) { + if (event->exclusiveGrabber(point) == this) + event->setExclusiveGrabber(point, nullptr); + } + } + setKeepTouchGrab(false); } -void QQuickPinchArea::cancelPinch() +void QQuickPinchArea::cancelPinch(QTouchEvent *event) { Q_D(QQuickPinchArea); @@ -421,25 +423,29 @@ void QQuickPinchArea::cancelPinch() d->pinchActivated = false; d->initPinch = false; d->pinchRejected = false; - d->stealMouse = false; d->id1 = -1; - QQuickWindow *win = window(); - if (win && win->mouseGrabberItem() == this) - ungrabMouse(); - setKeepMouseGrab(false); + for (const auto &point : event->points()) { + if (event->exclusiveGrabber(point) == this) + event->setExclusiveGrabber(point, nullptr); + } + setKeepTouchGrab(false); } -void QQuickPinchArea::updatePinch() +void QQuickPinchArea::updatePinch(QTouchEvent *event, bool filtering) { Q_D(QQuickPinchArea); - QQuickWindow *win = window(); - if (d->touchPoints.count() < 2) { - setKeepMouseGrab(false); - QQuickWindow *c = window(); - if (c && c->mouseGrabberItem() == this) - ungrabMouse(); + // A pinch gesture is not occurring, so stealing the grab is permitted. + setKeepTouchGrab(false); + // During filtering, there's no need to hold a grab for one point, + // because filtering happens for every event anyway. + // But if we receive the event via direct delivery, and give up the grab, + // not only will we not see any more updates, but any filtering parent + // (such as Flickable) will also not get a chance to filter them. + // Continuing to hold the grab in this case keeps tst_TouchMouse::pinchOnFlickable() working. + if (filtering && !d->touchPoints.isEmpty() && event->exclusiveGrabber(d->touchPoints.first()) == this) + event->setExclusiveGrabber(d->touchPoints.first(), nullptr); } if (d->touchPoints.count() == 0) { @@ -463,7 +469,6 @@ void QQuickPinchArea::updatePinch() } d->initPinch = false; d->pinchRejected = false; - d->stealMouse = false; return; } @@ -481,18 +486,13 @@ void QQuickPinchArea::updatePinch() // AND one or more of the points has just now been pressed (wasn't pressed already) // AND both points are inside the bounds. if (d->touchPoints.count() == 2 - && (touchPoint1.state() & QEventPoint::State::Pressed || touchPoint2.state() & QEventPoint::State::Pressed) && + && (touchPoint1.state() == QEventPoint::State::Pressed || touchPoint2.state() == QEventPoint::State::Pressed) && bounds.contains(touchPoint1.position()) && bounds.contains(touchPoint2.position())) { d->id1 = touchPoint1.id(); d->pinchActivated = true; d->initPinch = true; - - int touchMouseId = QQuickWindowPrivate::get(win)->touchMouseId; - if (touchPoint1.id() == touchMouseId || touchPoint2.id() == touchMouseId) { - if (win && win->mouseGrabberItem() != this) { - grabMouse(); - } - } + event->setExclusiveGrabber(touchPoint1, this); + event->setExclusiveGrabber(touchPoint2, this); } if (d->pinchActivated && !d->pinchRejected) { const int dragThreshold = QGuiApplication::styleHints()->startDragDistance(); @@ -550,13 +550,10 @@ void QQuickPinchArea::updatePinch() emit pinchStarted(&pe); if (pe.accepted()) { d->inPinch = true; - d->stealMouse = true; - if (win && win->mouseGrabberItem() != this) - grabMouse(); - setKeepMouseGrab(true); - grabTouchPoints(QList<int>() << touchPoint1.id() << touchPoint2.id()); + event->setExclusiveGrabber(touchPoint1, this); + event->setExclusiveGrabber(touchPoint2, this); + setKeepTouchGrab(true); d->inPinch = true; - d->stealMouse = true; if (d->pinch && d->pinch->target()) { d->pinchStartPos = pinch()->target()->position(); d->pinchStartScale = d->pinch->target()->scale(); @@ -631,28 +628,38 @@ void QQuickPinchArea::updatePinchTarget() } } +/*! \internal + PinchArea needs to filter touch events going to its children: in case + one of them stops event propagation by accepting the touch event, filtering + is the only way PinchArea can see the touch event. + + This method is called childMouseEventFilter instead of childPointerEventFilter + for historical reasons, but actually filters all pointer events (and the + occasional QEvent::UngrabMouse). +*/ bool QQuickPinchArea::childMouseEventFilter(QQuickItem *i, QEvent *e) { Q_D(QQuickPinchArea); if (!d->enabled || !isVisible()) return QQuickItem::childMouseEventFilter(i, e); + auto *te = static_cast<QTouchEvent*>(e); switch (e->type()) { case QEvent::TouchBegin: - clearPinch(); + clearPinch(te); Q_FALLTHROUGH(); case QEvent::TouchUpdate: { - const auto &points = static_cast<QTouchEvent*>(e)->points(); + const auto &points = te->points(); d->touchPoints.clear(); for (auto &tp : points) { - if (!(tp.state() & QEventPoint::State::Released)) + if (tp.state() != QEventPoint::State::Released) d->touchPoints << tp; } - updatePinch(); + updatePinch(te, true); } e->setAccepted(d->inPinch); return d->inPinch; case QEvent::TouchEnd: - clearPinch(); + clearPinch(te); break; default: break; @@ -683,7 +690,7 @@ bool QQuickPinchArea::event(QEvent *event) QNativeGestureEvent *gesture = static_cast<QNativeGestureEvent *>(event); switch (gesture->gestureType()) { case Qt::BeginNativeGesture: - clearPinch(); // probably not necessary; JIC + clearPinch(nullptr); // probably not necessary; JIC d->pinchStartCenter = gesture->position(); d->pinchStartAngle = 0.0; d->pinchStartRotation = 0.0; @@ -703,7 +710,7 @@ bool QQuickPinchArea::event(QEvent *event) } break; case Qt::EndNativeGesture: - clearPinch(); + clearPinch(nullptr); break; case Qt::ZoomNativeGesture: { qreal scale = d->pinchLastScale * (1.0 + gesture->value()); |