aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2025-07-08 14:59:56 +0200
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2025-07-08 19:40:03 +0200
commit9352ef3c167bf1edfc033f14027fe38df1b9bf17 (patch)
tree34159df8321f953f8b44839b561bbfbb6a8de970 /src
parentef75f234d2fc7125eddf8ab8c49d7a2f8ca4049f (diff)
Allow recursive layout of ApplicationWindow
The safe areas require recursive layouting of the ApplicationWindow menu bar, header, and footer (in particular). We added guards preventing that in 6dc95399797de4ec27984956df1fa587f4eb18ba, to fix QTBUG-87708, but the fix for that can be in QQuickLayout itself. Pick-to: 6.10 Task-number: QTBUG-87708 Change-Id: I0dc25d779fe76619591f35063826d50dff2e3d28 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Oliver Eftevaag <oliver.eftevaag@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/quicklayouts/qquicklayout.cpp20
-rw-r--r--src/quicktemplates/qquickapplicationwindow.cpp21
2 files changed, 32 insertions, 9 deletions
diff --git a/src/quicklayouts/qquicklayout.cpp b/src/quicklayouts/qquicklayout.cpp
index 3da13ba10a..0dd0d27eed 100644
--- a/src/quicklayouts/qquicklayout.cpp
+++ b/src/quicklayouts/qquicklayout.cpp
@@ -948,12 +948,30 @@ void QQuickLayout::itemChange(ItemChange change, const ItemChangeData &value)
void QQuickLayout::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_D(QQuickLayout);
+ qCDebug(lcQuickLayouts) << "QQuickLayout::geometryChange"
+ << oldGeometry << "-->" << newGeometry;
+
QQuickItem::geometryChange(newGeometry, oldGeometry);
+
if ((invalidated() && !qobject_cast<QQuickLayout *>(parentItem())) ||
d->m_disableRearrange || !isReady())
return;
- qCDebug(lcQuickLayouts) << "QQuickLayout::geometryChange" << newGeometry << oldGeometry;
+ // The geometryChange call above might recursively update the
+ // geometry of this layout, via item change listeners, in which
+ // case the recursive call has already rearranged the layout for
+ // the new size. We don't want to rearrange here based on the old
+ // 'new geometry', as that would revert the most up to date layout.
+ const qreal w = d->width.valueBypassingBindings();
+ const qreal h = d->height.valueBypassingBindings();
+ const QSizeF currentSize(w, h);
+ if (currentSize != newGeometry.size()) {
+ qCDebug(lcQuickLayouts) << "QQuickItem::geometryChange resulted"
+ << "in size change from" << newGeometry.size() << "to"
+ << currentSize << "; layout should already be up to date.";
+ return;
+ }
+
rearrange(newGeometry.size());
}
diff --git a/src/quicktemplates/qquickapplicationwindow.cpp b/src/quicktemplates/qquickapplicationwindow.cpp
index 489dd48f47..871ae593ed 100644
--- a/src/quicktemplates/qquickapplicationwindow.cpp
+++ b/src/quicktemplates/qquickapplicationwindow.cpp
@@ -139,20 +139,25 @@ void QQuickApplicationWindowPrivate::updateHasBackgroundFlags()
void QQuickApplicationWindowPrivate::relayout()
{
Q_Q(QQuickApplicationWindow);
- if (!componentComplete || insideRelayout)
+ if (!componentComplete)
return;
+ // Note: We track whether we are inside relayout, but we do
+ // allow nested relayouts, as those are necessary to compute
+ // the height and position of footers when using safe areas.
QScopedValueRollback<bool> guard(insideRelayout, true);
- qreal menuBarHeight = menuBar && menuBar->isVisible() ? menuBar->height() : 0;
- qreal headerheight = header && header->isVisible() ? header->height() : 0;
- qreal footerHeight = footer && footer->isVisible() ? footer->height() : 0;
+ // Re-evaluate component heights for each use, as they
+ // may change between each use due to recursive layouts.
+ auto menuBarHeight = [this]{ return menuBar && menuBar->isVisible() ? menuBar->height() : 0; };
+ auto headerheight = [this]{ return header && header->isVisible() ? header->height() : 0; };
+ auto footerHeight = [this]{ return footer && footer->isVisible() ? footer->height() : 0; };
control->setSize(q->size());
layoutItem(menuBar, 0, q->width());
- layoutItem(header, menuBarHeight, q->width());
- layoutItem(footer, control->height() - footerHeight, q->width());
+ layoutItem(header, menuBarHeight(), q->width());
+ layoutItem(footer, control->height() - footerHeight(), q->width());
if (background) {
if (!hasBackgroundWidth && qFuzzyIsNull(background->x()))
@@ -168,8 +173,8 @@ void QQuickApplicationWindowPrivate::relayout()
auto *windowSafeArea = static_cast<QQuickSafeArea*>(qmlAttachedPropertiesObject<QQuickSafeArea>(q));
const auto inheritedMargins = windowSafeArea->margins();
controlSafeArea->setAdditionalMargins(QMarginsF(
- 0, (menuBarHeight + headerheight) - inheritedMargins.top(),
- 0, footerHeight - inheritedMargins.bottom()));
+ 0, (menuBarHeight() + headerheight()) - inheritedMargins.top(),
+ 0, footerHeight() - inheritedMargins.bottom()));
}
void QQuickApplicationWindowPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff)