diff options
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoatheme.mm')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoatheme.mm | 422 |
1 files changed, 311 insertions, 111 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm index 7c10456824..6d15e8e5d2 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.mm +++ b/src/plugins/platforms/cocoa/qcocoatheme.mm @@ -1,51 +1,12 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#import <AppKit/AppKit.h> +// 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 "qcocoatheme.h" -#include "messages.h" -#include <QtCore/QOperatingSystemVersion> #include <QtCore/QVariant> -#include "qcocoasystemsettings.h" #include "qcocoasystemtrayicon.h" #include "qcocoamenuitem.h" #include "qcocoamenu.h" @@ -53,61 +14,221 @@ #include "qcocoahelpers.h" #include <QtCore/qfileinfo.h> +#include <QtCore/private/qcore_mac_p.h> #include <QtGui/private/qfont_p.h> #include <QtGui/private/qguiapplication_p.h> #include <QtGui/private/qcoregraphics_p.h> #include <QtGui/qpainter.h> #include <QtGui/qtextformat.h> -#include <QtFontDatabaseSupport/private/qcoretextfontdatabase_p.h> -#include <QtFontDatabaseSupport/private/qfontengine_coretext_p.h> -#include <QtThemeSupport/private/qabstractfileiconengine_p.h> +#include <QtGui/private/qcoretextfontdatabase_p.h> +#include <QtGui/private/qappleiconengine_p.h> +#include <QtGui/private/qfontengine_coretext_p.h> +#include <QtGui/private/qabstractfileiconengine_p.h> #include <qpa/qplatformdialoghelper.h> #include <qpa/qplatformintegration.h> #include <qpa/qplatformnativeinterface.h> -#ifdef QT_WIDGETS_LIB -#include <QtWidgets/qtwidgetsglobal.h> -#if QT_CONFIG(colordialog) #include "qcocoacolordialoghelper.h" -#endif -#if QT_CONFIG(filedialog) #include "qcocoafiledialoghelper.h" -#endif -#if QT_CONFIG(fontdialog) #include "qcocoafontdialoghelper.h" -#endif -#endif +#include "qcocoamessagedialog.h" #include <CoreServices/CoreServices.h> QT_BEGIN_NAMESPACE +static QPalette *qt_mac_createSystemPalette() +{ + QColor qc; + + // Standard palette initialization (copied from Qt 4 styles) + QBrush backgroundBrush = qt_mac_toQBrush([NSColor windowBackgroundColor]); + QColor background = backgroundBrush.color(); + QColor light(background.lighter(110)); + QColor dark(background.darker(160)); + QColor mid(background.darker(140)); + QPalette *palette = new QPalette(Qt::black, background, light, dark, mid, Qt::black, Qt::white); + + palette->setBrush(QPalette::Window, backgroundBrush); + + palette->setBrush(QPalette::Disabled, QPalette::WindowText, dark); + palette->setBrush(QPalette::Disabled, QPalette::Text, dark); + palette->setBrush(QPalette::Disabled, QPalette::Base, backgroundBrush); + QBrush textBackgroundBrush = qt_mac_toQBrush([NSColor textBackgroundColor]); + palette->setBrush(QPalette::Active, QPalette::Base, textBackgroundBrush); + palette->setBrush(QPalette::Inactive, QPalette::Base, textBackgroundBrush); + palette->setColor(QPalette::Disabled, QPalette::Dark, QColor(191, 191, 191)); + palette->setColor(QPalette::Active, QPalette::Dark, QColor(191, 191, 191)); + palette->setColor(QPalette::Inactive, QPalette::Dark, QColor(191, 191, 191)); + + // System palette initialization: + QBrush br = qt_mac_toQBrush([NSColor selectedControlColor]); + palette->setBrush(QPalette::Active, QPalette::Highlight, br); + const auto inactiveHighlight = qt_mac_toQBrush([NSColor unemphasizedSelectedContentBackgroundColor]); + palette->setBrush(QPalette::Inactive, QPalette::Highlight, inactiveHighlight); + palette->setBrush(QPalette::Disabled, QPalette::Highlight, inactiveHighlight); + + palette->setBrush(QPalette::Shadow, qt_mac_toQColor([NSColor shadowColor])); + + qc = qt_mac_toQColor([NSColor controlTextColor]); + palette->setColor(QPalette::Active, QPalette::Text, qc); + palette->setColor(QPalette::Active, QPalette::ButtonText, qc); + palette->setColor(QPalette::Active, QPalette::WindowText, qc); + palette->setColor(QPalette::Active, QPalette::HighlightedText, qc); + palette->setColor(QPalette::Inactive, QPalette::Text, qc); + palette->setColor(QPalette::Inactive, QPalette::WindowText, qc); + palette->setColor(QPalette::Inactive, QPalette::HighlightedText, qc); + + qc = qt_mac_toQColor([NSColor disabledControlTextColor]); + palette->setColor(QPalette::Disabled, QPalette::Text, qc); + palette->setColor(QPalette::Disabled, QPalette::ButtonText, qc); + palette->setColor(QPalette::Disabled, QPalette::WindowText, qc); + palette->setColor(QPalette::Disabled, QPalette::HighlightedText, qc); + + palette->setBrush(QPalette::ToolTipBase, qt_mac_toQBrush([NSColor controlColor])); + + palette->setColor(QPalette::Normal, QPalette::Link, qt_mac_toQColor([NSColor linkColor])); + + qc = qt_mac_toQColor([NSColor placeholderTextColor]); + palette->setColor(QPalette::Active, QPalette::PlaceholderText, qc); + palette->setColor(QPalette::Inactive, QPalette::PlaceholderText, qc); + palette->setColor(QPalette::Disabled, QPalette::PlaceholderText, qc); + + qc = qt_mac_toQColor([NSColor controlAccentColor]); + palette->setColor(QPalette::Accent, qc); + + return palette; +} + +struct QMacPaletteMap { + inline QMacPaletteMap(QPlatformTheme::Palette p, NSColor *a, NSColor *i) : + active(a), inactive(i), paletteRole(p) { } + + NSColor *active; + NSColor *inactive; + QPlatformTheme::Palette paletteRole; +}; + +#define MAC_PALETTE_ENTRY(pal, active, inactive) \ + QMacPaletteMap(pal, [NSColor active], [NSColor inactive]) +static QMacPaletteMap mac_widget_colors[] = { + MAC_PALETTE_ENTRY(QPlatformTheme::ToolButtonPalette, controlTextColor, disabledControlTextColor), + MAC_PALETTE_ENTRY(QPlatformTheme::ButtonPalette, controlTextColor, disabledControlTextColor), + MAC_PALETTE_ENTRY(QPlatformTheme::HeaderPalette, headerTextColor, disabledControlTextColor), + MAC_PALETTE_ENTRY(QPlatformTheme::ComboBoxPalette, controlTextColor, disabledControlTextColor), + MAC_PALETTE_ENTRY(QPlatformTheme::ItemViewPalette, textColor, disabledControlTextColor), + MAC_PALETTE_ENTRY(QPlatformTheme::MessageBoxLabelPalette, textColor, disabledControlTextColor), + MAC_PALETTE_ENTRY(QPlatformTheme::TabBarPalette, controlTextColor, disabledControlTextColor), + MAC_PALETTE_ENTRY(QPlatformTheme::LabelPalette, textColor, disabledControlTextColor), + MAC_PALETTE_ENTRY(QPlatformTheme::GroupBoxPalette, textColor, disabledControlTextColor), + MAC_PALETTE_ENTRY(QPlatformTheme::MenuPalette, controlTextColor, disabledControlTextColor), + MAC_PALETTE_ENTRY(QPlatformTheme::MenuBarPalette, controlTextColor, disabledControlTextColor), + MAC_PALETTE_ENTRY(QPlatformTheme::TextEditPalette, textColor, disabledControlTextColor), + MAC_PALETTE_ENTRY(QPlatformTheme::TextLineEditPalette, textColor, disabledControlTextColor) +}; +#undef MAC_PALETTE_ENTRY + +static const int mac_widget_colors_count = sizeof(mac_widget_colors) / sizeof(mac_widget_colors[0]); + +static QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes() +{ + QHash<QPlatformTheme::Palette, QPalette*> palettes; + QColor qc; + for (int i = 0; i < mac_widget_colors_count; i++) { + QPalette &pal = *qt_mac_createSystemPalette(); + if (mac_widget_colors[i].active) { + qc = qt_mac_toQColor(mac_widget_colors[i].active); + pal.setColor(QPalette::Active, QPalette::Text, qc); + pal.setColor(QPalette::Inactive, QPalette::Text, qc); + pal.setColor(QPalette::Active, QPalette::WindowText, qc); + pal.setColor(QPalette::Inactive, QPalette::WindowText, qc); + pal.setColor(QPalette::Active, QPalette::HighlightedText, qc); + pal.setColor(QPalette::Inactive, QPalette::HighlightedText, qc); + pal.setColor(QPalette::Active, QPalette::ButtonText, qc); + pal.setColor(QPalette::Inactive, QPalette::ButtonText, qc); + qc = qt_mac_toQColor(mac_widget_colors[i].inactive); + pal.setColor(QPalette::Disabled, QPalette::Text, qc); + pal.setColor(QPalette::Disabled, QPalette::WindowText, qc); + pal.setColor(QPalette::Disabled, QPalette::HighlightedText, qc); + pal.setColor(QPalette::Disabled, QPalette::ButtonText, qc); + } + if (mac_widget_colors[i].paletteRole == QPlatformTheme::MenuPalette + || mac_widget_colors[i].paletteRole == QPlatformTheme::MenuBarPalette) { + // Cheap approximation for NSVisualEffectView (see deprecation note for selectedMenuItemTextColor) + auto selectedMenuItemColor = [[NSColor controlAccentColor] highlightWithLevel:0.3]; + pal.setBrush(QPalette::Highlight, qt_mac_toQColor(selectedMenuItemColor)); + qc = qt_mac_toQColor([NSColor labelColor]); + pal.setBrush(QPalette::ButtonText, qc); + pal.setBrush(QPalette::Text, qc); + qc = qt_mac_toQColor([NSColor selectedMenuItemTextColor]); + pal.setBrush(QPalette::HighlightedText, qc); + qc = qt_mac_toQColor([NSColor disabledControlTextColor]); + pal.setBrush(QPalette::Disabled, QPalette::Text, qc); + } else if ((mac_widget_colors[i].paletteRole == QPlatformTheme::ButtonPalette) + || (mac_widget_colors[i].paletteRole == QPlatformTheme::HeaderPalette) + || (mac_widget_colors[i].paletteRole == QPlatformTheme::TabBarPalette)) { + pal.setColor(QPalette::Disabled, QPalette::ButtonText, + pal.color(QPalette::Disabled, QPalette::Text)); + pal.setColor(QPalette::Inactive, QPalette::ButtonText, + pal.color(QPalette::Inactive, QPalette::Text)); + pal.setColor(QPalette::Active, QPalette::ButtonText, + pal.color(QPalette::Active, QPalette::Text)); + } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::ItemViewPalette) { + NSArray<NSColor *> *baseColors = nil; + NSColor *activeHighlightColor = nil; + baseColors = [NSColor alternatingContentBackgroundColors]; + activeHighlightColor = [NSColor selectedContentBackgroundColor]; + pal.setBrush(QPalette::Inactive, QPalette::HighlightedText, + qt_mac_toQBrush([NSColor unemphasizedSelectedTextColor])); + pal.setBrush(QPalette::Base, qt_mac_toQBrush(baseColors[0])); + pal.setBrush(QPalette::AlternateBase, qt_mac_toQBrush(baseColors[1])); + pal.setBrush(QPalette::Active, QPalette::Highlight, + qt_mac_toQBrush(activeHighlightColor)); + pal.setBrush(QPalette::Active, QPalette::HighlightedText, + qt_mac_toQBrush([NSColor alternateSelectedControlTextColor])); + pal.setBrush(QPalette::Inactive, QPalette::Text, + pal.brush(QPalette::Active, QPalette::Text)); + } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::TextEditPalette) { + pal.setBrush(QPalette::Active, QPalette::Base, qt_mac_toQColor([NSColor textBackgroundColor])); + pal.setBrush(QPalette::Inactive, QPalette::Text, + pal.brush(QPalette::Active, QPalette::Text)); + pal.setBrush(QPalette::Inactive, QPalette::HighlightedText, + pal.brush(QPalette::Active, QPalette::Text)); + } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::TextLineEditPalette + || mac_widget_colors[i].paletteRole == QPlatformTheme::ComboBoxPalette) { + pal.setBrush(QPalette::Active, QPalette::Base, qt_mac_toQColor([NSColor textBackgroundColor])); + pal.setBrush(QPalette::Disabled, QPalette::Base, + pal.brush(QPalette::Active, QPalette::Base)); + } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::LabelPalette) { + qc = qt_mac_toQColor([NSColor labelColor]); + pal.setBrush(QPalette::Inactive, QPalette::ToolTipText, qc); + } + palettes.insert(mac_widget_colors[i].paletteRole, &pal); + } + return palettes; +} + const char *QCocoaTheme::name = "cocoa"; QCocoaTheme::QCocoaTheme() : m_systemPalette(nullptr) { -#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14) - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave) { - m_appearanceObserver = QMacKeyValueObserver(NSApp, @"effectiveAppearance", [this] { - if (__builtin_available(macOS 10.14, *)) - NSAppearance.currentAppearance = NSApp.effectiveAppearance; - - handleSystemThemeChange(); - }); - } -#endif + m_appearanceObserver = QMacKeyValueObserver(NSApp, @"effectiveAppearance", [this] { + NSAppearance.currentAppearance = NSApp.effectiveAppearance; + handleSystemThemeChange(); + }); m_systemColorObserver = QMacNotificationObserver(nil, NSSystemColorsDidChangeNotification, [this] { handleSystemThemeChange(); }); + + updateColorScheme(); } QCocoaTheme::~QCocoaTheme() { reset(); - qDeleteAll(m_fonts); } void QCocoaTheme::reset() @@ -121,6 +242,9 @@ void QCocoaTheme::reset() void QCocoaTheme::handleSystemThemeChange() { reset(); + + updateColorScheme(); + m_systemPalette = qt_mac_createSystemPalette(); m_palettes = qt_mac_createRolePalettes(); @@ -129,39 +253,33 @@ void QCocoaTheme::handleSystemThemeChange() QFontCache::instance()->clear(); } - QWindowSystemInterface::handleThemeChange(nullptr); + QWindowSystemInterface::handleThemeChange<QWindowSystemInterface::SynchronousDelivery>(); } bool QCocoaTheme::usePlatformNativeDialog(DialogType dialogType) const { - if (dialogType == QPlatformTheme::FileDialog) - return true; -#if defined(QT_WIDGETS_LIB) && QT_CONFIG(colordialog) - if (dialogType == QPlatformTheme::ColorDialog) - return true; -#endif -#if defined(QT_WIDGETS_LIB) && QT_CONFIG(fontdialog) - if (dialogType == QPlatformTheme::FontDialog) + switch (dialogType) { + case QPlatformTheme::FileDialog: + case QPlatformTheme::ColorDialog: + case QPlatformTheme::FontDialog: + case QPlatformTheme::MessageDialog: return true; -#endif - return false; + default: + return false; + } } QPlatformDialogHelper *QCocoaTheme::createPlatformDialogHelper(DialogType dialogType) const { switch (dialogType) { -#if defined(QT_WIDGETS_LIB) && QT_CONFIG(filedialog) case QPlatformTheme::FileDialog: return new QCocoaFileDialogHelper(); -#endif -#if defined(QT_WIDGETS_LIB) && QT_CONFIG(colordialog) case QPlatformTheme::ColorDialog: return new QCocoaColorDialogHelper(); -#endif -#if defined(QT_WIDGETS_LIB) && QT_CONFIG(fontdialog) case QPlatformTheme::FontDialog: return new QCocoaFontDialogHelper(); -#endif + case QPlatformTheme::MessageDialog: + return new QCocoaMessageDialog; default: return nullptr; } @@ -190,12 +308,9 @@ const QPalette *QCocoaTheme::palette(Palette type) const const QFont *QCocoaTheme::font(Font type) const { - if (m_fonts.isEmpty()) { - const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration(); - const auto *coreTextFontDb = static_cast<QCoreTextFontDatabase *>(platformIntegration->fontDatabase()); - m_fonts = coreTextFontDb->themeFonts(); - } - return m_fonts.value(type, nullptr); + const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration(); + const auto *coreTextFontDatabase = static_cast<QCoreTextFontDatabase *>(platformIntegration->fontDatabase()); + return coreTextFontDatabase->themeFont(type); } //! \internal @@ -272,11 +387,11 @@ QPixmap QCocoaTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const if (iconType != 0) { QPixmap pixmap; IconRef icon = nullptr; - GetIconRef(kOnSystemDisk, kSystemIconsCreator, iconType, &icon); + QT_IGNORE_DEPRECATIONS(GetIconRef(kOnSystemDisk, kSystemIconsCreator, iconType, &icon)); if (icon) { pixmap = qt_mac_convert_iconref(icon, size.width(), size.height()); - ReleaseIconRef(icon); + QT_IGNORE_DEPRECATIONS(ReleaseIconRef(icon)); } return pixmap; @@ -292,19 +407,8 @@ public: QPlatformTheme::IconOptions opts) : QAbstractFileIconEngine(info, opts) {} - static QList<QSize> availableIconSizes() - { - const qreal devicePixelRatio = qGuiApp->devicePixelRatio(); - const int sizes[] = { - qRound(16 * devicePixelRatio), qRound(32 * devicePixelRatio), - qRound(64 * devicePixelRatio), qRound(128 * devicePixelRatio), - qRound(256 * devicePixelRatio) - }; - return QAbstractFileIconEngine::toSizeList(sizes, sizes + sizeof(sizes) / sizeof(sizes[0])); - } - - QList<QSize> availableSizes(QIcon::Mode = QIcon::Normal, QIcon::State = QIcon::Off) const override - { return QCocoaFileIconEngine::availableIconSizes(); } + QList<QSize> availableSizes(QIcon::Mode = QIcon::Normal, QIcon::State = QIcon::Off) override + { return QAppleIconEngine::availableIconSizes(); } protected: QPixmap filePixmap(const QSize &size, QIcon::Mode, QIcon::State) override @@ -323,11 +427,16 @@ QIcon QCocoaTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptio return QIcon(new QCocoaFileIconEngine(fileInfo, iconOptions)); } +QIconEngine *QCocoaTheme::createIconEngine(const QString &iconName) const +{ + return new QAppleIconEngine(iconName); +} + QVariant QCocoaTheme::themeHint(ThemeHint hint) const { switch (hint) { case QPlatformTheme::StyleNames: - return QStringList(QStringLiteral("macintosh")); + return QStringList(QStringLiteral("macOS")); case QPlatformTheme::DialogButtonBoxLayout: return QVariant(QPlatformDialogHelper::MacLayout); case KeyboardScheme: @@ -336,7 +445,7 @@ QVariant QCocoaTheme::themeHint(ThemeHint hint) const return QVariant([[NSApplication sharedApplication] isFullKeyboardAccessEnabled] ? int(Qt::TabFocusAllControls) : int(Qt::TabFocusTextControls | Qt::TabFocusListControls)); case IconPixmapSizes: - return QVariant::fromValue(QCocoaFileIconEngine::availableIconSizes()); + return QVariant::fromValue(QAppleIconEngine::availableIconSizes()); case QPlatformTheme::PasswordMaskCharacter: return QVariant(QChar(0x2022)); case QPlatformTheme::UiEffects: @@ -344,16 +453,64 @@ QVariant QCocoaTheme::themeHint(ThemeHint hint) const case QPlatformTheme::SpellCheckUnderlineStyle: return QVariant(int(QTextCharFormat::DotLine)); case QPlatformTheme::UseFullScreenForPopupMenu: - return QVariant(bool([[NSApplication sharedApplication] presentationOptions] & NSApplicationPresentationFullScreen)); + return false; + case QPlatformTheme::InteractiveResizeAcrossScreens: + return !NSScreen.screensHaveSeparateSpaces; + case QPlatformTheme::ShowDirectoriesFirst: + return false; + case QPlatformTheme::MouseDoubleClickInterval: + return NSEvent.doubleClickInterval * 1000; + case QPlatformTheme::KeyboardInputInterval: + return NSEvent.keyRepeatDelay * 1000; + case QPlatformTheme::KeyboardAutoRepeatRate: + return 1.0 / NSEvent.keyRepeatInterval; + case QPlatformTheme::ShowIconsInMenus: + return false; default: break; } return QPlatformTheme::themeHint(hint); } +Qt::ColorScheme QCocoaTheme::colorScheme() const +{ + return m_colorScheme; +} + +void QCocoaTheme::requestColorScheme(Qt::ColorScheme scheme) +{ + NSAppearance *appearance = nil; + switch (scheme) { + case Qt::ColorScheme::Dark: + appearance = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua]; + break; + case Qt::ColorScheme::Light: + appearance = [NSAppearance appearanceNamed:NSAppearanceNameAqua]; + break; + case Qt::ColorScheme::Unknown: + break; + } + if (appearance != NSApp.effectiveAppearance) + NSApplication.sharedApplication.appearance = appearance; +} + +/* + Update the theme's color scheme based on the current appearance. + + We can only reference the appearance on the main thread, but the + CoreText font engine needs to know the color scheme, and might be + used from secondary threads, so we cache the color scheme. +*/ +void QCocoaTheme::updateColorScheme() +{ + m_colorScheme = qt_mac_applicationIsInDarkMode() ? Qt::ColorScheme::Dark : Qt::ColorScheme::Light; +} + QString QCocoaTheme::standardButtonText(int button) const { - return button == QPlatformDialogHelper::Discard ? msgDialogButtonDiscard() : QPlatformTheme::standardButtonText(button); + return button == QPlatformDialogHelper::Discard ? + QCoreApplication::translate("QCocoaTheme", "Don't Save") + : QPlatformTheme::standardButtonText(button); } QKeySequence QCocoaTheme::standardButtonShortcut(int button) const @@ -364,12 +521,16 @@ QKeySequence QCocoaTheme::standardButtonShortcut(int button) const QPlatformMenuItem *QCocoaTheme::createPlatformMenuItem() const { - return new QCocoaMenuItem(); + auto *menuItem = new QCocoaMenuItem(); + qCDebug(lcQpaMenus) << "Created" << menuItem; + return menuItem; } QPlatformMenu *QCocoaTheme::createPlatformMenu() const { - return new QCocoaMenu(); + auto *menu = new QCocoaMenu(); + qCDebug(lcQpaMenus) << "Created" << menu; + return menu; } QPlatformMenuBar *QCocoaTheme::createPlatformMenuBar() const @@ -382,7 +543,46 @@ QPlatformMenuBar *QCocoaTheme::createPlatformMenuBar() const SLOT(onAppFocusWindowChanged(QWindow*))); } - return new QCocoaMenuBar(); + auto *menuBar = new QCocoaMenuBar(); + qCDebug(lcQpaMenus) << "Created" << menuBar; + return menuBar; +} + +#ifndef QT_NO_SHORTCUT +QList<QKeySequence> QCocoaTheme::keyBindings(QKeySequence::StandardKey key) const +{ + // The default key bindings in QPlatformTheme all hard-coded to use the Ctrl + // modifier, to match other platforms. In the normal case, when translating + // those to key sequences, we'll end up with Qt::ControlModifier+X, which is + // then matched against incoming key events that have been mapped from the + // command key to Qt::ControlModifier, and we'll get a match. If, however, + // the AA_MacDontSwapCtrlAndMeta application attribute is set, we need to + // fix the resulting key sequence so that it will match against unmapped + // key events that contain Qt::MetaModifier. + auto bindings = QPlatformTheme::keyBindings(key); + + if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { + static auto swapCtrlMeta = [](QKeyCombination keyCombination) { + const auto originalKeyModifiers = keyCombination.keyboardModifiers(); + auto newKeyboardModifiers = originalKeyModifiers & ~(Qt::ControlModifier | Qt::MetaModifier); + if (originalKeyModifiers & Qt::ControlModifier) + newKeyboardModifiers |= Qt::MetaModifier; + if (originalKeyModifiers & Qt::MetaModifier) + newKeyboardModifiers |= Qt::ControlModifier; + return QKeyCombination(newKeyboardModifiers, keyCombination.key()); + }; + + QList<QKeySequence> swappedBindings; + for (auto binding : bindings) { + Q_ASSERT(binding.count() == 1); + swappedBindings.append(QKeySequence(swapCtrlMeta(binding[0]))); + } + + bindings = swappedBindings; + } + + return bindings; } +#endif QT_END_NAMESPACE |