aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2023-11-07 16:00:27 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-11-09 20:33:16 +0000
commitc8ce47f8de498d73ce42174ecbd95eaa5af8da28 (patch)
tree7b724b4f8ce7649000ddf1e46b1c7701b3659e69
parent92dd430960d87a9dff08c4c3c33759526452aff2 (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.cpp15
-rw-r--r--src/quicktemplates/qquickpopup_p_p.h1
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/fadeDimmer.qml39
-rw-r--r--tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp41
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"