macOS: Always propagate QCocoaWindow::setGeometry to NSView/NSWindow

We had an optimization that tried to avoid calling setFrame on the
view if the geometry had already been applied, but this logic could
fail if the NSView or NSWindow for various reasons did not reflect
our view of the world through QPlatformWindow::geometry().

One such case was when adding a NSToolBar to a window, in which
case we would end up with the wrong window size.

We now always propagate the geometry, under the assumption that
AppKit will handle the case of setting the same geometry as a noop.

We also pick up any geometry changes that happen during the initial
initializion of the window, even if we are not sending geometry change
events for those until the window is made visible. This ensures we
have an as accurate view of the native window state as possible.

Pick-to: 6.8
Change-Id: I76c753b6f4be8fdbb7a5f6ca3a8b91e013c0b36b
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
This commit is contained in:
Tor Arne Vestbø 2024-11-11 14:08:34 +01:00
parent 6899e072ed
commit f1efa7d60b

View File

@ -214,8 +214,6 @@ void QCocoaWindow::setGeometry(const QRect &rectIn)
const QMargins margins = frameMargins();
rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top()));
}
if (geometry() == rect)
return;
setCocoaGeometry(rect);
}
@ -1483,18 +1481,6 @@ bool QCocoaWindow::windowShouldClose()
void QCocoaWindow::handleGeometryChange()
{
// Prevent geometry change during initialization, as that will result
// in a resize event, and Qt expects those to come after the show event.
// FIXME: Remove once we've clarified the Qt behavior for this.
if (!m_initialized)
return;
// It can happen that the current NSWindow is nil (if we are changing styleMask
// from/to borderless, and the content view is being re-parented), which results
// in invalid coordinates.
if (m_inSetStyleMask && !m_view.window)
return;
QRect newGeometry;
if (isContentView() && !isEmbedded()) {
// Content views are positioned at (0, 0) in the window, so we resolve via the window
@ -1510,6 +1496,24 @@ void QCocoaWindow::handleGeometryChange()
qCDebug(lcQpaWindow) << "QCocoaWindow::handleGeometryChange" << window()
<< "current" << geometry() << "new" << newGeometry;
// It can happen that the current NSWindow is nil (if we are changing styleMask
// from/to borderless, and the content view is being re-parented), which results
// in invalid coordinates.
if (m_inSetStyleMask && !m_view.window) {
qCDebug(lcQpaWindow) << "Lacking window during style mask update, ignoring geometry change";
return;
}
// Prevent geometry change during initialization, as that will result
// in a resize event, and Qt expects those to come after the show event.
// FIXME: Remove once we've clarified the Qt behavior for this.
if (!m_initialized) {
// But update the QPlatformWindow reality
QPlatformWindow::setGeometry(newGeometry);
qCDebug(lcQpaWindow) << "Window still initializing, skipping event";
return;
}
QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
// Changing the window geometry may affect the safe area margins