diff options
author | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2016-10-26 16:52:41 +0200 |
---|---|---|
committer | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2016-10-28 08:04:26 +0000 |
commit | 1ad6ae21f015ead3dcc4bed21a988f0d7d5d0d2d (patch) | |
tree | 3e05f23c6ba3fe915efe4ae634eb799fa897f9b8 /src/plugins/platforms/cocoa | |
parent | e39a436d0ca00fbcbef1428e32f74266c7a8d34d (diff) |
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>
Diffstat (limited to 'src/plugins/platforms/cocoa')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.h | 2 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.mm | 53 |
2 files changed, 38 insertions, 17 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index a560650a33..52b3c19768 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -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; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index d5b405c951..43bab0d6d8 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -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:)]) |