Add public QWindow API for safe area margins

The margins are exposed as a simple QMargins, as this is covers the
primary use-cases sufficiently at this point.

A Q_PROPERTY is not added, as this would conflict with the explicit
Qt Quick API that will also be added.

Task-number: QTBUG-125374
Change-Id: I504c3000473de0b09272aa5a3e58ebf9a41aa942
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
This commit is contained in:
Tor Arne Vestbø 2024-11-14 22:08:59 +01:00 committed by Volker Hilsheimer
parent ed0eb386da
commit 7707ab210f
7 changed files with 50 additions and 13 deletions

View File

@ -230,6 +230,8 @@ Q_TRACE_POINT(qtcore, QEvent_dtor, QEvent *event, QEvent::Type type);
\value WindowUnblocked The window is unblocked after a modal dialog exited.
\value WinIdChange The window system identifier for this native widget has changed.
\value ZOrderChange The widget's z-order has changed. This event is never sent to top level windows.
\value [since 6.9] SafeAreaMarginsChange
The window's safe area margins have changed.
User events should have values between \c User and \c{MaxUser}:

View File

@ -292,6 +292,8 @@ public:
ParentWindowAboutToChange = 225,
ParentWindowChange = 226,
SafeAreaMarginsChange = 227,
// 512 reserved for Qt Jambi's MetaCall event
// 513 reserved for Qt Jambi's DeleteOnMainThread event

View File

@ -2785,10 +2785,10 @@ void QGuiApplicationPrivate::processSafeAreaMarginsChangedEvent(QWindowSystemInt
if (wse->window.isNull())
return;
// Handle by forwarding directly to QWindowPrivate, instead of sending spontaneous
// QEvent like most other functions, as there's no QEvent type for the safe area
// change, and we don't want to add one until we know that this is a good API.
qt_window_private(wse->window)->processSafeAreaMarginsChanged();
emit wse->window->safeAreaMarginsChanged(wse->window->safeAreaMargins());
QEvent event(QEvent::SafeAreaMarginsChange);
QGuiApplication::sendSpontaneousEvent(wse->window, &event);
}
void QGuiApplicationPrivate::processThemeChanged(QWindowSystemInterfacePrivate::ThemeChangeEvent *tce)

View File

@ -1967,6 +1967,37 @@ void QWindow::setFramePosition(const QPoint &point)
}
}
/*!
Returns the safe area margins of the window.
The safe area represents the part of the window where content
can be safely placed without risk of being obscured by, or
conflicting with, other UI elements, such as system UIs.
The margins are relative to the internal geometry of the
window, i.e QRect(0, 0, width(), height()).
\code
void PaintDeviceWindow::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QRect rect(0, 0, width(), height());
painter.fillRect(rect, QGradient::SunnyMorning);
painter.fillRect(rect - safeAreaMargins(), QGradient::DustyGrass);
}
\endcode
\since 6.9
\sa geometry()
*/
QMargins QWindow::safeAreaMargins() const
{
Q_D(const QWindow);
if (d->platformWindow)
return QHighDpi::fromNativePixels(d->platformWindow->safeAreaMargins(), this);
return {};
}
/*!
\brief set the position of the window on the desktop to \a pt
@ -3255,6 +3286,9 @@ QDebug operator<<(QDebug debug, const QWindow *window)
const QMargins margins = window->frameMargins();
if (!margins.isNull())
debug << ", margins=" << margins;
const QMargins safeAreaMargins = window->safeAreaMargins();
if (!safeAreaMargins.isNull())
debug << ", safeAreaMargins=" << safeAreaMargins;
debug << ", devicePixelRatio=" << window->devicePixelRatio();
if (const QPlatformWindow *platformWindow = window->handle())
debug << ", winId=0x" << Qt::hex << platformWindow->winId() << Qt::dec;

View File

@ -202,6 +202,8 @@ public:
QPoint framePosition() const;
void setFramePosition(const QPoint &point);
QMargins safeAreaMargins() const;
inline int width() const { return geometry().width(); }
inline int height() const { return geometry().height(); }
inline int x() const { return geometry().x(); }
@ -309,6 +311,8 @@ Q_SIGNALS:
void maximumWidthChanged(int arg);
void maximumHeightChanged(int arg);
void safeAreaMarginsChanged(QMargins arg);
void visibleChanged(bool arg);
Q_REVISION(2, 1) void visibilityChanged(QWindow::Visibility visibility);
Q_REVISION(2, 1) void activeChanged();

View File

@ -92,8 +92,6 @@ public:
qxp::function_ref<void()> funcWidthChanged,
qxp::function_ref<void()> funcHeightChanged);
virtual void processSafeAreaMarginsChanged() {}
virtual bool participatesInLastWindowClosed() const;
virtual bool treatAsVisible() const;

View File

@ -106,13 +106,6 @@ public:
QRectF closestAcceptableGeometry(const QRectF &rect) const override;
void processSafeAreaMarginsChanged() override
{
Q_Q(QWidgetWindow);
if (QWidget *widget = q->widget())
QWidgetPrivate::get(widget)->updateContentsRect();
}
bool participatesInLastWindowClosed() const override;
bool treatAsVisible() const override;
};
@ -391,6 +384,10 @@ bool QWidgetWindow::event(QEvent *event)
handleDevicePixelRatioChange();
break;
case QEvent::SafeAreaMarginsChange:
QWidgetPrivate::get(m_widget)->updateContentsRect();
break;
default:
break;
}