diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2024-02-16 20:21:32 -0700 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2024-02-22 21:13:18 +0000 |
commit | 56c0a6f66e92a07e6427fd3b9ba0b6eed1934674 (patch) | |
tree | a7792ed3def106f2501f024384af1204d12bea5a | |
parent | 49e9a9a94269a6e70c2de5681584a241b2da3063 (diff) |
HoverHandler: setHovered(false) for any pointer event outside bounds
8e822e981d91e688799c8670f11dfdf6aaf9e0d1 was expecting HoverHandler to
receive a QTabletEvent when hover leaves. That worked before
bbcc2657fa0dbf715e6db7d675662e4be94a1e04: a HoverHandler had a passive
grab, so it would receive the next QTabletEvent that moved outside the
item. Now that we stopped doing passive grabs, the event that indicates
that the cursor is leaving the item is always a QMouseEvent sent from
QQuickDeliveryAgentPrivate::deliverHoverEvent().
If the mouse event says the cursor is outside the item, it doesn't
matter what device it came from: this handler is no longer hovered.
But as before, if the position is still inside, and a particular
HoverHandler is hovered because a tablet stylus was previously detected,
do not un-hover merely because of a synth-mouse event at the same
position. Amends 79893e1773be9d04208243cb88c1daf793d830a4
Fixes: QTBUG-116505
Task-number: QTBUG-101932
Pick-to: 6.5
Change-Id: Id0b622fad524ae4be8b37b9cb55e68384056964a
Reviewed-by: Doris Verria <doris.verria@qt.io>
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
(cherry picked from commit 5a762ba09cdeb8df5cf54ce562bc60dfcc11c97f)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 688bd00cc7e8ad173fb007cd07a593a01a049098)
3 files changed, 57 insertions, 39 deletions
diff --git a/src/quick/handlers/qquickhoverhandler.cpp b/src/quick/handlers/qquickhoverhandler.cpp index 1643f89fea..c6dbd46e0b 100644 --- a/src/quick/handlers/qquickhoverhandler.cpp +++ b/src/quick/handlers/qquickhoverhandler.cpp @@ -145,7 +145,8 @@ bool QQuickHoverHandler::wantsPointerEvent(QPointerEvent *event) if (event->isSinglePointEvent() && static_cast<QSinglePointEvent *>(event)->button()) return false; auto &point = event->point(0); - if (QQuickPointerDeviceHandler::wantsPointerEvent(event) && wantsEventPoint(event, point) && parentContains(point)) { + const bool inside = parentContains(point); + if (QQuickPointerDeviceHandler::wantsPointerEvent(event) && wantsEventPoint(event, point) && inside) { // assume this is a mouse or tablet event, so there's only one point setPointId(point.id()); return true; @@ -162,7 +163,7 @@ bool QQuickHoverHandler::wantsPointerEvent(QPointerEvent *event) // But after kCursorOverrideTimeout ms, QQuickItemPrivate::effectiveCursorHandler() // will ignore it, just in case there is no QQuickPointerTabletEvent to unset it. // For example, a tablet proximity leave event could occur, but we don't deliver it to the window. - if (!(m_hoveredTablet && QQuickDeliveryAgentPrivate::isMouseEvent(event))) + if (!inside || !(m_hoveredTablet && QQuickDeliveryAgentPrivate::isMouseEvent(event))) setHovered(false); return false; diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverDeviceCursors.qml b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverDeviceCursors.qml index edb56ffdc6..48e130a35e 100644 --- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverDeviceCursors.qml +++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverDeviceCursors.qml @@ -3,47 +3,53 @@ import QtQuick Item { width: 200; height: 200 - HoverHandler { - objectName: "stylus" - acceptedDevices: PointerDevice.Stylus - acceptedPointerTypes: PointerDevice.Pen - cursorShape: Qt.CrossCursor - } + Rectangle { + width: 100; height: 100 + anchors.centerIn: parent + border.color: "black" - HoverHandler { - objectName: "stylus eraser" - acceptedDevices: PointerDevice.Stylus - acceptedPointerTypes: PointerDevice.Eraser - cursorShape: Qt.PointingHandCursor - } + HoverHandler { + objectName: "stylus" + acceptedDevices: PointerDevice.Stylus + acceptedPointerTypes: PointerDevice.Pen + cursorShape: Qt.CrossCursor + } - HoverHandler { - objectName: "airbrush" - acceptedDevices: PointerDevice.Airbrush - acceptedPointerTypes: PointerDevice.Pen - cursorShape: Qt.BusyCursor - } + HoverHandler { + objectName: "stylus eraser" + acceptedDevices: PointerDevice.Stylus + acceptedPointerTypes: PointerDevice.Eraser + cursorShape: Qt.PointingHandCursor + } - HoverHandler { - objectName: "airbrush eraser" - acceptedDevices: PointerDevice.Airbrush - acceptedPointerTypes: PointerDevice.Eraser - cursorShape: Qt.OpenHandCursor - } + HoverHandler { + objectName: "airbrush" + acceptedDevices: PointerDevice.Airbrush + acceptedPointerTypes: PointerDevice.Pen + cursorShape: Qt.BusyCursor + } - HoverHandler { - objectName: "mouse" - acceptedDevices: PointerDevice.Mouse - // acceptedPointerTypes can be omitted because Mouse is not ambiguous. - // When a genuine mouse move is sent, there's a conflict, and this one should win. - cursorShape: Qt.IBeamCursor - } + HoverHandler { + objectName: "airbrush eraser" + acceptedDevices: PointerDevice.Airbrush + acceptedPointerTypes: PointerDevice.Eraser + cursorShape: Qt.OpenHandCursor + } + + HoverHandler { + objectName: "mouse" + acceptedDevices: PointerDevice.Mouse + // acceptedPointerTypes can be omitted because Mouse is not ambiguous. + // When a genuine mouse move is sent, there's a conflict, and this one should win. + cursorShape: Qt.IBeamCursor + } - HoverHandler { - objectName: "conflictingMouse" - acceptedDevices: PointerDevice.Mouse - // acceptedPointerTypes can be omitted because Mouse is not ambiguous. - // When a genuine mouse move is sent, there's a conflict, and this one should lose. - cursorShape: Qt.ClosedHandCursor + HoverHandler { + objectName: "conflictingMouse" + acceptedDevices: PointerDevice.Mouse + // acceptedPointerTypes can be omitted because Mouse is not ambiguous. + // When a genuine mouse move is sent, there's a conflict, and this one should lose. + cursorShape: Qt.ClosedHandCursor + } } } diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp index ace99daa6a..920bf77978 100644 --- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp @@ -571,6 +571,17 @@ void tst_HoverHandler::deviceCursor() QCOMPARE(eraserHandler->isHovered(), false); QCOMPARE(aibrushHandler->isHovered(), false); QCOMPARE(airbrushEraserHandler->isHovered(), true); // there was no fresh QTabletEvent to tell it not to be hovered + + // hover with the stylus again, then move the mouse outside the handlers' parent item + testStylusDevice(QInputDevice::DeviceType::Stylus, QPointingDevice::PointerType::Pen, + Qt::CrossCursor, stylusHandler); + QTest::mouseMove(&window, QPoint(180, 180)); + // the mouse has left the item: all its HoverHandlers should be unhovered (QTBUG-116505) + QCOMPARE(stylusHandler->isHovered(), false); + QCOMPARE(eraserHandler->isHovered(), false); + QCOMPARE(aibrushHandler->isHovered(), false); + QCOMPARE(airbrushEraserHandler->isHovered(), false); + QCOMPARE(mouseHandler->isHovered(), false); } void tst_HoverHandler::addHandlerFromCpp() |