macOS: Ensure all windows are created on a valid screen
We rely on AppKit repositioning the window if the original position is not on any of the available screens. We do this by keeping the original position, but using the primary screen as reference. This doesn't work unless the window has a title bar, so in the corner case where the window has an invalid position, we apply the title bar style mask for a brief moment, so that AppKit will place the window correctly. Task-number: QTBUG-69221 Change-Id: If66cac36bf36f051570ba5854951ce4504fe771f Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
This commit is contained in:
parent
55fc9a5dd9
commit
6caaa050ab
@ -1355,6 +1355,15 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel)
|
||||
{
|
||||
QMacAutoReleasePool pool;
|
||||
|
||||
Qt::WindowType type = window()->type();
|
||||
Qt::WindowFlags flags = window()->flags();
|
||||
|
||||
// Note: The macOS window manager has a bug, where if a screen is rotated, it will not allow
|
||||
// a window to be created within the area of the screen that has a Y coordinate (I quadrant)
|
||||
// higher than the height of the screen in its non-rotated state, unless the window is
|
||||
// created with the NSWindowStyleMaskBorderless style mask.
|
||||
NSWindowStyleMask styleMask = windowStyleMask(flags);
|
||||
|
||||
QRect rect = geometry();
|
||||
|
||||
QScreen *targetScreen = nullptr;
|
||||
@ -1366,26 +1375,22 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel)
|
||||
}
|
||||
|
||||
if (!targetScreen) {
|
||||
qCWarning(lcQpaCocoaWindow) << "Window position outside any known screen, using primary screen";
|
||||
qCWarning(lcQpaCocoaWindow) << "Window position" << rect << "outside any known screen, using primary screen";
|
||||
targetScreen = QGuiApplication::primaryScreen();
|
||||
// AppKit will only reposition a window that's outside the target screen area if
|
||||
// the window has a title bar. If left out, the window ends up with no screen.
|
||||
// The style mask will be corrected to the original style mask in setWindowFlags.
|
||||
styleMask |= NSWindowStyleMaskTitled;
|
||||
}
|
||||
|
||||
rect.translate(-targetScreen->geometry().topLeft());
|
||||
QCocoaScreen *cocoaScreen = static_cast<QCocoaScreen *>(targetScreen->handle());
|
||||
NSRect frame = QCocoaScreen::mapToNative(rect, cocoaScreen);
|
||||
|
||||
// Note: The macOS window manager has a bug, where if a screen is rotated, it will not allow
|
||||
// a window to be created within the area of the screen that has a Y coordinate (I quadrant)
|
||||
// higher than the height of the screen in its non-rotated state, unless the window is
|
||||
// created with the NSWindowStyleMaskBorderless style mask.
|
||||
|
||||
Qt::WindowType type = window()->type();
|
||||
Qt::WindowFlags flags = window()->flags();
|
||||
|
||||
// Create NSWindow
|
||||
Class windowClass = shouldBePanel ? [QNSPanel class] : [QNSWindow class];
|
||||
QCocoaNSWindow *nsWindow = [[windowClass alloc] initWithContentRect:frame
|
||||
styleMask:windowStyleMask(flags)
|
||||
styleMask:styleMask
|
||||
// Deferring window creation breaks OpenGL (the GL context is
|
||||
// set up before the window is shown and needs a proper window)
|
||||
backing:NSBackingStoreBuffered defer:NO
|
||||
@ -1394,6 +1399,9 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel)
|
||||
Q_ASSERT_X(nsWindow.screen == cocoaScreen->nativeScreen(), "QCocoaWindow",
|
||||
"Resulting NSScreen should match the requested NSScreen");
|
||||
|
||||
if (targetScreen != window()->screen())
|
||||
QWindowSystemInterface::handleWindowScreenChanged(window(), targetScreen);
|
||||
|
||||
nsWindow.delegate = [[QNSWindowDelegate alloc] initWithQCocoaWindow:this];
|
||||
|
||||
// Prevent Cocoa from releasing the window on close. Qt
|
||||
@ -1413,9 +1421,6 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel)
|
||||
});
|
||||
}
|
||||
|
||||
if (targetScreen != window()->screen())
|
||||
QWindowSystemInterface::handleWindowScreenChanged(window(), targetScreen);
|
||||
|
||||
nsWindow.restorable = NO;
|
||||
nsWindow.level = windowLevel(flags);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user