summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa/qcocoaintegration.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoaintegration.mm')
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm254
1 files changed, 89 insertions, 165 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index b2698b05fe..2ce39ff897 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -1,41 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <AppKit/AppKit.h>
#include "qcocoaintegration.h"
@@ -55,31 +21,28 @@
#if QT_CONFIG(sessionmanager)
# include "qcocoasessionmanager.h"
#endif
+#include "qcocoawindowmanager.h"
#include <qpa/qplatforminputcontextfactory_p.h>
#include <qpa/qplatformaccessibility.h>
#include <qpa/qplatforminputcontextfactory_p.h>
#include <qpa/qplatformoffscreensurface.h>
#include <QtCore/qcoreapplication.h>
+#include <QtGui/qpointingdevice.h>
-#include <QtPlatformHeaders/qcocoanativecontext.h>
-
+#include <QtCore/private/qcore_mac_p.h>
#include <QtGui/private/qcoregraphics_p.h>
-
-#include <QtFontDatabaseSupport/private/qfontengine_coretext_p.h>
-
-#if QT_CONFIG(opengl)
-#include <QtPlatformCompositorSupport/qpa/qplatformbackingstoreopenglsupport.h>
-#endif
-
-#ifdef QT_WIDGETS_LIB
-#include <QtWidgets/qtwidgetsglobal.h>
-#if QT_CONFIG(filedialog)
-#include "qcocoafiledialoghelper.h"
-#endif
+#include <QtGui/private/qmacmimeregistry_p.h>
+#ifndef QT_NO_OPENGL
+# include <QtGui/private/qopenglcontext_p.h>
#endif
+#include <QtGui/private/qrhibackingstore_p.h>
+#include <QtGui/private/qfontengine_coretext_p.h>
#include <IOKit/graphics/IOGraphicsLib.h>
+#include <UniformTypeIdentifiers/UTCoreTypes.h>
+
+#include <inttypes.h>
static void initResources()
{
@@ -88,6 +51,8 @@ static void initResources()
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Q_LOGGING_CATEGORY(lcQpa, "qt.qpa", QtWarningMsg);
static void logVersionInformation()
@@ -120,9 +85,9 @@ class QFontEngineFT;
static QCocoaIntegration::Options parseOptions(const QStringList &paramList)
{
QCocoaIntegration::Options options;
- foreach (const QString &param, paramList) {
+ for (const QString &param : paramList) {
#ifndef QT_NO_FREETYPE
- if (param == QLatin1String("fontengine=freetype"))
+ if (param == "fontengine=freetype"_L1)
options |= QCocoaIntegration::UseFreeTypeFontEngine;
else
#endif
@@ -136,7 +101,7 @@ QCocoaIntegration *QCocoaIntegration::mInstance = nullptr;
QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
: mOptions(parseOptions(paramList))
, mFontDb(nullptr)
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
, mAccessibility(new QCocoaAccessibility)
#endif
#ifndef QT_NO_CLIPBOARD
@@ -145,7 +110,7 @@ QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
, mCocoaDrag(new QCocoaDrag)
, mNativeInterface(new QCocoaNativeInterface)
, mServices(new QCocoaServices)
- , mKeyboardMapper(new QCocoaKeyMapper)
+ , mKeyboardMapper(new QAppleKeyMapper)
{
logVersionInformation();
@@ -160,9 +125,9 @@ QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
#endif
mFontDb.reset(new QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>);
- QString icStr = QPlatformInputContextFactory::requested();
- icStr.isNull() ? mInputContext.reset(new QCocoaInputContext)
- : mInputContext.reset(QPlatformInputContextFactory::create(icStr));
+ auto icStrs = QPlatformInputContextFactory::requested();
+ icStrs.isEmpty() ? mInputContext.reset(new QCocoaInputContext)
+ : mInputContext.reset(QPlatformInputContextFactory::create(icStrs));
initResources();
QMacAutoReleasePool pool;
@@ -172,24 +137,13 @@ QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
if (qEnvironmentVariableIsEmpty("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM")) {
// Applications launched from plain executables (without an app
- // bundle) are "background" applications that does not take keybaord
+ // bundle) are "background" applications that does not take keyboard
// focus or have a dock icon or task switcher entry. Qt Gui apps generally
// wants to be foreground applications so change the process type. (But
// see the function implementation for exceptions.)
qt_mac_transformProccessToForegroundApplication();
-
- // Move the application window to front to make it take focus, also when launching
- // from the terminal. On 10.12+ this call has been moved to applicationDidFinishLauching
- // to work around issues with loss of focus at startup.
- if (QOperatingSystemVersion::current() < QOperatingSystemVersion::MacOSSierra) {
- // Ignoring other apps is necessary (we must ignore the terminal), but makes
- // Qt apps play slightly less nice with other apps when lanching from Finder
- // (See the activateIgnoringOtherApps docs.)
- [cocoaApplication activateIgnoringOtherApps : YES];
- }
}
- // ### For AA_MacPluginApplication we don't want to load the menu nib.
// Qt 4 also does not set the application delegate, so that behavior
// is matched here.
if (!QCoreApplication::testAttribute(Qt::AA_PluginApplication)) {
@@ -206,9 +160,11 @@ QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
QCocoaScreen::initializeScreens();
- QMacInternalPasteboardMime::initializeMimeTypes();
+ QMacMimeRegistry::initializeMimeTypes();
QCocoaMimeTypes::initializeMimeTypes();
QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
+ QWindowSystemInterface::registerInputDevice(new QInputDevice(QString("keyboard"), 0,
+ QInputDevice::DeviceType::Keyboard, QString(), this));
connect(qGuiApp, &QGuiApplication::focusWindowChanged,
this, &QCocoaIntegration::focusWindowChanged);
@@ -229,17 +185,18 @@ QCocoaIntegration::~QCocoaIntegration()
[[NSApplication sharedApplication] setDelegate:nil];
}
+ // Stop global mouse event and app activation monitoring
+ QCocoaWindow::removePopupMonitor();
+
#ifndef QT_NO_CLIPBOARD
// Delete the clipboard integration and destroy mime type converters.
// Deleting the clipboard integration flushes promised pastes using
// the mime converters - the ordering here is important.
delete mCocoaClipboard;
- QMacInternalPasteboardMime::destroyMimeTypes();
+ QMacMimeRegistry::destroyMimeTypes();
#endif
QCocoaScreen::cleanupScreens();
-
- clearToolbars();
}
QCocoaIntegration *QCocoaIntegration::instance()
@@ -267,8 +224,8 @@ bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) cons
// AppKit expects rendering to happen on the main thread, and we can
// easily end up in situations where rendering on secondary threads
// will result in visual artifacts, bugs, or even deadlocks, when
- // building with SDK 10.14 or higher which enbles view layer-backing.
- return QMacVersion::buildSDK() < QOperatingSystemVersion(QOperatingSystemVersion::MacOSMojave);
+ // layer-backed.
+ return false;
case OpenGL:
case BufferQueueingOpenGL:
#endif
@@ -279,6 +236,7 @@ bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) cons
case RasterGLSurface:
case ApplicationState:
case ApplicationIcon:
+ case BackingStoreStaticContents:
return true;
default:
return QPlatformIntegration::hasCapability(cap);
@@ -318,6 +276,19 @@ QPlatformOpenGLContext *QCocoaIntegration::createPlatformOpenGLContext(QOpenGLCo
{
return new QCocoaGLContext(context);
}
+
+QOpenGLContext *QCocoaIntegration::createOpenGLContext(NSOpenGLContext *nativeContext, QOpenGLContext *shareContext) const
+{
+ if (!nativeContext)
+ return nullptr;
+
+ auto *context = new QOpenGLContext;
+ context->setShareContext(shareContext);
+ auto *contextPrivate = QOpenGLContextPrivate::get(context);
+ contextPrivate->adopt(new QCocoaGLContext(nativeContext));
+ return context;
+}
+
#endif
QPlatformBackingStore *QCocoaIntegration::createPlatformBackingStore(QWindow *window) const
@@ -328,16 +299,27 @@ QPlatformBackingStore *QCocoaIntegration::createPlatformBackingStore(QWindow *wi
return nullptr;
}
- QPlatformBackingStore *backingStore = nullptr;
- if (platformWindow->view().layer)
- backingStore = new QCALayerBackingStore(window);
- else
- backingStore = new QNSWindowBackingStore(window);
-
-#if QT_CONFIG(opengl)
- backingStore->setOpenGLSupport(new QPlatformBackingStoreOpenGLSupport(backingStore));
-#endif
- return backingStore;
+ switch (window->surfaceType()) {
+ case QSurface::RasterSurface:
+ return new QCALayerBackingStore(window);
+ case QSurface::MetalSurface:
+ case QSurface::OpenGLSurface:
+ case QSurface::VulkanSurface:
+ // If the window is a widget window, we know that the QWidgetRepaintManager
+ // will explicitly use rhiFlush() for the window owning the backingstore,
+ // and any child window with the same surface format. This means we can
+ // safely return a QCALayerBackingStore here, to ensure that any plain
+ // flush() for child windows that don't have a matching surface format
+ // will still work, by setting the layer's contents property.
+ if (window->inherits("QWidgetWindow"))
+ return new QCALayerBackingStore(window);
+
+ // Otherwise we return a QRhiBackingStore, that implements flush() in
+ // terms of rhiFlush().
+ return new QRhiBackingStore(window);
+ default:
+ return nullptr;
+ }
}
QAbstractEventDispatcher *QCocoaIntegration::createEventDispatcher() const
@@ -373,7 +355,7 @@ QPlatformInputContext *QCocoaIntegration::inputContext() const
return mInputContext.data();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QCocoaAccessibility *QCocoaIntegration::accessibility() const
{
return mAccessibility.data();
@@ -394,12 +376,12 @@ QCocoaDrag *QCocoaIntegration::drag() const
QStringList QCocoaIntegration::themeNames() const
{
- return QStringList(QLatin1String(QCocoaTheme::name));
+ return QStringList(QLatin1StringView(QCocoaTheme::name));
}
QPlatformTheme *QCocoaIntegration::createPlatformTheme(const QString &name) const
{
- if (name == QLatin1String(QCocoaTheme::name))
+ if (name == QLatin1StringView(QCocoaTheme::name))
return new QCocoaTheme;
return QPlatformIntegration::createPlatformTheme(name);
}
@@ -416,80 +398,29 @@ QVariant QCocoaIntegration::styleHint(StyleHint hint) const
return QCoreTextFontEngine::fontSmoothingGamma();
case ShowShortcutsInContextMenus:
return QVariant(false);
+ case ReplayMousePressOutsidePopup:
+ return QVariant(false);
default: break;
}
return QPlatformIntegration::styleHint(hint);
}
-Qt::KeyboardModifiers QCocoaIntegration::queryKeyboardModifiers() const
+QPlatformKeyMapper *QCocoaIntegration::keyMapper() const
{
- return QCocoaKeyMapper::queryKeyboardModifiers();
+ return mKeyboardMapper.data();
}
-QList<int> QCocoaIntegration::possibleKeys(const QKeyEvent *event) const
-{
- return mKeyboardMapper->possibleKeys(event);
-}
-
-void QCocoaIntegration::setToolbar(QWindow *window, NSToolbar *toolbar)
-{
- if (NSToolbar *prevToolbar = mToolbars.value(window))
- [prevToolbar release];
-
- [toolbar retain];
- mToolbars.insert(window, toolbar);
-}
-
-NSToolbar *QCocoaIntegration::toolbar(QWindow *window) const
-{
- return mToolbars.value(window);
-}
-
-void QCocoaIntegration::clearToolbars()
-{
- QHash<QWindow *, NSToolbar *>::const_iterator it = mToolbars.constBegin();
- while (it != mToolbars.constEnd()) {
- [it.value() release];
- ++it;
- }
- mToolbars.clear();
-}
-
-void QCocoaIntegration::pushPopupWindow(QCocoaWindow *window)
-{
- m_popupWindowStack.append(window);
-}
-
-QCocoaWindow *QCocoaIntegration::popPopupWindow()
-{
- if (m_popupWindowStack.isEmpty())
- return nullptr;
- return m_popupWindowStack.takeLast();
-}
-
-QCocoaWindow *QCocoaIntegration::activePopupWindow() const
-{
- if (m_popupWindowStack.isEmpty())
- return nullptr;
- return m_popupWindowStack.front();
-}
-
-QList<QCocoaWindow *> *QCocoaIntegration::popupWindowStack()
+void QCocoaIntegration::setApplicationIcon(const QIcon &icon) const
{
- return &m_popupWindowStack;
+ // Fall back to a size that looks good on the highest resolution screen available
+ auto fallbackSize = NSApp.dockTile.size.width * qGuiApp->devicePixelRatio();
+ NSApp.applicationIconImage = [NSImage imageFromQIcon:icon withSize:fallbackSize];
}
-void QCocoaIntegration::setApplicationIcon(const QIcon &icon) const
+void QCocoaIntegration::setApplicationBadge(qint64 number)
{
- NSImage *image = nil;
- if (!icon.isNull()) {
- NSSize size = [[[NSApplication sharedApplication] dockTile] size];
- QPixmap pixmap = icon.pixmap(size.width, size.height);
- image = static_cast<NSImage *>(qt_mac_create_nsimage(pixmap));
- }
- [[NSApplication sharedApplication] setApplicationIconImage:image];
- [image release];
+ NSApp.dockTile.badgeLabel = number ? [NSString stringWithFormat:@"%" PRId64, number] : nil;
}
void QCocoaIntegration::beep() const
@@ -497,17 +428,10 @@ void QCocoaIntegration::beep() const
NSBeep();
}
-void QCocoaIntegration::closePopups(QWindow *forWindow)
+void QCocoaIntegration::quit() const
{
- for (auto it = m_popupWindowStack.begin(); it != m_popupWindowStack.end();) {
- auto *popup = *it;
- if (!forWindow || popup->window()->transientParent() == forWindow) {
- it = m_popupWindowStack.erase(it);
- QWindowSystemInterface::handleCloseEvent<QWindowSystemInterface::SynchronousDelivery>(popup->window());
- } else {
- ++it;
- }
- }
+ qCDebug(lcQpaApplication) << "Terminating application";
+ [NSApp terminate:nil];
}
void QCocoaIntegration::focusWindowChanged(QWindow *focusWindow)
@@ -517,8 +441,8 @@ void QCocoaIntegration::focusWindowChanged(QWindow *focusWindow)
return;
static bool hasDefaultApplicationIcon = [](){
- NSImage *genericApplicationIcon = [[NSWorkspace sharedWorkspace]
- iconForFileType:NSFileTypeForHFSTypeCode(kGenericApplicationIcon)];
+ NSImage *genericApplicationIcon = [NSWorkspace.sharedWorkspace
+ iconForContentType:UTTypeApplicationBundle];
NSImage *applicationIcon = [NSImage imageNamed:NSImageNameApplicationIcon];
NSRect rect = NSMakeRect(0, 0, 32, 32);
@@ -537,6 +461,6 @@ void QCocoaIntegration::focusWindowChanged(QWindow *focusWindow)
setApplicationIcon(focusWindow->icon());
}
-#include "moc_qcocoaintegration.cpp"
-
QT_END_NAMESPACE
+
+#include "moc_qcocoaintegration.cpp"