diff options
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoatheme.mm')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoatheme.mm | 217 |
1 files changed, 99 insertions, 118 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm index 21f127103f..d9135c76c8 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.mm +++ b/src/plugins/platforms/cocoa/qcocoatheme.mm @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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> @@ -51,12 +15,14 @@ #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 <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> @@ -66,21 +32,10 @@ #include "qcocoacolordialoghelper.h" #include "qcocoafiledialoghelper.h" #include "qcocoafontdialoghelper.h" +#include "qcocoamessagedialog.h" #include <CoreServices/CoreServices.h> -#if !QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14) -@interface NSColor (MojaveForwardDeclarations) -@property (class, strong, readonly) NSColor *selectedContentBackgroundColor NS_AVAILABLE_MAC(10_14); -@property (class, strong, readonly) NSColor *unemphasizedSelectedTextBackgroundColor NS_AVAILABLE_MAC(10_14); -@property (class, strong, readonly) NSColor *unemphasizedSelectedTextColor NS_AVAILABLE_MAC(10_14); -@property (class, strong, readonly) NSColor *unemphasizedSelectedContentBackgroundColor NS_AVAILABLE_MAC(10_14); -@property (class, strong, readonly) NSArray<NSColor *> *alternatingContentBackgroundColors NS_AVAILABLE_MAC(10_14); -// Missing from non-Mojave SDKs, even if introduced in 10.10 -@property (class, strong, readonly) NSColor *linkColor NS_AVAILABLE_MAC(10_10); -@end -#endif - QT_BEGIN_NAMESPACE static QPalette *qt_mac_createSystemPalette() @@ -99,7 +54,6 @@ static QPalette *qt_mac_createSystemPalette() palette->setBrush(QPalette::Disabled, QPalette::WindowText, dark); palette->setBrush(QPalette::Disabled, QPalette::Text, dark); - palette->setBrush(QPalette::Disabled, QPalette::ButtonText, dark); palette->setBrush(QPalette::Disabled, QPalette::Base, backgroundBrush); QBrush textBackgroundBrush = qt_mac_toQBrush([NSColor textBackgroundColor]); palette->setBrush(QPalette::Active, QPalette::Base, textBackgroundBrush); @@ -111,19 +65,15 @@ static QPalette *qt_mac_createSystemPalette() // System palette initialization: QBrush br = qt_mac_toQBrush([NSColor selectedControlColor]); palette->setBrush(QPalette::Active, QPalette::Highlight, br); - if (__builtin_available(macOS 10.14, *)) { - const auto inactiveHighlight = qt_mac_toQBrush([NSColor unemphasizedSelectedContentBackgroundColor]); - palette->setBrush(QPalette::Inactive, QPalette::Highlight, inactiveHighlight); - palette->setBrush(QPalette::Disabled, QPalette::Highlight, inactiveHighlight); - } else { - palette->setBrush(QPalette::Inactive, QPalette::Highlight, br); - palette->setBrush(QPalette::Disabled, 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); @@ -132,6 +82,7 @@ static QPalette *qt_mac_createSystemPalette() 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); @@ -144,6 +95,9 @@ static QPalette *qt_mac_createSystemPalette() 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; } @@ -201,17 +155,8 @@ static QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes() } if (mac_widget_colors[i].paletteRole == QPlatformTheme::MenuPalette || mac_widget_colors[i].paletteRole == QPlatformTheme::MenuBarPalette) { - NSColor *selectedMenuItemColor = nil; - if (__builtin_available(macOS 10.14, *)) { - // Cheap approximation for NSVisualEffectView (see deprecation note for selectedMenuItemTextColor) - selectedMenuItemColor = [[NSColor selectedContentBackgroundColor] highlightWithLevel:0.4]; - } else { - // selectedMenuItemColor would presumably be the correct color to use as the background - // for selected menu items. But that color is always blue, and doesn't follow the - // appearance color in system preferences. So we therefore deliberatly choose to use - // keyboardFocusIndicatorColor instead, which appears to have the same color value. - selectedMenuItemColor = [NSColor keyboardFocusIndicatorColor]; - } + // 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); @@ -232,17 +177,10 @@ static QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes() } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::ItemViewPalette) { NSArray<NSColor *> *baseColors = nil; NSColor *activeHighlightColor = nil; - if (__builtin_available(macOS 10.14, *)) { - baseColors = [NSColor alternatingContentBackgroundColors]; - activeHighlightColor = [NSColor selectedContentBackgroundColor]; - pal.setBrush(QPalette::Inactive, QPalette::HighlightedText, - qt_mac_toQBrush([NSColor unemphasizedSelectedTextColor])); - } else { - baseColors = [NSColor controlAlternatingRowBackgroundColors]; - activeHighlightColor = [NSColor alternateSelectedControlColor]; - pal.setBrush(QPalette::Inactive, QPalette::HighlightedText, - pal.brush(QPalette::Active, QPalette::Text)); - } + 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, @@ -276,27 +214,24 @@ 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; - + NSAppearance.currentAppearance = NSApp.effectiveAppearance; handleSystemThemeChange(); }); } -#endif m_systemColorObserver = QMacNotificationObserver(nil, NSSystemColorsDidChangeNotification, [this] { handleSystemThemeChange(); }); + + updateColorScheme(); } QCocoaTheme::~QCocoaTheme() { reset(); - qDeleteAll(m_fonts); } void QCocoaTheme::reset() @@ -310,6 +245,9 @@ void QCocoaTheme::reset() void QCocoaTheme::handleSystemThemeChange() { reset(); + + updateColorScheme(); + m_systemPalette = qt_mac_createSystemPalette(); m_palettes = qt_mac_createRolePalettes(); @@ -318,18 +256,20 @@ void QCocoaTheme::handleSystemThemeChange() QFontCache::instance()->clear(); } - QWindowSystemInterface::handleThemeChange<QWindowSystemInterface::SynchronousDelivery>(nullptr); + QWindowSystemInterface::handleThemeChange<QWindowSystemInterface::SynchronousDelivery>(); } bool QCocoaTheme::usePlatformNativeDialog(DialogType dialogType) const { - if (dialogType == QPlatformTheme::FileDialog) - return true; - if (dialogType == QPlatformTheme::ColorDialog) - return true; - if (dialogType == QPlatformTheme::FontDialog) + switch (dialogType) { + case QPlatformTheme::FileDialog: + case QPlatformTheme::ColorDialog: + case QPlatformTheme::FontDialog: + case QPlatformTheme::MessageDialog: return true; - return false; + default: + return false; + } } QPlatformDialogHelper *QCocoaTheme::createPlatformDialogHelper(DialogType dialogType) const @@ -341,6 +281,8 @@ QPlatformDialogHelper *QCocoaTheme::createPlatformDialogHelper(DialogType dialog return new QCocoaColorDialogHelper(); case QPlatformTheme::FontDialog: return new QCocoaFontDialogHelper(); + case QPlatformTheme::MessageDialog: + return new QCocoaMessageDialog; default: return nullptr; } @@ -369,12 +311,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 @@ -451,11 +390,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; @@ -471,19 +410,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) override - { return QCocoaFileIconEngine::availableIconSizes(); } + { return QAppleIconEngine::availableIconSizes(); } protected: QPixmap filePixmap(const QSize &size, QIcon::Mode, QIcon::State) override @@ -502,6 +430,11 @@ 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) { @@ -515,7 +448,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: @@ -526,12 +459,54 @@ QVariant QCocoaTheme::themeHint(ThemeHint hint) const return QVariant(bool([[NSApplication sharedApplication] presentationOptions] & NSApplicationPresentationFullScreen)); 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; 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 ? @@ -547,12 +522,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 @@ -565,7 +544,9 @@ QPlatformMenuBar *QCocoaTheme::createPlatformMenuBar() const SLOT(onAppFocusWindowChanged(QWindow*))); } - return new QCocoaMenuBar(); + auto *menuBar = new QCocoaMenuBar(); + qCDebug(lcQpaMenus) << "Created" << menuBar; + return menuBar; } #ifndef QT_NO_SHORTCUT |