Only default top levels to Qt::WA_ContentsMarginsRespectsSafeArea

When safe area margins are in play, such as on iOS and Android, or on
macOS in 6.8 and above when the NSWindowStyleMaskFullSizeContentView
styleMask has been set (manually or via Qt::ExpandedClientAreaHint in
6.9), then widgets with a layout will by default try to avoid the non-
safe areas.

This worked well as a safe default, ensuring widget applications filled
the entire window with its background color, while constraining the
layout of children to the safe area.

However, for those that explicitly want to put content in the non-safe
areas, by setting Qt::WA_ContentsMarginsRespectsSafeArea to false, the
story was a bit cumbersome, as we set the attribute to true by default
for all widgets. Meaning, any child widget put into the non-safe areas
that itself had a layout (such as a push button) would also need the
Qt::WA_ContentsMarginsRespectsSafeArea = false override.

We now default Qt::WA_ContentsMarginsRespectsSafeArea to true only for
top level widgets on creation, and leave it up to the user to manage the
attribute for the other use-cases, as they then need to be in full control.

[ChangeLog][QtWidgets] The Qt::WA_ContentsMarginsRespectsSafeArea attribute
is no longer set by default for non-top-level widgets. Top level widgets
still default to Qt::WA_ContentsMarginsRespectsSafeArea=true, so children
are laid out in the safe areas, but overriding the attribute for the top
level now allows placing widgets in the non-safe areas without also setting
the Qt::WA_ContentsMarginsRespectsSafeArea attribute to false for every
descendant widget that overlaps the non-safe area.

Task-number: QTBUG-133215
Pick-to: 6.8
Change-Id: I7b1d420d730ee896ec2fb61aadacd94473dc9681
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
(cherry picked from commit 16081f414d9cfd752c0e6152fbfa386bdbade7a4)
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
Tor Arne Vestbø 2025-02-20 14:11:30 +01:00
parent 8287fb63ef
commit a833d93f59
2 changed files with 23 additions and 2 deletions

View File

@ -103,6 +103,9 @@ static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
static void setAttribute_internal(Qt::WidgetAttribute attribute,
bool on, QWidgetData *data, QWidgetPrivate *d);
QWidgetPrivate::QWidgetPrivate(int version)
: QObjectPrivate(version)
, focus_next(nullptr)
@ -978,7 +981,6 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute()
adjustQuitOnCloseAttribute();
q->setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea);
q->setAttribute(Qt::WA_WState_Hidden);
//give potential windows a bigger "pre-initial" size; create() will give them a new size later
@ -1205,6 +1207,15 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
if (QApplicationPrivate::testAttribute(Qt::AA_NativeWindows))
setAttribute(Qt::WA_NativeWindow);
if (isWindow()) {
// Make top levels automatically respect safe areas by default
auto *topExtra = d->maybeTopData();
if (!topExtra || !topExtra->explicitContentsMarginsRespectsSafeArea) {
setAttribute_internal(Qt::WA_ContentsMarginsRespectsSafeArea,
true, data, d);
}
}
d->updateIsOpaque();
setAttribute(Qt::WA_WState_Created); // set created flag
@ -1623,6 +1634,7 @@ void QWidgetPrivate::createTLExtra()
x->posIncludesFrame = 0;
x->sizeAdjusted = false;
x->embedded = 0;
x->explicitContentsMarginsRespectsSafeArea = 0;
x->window = nullptr;
x->initialScreen = nullptr;
@ -11367,10 +11379,18 @@ void QWidgetPrivate::macUpdateSizeAttribute()
*/
void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
{
Q_D(QWidget);
if (attribute == Qt::WA_ContentsMarginsRespectsSafeArea) {
if (isWindow()) {
auto *topExtra = d->topData();
topExtra->explicitContentsMarginsRespectsSafeArea = true;
}
}
if (testAttribute(attribute) == on)
return;
Q_D(QWidget);
static_assert(sizeof(d->high_attributes)*8 >= (Qt::WA_AttributeCount - sizeof(uint)*8),
"QWidget::setAttribute(WidgetAttribute, bool): "
"QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute");

View File

@ -118,6 +118,7 @@ struct QTLWExtra {
uint posIncludesFrame : 1;
uint sizeAdjusted : 1;
uint embedded : 1;
uint explicitContentsMarginsRespectsSafeArea: 1;
};
struct QWExtra {