macOS: Update safe area margins via KVO on NSView.safeAreaInsets

We still need to check if the margins need update on geometry change,
as we also take the screen safe area margins into account, which
NSView.safeAreaInsets does not.

Change-Id: I193544966f983744bb798cece9c4eaf17cd858f3
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
This commit is contained in:
Tor Arne Vestbø 2024-11-30 17:51:35 +01:00
parent d14addfd45
commit ea1409afc1
2 changed files with 22 additions and 4 deletions

View File

@ -247,6 +247,8 @@ public: // for QNSView
int m_registerTouchCount = 0; int m_registerTouchCount = 0;
bool m_resizableTransientParent = false; bool m_resizableTransientParent = false;
QMacKeyValueObserver m_safeAreaInsetsObserver;
void updateSafeAreaMarginsIfNeeded();
QMargins m_lastReportedSafeAreaMargins; QMargins m_lastReportedSafeAreaMargins;
static const int NoAlertRequest; static const int NoAlertRequest;

View File

@ -132,6 +132,15 @@ void QCocoaWindow::initialize()
setMask(QHighDpi::toNativeLocalRegion(window()->mask(), window())); setMask(QHighDpi::toNativeLocalRegion(window()->mask(), window()));
m_safeAreaInsetsObserver = QMacKeyValueObserver(
m_view, @"safeAreaInsets", [this] {
// Defer to next runloop pass, so that any changes to the
// margins during resizing have settled down.
QMetaObject::invokeMethod(this, [this]{
updateSafeAreaMarginsIfNeeded();
}, Qt::QueuedConnection);
}, NSKeyValueObservingOptionNew);
} else { } else {
// Pick up essential foreign window state // Pick up essential foreign window state
QPlatformWindow::setGeometry(QRectF::fromCGRect(m_view.frame).toRect()); QPlatformWindow::setGeometry(QRectF::fromCGRect(m_view.frame).toRect());
@ -152,6 +161,8 @@ QCocoaWindow::~QCocoaWindow()
[m_nsWindow makeFirstResponder:nil]; [m_nsWindow makeFirstResponder:nil];
[m_nsWindow setContentView:nil]; [m_nsWindow setContentView:nil];
m_safeAreaInsetsObserver = {};
// Remove from superview only if we have a Qt window parent, // Remove from superview only if we have a Qt window parent,
// as we don't want to affect window container foreign windows. // as we don't want to affect window container foreign windows.
if (QPlatformWindow::parent()) if (QPlatformWindow::parent())
@ -346,6 +357,14 @@ QMargins QCocoaWindow::safeAreaMargins() const
return (screenSafeAreaMargins | viewSafeAreaMargins).toMargins(); return (screenSafeAreaMargins | viewSafeAreaMargins).toMargins();
} }
void QCocoaWindow::updateSafeAreaMarginsIfNeeded()
{
if (safeAreaMargins() != m_lastReportedSafeAreaMargins) {
m_lastReportedSafeAreaMargins = safeAreaMargins();
QWindowSystemInterface::handleSafeAreaMarginsChanged(window());
}
}
bool QCocoaWindow::startSystemMove() bool QCocoaWindow::startSystemMove()
{ {
switch (NSApp.currentEvent.type) { switch (NSApp.currentEvent.type) {
@ -1521,10 +1540,7 @@ void QCocoaWindow::handleGeometryChange()
QWindowSystemInterface::handleGeometryChange(window(), newGeometry); QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
// Changing the window geometry may affect the safe area margins // Changing the window geometry may affect the safe area margins
if (safeAreaMargins() != m_lastReportedSafeAreaMargins) { updateSafeAreaMarginsIfNeeded();
m_lastReportedSafeAreaMargins = safeAreaMargins();
QWindowSystemInterface::handleSafeAreaMarginsChanged(window());
}
// Guard against processing window system events during QWindow::setGeometry // Guard against processing window system events during QWindow::setGeometry
// calls, which Qt and Qt applications do not expect. // calls, which Qt and Qt applications do not expect.