diff options
-rw-r--r-- | src/quicktemplates2/qquickapplicationwindow.cpp | 17 | ||||
-rw-r--r-- | src/quicktemplates2/qquickdrawer.cpp | 2 | ||||
-rw-r--r-- | src/quicktemplates2/qquickoverlay.cpp | 153 | ||||
-rw-r--r-- | src/quicktemplates2/qquickoverlay_p.h | 13 | ||||
-rw-r--r-- | src/quicktemplates2/qquickpopup.cpp | 1 | ||||
-rw-r--r-- | src/quicktemplates2/qquickpopup_p_p.h | 1 | ||||
-rw-r--r-- | tests/auto/controls/data/tst_popup.qml | 114 | ||||
-rw-r--r-- | tests/auto/popup/tst_popup.cpp | 28 |
8 files changed, 181 insertions, 148 deletions
diff --git a/src/quicktemplates2/qquickapplicationwindow.cpp b/src/quicktemplates2/qquickapplicationwindow.cpp index 940e5eeb..6f070ab7 100644 --- a/src/quicktemplates2/qquickapplicationwindow.cpp +++ b/src/quicktemplates2/qquickapplicationwindow.cpp @@ -454,8 +454,8 @@ QQuickItem *QQuickApplicationWindow::activeFocusControl() const /*! \qmlpropertygroup QtQuick.Controls::ApplicationWindow::overlay \qmlproperty Item QtQuick.Controls::ApplicationWindow::overlay - \qmlproperty Item QtQuick.Controls::ApplicationWindow::overlay.modal - \qmlproperty Item QtQuick.Controls::ApplicationWindow::overlay.modeless + \qmlproperty Component QtQuick.Controls::ApplicationWindow::overlay.modal + \qmlproperty Component QtQuick.Controls::ApplicationWindow::overlay.modeless This property holds the window overlay item. Popups are automatically reparented to the overlay. @@ -466,15 +466,14 @@ QQuickItem *QQuickApplicationWindow::activeFocusControl() const \li Description \row \li overlay.modal - \li This property holds a visual item that implements background - dimming for modal popups. It is stacked below the top-most open - modal popup, or hidden when there are no modal popups open. + \li This property holds a component to use as a visual item that implements + background dimming for modal popups. It is created for and stacked below + visible modal popups. \row \li overlay.modeless - \li This property holds a visual item that implements background - dimming for modeless popups. It is stacked below the top-most - open modeless dimming popup, or hidden when there are no modeless - dimming popups open. + \li This property holds a component to use as a visual item that implements + background dimming for modeless popups. It is created for and stacked below + visible dimming popups. \endtable \sa Popup::modal, Popup::dim diff --git a/src/quicktemplates2/qquickdrawer.cpp b/src/quicktemplates2/qquickdrawer.cpp index 74d79b28..d655f114 100644 --- a/src/quicktemplates2/qquickdrawer.cpp +++ b/src/quicktemplates2/qquickdrawer.cpp @@ -420,6 +420,8 @@ void QQuickDrawer::setPosition(qreal position) d->position = position; if (isComponentComplete()) d->reposition(); + if (d->dimmer) + d->dimmer->setOpacity(position); emit positionChanged(); } diff --git a/src/quicktemplates2/qquickoverlay.cpp b/src/quicktemplates2/qquickoverlay.cpp index 0fb9f3ca..67eb3ceb 100644 --- a/src/quicktemplates2/qquickoverlay.cpp +++ b/src/quicktemplates2/qquickoverlay.cpp @@ -39,6 +39,7 @@ #include "qquickdrawer_p.h" #include <QtQml/qqmlinfo.h> #include <QtQml/qqmlproperty.h> +#include <QtQml/qqmlcomponent.h> #include <QtQuick/private/qquickitem_p.h> QT_BEGIN_NAMESPACE @@ -52,12 +53,14 @@ public: void popupAboutToShow(); void popupAboutToHide(); - void drawerPositionChange(); - void resizeOverlay(QQuickItem *overlay); - void restackOverlay(); + void popupClosed(); - QQuickItem *modal; - QQuickItem *modeless; + void createOverlay(QQuickPopup *popup); + void destroyOverlay(QQuickPopup *popup); + void resizeOverlay(QQuickPopup *popup); + + QQmlComponent *modal; + QQmlComponent *modeless; QVector<QQuickDrawer *> drawers; QVector<QQuickPopup *> popups; QPointer<QQuickPopup> mouseGrabberPopup; @@ -71,14 +74,12 @@ void QQuickOverlayPrivate::popupAboutToShow() if (!popup || !popup->dim()) return; + createOverlay(popup); + // use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors - if (popup->isModal()) { - if (modal) - QQmlProperty::write(modal, QStringLiteral("opacity"), 1.0); - } else { - if (modeless) - QQmlProperty::write(modeless, QStringLiteral("opacity"), 1.0); - } + QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup); + if (p->dimmer) + QQmlProperty::write(p->dimmer, QStringLiteral("opacity"), 1.0); } void QQuickOverlayPrivate::popupAboutToHide() @@ -89,71 +90,67 @@ void QQuickOverlayPrivate::popupAboutToHide() return; // use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors - if (popup->isModal()) { - if (modal && modalPopups <= 1) - QQmlProperty::write(modal, QStringLiteral("opacity"), 0.0); - } else { - if (modeless) - QQmlProperty::write(modeless, QStringLiteral("opacity"), 0.0); - } + QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup); + if (p->dimmer) + QQmlProperty::write(p->dimmer, QStringLiteral("opacity"), 0.0); } -void QQuickOverlayPrivate::drawerPositionChange() +void QQuickOverlayPrivate::popupClosed() { Q_Q(QQuickOverlay); - QQuickDrawer *drawer = qobject_cast<QQuickDrawer *>(q->sender()); - if (!drawer || !drawer->dim()) + QQuickPopup *popup = qobject_cast<QQuickPopup *>(q->sender()); + if (!popup || !popup->dim()) return; - // call QQuickItem::setOpacity() directly to avoid triggering QML Behaviors - // which would make the fading feel laggy compared to the drawer movement - if (drawer->isModal()) { - if (modal) - modal->setOpacity(drawer->position()); - } else { - if (modeless) - modeless->setOpacity(drawer->position()); + destroyOverlay(popup); +} + +static QQuickItem *createDimmer(QQmlComponent *component, QQuickPopup *popup, QQuickItem *parent) +{ + if (!component) + return nullptr; + + QQmlContext *creationContext = component->creationContext(); + if (!creationContext) + creationContext = qmlContext(parent); + QQmlContext *context = new QQmlContext(creationContext); + context->setContextObject(popup); + QQuickItem *item = qobject_cast<QQuickItem*>(component->beginCreate(context)); + if (item) { + item->setOpacity(0.0); + item->setParentItem(parent); + item->stackBefore(popup->popupItem()); + item->setZ(popup->z()); + component->completeCreate(); } + return item; } -void QQuickOverlayPrivate::resizeOverlay(QQuickItem *overlay) +void QQuickOverlayPrivate::createOverlay(QQuickPopup *popup) { Q_Q(QQuickOverlay); - overlay->setWidth(q->width()); - overlay->setHeight(q->height()); + QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup); + if (!p->dimmer) + p->dimmer = createDimmer(popup->isModal() ? modal : modeless, popup, q); + resizeOverlay(popup); } -void QQuickOverlayPrivate::restackOverlay() +void QQuickOverlayPrivate::destroyOverlay(QQuickPopup *popup) { - if (!modal && !modeless) - return; - - // find the bottom-most modal and top-most modeless dimming popups - QQuickPopup *modalPopup = nullptr; - QQuickPopup *modelessPopup = nullptr; - for (auto it = popups.crbegin(), end = popups.crend(); it != end; ++it) { - QQuickPopup *popup = (*it); - if (!popup->dim()) - continue; - - if (popup->isModal()) { - if (!modalPopup || modalPopup->z() >= popup->z()) - modalPopup = popup; - } else { - if (!modelessPopup) - modelessPopup = popup; - } + QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup); + if (p->dimmer) { + p->dimmer->deleteLater(); + p->dimmer = nullptr; } +} - if (modal) { - modal->setZ(modalPopup ? modalPopup->z() : 0.0); - if (modalPopup) - modal->stackBefore(modalPopup->popupItem()); - } - if (modeless) { - modeless->setZ(modelessPopup ? modelessPopup->z() : 0.0); - if (modelessPopup) - modeless->stackBefore(modelessPopup->popupItem()); +void QQuickOverlayPrivate::resizeOverlay(QQuickPopup *popup) +{ + Q_Q(QQuickOverlay); + QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup); + if (p->dimmer) { + p->dimmer->setWidth(q->width()); + p->dimmer->setHeight(q->height()); } } @@ -172,13 +169,13 @@ QQuickOverlay::QQuickOverlay(QQuickItem *parent) setVisible(false); } -QQuickItem *QQuickOverlay::modal() const +QQmlComponent *QQuickOverlay::modal() const { Q_D(const QQuickOverlay); return d->modal; } -void QQuickOverlay::setModal(QQuickItem *modal) +void QQuickOverlay::setModal(QQmlComponent *modal) { Q_D(QQuickOverlay); if (d->modal == modal) @@ -186,22 +183,16 @@ void QQuickOverlay::setModal(QQuickItem *modal) delete d->modal; d->modal = modal; - if (modal) { - modal->setOpacity(0.0); - modal->setParentItem(this); - if (isComponentComplete()) - d->resizeOverlay(modal); - } emit modalChanged(); } -QQuickItem *QQuickOverlay::modeless() const +QQmlComponent *QQuickOverlay::modeless() const { Q_D(const QQuickOverlay); return d->modeless; } -void QQuickOverlay::setModeless(QQuickItem *modeless) +void QQuickOverlay::setModeless(QQmlComponent *modeless) { Q_D(QQuickOverlay); if (d->modeless == modeless) @@ -209,12 +200,6 @@ void QQuickOverlay::setModeless(QQuickItem *modeless) delete d->modeless; d->modeless = modeless; - if (modeless) { - modeless->setOpacity(0.0); - modeless->setParentItem(this); - if (isComponentComplete()) - d->resizeOverlay(modeless); - } emit modelessChanged(); } @@ -233,33 +218,33 @@ void QQuickOverlay::itemChange(ItemChange change, const ItemChangeData &data) if (change == ItemChildAddedChange) { d->popups.append(popup); - d->restackOverlay(); QQuickDrawer *drawer = qobject_cast<QQuickDrawer *>(popup); if (drawer) { - QObjectPrivate::connect(drawer, &QQuickDrawer::positionChanged, d, &QQuickOverlayPrivate::drawerPositionChange); d->drawers.append(drawer); + d->createOverlay(drawer); } else { if (popup->isModal()) ++d->modalPopups; QObjectPrivate::connect(popup, &QQuickPopup::aboutToShow, d, &QQuickOverlayPrivate::popupAboutToShow); QObjectPrivate::connect(popup, &QQuickPopup::aboutToHide, d, &QQuickOverlayPrivate::popupAboutToHide); + QObjectPrivate::connect(popup, &QQuickPopup::closed, d, &QQuickOverlayPrivate::popupClosed); } } else if (change == ItemChildRemovedChange) { d->popups.removeOne(popup); - d->restackOverlay(); QQuickDrawer *drawer = qobject_cast<QQuickDrawer *>(popup); if (drawer) { - QObjectPrivate::disconnect(drawer, &QQuickDrawer::positionChanged, d, &QQuickOverlayPrivate::drawerPositionChange); d->drawers.removeOne(drawer); + d->destroyOverlay(drawer); } else { if (popup->isModal()) --d->modalPopups; QObjectPrivate::disconnect(popup, &QQuickPopup::aboutToShow, d, &QQuickOverlayPrivate::popupAboutToShow); QObjectPrivate::disconnect(popup, &QQuickPopup::aboutToHide, d, &QQuickOverlayPrivate::popupAboutToHide); + QObjectPrivate::disconnect(popup, &QQuickPopup::closed, d, &QQuickOverlayPrivate::popupClosed); } } } @@ -268,10 +253,8 @@ void QQuickOverlay::geometryChanged(const QRectF &newGeometry, const QRectF &old { Q_D(QQuickOverlay); QQuickItem::geometryChanged(newGeometry, oldGeometry); - if (d->modal) - d->resizeOverlay(d->modal); - if (d->modeless) - d->resizeOverlay(d->modeless); + for (QQuickPopup *popup : d->popups) + d->resizeOverlay(popup); } bool QQuickOverlay::event(QEvent *event) diff --git a/src/quicktemplates2/qquickoverlay_p.h b/src/quicktemplates2/qquickoverlay_p.h index 77137257..99d7ba75 100644 --- a/src/quicktemplates2/qquickoverlay_p.h +++ b/src/quicktemplates2/qquickoverlay_p.h @@ -53,22 +53,23 @@ QT_BEGIN_NAMESPACE +class QQmlComponent; class QQuickOverlayPrivate; class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickOverlay : public QQuickItem { Q_OBJECT - Q_PROPERTY(QQuickItem *modal READ modal WRITE setModal NOTIFY modalChanged FINAL) - Q_PROPERTY(QQuickItem *modeless READ modeless WRITE setModeless NOTIFY modelessChanged FINAL) + Q_PROPERTY(QQmlComponent *modal READ modal WRITE setModal NOTIFY modalChanged FINAL) + Q_PROPERTY(QQmlComponent *modeless READ modeless WRITE setModeless NOTIFY modelessChanged FINAL) public: explicit QQuickOverlay(QQuickItem *parent = nullptr); - QQuickItem *modal() const; - void setModal(QQuickItem *modal); + QQmlComponent *modal() const; + void setModal(QQmlComponent *modal); - QQuickItem *modeless() const; - void setModeless(QQuickItem *modeless); + QQmlComponent *modeless() const; + void setModeless(QQmlComponent *modeless); Q_SIGNALS: void modalChanged(); diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp index cb13d7b6..6682fec2 100644 --- a/src/quicktemplates2/qquickpopup.cpp +++ b/src/quicktemplates2/qquickpopup.cpp @@ -145,6 +145,7 @@ QQuickPopupPrivate::QQuickPopupPrivate() , contentHeight(0) , closePolicy(QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutside) , parentItem(nullptr) + , dimmer(nullptr) , window(nullptr) , enter(nullptr) , exit(nullptr) diff --git a/src/quicktemplates2/qquickpopup_p_p.h b/src/quicktemplates2/qquickpopup_p_p.h index 9ea5a7f0..ffe2c2bb 100644 --- a/src/quicktemplates2/qquickpopup_p_p.h +++ b/src/quicktemplates2/qquickpopup_p_p.h @@ -204,6 +204,7 @@ public: qreal contentHeight; QQuickPopup::ClosePolicy closePolicy; QQuickItem *parentItem; + QQuickItem *dimmer; QQuickWindow *window; QQuickTransition *enter; QQuickTransition *exit; diff --git a/tests/auto/controls/data/tst_popup.qml b/tests/auto/controls/data/tst_popup.qml index 20b5a551..50933c20 100644 --- a/tests/auto/controls/data/tst_popup.qml +++ b/tests/auto/controls/data/tst_popup.qml @@ -1013,91 +1013,121 @@ TestCase { } } + function indexOf(array, item) { + for (var idx = 0; idx < array.length; ++idx) { + if (item === array[idx]) + return idx; + } + return -1 + } + + function findOverlay(window, popup) { + var item = popup.contentItem.parent + var idx = indexOf(window.overlay.children, item) + return window.overlay.children[idx - 1] + } + function test_overlay() { var window = overlayTest.createObject(testCase) verify(window) window.requestActivate() tryCompare(window, "active", true) - compare(window.overlay.modal.opacity, 0.0) - compare(window.overlay.modeless.opacity, 0.0) + compare(window.overlay.children.length, 6) // 3 drawers + 3 overlays + + var firstOverlay = findOverlay(window, window.firstDrawer) + verify(firstOverlay) + compare(firstOverlay.opacity, 0.0) + compare(firstOverlay.z, window.firstDrawer.z) + compare(indexOf(window.overlay.children, firstOverlay), + indexOf(window.overlay.children, window.firstDrawer.contentItem.parent) - 1) + + var secondOverlay = findOverlay(window, window.secondDrawer) + verify(secondOverlay) + compare(secondOverlay.opacity, 0.0) + compare(secondOverlay.z, window.secondDrawer.z) + compare(indexOf(window.overlay.children, secondOverlay), + indexOf(window.overlay.children, window.secondDrawer.contentItem.parent) - 1) + + var upperOverlay = findOverlay(window, window.upperDrawer) + verify(upperOverlay) + compare(upperOverlay.opacity, 0.0) + compare(upperOverlay.z, window.upperDrawer.z) + compare(indexOf(window.overlay.children, upperOverlay), + indexOf(window.overlay.children, window.upperDrawer.contentItem.parent) - 1) window.firstDrawer.open() - compare(window.overlay.modal.z, 1.0) - tryCompare(window.overlay.modal, "opacity", 1.0) + compare(firstOverlay.z, 1.0) + tryCompare(firstOverlay, "opacity", 1.0) window.firstDrawer.close() - tryCompare(window.overlay.modal, "opacity", 0.0) + tryCompare(firstOverlay, "opacity", 0.0) + tryCompare(window.firstDrawer, "visible", false) window.secondDrawer.open() - compare(window.overlay.modal.z, 1.0) - tryCompare(window.overlay.modal, "opacity", 1.0) + compare(secondOverlay.z, 1.0) + tryCompare(secondOverlay, "opacity", 1.0) window.secondDrawer.close() - tryCompare(window.overlay.modal, "opacity", 0.0) + tryCompare(secondOverlay, "opacity", 0.0) + tryCompare(window.secondDrawer, "visible", false) window.firstDrawer.open() window.secondDrawer.open() - compare(window.overlay.modal.z, 1.0) - tryCompare(window.overlay.modal, "opacity", 1.0) + tryCompare(firstOverlay, "opacity", 1.0) + tryCompare(secondOverlay, "opacity", 1.0) window.firstDrawer.close() window.secondDrawer.close() - tryCompare(window.overlay.modal, "opacity", 0.0) + tryCompare(firstOverlay, "opacity", 0.0) + tryCompare(secondOverlay, "opacity", 0.0) + var modalOverlay = findOverlay(window, window.modalPopup) + verify(!modalOverlay) window.modalPopup.open() - compare(window.overlay.modal.z, 1.0) + modalOverlay = findOverlay(window, window.modalPopup) + verify(modalOverlay) + compare(modalOverlay.z, window.modalPopup.z) compare(window.modalPopup.visible, true) - tryCompare(window.overlay.modal, "opacity", 1.0) + tryCompare(modalOverlay, "opacity", 1.0) + var modelessOverlay = findOverlay(window, window.modelessPopup) + verify(!modelessOverlay) window.modelessPopup.open() - compare(window.overlay.modeless.z, 3.0) + modelessOverlay = findOverlay(window, window.modelessPopup) + verify(modelessOverlay) + compare(modelessOverlay.z, window.modelessPopup.z) compare(window.modelessPopup.visible, true) - tryCompare(window.overlay.modeless, "opacity", 1.0) + tryCompare(modelessOverlay, "opacity", 1.0) window.modelessPopup.close() + tryCompare(modelessOverlay, "opacity", 0.0) tryCompare(window.modelessPopup, "visible", false) - tryCompare(window.overlay.modeless, "opacity", 0.0) - compare(window.overlay.modeless.z, 0.0) + modelessOverlay = findOverlay(window, window.modelessPopup) + verify(!modelessOverlay) compare(window.modalPopup.visible, true) - compare(window.overlay.modal.opacity, 1.0) + compare(modalOverlay.opacity, 1.0) window.modalPopup.close() + tryCompare(modalOverlay, "opacity", 0.0) tryCompare(window.modalPopup, "visible", false) - tryCompare(window.overlay.modal, "opacity", 0.0) - compare(window.overlay.modal.z, 1.0) + modalOverlay = findOverlay(window, window.modalPopup) + verify(!modalOverlay) + var countBefore = window.overlay.children.length window.plainPopup.open() tryCompare(window.plainPopup, "visible", true) - compare(window.overlay.modal.opacity, 0.0) - compare(window.overlay.modeless.opacity, 0.0) + compare(window.overlay.children.length, countBefore + 1) // only popup added, no overlays involved window.plainPopup.close() tryCompare(window.plainPopup, "visible", false) - compare(window.overlay.modal.opacity, 0.0) - compare(window.overlay.modeless.opacity, 0.0) + compare(window.overlay.children.length, countBefore) // only popup removed, no overlays involved window.modalPopupWithoutDim.open() tryCompare(window.modalPopupWithoutDim, "visible", true) - compare(window.overlay.modal.opacity, 0.0) - compare(window.overlay.modeless.opacity, 0.0) + compare(window.overlay.children.length, countBefore + 1) // only popup added, no overlays involved window.modalPopupWithoutDim.close() tryCompare(window.modalPopupWithoutDim, "visible", false) - compare(window.overlay.modal.opacity, 0.0) - compare(window.overlay.modeless.opacity, 0.0) - - window.upperDrawer.open() - compare(window.overlay.modal.z, 1.0) - tryCompare(window.overlay.modal, "opacity", 1.0) - window.upperDrawer.close() - tryCompare(window.overlay.modal, "opacity", 0.0) - - window.firstDrawer.open() - window.upperDrawer.open() - compare(window.overlay.modal.z, 1.0) - tryCompare(window.overlay.modal, "opacity", 1.0) - window.firstDrawer.close() - window.upperDrawer.close() - tryCompare(window.overlay.modal, "opacity", 0.0) + compare(window.overlay.children.length, countBefore) // only popup added, no overlays involved window.destroy() } diff --git a/tests/auto/popup/tst_popup.cpp b/tests/auto/popup/tst_popup.cpp index 97cbb474..3da32407 100644 --- a/tests/auto/popup/tst_popup.cpp +++ b/tests/auto/popup/tst_popup.cpp @@ -105,13 +105,11 @@ void tst_popup::overlay() QVERIFY(overlayPressedSignal.isValid()); QVERIFY(overlayReleasedSignal.isValid()); - QTest::mousePress(window, Qt::LeftButton); - QCOMPARE(overlayPressedSignal.count(), 1); - QCOMPARE(overlayReleasedSignal.count(), 0); + QVERIFY(!overlay->isVisible()); // no popups open - QTest::mouseRelease(window, Qt::LeftButton); - QCOMPARE(overlayPressedSignal.count(), 1); - QCOMPARE(overlayReleasedSignal.count(), 0); // no modal popups open + QTest::mouseClick(window, Qt::LeftButton); + QCOMPARE(overlayPressedSignal.count(), 0); + QCOMPARE(overlayReleasedSignal.count(), 0); QQuickPopup *popup = helper.window->property("popup").value<QQuickPopup*>(); QVERIFY(popup); @@ -119,10 +117,27 @@ void tst_popup::overlay() QQuickButton *button = helper.window->property("button").value<QQuickButton*>(); QVERIFY(button); + popup->open(); + QVERIFY(popup->isVisible()); + QVERIFY(overlay->isVisible()); + + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1)); + QCOMPARE(overlayPressedSignal.count(), 1); + QCOMPARE(overlayReleasedSignal.count(), 0); + + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1)); + QCOMPARE(overlayPressedSignal.count(), 1); + QCOMPARE(overlayReleasedSignal.count(), 0); // no modal-popups open + + popup->close(); + QVERIFY(!popup->isVisible()); + QVERIFY(!overlay->isVisible()); + popup->setModal(true); popup->open(); QVERIFY(popup->isVisible()); + QVERIFY(overlay->isVisible()); QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1)); QCOMPARE(overlayPressedSignal.count(), 2); @@ -133,6 +148,7 @@ void tst_popup::overlay() QCOMPARE(overlayReleasedSignal.count(), 1); QVERIFY(!popup->isVisible()); + QVERIFY(overlay->isVisible()); } void tst_popup::windowChange() |