macOS: Add support for safe area margins
We reflect both the NSView's own safeAreaInsets as well as the screen's safeAreaInsets mapped to the view. This covers both in-window views that obscure the view, e.g. toolbars or the titlebar, as well as areas outside of the window that affect the window if it has geometry that overlaps these areas (such as the notch on MacBook Pro laptops). Fixes: QTBUG-125372 Change-Id: I17af7f456ade83eef910ef5b0eaeab7cd8075263 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>bb10
parent
bee9de0452
commit
fd97a820df
|
|
@ -80,6 +80,8 @@ public:
|
|||
QRect normalGeometry() const override;
|
||||
void setCocoaGeometry(const QRect &rect);
|
||||
|
||||
QMargins safeAreaMargins() const override;
|
||||
|
||||
void setVisible(bool visible) override;
|
||||
void setWindowFlags(Qt::WindowFlags flags) override;
|
||||
void setWindowState(Qt::WindowStates state) override;
|
||||
|
|
@ -241,6 +243,8 @@ public: // for QNSView
|
|||
int m_registerTouchCount = 0;
|
||||
bool m_resizableTransientParent = false;
|
||||
|
||||
QMargins m_lastReportedSafeAreaMargins;
|
||||
|
||||
static const int NoAlertRequest;
|
||||
NSInteger m_alertRequest = NoAlertRequest;
|
||||
|
||||
|
|
|
|||
|
|
@ -285,6 +285,54 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect)
|
|||
// will call QPlatformWindow::setGeometry(rect) during resize confirmation (see qnsview.mm)
|
||||
}
|
||||
|
||||
QMargins QCocoaWindow::safeAreaMargins() const
|
||||
{
|
||||
// The safe area of the view reflects the area not covered by navigation
|
||||
// bars, tab bars, toolbars, and other ancestor views that might obscure
|
||||
// the current view (by setting additionalSafeAreaInsets). If the window
|
||||
// uses NSWindowStyleMaskFullSizeContentView this also includes the area
|
||||
// of the view covered by the title bar.
|
||||
QMarginsF viewSafeAreaMargins = {
|
||||
m_view.safeAreaInsets.left,
|
||||
m_view.safeAreaInsets.top,
|
||||
m_view.safeAreaInsets.right,
|
||||
m_view.safeAreaInsets.bottom
|
||||
};
|
||||
|
||||
// The screen's safe area insets represent the distances from the screen's
|
||||
// edges at which content isn't obscured. The view's safe area margins do
|
||||
// not include the screen's insets automatically, so we need to manually
|
||||
// merge them.
|
||||
auto screenRect = m_view.window.screen.frame;
|
||||
auto screenInsets = m_view.window.screen.safeAreaInsets;
|
||||
auto screenRelativeViewBounds = QCocoaScreen::mapFromNative(
|
||||
[m_view.window convertRectToScreen:
|
||||
[m_view convertRect:m_view.bounds toView:nil]]
|
||||
);
|
||||
|
||||
// The margins are relative to the screen the window is on.
|
||||
// Note that we do not want represent the area outside of the
|
||||
// screen as being outside of the safe area.
|
||||
QMarginsF screenSafeAreaMargins = {
|
||||
screenInsets.left ?
|
||||
qMax(0.0f, screenInsets.left - screenRelativeViewBounds.left())
|
||||
: 0.0f,
|
||||
screenInsets.top ?
|
||||
qMax(0.0f, screenInsets.top - screenRelativeViewBounds.top())
|
||||
: 0.0f,
|
||||
screenInsets.right ?
|
||||
qMax(0.0f, screenInsets.right
|
||||
- (screenRect.size.width - screenRelativeViewBounds.right()))
|
||||
: 0.0f,
|
||||
screenInsets.bottom ?
|
||||
qMax(0.0f, screenInsets.bottom
|
||||
- (screenRect.size.height - screenRelativeViewBounds.bottom()))
|
||||
: 0.0f
|
||||
};
|
||||
|
||||
return (screenSafeAreaMargins | viewSafeAreaMargins).toMargins();
|
||||
}
|
||||
|
||||
bool QCocoaWindow::startSystemMove()
|
||||
{
|
||||
switch (NSApp.currentEvent.type) {
|
||||
|
|
@ -1435,6 +1483,12 @@ void QCocoaWindow::handleGeometryChange()
|
|||
|
||||
QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
|
||||
|
||||
// Changing the window geometry may affect the safe area margins
|
||||
if (safeAreaMargins() != m_lastReportedSafeAreaMargins) {
|
||||
m_lastReportedSafeAreaMargins = safeAreaMargins();
|
||||
QWindowSystemInterface::handleSafeAreaMarginsChanged(window());
|
||||
}
|
||||
|
||||
// Guard against processing window system events during QWindow::setGeometry
|
||||
// calls, which Qt and Qt applications do not expect.
|
||||
if (!m_inSetGeometry)
|
||||
|
|
|
|||
Loading…
Reference in New Issue