From 2dd530ca35032465d4e928aa7c8f29563eb0c5da Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 4 Oct 2017 11:54:53 +0200 Subject: pre-accept the mouse event before childMouseEventFilter; grab after MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/quick/items/qquickwindow.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'src/quick/items/qquickwindow.cpp') 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 grab(handler, pointerEventPoint); -- cgit v1.2.3