diff options
-rw-r--r-- | examples/quick/pointerhandlers/sidebar.qml | 26 | ||||
-rw-r--r-- | src/quick/handlers/qquickhoverhandler.cpp | 16 | ||||
-rw-r--r-- | src/quick/handlers/qquickhoverhandler_p.h | 6 | ||||
-rw-r--r-- | src/quick/util/qquickdeliveryagent.cpp | 5 | ||||
-rw-r--r-- | tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp | 22 |
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) |