summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2019-08-13 09:46:17 +0200
committerLiang Qi <liang.qi@qt.io>2019-08-13 09:46:17 +0200
commit1dade1bd8ad13a16152aff36351ac570b5b9fdf6 (patch)
treeeafed5710b34c327a98381ca15fe1985a6487b10 /src/plugins/platforms/cocoa
parentd45908e24292a41ff7838366b34be7340bf9fda5 (diff)
parentfb703aea697b12de4810deec9f8605fd062208bd (diff)
Merge remote-tracking branch 'origin/5.13' into dev
Conflicts: mkspecs/win32-clang-msvc/qmake.conf src/corelib/tools/qlist.h src/gui/painting/qcompositionfunctions.cpp src/gui/painting/qtriangulator_p.h src/gui/text/qfontengine_p.h src/network/kernel/qhostinfo_p.h src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp Done-With: Allan Sandfeld Jensen <allan.jensen@qt.io> Change-Id: Ib8a0308cf77224c4fbdcf56778fdac4a43e37798
Diffstat (limited to 'src/plugins/platforms/cocoa')
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm11
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuloader.mm48
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.mm3
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm52
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindowmanager.mm3
5 files changed, 75 insertions, 42 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index 7b124ea517..ba7d12ce30 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -197,8 +197,15 @@ NSOpenGLPixelFormat *QCocoaGLContext::pixelFormatForSurfaceFormat(const QSurface
attrs << NSOpenGLPFAStencilSize << format.stencilBufferSize();
if (format.alphaBufferSize() > 0)
attrs << NSOpenGLPFAAlphaSize << format.alphaBufferSize();
- if (format.redBufferSize() > 0 && format.greenBufferSize() > 0 && format.blueBufferSize() > 0) {
- const int colorSize = format.redBufferSize() + format.greenBufferSize() + format.blueBufferSize();
+
+ auto rbz = format.redBufferSize();
+ auto gbz = format.greenBufferSize();
+ auto bbz = format.blueBufferSize();
+ if (rbz > 0 || gbz > 0 || bbz > 0) {
+ auto fallbackSize = qMax(rbz, qMax(gbz, bbz));
+ auto colorSize = (rbz > 0 ? rbz : fallbackSize)
+ + (gbz > 0 ? gbz : fallbackSize)
+ + (bbz > 0 ? bbz : fallbackSize);
attrs << NSOpenGLPFAColorSize << colorSize << NSOpenGLPFAMinimumPolicy;
}
diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.mm b/src/plugins/platforms/cocoa/qcocoamenuloader.mm
index da0fc5c6a1..d384078e91 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuloader.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuloader.mm
@@ -59,7 +59,6 @@
NSMenuItem *aboutItem;
NSMenuItem *aboutQtItem;
NSMenuItem *hideItem;
- NSMenuItem *lastAppSpecificItem;
NSMenuItem *servicesItem;
NSMenuItem *hideAllOthersItem;
NSMenuItem *showAllItem;
@@ -118,6 +117,9 @@
[appMenu addItem:[NSMenuItem separatorItem]];
// Preferences
+ // We'll be adding app specific items after this. The macOS HIG state that,
+ // "In general, a Preferences menu item should be the first app-specific menu item."
+ // https://developer.apple.com/macos/human-interface-guidelines/menus/menu-bar-menus/
preferencesItem = [[QCocoaNSMenuItem alloc] init];
preferencesItem.title = @"Preferences…";
preferencesItem.keyEquivalent = @",";
@@ -126,11 +128,6 @@
preferencesItem.hidden = YES;
[appMenu addItem:preferencesItem];
- // We'll be adding app specific items after this. The macOS HIG state that,
- // "In general, a Preferences menu item should be the first app-specific menu item."
- // https://developer.apple.com/macos/human-interface-guidelines/menus/menu-bar-menus/
- lastAppSpecificItem = preferencesItem;
-
[appMenu addItem:[NSMenuItem separatorItem]];
// Services item and menu
@@ -194,8 +191,6 @@
[showAllItem release];
[quitItem release];
- [lastAppSpecificItem release];
-
[super dealloc];
}
@@ -272,25 +267,20 @@
// No reason to create the item if it already exists.
for (NSMenuItem *item in appMenu.itemArray)
if (qt_objc_cast<QCocoaNSMenuItem *>(item).platformMenuItem == platformItem)
- return [[item retain] autorelease];
+ return item;
// Create an App-Specific menu item, insert it into the menu and return
// it as an autorelease item.
QCocoaNSMenuItem *item;
if (platformItem->isSeparator())
- item = [[QCocoaNSMenuItem separatorItemWithPlatformMenuItem:platformItem] retain];
+ item = [QCocoaNSMenuItem separatorItemWithPlatformMenuItem:platformItem];
else
- item = [[QCocoaNSMenuItem alloc] initWithPlatformMenuItem:platformItem];
-
- const auto location = [appMenu indexOfItem:lastAppSpecificItem];
+ item = [[[QCocoaNSMenuItem alloc] initWithPlatformMenuItem:platformItem] autorelease];
- if (!lastAppSpecificItem.separatorItem)
- [lastAppSpecificItem release];
- lastAppSpecificItem = item; // Keep track of this for later (i.e., don't release it)
+ const auto location = [self indexOfLastAppSpecificMenuItem];
+ [appMenu insertItem:item atIndex:NSInteger(location) + 1];
- [appMenu insertItem:item atIndex:location + 1];
-
- return [[item retain] autorelease];
+ return item;
}
- (void)orderFrontStandardAboutPanel:(id)sender
@@ -344,8 +334,24 @@
- (NSArray<NSMenuItem *> *)mergeable
{
// Don't include the quitItem here, since we want it always visible and enabled regardless
- // Note that lastAppSpecificItem may be nil, so we can't use @[] here.
- return [NSArray arrayWithObjects:preferencesItem, aboutItem, aboutQtItem, lastAppSpecificItem, nil];
+ auto items = [NSArray arrayWithObjects:preferencesItem, aboutItem, aboutQtItem,
+ appMenu.itemArray[[self indexOfLastAppSpecificMenuItem]], nil];
+ return items;
}
+- (NSUInteger)indexOfLastAppSpecificMenuItem
+{
+ // Either the 'Preferences', which is the first app specific menu item, or something
+ // else we appended later (thus the reverse order):
+ const auto location = [appMenu.itemArray indexOfObjectWithOptions:NSEnumerationReverse
+ passingTest:^BOOL(NSMenuItem *item, NSUInteger, BOOL *) {
+ if (auto qtItem = qt_objc_cast<QCocoaNSMenuItem*>(item))
+ return qtItem != quitItem;
+ return NO;
+ }];
+ Q_ASSERT(location != NSNotFound);
+ return location;
+}
+
+
@end
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
index 7979e430ac..9bd19dd07c 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
@@ -177,6 +177,9 @@ void *QCocoaNativeInterface::NSPrintInfoForPrintEngine(QPrintEngine *printEngine
QPixmap QCocoaNativeInterface::defaultBackgroundPixmapForQWizard()
{
+ // Note: starting with macOS 10.14, the KeyboardSetupAssistant app bundle no
+ // longer contains the "Background.png" image. This function then returns a
+ // null pixmap.
const int ExpectedImageWidth = 242;
const int ExpectedImageHeight = 414;
QCFType<CFArrayRef> urls = LSCopyApplicationURLsForBundleIdentifier(
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 8f3c192745..0c7ec7f736 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -1544,12 +1544,6 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel)
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;
@@ -1560,35 +1554,57 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel)
}
}
+ NSWindowStyleMask styleMask = windowStyleMask(flags);
+
if (!targetScreen) {
qCWarning(lcQpaWindow) << "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;
+ // Unless the window is created as borderless AppKit won't find a position and
+ // screen that's close to the requested invalid position, and will always place
+ // the window on the primary screen.
+ styleMask = NSWindowStyleMaskBorderless;
}
rect.translate(-targetScreen->geometry().topLeft());
- QCocoaScreen *cocoaScreen = static_cast<QCocoaScreen *>(targetScreen->handle());
- NSRect frame = QCocoaScreen::mapToNative(rect, cocoaScreen);
+ auto *targetCocoaScreen = static_cast<QCocoaScreen *>(targetScreen->handle());
+ NSRect contentRect = QCocoaScreen::mapToNative(rect, targetCocoaScreen);
+
+ if (targetScreen->primaryOrientation() == Qt::PortraitOrientation) {
+ // 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 (including a magic padding
+ // of 24 points), unless the window is created with the NSWindowStyleMaskBorderless style mask.
+ if (styleMask && (contentRect.origin.y + 24 > targetScreen->geometry().width())) {
+ qCDebug(lcQpaWindow) << "Window positioned on portrait screen."
+ << "Adjusting style mask during creation";
+ styleMask = NSWindowStyleMaskBorderless;
+ }
+ }
// Create NSWindow
Class windowClass = shouldBePanel ? [QNSPanel class] : [QNSWindow class];
- QCocoaNSWindow *nsWindow = [[windowClass alloc] initWithContentRect:frame
+ QCocoaNSWindow *nsWindow = [[windowClass alloc] initWithContentRect:contentRect
+ // Mask will be updated in setWindowFlags if not the final mask
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
- screen:cocoaScreen->nativeScreen()
+ screen:targetCocoaScreen->nativeScreen()
platformWindow:this];
- Q_ASSERT_X(nsWindow.screen == cocoaScreen->nativeScreen(), "QCocoaWindow",
- "Resulting NSScreen should match the requested NSScreen");
+ // The resulting screen can be different from the screen requested if
+ // for example the application has been assigned to a specific display.
+ auto resultingScreen = QCocoaScreen::get(nsWindow.screen);
+
+ // But may not always be resolved at this point, in which case we fall back
+ // to the target screen. The real screen will be delivered as a screen change
+ // when resolved as part of ordering the window on screen.
+ if (!resultingScreen)
+ resultingScreen = targetCocoaScreen;
- if (targetScreen != window()->screen()) {
+ if (resultingScreen->screen() != window()->screen()) {
QWindowSystemInterface::handleWindowScreenChanged<
- QWindowSystemInterface::SynchronousDelivery>(window(), targetScreen);
+ QWindowSystemInterface::SynchronousDelivery>(window(), resultingScreen->screen());
}
static QSharedPointer<QNSWindowDelegate> sharedDelegate([[QNSWindowDelegate alloc] init],
diff --git a/src/plugins/platforms/cocoa/qcocoawindowmanager.mm b/src/plugins/platforms/cocoa/qcocoawindowmanager.mm
index 879bfaa546..9c45d8c7fc 100644
--- a/src/plugins/platforms/cocoa/qcocoawindowmanager.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindowmanager.mm
@@ -92,7 +92,8 @@ void QCocoaWindowManager::modalSessionChanged()
if (NSApp.modalWindow) {
// Lower window to that of the modal windows, but no less
nativeWindow.level = NSModalPanelWindowLevel;
- [nativeWindow orderBack:nil];
+ if ([nativeWindow isVisible])
+ [nativeWindow orderBack:nil];
} else {
// Restore window's natural window level, whatever that was
nativeWindow.level = naturalWindowLevel;