aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2018-10-01 14:51:29 +0200
committerShawn Rutledge <shawn.rutledge@qt.io>2018-10-03 04:54:42 +0000
commitf27a16b7bdd5f55ce210053773276c4977466efd (patch)
tree098e9de69852dbe1476a062f7711d1526a581e76
parent3bdb3c1d8a581906f49cd4dc89d55c04d9159f40 (diff)
Don't get confused about the grabber during replayDelayedPress
Re-apply a fix equivalent to 8bdf33051aa679db1f060314c6ccab1cb9a77a7a which seemingly never got included in 5.10 or newer branches. If a ListView with pressDelay contains a MouseArea in a delegate, and you tap the MouseArea on a touchscreen, QQuickFlickablePrivate::replayDelayedPress() sends a saved copy of the original QMouseEvent, and then a synthetic release, without marking it as synthetic. (QQuickFlickable is not touch-aware in any way: it thinks the mouse events it receives are real ones.) As a result of sending the delayed press through, QQuickWindowPrivate::setMouseGrabber() is called and sets the touchpoint's grabber to the MouseArea, but does not set the core pointer's eventpoint's grabber. Flickable then ungrabs for itself, so we have to ensure that the ungrab affects either the actual mouse or the synth-mouse, whichever was in use. Then because the synthetic release is not known to come from a touchscreen, QQuickWindowPrivate::deliverMouseEvent() was checking the core pointer's grabber and concluding that there is no grabber. In such a case, it now checks whether touchMouseId is set, meaning that we are somewhere between sending a synthesized press and release, gets the touchpoint's grabber (which is MouseArea, because it didn't reject the press), and sends the release there. Task-number: QTBUG-61144 Fixes: QTBUG-69059 Change-Id: Ie027bef4c8de16e1cbf5d19e120cb22a3df4c037 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
-rw-r--r--src/quick/items/qquickwindow.cpp70
1 files changed, 35 insertions, 35 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 5cd04decf7..1c44afc594 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -1713,46 +1713,46 @@ void QQuickWindowPrivate::deliverToPassiveGrabbers(const QVector<QPointer <QQuic
void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEvent)
{
+ Q_Q(QQuickWindow);
auto point = pointerEvent->point(0);
lastMousePosition = point->scenePosition();
const bool mouseIsReleased = (point->state() == QQuickEventPoint::Released && pointerEvent->buttons() == Qt::NoButton);
+ QQuickItem *grabberItem = point->grabberItem();
+ if (!grabberItem && isDeliveringTouchAsMouse())
+ grabberItem = q->mouseGrabberItem();
+
+ if (grabberItem) {
+ bool handled = false;
+ if (sendFilteredPointerEvent(pointerEvent, grabberItem))
+ handled = true;
+ // if the grabber is an Item:
+ // if the update consists of changing button state, don't accept it unless
+ // the button is one in which the grabber is interested
+ Qt::MouseButtons acceptedButtons = grabberItem->acceptedMouseButtons();
+ if (!handled && pointerEvent->button() != Qt::NoButton && acceptedButtons
+ && !(acceptedButtons & pointerEvent->button())) {
+ pointerEvent->setAccepted(false);
+ handled = true;
+ }
- if (point->exclusiveGrabber()) {
- if (auto grabber = point->grabberItem()) {
- bool handled = false;
- if (sendFilteredPointerEvent(pointerEvent, grabber))
- handled = true;
- // if the grabber is an Item:
- // if the update consists of changing button state, don't accept it unless
- // the button is one in which the grabber is interested
- Qt::MouseButtons acceptedButtons = grabber->acceptedMouseButtons();
- if (!handled && pointerEvent->button() != Qt::NoButton && acceptedButtons
- && !(acceptedButtons & pointerEvent->button())) {
- pointerEvent->setAccepted(false);
- handled = true;
- }
-
- // send update
- if (!handled) {
- QPointF localPos = grabber->mapFromScene(lastMousePosition);
- auto me = pointerEvent->asMouseEvent(localPos);
- me->accept();
- QCoreApplication::sendEvent(grabber, me);
- point->setAccepted(me->isAccepted());
- }
-
- // release event: ungrab if no buttons are pressed anymore
- if (mouseIsReleased)
- removeGrabber(grabber, true, isDeliveringTouchAsMouse());
- } else {
- // if the grabber is not an Item, it must be a PointerHandler
- auto handler = point->grabberPointerHandler();
- pointerEvent->localize(handler->parentItem());
- if (!sendFilteredPointerEvent(pointerEvent, handler->parentItem()))
- handler->handlePointerEvent(pointerEvent);
- if (mouseIsReleased)
- point->setGrabberPointerHandler(nullptr, true);
+ // send update
+ if (!handled) {
+ QPointF localPos = grabberItem->mapFromScene(lastMousePosition);
+ auto me = pointerEvent->asMouseEvent(localPos);
+ me->accept();
+ QCoreApplication::sendEvent(grabberItem, me);
+ point->setAccepted(me->isAccepted());
}
+
+ // release event: ungrab if no buttons are pressed anymore
+ if (mouseIsReleased)
+ removeGrabber(grabberItem, true, isDeliveringTouchAsMouse());
+ } else if (auto handler = point->grabberPointerHandler()) {
+ pointerEvent->localize(handler->parentItem());
+ if (!sendFilteredPointerEvent(pointerEvent, handler->parentItem()))
+ handler->handlePointerEvent(pointerEvent);
+ if (mouseIsReleased)
+ point->setGrabberPointerHandler(nullptr, true);
deliverToPassiveGrabbers(point->passiveGrabbers(), pointerEvent);
} else {
bool delivered = false;