From ea1409afc1d13c30dac856cdb298a9d2a42f2abc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sat, 30 Nov 2024 17:51:35 +0100 Subject: [PATCH] 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 --- src/plugins/platforms/cocoa/qcocoawindow.h | 2 ++ src/plugins/platforms/cocoa/qcocoawindow.mm | 24 +++++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index a2fbbc3f200..765b7e6619f 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -247,6 +247,8 @@ public: // for QNSView int m_registerTouchCount = 0; bool m_resizableTransientParent = false; + QMacKeyValueObserver m_safeAreaInsetsObserver; + void updateSafeAreaMarginsIfNeeded(); QMargins m_lastReportedSafeAreaMargins; static const int NoAlertRequest; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 8904570e558..8bcc200b57c 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -132,6 +132,15 @@ void QCocoaWindow::initialize() 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 { // Pick up essential foreign window state QPlatformWindow::setGeometry(QRectF::fromCGRect(m_view.frame).toRect()); @@ -152,6 +161,8 @@ QCocoaWindow::~QCocoaWindow() [m_nsWindow makeFirstResponder:nil]; [m_nsWindow setContentView:nil]; + m_safeAreaInsetsObserver = {}; + // Remove from superview only if we have a Qt window parent, // as we don't want to affect window container foreign windows. if (QPlatformWindow::parent()) @@ -346,6 +357,14 @@ QMargins QCocoaWindow::safeAreaMargins() const return (screenSafeAreaMargins | viewSafeAreaMargins).toMargins(); } +void QCocoaWindow::updateSafeAreaMarginsIfNeeded() +{ + if (safeAreaMargins() != m_lastReportedSafeAreaMargins) { + m_lastReportedSafeAreaMargins = safeAreaMargins(); + QWindowSystemInterface::handleSafeAreaMarginsChanged(window()); + } +} + bool QCocoaWindow::startSystemMove() { switch (NSApp.currentEvent.type) { @@ -1521,10 +1540,7 @@ 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()); - } + updateSafeAreaMarginsIfNeeded(); // Guard against processing window system events during QWindow::setGeometry // calls, which Qt and Qt applications do not expect.