summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2016-10-26 16:52:41 +0200
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2016-10-28 08:04:26 +0000
commit1ad6ae21f015ead3dcc4bed21a988f0d7d5d0d2d (patch)
tree3e05f23c6ba3fe915efe4ae634eb799fa897f9b8 /src/plugins/platforms/cocoa
parente39a436d0ca00fbcbef1428e32f74266c7a8d34d (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.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm53
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:)])