diff options
author | J-P Nurmi <jpnurmi@qt.io> | 2016-10-26 21:31:03 +0200 |
---|---|---|
committer | J-P Nurmi <jpnurmi@qt.io> | 2016-10-27 13:20:20 +0000 |
commit | a7e39a28575dc3421970e007b78731b614da258a (patch) | |
tree | b6fb24d01f6eca329b0e47a91898c93620809335 | |
parent | e711ce99c8cafe2e7c1d81a20a280f3029c98ccb (diff) |
QQuickPopup: fix binding loops with size-dependent positioning
Dependencies between popup's size and position easily lead to recursion
into reposition(). Blocking recursive reposition() calls messes up the
positioning, so schedule polish events instead.
Task-number: QTBUG-56755
Change-Id: I72afd14573e5cd57f8162df04e193d4c42fd7236
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
-rw-r--r-- | src/quicktemplates2/qquickpopup.cpp | 16 | ||||
-rw-r--r-- | src/quicktemplates2/qquickpopup_p_p.h | 3 | ||||
-rw-r--r-- | tests/auto/controls/data/tst_popup.qml | 31 | ||||
-rw-r--r-- | tests/auto/drawer/tst_drawer.cpp | 2 |
4 files changed, 51 insertions, 1 deletions
diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp index 124b8c5b..d343fad6 100644 --- a/src/quicktemplates2/qquickpopup.cpp +++ b/src/quicktemplates2/qquickpopup.cpp @@ -128,6 +128,7 @@ QQuickPopupPrivate::QQuickPopupPrivate() , hasDim(false) , visible(false) , complete(false) + , positioning(false) , hasWidth(false) , hasHeight(false) , hasTopMargin(false) @@ -401,6 +402,12 @@ QQuickPopupItem::QQuickPopupItem(QQuickPopup *popup) : // connect(QGuiApplication::styleHints(), &QStyleHints::useHoverEffectsChanged, this, &QQuickItem::setAcceptHoverEvents); } +void QQuickPopupItem::updatePolish() +{ + Q_D(QQuickPopupItem); + return QQuickPopupPrivate::get(d->popup)->reposition(); +} + bool QQuickPopupItem::childMouseEventFilter(QQuickItem *child, QEvent *event) { Q_D(QQuickPopupItem); @@ -594,6 +601,11 @@ void QQuickPopupPrivate::reposition() if (!popupItem->isVisible()) return; + if (positioning) { + popupItem->polish(); + return; + } + const qreal w = popupItem->width(); const qreal h = popupItem->height(); const qreal iw = popupItem->implicitWidth(); @@ -702,6 +714,8 @@ void QQuickPopupPrivate::reposition() } } + positioning = true; + popupItem->setPosition(rect.topLeft()); const QPointF effectivePos = parentItem ? parentItem->mapFromScene(rect.topLeft()) : rect.topLeft(); @@ -718,6 +732,8 @@ void QQuickPopupPrivate::reposition() popupItem->setWidth(rect.width()); if (!hasHeight && heightAdjusted && rect.height() > 0) popupItem->setHeight(rect.height()); + + positioning = false; } void QQuickPopupPrivate::resizeOverlay() diff --git a/src/quicktemplates2/qquickpopup_p_p.h b/src/quicktemplates2/qquickpopup_p_p.h index c8c83ada..d2f16e11 100644 --- a/src/quicktemplates2/qquickpopup_p_p.h +++ b/src/quicktemplates2/qquickpopup_p_p.h @@ -87,6 +87,8 @@ public: explicit QQuickPopupItem(QQuickPopup *popup); protected: + void updatePolish() override; + bool childMouseEventFilter(QQuickItem *child, QEvent *event) override; void focusInEvent(QFocusEvent *event) override; void focusOutEvent(QFocusEvent *event) override; @@ -185,6 +187,7 @@ public: bool hasDim; bool visible; bool complete; + bool positioning; bool hasWidth; bool hasHeight; bool hasTopMargin; diff --git a/tests/auto/controls/data/tst_popup.qml b/tests/auto/controls/data/tst_popup.qml index 82fcbf8b..0ca8ce57 100644 --- a/tests/auto/controls/data/tst_popup.qml +++ b/tests/auto/controls/data/tst_popup.qml @@ -1229,4 +1229,35 @@ TestCase { control.destroy() } + + Component { + id: xyBindingLoop + ApplicationWindow { + id: window + width: 360 + height: 360 + visible: true + property alias popup: popup + + Popup { + id: popup + visible: true + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + Label { + text: "Content" + anchors.fill: parent + } + } + } + } + + function test_xyBindingLoop() { + var window = xyBindingLoop.createObject(testCase) + var control = window.popup + waitForRendering(control.contentItem) + compare(control.x, (control.parent.width - control.width) / 2) + compare(control.y, (control.parent.height - control.height) / 2) + window.destroy() + } } diff --git a/tests/auto/drawer/tst_drawer.cpp b/tests/auto/drawer/tst_drawer.cpp index 80385421..830f63b0 100644 --- a/tests/auto/drawer/tst_drawer.cpp +++ b/tests/auto/drawer/tst_drawer.cpp @@ -380,7 +380,7 @@ void tst_Drawer::reposition() window->setWidth(window->width() + 100); QTRY_COMPARE(geometry(dimmer), QRectF(0, 150, window->width(), window->height() - 150)); - QCOMPARE(geometry(popupItem), QRectF(window->width() - drawer->width(), 150, window->width() / 2, window->height() - 150)); + QTRY_COMPARE(geometry(popupItem), QRectF(window->width() - drawer->width(), 150, window->width() / 2, window->height() - 150)); drawer->close(); QTRY_COMPARE(geometry(popupItem), QRectF(window->width(), 150, window->width() / 2, window->height() - 150)); |