aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/quick/pointerhandlers/sidebar.qml26
-rw-r--r--src/quick/handlers/qquickhoverhandler.cpp16
-rw-r--r--src/quick/handlers/qquickhoverhandler_p.h6
-rw-r--r--src/quick/util/qquickdeliveryagent.cpp5
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp22
5 files changed, 66 insertions, 9 deletions
diff --git a/examples/quick/pointerhandlers/sidebar.qml b/examples/quick/pointerhandlers/sidebar.qml
index 7406931b28..29727b5684 100644
--- a/examples/quick/pointerhandlers/sidebar.qml
+++ b/examples/quick/pointerhandlers/sidebar.qml
@@ -55,7 +55,7 @@ Rectangle {
id: root
width: 640
height: 480
- color: "#444"
+ color: rootHover.hovered ? "#555" : "#444"
Component {
id: buttonsAndStuff
@@ -64,6 +64,11 @@ Rectangle {
anchors.margins: 8
spacing: 8
+ CheckBox {
+ id: hoverBlockingCB
+ text: "Button hover is blocking"
+ }
+
Rectangle {
objectName: "buttonWithMA"
width: parent.width
@@ -98,6 +103,7 @@ Rectangle {
id: buttonHH
objectName: "buttonHH"
acceptedDevices: PointerDevice.AllDevices
+ blocking: hoverBlockingCB.checked
cursorShape: tapHandler.pressed ? Qt.BusyCursor : Qt.PointingHandCursor
}
@@ -152,9 +158,9 @@ Rectangle {
objectName: "topSidebar"
radius: 5
antialiasing: true
- x: -radius
+ x: -10
y: -radius
- width: 120
+ width: 200
height: 200
border.color: topSidebarHH.hovered ? "cyan" : "black"
color: "#777"
@@ -181,16 +187,21 @@ Rectangle {
sourceComponent: buttonsAndStuff
anchors.fill: parent
}
+
+ Text {
+ anchors { left: parent.left; bottom: parent.bottom; margins: 12 }
+ text: "Hover Handler"
+ }
}
Rectangle {
objectName: "bottomSidebar"
radius: 5
antialiasing: true
- x: -radius
+ x: -10
anchors.bottom: parent.bottom
anchors.bottomMargin: -radius
- width: 120
+ width: 200
height: 200
border.color: bottomSidebarMA.containsMouse ? "cyan" : "black"
color: "#777"
@@ -208,6 +219,11 @@ Rectangle {
sourceComponent: buttonsAndStuff
anchors.fill: parent
}
+
+ Text {
+ anchors { left: parent.left; bottom: parent.bottom; margins: 12 }
+ text: "MouseArea"
+ }
}
HoverHandler {
diff --git a/src/quick/handlers/qquickhoverhandler.cpp b/src/quick/handlers/qquickhoverhandler.cpp
index d72123bdcb..989109dfd3 100644
--- a/src/quick/handlers/qquickhoverhandler.cpp
+++ b/src/quick/handlers/qquickhoverhandler.cpp
@@ -83,6 +83,22 @@ QQuickHoverHandler::~QQuickHoverHandler()
QQuickItemPrivate::get(parent)->setHasHoverInChild(false);
}
+/*!
+ \qmlproperty bool QtQuick::HoverHandler::blocking
+ \since 6.3
+
+ Whether this handler prevents other items or handlers behind it from
+ being hovered at the same timee. This property is \c false by default.
+*/
+void QQuickHoverHandler::setBlocking(bool blocking)
+{
+ if (m_blocking == blocking)
+ return;
+
+ m_blocking = blocking;
+ emit blockingChanged();
+}
+
bool QQuickHoverHandler::event(QEvent *event)
{
switch (event->type())
diff --git a/src/quick/handlers/qquickhoverhandler_p.h b/src/quick/handlers/qquickhoverhandler_p.h
index 8d87a36727..e73e7ee71f 100644
--- a/src/quick/handlers/qquickhoverhandler_p.h
+++ b/src/quick/handlers/qquickhoverhandler_p.h
@@ -62,6 +62,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickHoverHandler : public QQuickSinglePointHandle
{
Q_OBJECT
Q_PROPERTY(bool hovered READ isHovered NOTIFY hoveredChanged)
+ Q_PROPERTY(bool blocking READ isBlocking WRITE setBlocking NOTIFY blockingChanged REVISION(6, 3))
QML_NAMED_ELEMENT(HoverHandler)
QML_ADDED_IN_VERSION(2, 12)
@@ -73,8 +74,12 @@ public:
bool isHovered() const { return m_hovered; }
+ bool isBlocking() const { return m_blocking; }
+ void setBlocking(bool blocking);
+
Q_SIGNALS:
void hoveredChanged();
+ Q_REVISION(6, 3) void blockingChanged();
protected:
void componentComplete() override;
@@ -87,6 +92,7 @@ private:
private:
bool m_hovered = false;
bool m_hoveredTablet = false;
+ bool m_blocking = false;
};
QT_END_NAMESPACE
diff --git a/src/quick/util/qquickdeliveryagent.cpp b/src/quick/util/qquickdeliveryagent.cpp
index 6c0596c4b3..5eebcfecc1 100644
--- a/src/quick/util/qquickdeliveryagent.cpp
+++ b/src/quick/util/qquickdeliveryagent.cpp
@@ -1145,6 +1145,11 @@ bool QQuickDeliveryAgentPrivate::deliverHoverEventToItem(
// Mark the whole item as updated, even if only the handler is
// actually in a hovered state (because of HoverHandler.margins)
hoverItems[item] = currentHoverId;
+ if (hh->isBlocking()) {
+ qCDebug(lcHoverTrace) << "skipping rest of hover delivery due to blocking" << hh;
+ accepted = true;
+ break;
+ }
}
}
}
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp
index 8e92714a84..5cafaf42ea 100644
--- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp
@@ -58,6 +58,7 @@ public:
{}
private slots:
+ void hoverHandlerAndUnderlyingHoverHandler_data();
void hoverHandlerAndUnderlyingHoverHandler();
void mouseAreaAndUnderlyingHoverHandler();
void hoverHandlerAndUnderlyingMouseArea();
@@ -82,8 +83,18 @@ void tst_HoverHandler::createView(QScopedPointer<QQuickView> &window, const char
QVERIFY(window->rootObject() != nullptr);
}
+void tst_HoverHandler::hoverHandlerAndUnderlyingHoverHandler_data()
+{
+ QTest::addColumn<bool>("blocking");
+
+ QTest::newRow("default: nonblocking") << false;
+ QTest::newRow("blocking") << true;
+}
+
void tst_HoverHandler::hoverHandlerAndUnderlyingHoverHandler()
{
+ QFETCH(bool, blocking);
+
QScopedPointer<QQuickView> windowPtr;
createView(windowPtr, "lesHoverables.qml");
QQuickView * window = windowPtr.data();
@@ -96,6 +107,9 @@ void tst_HoverHandler::hoverHandlerAndUnderlyingHoverHandler()
QQuickHoverHandler *buttonHH = button->findChild<QQuickHoverHandler *>("buttonHH");
QVERIFY(buttonHH);
+ QCOMPARE(buttonHH->isBlocking(), false); // default property value
+ buttonHH->setBlocking(blocking);
+
QPoint buttonCenter(button->mapToScene(QPointF(button->width() / 2, button->height() / 2)).toPoint());
QPoint rightOfButton(button->mapToScene(QPointF(button->width() + 2, button->height() / 2)).toPoint());
QPoint outOfSidebar(topSidebar->mapToScene(QPointF(topSidebar->width() + 2, topSidebar->height() / 2)).toPoint());
@@ -121,8 +135,8 @@ void tst_HoverHandler::hoverHandlerAndUnderlyingHoverHandler()
#endif
QTest::mouseMove(window, buttonCenter);
- QCOMPARE(topSidebarHH->isHovered(), true);
- QCOMPARE(sidebarHoveredSpy.count(), 1);
+ QCOMPARE(topSidebarHH->isHovered(), !blocking);
+ QCOMPARE(sidebarHoveredSpy.count(), blocking ? 2 : 1);
QCOMPARE(buttonHH->isHovered(), true);
QCOMPARE(buttonHoveredSpy.count(), 1);
#if QT_CONFIG(cursor)
@@ -131,7 +145,7 @@ void tst_HoverHandler::hoverHandlerAndUnderlyingHoverHandler()
QTest::mouseMove(window, rightOfButton);
QCOMPARE(topSidebarHH->isHovered(), true);
- QCOMPARE(sidebarHoveredSpy.count(), 1);
+ QCOMPARE(sidebarHoveredSpy.count(), blocking ? 3 : 1);
QCOMPARE(buttonHH->isHovered(), false);
QCOMPARE(buttonHoveredSpy.count(), 2);
#if QT_CONFIG(cursor)
@@ -140,7 +154,7 @@ void tst_HoverHandler::hoverHandlerAndUnderlyingHoverHandler()
QTest::mouseMove(window, outOfSidebar);
QCOMPARE(topSidebarHH->isHovered(), false);
- QCOMPARE(sidebarHoveredSpy.count(), 2);
+ QCOMPARE(sidebarHoveredSpy.count(), blocking ? 4 : 2);
QCOMPARE(buttonHH->isHovered(), false);
QCOMPARE(buttonHoveredSpy.count(), 2);
#if QT_CONFIG(cursor)