diff options
author | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2023-11-07 16:00:27 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-11-09 20:33:16 +0000 |
commit | c8ce47f8de498d73ce42174ecbd95eaa5af8da28 (patch) | |
tree | 7b724b4f8ce7649000ddf1e46b1c7701b3659e69 | |
parent | 92dd430960d87a9dff08c4c3c33759526452aff2 (diff) |
Popup: fix fading in and out of the dimmer
When showing and hiding the overlay we go through QQmlProperty to enable
behaviors, e.g. for fading the dimmer in and out, but since we already
set the opacity to 1.0 when creating the dimmer any fade-in behavior is
ignored (as the property already has the target value).
Fix this by creating the dimmer with opacity 0, and calling showOverlay
to make it visible if the popup is already visible. In addition, store
the target opacity of the dimmer component, and set opacity to that
value instead of 1.0 to respect an explicitly set opacity on the modal
or modeless item.
Add a test to verify that we respect the opacity that is set on the
attached modal or modeless dimmer item, and that we correctly trigger
behaviors on the dimmer item. For that to work, the exit transition of
the popup itself needs to be at least as long as the behavior's
duration.
Fixes: QTBUG-118461
Change-Id: I5259ea54f7e4a98bf671e8b52c26676d591a0176
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
(cherry picked from commit ef8bde838ec708ff45ad68c5db899a86116b4e94)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | src/quicktemplates/qquickpopup.cpp | 15 | ||||
-rw-r--r-- | src/quicktemplates/qquickpopup_p_p.h | 1 | ||||
-rw-r--r-- | tests/auto/quickcontrols/qquickpopup/data/fadeDimmer.qml | 39 | ||||
-rw-r--r-- | tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp | 41 |
4 files changed, 93 insertions, 3 deletions
diff --git a/src/quicktemplates/qquickpopup.cpp b/src/quicktemplates/qquickpopup.cpp index 93c8595315..ca7f89c955 100644 --- a/src/quicktemplates/qquickpopup.cpp +++ b/src/quicktemplates/qquickpopup.cpp @@ -837,7 +837,6 @@ static QQuickItem *createDimmer(QQmlComponent *component, QQuickPopup *popup, QQ item = new QQuickItem; if (item) { - item->setOpacity(popup->isVisible() ? 1.0 : 0.0); item->setParentItem(parent); item->stackBefore(popup->popupItem()); item->setZ(popup->z()); @@ -879,8 +878,18 @@ void QQuickPopupPrivate::createOverlay() if (!component) component = modal ? overlay->modal() : overlay->modeless(); - if (!dimmer) + if (!dimmer) { dimmer = createDimmer(component, q, overlay); + // We cannot update explicitDimmerOpacity when dimmer's opacity changes, + // as it is expected to do so when we fade the dimmer in and out in + // show/hideOverlay, and any binding of the dimmer's opacity will be + // implicitly broken anyway. + explicitDimmerOpacity = dimmer->opacity(); + // initially fully transparent, showOverlay fades the dimmer in. + dimmer->setOpacity(0); + if (q->isVisible()) + showOverlay(); + } resizeOverlay(); } @@ -918,7 +927,7 @@ void QQuickPopupPrivate::showOverlay() { // use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors if (dim && dimmer) - QQmlProperty::write(dimmer, QStringLiteral("opacity"), 1.0); + QQmlProperty::write(dimmer, QStringLiteral("opacity"), explicitDimmerOpacity); } void QQuickPopupPrivate::hideOverlay() diff --git a/src/quicktemplates/qquickpopup_p_p.h b/src/quicktemplates/qquickpopup_p_p.h index eb48ce913e..ddff2b19ed 100644 --- a/src/quicktemplates/qquickpopup_p_p.h +++ b/src/quicktemplates/qquickpopup_p_p.h @@ -178,6 +178,7 @@ public: QList<QQuickStateAction> exitActions; QQuickPopupTransitionManager transitionManager; QQuickPopupAnchors *anchors = nullptr; + qreal explicitDimmerOpacity = 0; qreal prevOpacity = 0; qreal prevScale = 0; diff --git a/tests/auto/quickcontrols/qquickpopup/data/fadeDimmer.qml b/tests/auto/quickcontrols/qquickpopup/data/fadeDimmer.qml new file mode 100644 index 0000000000..d5edc11466 --- /dev/null +++ b/tests/auto/quickcontrols/qquickpopup/data/fadeDimmer.qml @@ -0,0 +1,39 @@ +import QtQuick +import QtQuick.Controls + +Window { + id: window + + Text {text: "Hello"} + Popup { + id: popup + anchors.centerIn: parent + dim: true + property double dimmerOpacity: 0.5 + + Overlay.modeless: Rectangle { + color: "blue" + opacity: popup.dimmerOpacity + + Behavior on opacity { + NumberAnimation { from: 0; to: popup.dimmerOpacity; duration: 250 } + } + } + + Overlay.modal: Rectangle { + color: "blue" + opacity: popup.dimmerOpacity + + Behavior on opacity { + NumberAnimation { from: 0; to: popup.dimmerOpacity; duration: 250 } + } + } + + enter: Transition { + NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 250 } + } + exit: Transition { + NumberAnimation { property: "opacity"; from: 1; to: 0; duration: 250 } + } + } +} diff --git a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp index 19add80c54..0eb67b432f 100644 --- a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp +++ b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp @@ -102,6 +102,8 @@ private slots: void focusMultiplePopup(); void contentChildrenChange(); void doubleClickInMouseArea(); + void fadeDimmer_data(); + void fadeDimmer(); private: static bool hasWindowActivation(); @@ -2286,6 +2288,45 @@ void tst_QQuickPopup::doubleClickInMouseArea() QCOMPARE(longPressSpy.count(), 0); } +void tst_QQuickPopup::fadeDimmer_data() +{ + QTest::addColumn<bool>("modality"); + + QTest::addRow("modal") << true; + QTest::addRow("modeless") << true; +} + +void tst_QQuickPopup::fadeDimmer() +{ + QFETCH(const bool, modality); + QQuickApplicationHelper helper(this, "fadeDimmer.qml"); + QVERIFY2(helper.ready, helper.failureMessage()); + + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + auto *popup = window->contentItem()->findChild<QQuickPopup *>(); + QVERIFY(popup); + + popup->setModal(modality); + popup->open(); + auto dimmer = QQuickPopupPrivate::get(popup)->dimmer; + QVERIFY(dimmer); + int opacityChangeCount = 0; + connect(dimmer, &QQuickItem::opacityChanged, this, [&opacityChangeCount]{ + ++opacityChangeCount; + }); + QTRY_VERIFY(popup->isOpened()); + QTRY_COMPARE(dimmer->opacity(), popup->property("dimmerOpacity").toDouble()); + QCOMPARE_GT(opacityChangeCount, 2); + + opacityChangeCount = 0; + popup->setVisible(false); + QTRY_VERIFY(!popup->isVisible()); + QCOMPARE_GT(opacityChangeCount, 2); +} + QTEST_QUICKCONTROLS_MAIN(tst_QQuickPopup) #include "tst_qquickpopup.moc" |