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 Pick-to: 6.6 Change-Id: I5259ea54f7e4a98bf671e8b52c26676d591a0176 Reviewed-by: Mitch Curtis <mitch.curtis@qt.io> Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
This commit is contained in:
parent
9ca4969307
commit
ef8bde838e
|
@ -841,7 +841,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());
|
||||
|
@ -883,8 +882,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();
|
||||
}
|
||||
|
||||
|
@ -922,7 +931,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()
|
||||
|
|
|
@ -181,6 +181,7 @@ public:
|
|||
QList<QQuickStateAction> exitActions;
|
||||
QQuickPopupTransitionManager transitionManager;
|
||||
QQuickPopupAnchors *anchors = nullptr;
|
||||
qreal explicitDimmerOpacity = 0;
|
||||
qreal prevOpacity = 0;
|
||||
qreal prevScale = 0;
|
||||
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -102,6 +102,8 @@ private slots:
|
|||
void focusMultiplePopup();
|
||||
void contentChildrenChange();
|
||||
void doubleClickInMouseArea();
|
||||
void fadeDimmer_data();
|
||||
void fadeDimmer();
|
||||
|
||||
private:
|
||||
static bool hasWindowActivation();
|
||||
|
@ -2287,6 +2289,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"
|
||||
|
|
Loading…
Reference in New Issue