diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2017-10-04 11:54:53 +0200 |
---|---|---|
committer | Jan Arve Sæther <jan-arve.saether@qt.io> | 2017-10-05 11:09:17 +0000 |
commit | 2dd530ca35032465d4e928aa7c8f29563eb0c5da (patch) | |
tree | 1244ab00a76f5e4b603afa1d0de08d04e99d3c5a /src/quick/items | |
parent | 22e0de4a9fd2124a992c9e47540bf37bb273fbea (diff) |
pre-accept the mouse event before childMouseEventFilter; grab after
In 5.9 a typical filtering sequence would be
deliverPressEvent -> deliverMatchingPointsToItem -> QQuickWindow::sendEvent ->
sendFilteredMouseEvent -> Test::childMouseEventFilter, let's say it returns true;
then because the event is accepted, deliverMatchingPointsToItem grabs the mouse.
In 5.10, we rather do
deliverPressOrReleaseEvent -> sendFilteredPointerEvent -> sendFilteredPointerEventImpl ->
Test::childMouseEventFilter, which returns true; and in this case, setGrabberItem
was missing until now.
In case of touch rather than mouse, it grabs the touchpoints in this
kind of scenario.
Also made the failsafe more reliable to ensure that no grabs are retained
after release (after seeing that one failing autotest can cause failures
in subsequent tests).
Done-with: Jan-Arve Sæther
Task-number: QTBUG-62631
Task-number: QTBUG-62549
Task-number: QTBUG-62628
Change-Id: I16dafc9aa0de2fc163c524f7f5b109f82d7e84fd
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
Diffstat (limited to 'src/quick/items')
-rw-r--r-- | src/quick/items/qquickevents.cpp | 2 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 24 |
2 files changed, 19 insertions, 7 deletions
diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index 5b14a5ff90..8653d758de 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -1460,7 +1460,7 @@ bool QQuickPointerMouseEvent::isUpdateEvent() const bool QQuickPointerMouseEvent::isReleaseEvent() const { auto me = static_cast<QMouseEvent*>(m_event); - return me->type() == QEvent::MouseButtonRelease; + return me && me->type() == QEvent::MouseButtonRelease; } bool QQuickPointerTouchEvent::allPointsAccepted() const { diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 9f3f8531e4..c15079b3d7 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1745,9 +1745,6 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven // make sure not to accept unhandled events pointerEvent->setAccepted(false); } - // failsafe: never allow any kind of grab to persist after release - if (mouseIsReleased) - pointerEvent->clearGrabbers(); } bool QQuickWindowPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item, @@ -2263,6 +2260,9 @@ void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event) skipDelivery.clear(); if (event->asPointerMouseEvent()) { deliverMouseEvent(event->asPointerMouseEvent()); + // failsafe: never allow any kind of grab to persist after release + if (event->isReleaseEvent() && event->buttons() == Qt::NoButton) + event->clearGrabbers(); } else if (event->asPointerTouchEvent()) { deliverTouchEvent(event->asPointerTouchEvent()); } else { @@ -2768,10 +2768,20 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event if (receiver->acceptedMouseButtons()) { QPointF localPos = receiver->mapFromScene(pme->point(0)->scenePosition()); QMouseEvent *me = pme->asMouseEvent(localPos); + me->setAccepted(true); + auto oldMouseGrabber = pme->point(0)->grabberItem(); if (filteringParent->childMouseEventFilter(receiver, me)) { qCDebug(DBG_MOUSE) << "mouse event intercepted by childMouseEventFilter of " << filteringParent; skipDelivery.append(filteringParent); filtered = true; + if (me->isAccepted() && pme->isPressEvent()) { + auto mouseGrabber = pme->point(0)->grabberItem(); + if (mouseGrabber && mouseGrabber != receiver && mouseGrabber != oldMouseGrabber) { + receiver->mouseUngrabEvent(); + } else { + pme->point(0)->setGrabberItem(receiver); + } + } } } } else if (QQuickPointerTouchEvent *pte = event->asPointerTouchEvent()) { @@ -2789,7 +2799,6 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event if (filteringParent->childMouseEventFilter(receiver, filteringParentTouchEvent.data())) { qCDebug(DBG_TOUCH) << "touch event intercepted by childMouseEventFilter of " << filteringParent; skipDelivery.append(filteringParent); - filteringParent->grabMouse(); for (auto point: qAsConst(filteringParentTouchEvent->touchPoints())) { auto pointerEventPoint = pte->pointById(point.id()); for (auto handler : pointerEventPoint->passiveGrabbers()) { @@ -2797,7 +2806,9 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event if (!passiveGrabsToCancel.contains(grab)) passiveGrabsToCancel.append(grab); } - event->pointById(point.id())->setAccepted(); + QQuickEventPoint *pt = event->pointById(point.id()); + pt->setAccepted(); + pt->setGrabberItem(filteringParent); } return true; } else { @@ -2838,7 +2849,8 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << hex << tp.id() << "->" << filteringParent; pointerEventInstance(touchMouseDevice)->pointById(tp.id())->setGrabberItem(filteringParent); touchMouseUnset = false; // We want to leave touchMouseId and touchMouseDevice set - filteringParent->grabMouse(); + if (mouseEvent->isAccepted()) + filteringParent->grabMouse(); auto pointerEventPoint = pte->pointById(tp.id()); for (auto handler : pointerEventPoint->passiveGrabbers()) { QPair<QQuickPointerHandler *, QQuickEventPoint *> grab(handler, pointerEventPoint); |