macOS: Allow windows to be created on any screen within the virtual desktop
Setting the geometry of a window to a position outside of the primary screen, but within the virtual desktop, would not result in the window being created on the secondary screen, as macOS does not seem to translate the global screen position when creating new windows. We work around this by translating the position ourselves, and using the overload of [NSWindow initWithContentRect:] that takes the NSScreen to create the window on. Due to a bug in the macOS window manger, this fails for windows that are created within a certain region of rotated screens. This is not an issue for setting the geometry after creating a window, so we should investigate making the window-creation code set its geometry via the same code path, after creating the window (without having the window momentarily show up in the wrong position). Change-Id: Iba8eefe65e2c91667856299d90a8606e361ceacb Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>bb10
parent
e39a436d0c
commit
1ad6ae21f0
|
|
@ -96,6 +96,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSWindowHelper);
|
|||
@property (nonatomic, readonly) QNSWindowHelper *helper;
|
||||
|
||||
- (id)initWithContentRect:(NSRect)contentRect
|
||||
screen:(NSScreen*)screen
|
||||
styleMask:(NSUInteger)windowStyle
|
||||
qPlatformWindow:(QCocoaWindow *)qpw;
|
||||
|
||||
|
|
@ -111,6 +112,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSWindow);
|
|||
@property (nonatomic, readonly) QNSWindowHelper *helper;
|
||||
|
||||
- (id)initWithContentRect:(NSRect)contentRect
|
||||
screen:(NSScreen*)screen
|
||||
styleMask:(NSUInteger)windowStyle
|
||||
qPlatformWindow:(QCocoaWindow *)qpw;
|
||||
|
||||
|
|
|
|||
|
|
@ -201,13 +201,14 @@ static void qt_closePopups()
|
|||
@synthesize helper = _helper;
|
||||
|
||||
- (id)initWithContentRect:(NSRect)contentRect
|
||||
screen:(NSScreen*)screen
|
||||
styleMask:(NSUInteger)windowStyle
|
||||
qPlatformWindow:(QCocoaWindow *)qpw
|
||||
{
|
||||
self = [super initWithContentRect:contentRect
|
||||
styleMask:windowStyle
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:NO]; // Deferring window creation breaks OpenGL (the GL context is
|
||||
defer:NO screen:screen]; // Deferring window creation breaks OpenGL (the GL context is
|
||||
// set up before the window is shown and needs a proper window)
|
||||
|
||||
if (self) {
|
||||
|
|
@ -283,13 +284,14 @@ static void qt_closePopups()
|
|||
@synthesize helper = _helper;
|
||||
|
||||
- (id)initWithContentRect:(NSRect)contentRect
|
||||
screen:(NSScreen*)screen
|
||||
styleMask:(NSUInteger)windowStyle
|
||||
qPlatformWindow:(QCocoaWindow *)qpw
|
||||
{
|
||||
self = [super initWithContentRect:contentRect
|
||||
styleMask:windowStyle
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:NO]; // Deferring window creation breaks OpenGL (the GL context is
|
||||
defer:NO screen:screen]; // Deferring window creation breaks OpenGL (the GL context is
|
||||
// set up before the window is shown and needs a proper window)
|
||||
|
||||
if (self) {
|
||||
|
|
@ -1642,7 +1644,28 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBeChildNSWindow, bool sh
|
|||
QMacAutoReleasePool pool;
|
||||
|
||||
QRect rect = initialGeometry(window(), windowGeometry(), defaultWindowWidth, defaultWindowHeight);
|
||||
NSRect frame = qt_mac_flipRect(rect);
|
||||
|
||||
QScreen *targetScreen = nullptr;
|
||||
for (QScreen *screen : QGuiApplication::screens()) {
|
||||
if (screen->geometry().contains(rect.topLeft())) {
|
||||
targetScreen = screen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!targetScreen) {
|
||||
qCWarning(lcQpaCocoaWindow) << "Window position outside any known screen, using primary screen";
|
||||
targetScreen = QGuiApplication::primaryScreen();
|
||||
}
|
||||
|
||||
rect.translate(-targetScreen->geometry().topLeft());
|
||||
QCocoaScreen *cocoaScreen = static_cast<QCocoaScreen *>(targetScreen->handle());
|
||||
NSRect frame = cocoaScreen->mapToNative(rect).toCGRect();
|
||||
|
||||
// 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();
|
||||
|
|
@ -1658,31 +1681,27 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBeChildNSWindow, bool sh
|
|||
// Use NSPanel for popup-type windows. (Popup, Tool, ToolTip, SplashScreen)
|
||||
// and dialogs
|
||||
if (shouldBePanel) {
|
||||
QNSPanel *window;
|
||||
window = [[QNSPanel alloc] initWithContentRect:frame
|
||||
styleMask: styleMask
|
||||
qPlatformWindow:this];
|
||||
QNSPanel *panel = [[QNSPanel alloc] initWithContentRect:frame screen:cocoaScreen->nsScreen()
|
||||
styleMask: styleMask qPlatformWindow:this];
|
||||
|
||||
if ((type & Qt::Popup) == Qt::Popup)
|
||||
[window setHasShadow:YES];
|
||||
[panel setHasShadow:YES];
|
||||
|
||||
// Qt::Tool windows hide on app deactivation, unless Qt::WA_MacAlwaysShowToolWindow is set.
|
||||
QVariant showWithoutActivating = QPlatformWindow::window()->property("_q_macAlwaysShowToolWindow");
|
||||
bool shouldHideOnDeactivate = ((type & Qt::Tool) == Qt::Tool) &&
|
||||
!(showWithoutActivating.isValid() && showWithoutActivating.toBool());
|
||||
[window setHidesOnDeactivate: shouldHideOnDeactivate];
|
||||
[panel setHidesOnDeactivate: shouldHideOnDeactivate];
|
||||
|
||||
// Make popup windows show on the same desktop as the parent full-screen window.
|
||||
[window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
|
||||
[panel setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
|
||||
if ((type & Qt::Popup) == Qt::Popup)
|
||||
[window setAnimationBehavior:NSWindowAnimationBehaviorUtilityWindow];
|
||||
[panel setAnimationBehavior:NSWindowAnimationBehaviorUtilityWindow];
|
||||
|
||||
createdWindow = window;
|
||||
createdWindow = panel;
|
||||
} else {
|
||||
QNSWindow *window;
|
||||
window = [[QNSWindow alloc] initWithContentRect:frame
|
||||
styleMask: styleMask
|
||||
qPlatformWindow:this];
|
||||
createdWindow = window;
|
||||
createdWindow = [[QNSWindow alloc] initWithContentRect:frame screen:cocoaScreen->nsScreen()
|
||||
styleMask: styleMask qPlatformWindow:this];
|
||||
}
|
||||
|
||||
if ([createdWindow respondsToSelector:@selector(setRestorable:)])
|
||||
|
|
|
|||
Loading…
Reference in New Issue