aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2021-07-14 16:11:24 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-07-15 16:59:45 +0000
commita0be1dc746b2dc23ef8fff2f0e3b4224d9d74c81 (patch)
tree8cb1faf21a43ece476fea2472db7c41b58012005
parent5c1268f13a69cacae17d4dcc364f8fdfee1ca24c (diff)
HoverHandler: don't change state if the event involves buttons
In the bug, HoverHandler was getting "hovered" during clicking, even though it already had the opportunity to be hovered while the mouse got into its parent's bounds (and at that time, it got un-hovered while Button was hovered instead). It gets hovered because QQuickDeliveryAgentPrivate::deliverMatchingPointsToItem() calls QQuickItemPrivate::handlePointerEvent() on the ListView's contentItem, because it has a handler. So it seems HoverHandler should not react to that event, because a button is being pressed. Fixes: QTBUG-72843 Change-Id: I0bbcd351130a8d16165f04809c039b24b3864bf9 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io> (cherry picked from commit 8449180c5ebd609b6788680173a79df2f239abb8) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/quick/handlers/qquickhoverhandler.cpp3
-rw-r--r--tests/auto/quick/pointerhandlers/mousearea_interop/data/hoverHandlerInGrandparentOfHoverableItem.qml33
-rw-r--r--tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp34
3 files changed, 70 insertions, 0 deletions
diff --git a/src/quick/handlers/qquickhoverhandler.cpp b/src/quick/handlers/qquickhoverhandler.cpp
index e3b60ad9c6..e953a5b311 100644
--- a/src/quick/handlers/qquickhoverhandler.cpp
+++ b/src/quick/handlers/qquickhoverhandler.cpp
@@ -109,6 +109,9 @@ void QQuickHoverHandler::componentComplete()
bool QQuickHoverHandler::wantsPointerEvent(QPointerEvent *event)
{
+ // No state change should occur if a button is being pressed or released.
+ if (event->isSinglePointEvent() && static_cast<QSinglePointEvent *>(event)->button())
+ return false;
auto &point = event->point(0);
if (QQuickPointerDeviceHandler::wantsPointerEvent(event) && wantsEventPoint(event, point) && parentContains(point)) {
// assume this is a mouse or tablet event, so there's only one point
diff --git a/tests/auto/quick/pointerhandlers/mousearea_interop/data/hoverHandlerInGrandparentOfHoverableItem.qml b/tests/auto/quick/pointerhandlers/mousearea_interop/data/hoverHandlerInGrandparentOfHoverableItem.qml
new file mode 100644
index 0000000000..a3b957a1f7
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/mousearea_interop/data/hoverHandlerInGrandparentOfHoverableItem.qml
@@ -0,0 +1,33 @@
+import QtQuick 2.12
+
+Item {
+ width: 320
+ height: 240
+
+ Rectangle {
+ color: hh.hovered ? "orange" : "gray"
+ anchors.fill: container
+ }
+
+ Item {
+ id: container
+ anchors.fill: parent
+ anchors.margins: 40
+
+ Rectangle {
+ width: parent.width
+ height: 40
+ color: ma.pressed ? "blue" : ma.containsMouse ? "aquamarine" : "beige"
+
+ MouseArea {
+ id: ma
+ anchors.fill: parent
+ hoverEnabled: true
+ }
+ }
+
+ HoverHandler {
+ id: hh
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp b/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp
index 4709622245..ee8f079978 100644
--- a/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp
+++ b/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp
@@ -31,6 +31,7 @@
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlproperty.h>
#include <QtQuick/private/qquickdraghandler_p.h>
+#include <QtQuick/private/qquickhoverhandler_p.h>
#include <QtQuick/private/qquickmousearea_p.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
@@ -52,6 +53,7 @@ private slots:
void dragHandlerInSiblingStealingGrabFromMouseAreaViaMouse();
void dragHandlerInSiblingStealingGrabFromMouseAreaViaTouch_data();
void dragHandlerInSiblingStealingGrabFromMouseAreaViaTouch();
+ void hoverHandlerDoesntHoverOnPress();
private:
void createView(QScopedPointer<QQuickView> &window, const char *fileName);
@@ -175,6 +177,38 @@ void tst_MouseAreaInterop::dragHandlerInSiblingStealingGrabFromMouseAreaViaTouch
QCOMPARE(handler->active(), false);
}
+void tst_MouseAreaInterop::hoverHandlerDoesntHoverOnPress() // QTBUG-72843
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("hoverHandlerInGrandparentOfHoverableItem.qml")));
+
+ QPointer<QQuickHoverHandler> handler = window.rootObject()->findChild<QQuickHoverHandler*>();
+ QVERIFY(handler);
+ QQuickMouseArea *ma = window.rootObject()->findChild<QQuickMouseArea*>();
+ QVERIFY(ma);
+ QPoint p = ma->mapToScene(ma->boundingRect().center()).toPoint();
+
+ // move the mouse below the "button" but within HoverHandler's region of interest
+ QTest::mouseMove(&window, p + QPoint(0, 50));
+ QTRY_COMPARE(handler->isHovered(), true);
+ // move the mouse into the "button"
+ QTest::mouseMove(&window, p);
+ // current behavior: the mouse is still within the HoverHandler's region of interest, but MouseArea is obstructing.
+ QTRY_COMPARE(handler->isHovered(), false);
+ QCOMPARE(ma->hovered(), true);
+
+ // So HoverHandler is no longer hovered (unfortunately). Clicking should not change it.
+ QSignalSpy hoveredChangedSpy(handler, SIGNAL(hoveredChanged()));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, p);
+ QTRY_COMPARE(ma->pressed(), true);
+ QCOMPARE(handler->isHovered(), false);
+ QCOMPARE(hoveredChangedSpy.count(), 0);
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, p);
+ QTRY_COMPARE(ma->pressed(), false);
+ QCOMPARE(handler->isHovered(), false);
+ QCOMPARE(hoveredChangedSpy.count(), 0);
+}
+
QTEST_MAIN(tst_MouseAreaInterop)
#include "tst_mousearea_interop.moc"