From da62e76eacd538eb61e188bc53e24cd1aaf01e49 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 15 Jun 2018 23:18:49 +0200 Subject: Cocoa: Update palette after accent color or appearance changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This updates the UI after the accent color or NSApp's effective appearance have changed. For the accent color, we listen to NSSystemColorsDidChangeNotification. For the effective appearance changes, we do KVO on NSApp.effectiveAppearance. Both changes will trigger rebuilding the system palettes followed by a ThemeChangeEvent in the window system interface layer. Task-number: QTBUG-68891 Change-Id: Iab1ec874e05f1f6d54cd60217c273e0f8ffbf49e Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoatheme.mm | 73 ++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 19 deletions(-) (limited to 'src/plugins/platforms/cocoa/qcocoatheme.mm') diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm index 0f1bfea7b5..a2229159b5 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.mm +++ b/src/plugins/platforms/cocoa/qcocoatheme.mm @@ -42,6 +42,7 @@ #include "qcocoatheme.h" #include "messages.h" +#include #include #include "qcocoasystemsettings.h" @@ -77,26 +78,48 @@ #include -@interface QT_MANGLE_NAMESPACE(QCocoaThemeNotificationReceiver) : NSObject +#if !QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14) +@interface NSApplication (MojaveForwardDeclarations) +@property (readonly, strong) NSAppearance *effectiveAppearance NS_AVAILABLE_MAC(10_14); @end +#endif -QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaThemeNotificationReceiver); +@interface QT_MANGLE_NAMESPACE(QCocoaThemeAppAppearanceObserver) : NSObject +@property (readonly, nonatomic) QCocoaTheme *theme; +- (instancetype)initWithTheme:(QCocoaTheme *)theme; +@end -@implementation QCocoaThemeNotificationReceiver { - QCocoaTheme *mPrivate; -} +QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaThemeAppAppearanceObserver); -- (instancetype)initWithPrivate:(QCocoaTheme *)priv +@implementation QCocoaThemeAppAppearanceObserver +- (instancetype)initWithTheme:(QCocoaTheme *)theme { - if ((self = [self init])) - mPrivate = priv; + if ((self = [super init])) { + _theme = theme; + [NSApp addObserver:self forKeyPath:@"effectiveAppearance" options:NSKeyValueObservingOptionNew context:nullptr]; + } return self; } -- (void)systemColorsDidChange:(NSNotification *)__unused notification +- (void)dealloc { - mPrivate->reset(); - QWindowSystemInterface::handleThemeChange(nullptr); + [NSApp removeObserver:self forKeyPath:@"effectiveAppearance"]; + [super dealloc]; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object + change:(NSDictionary *)change context:(void *)context +{ + Q_UNUSED(change); + Q_UNUSED(context); + + Q_ASSERT(object == NSApp); + Q_ASSERT([keyPath isEqualToString:@"effectiveAppearance"]); + + if (__builtin_available(macOS 10.14, *)) + NSAppearance.currentAppearance = NSApp.effectiveAppearance; + + self.theme->handleSystemThemeChange(); } @end @@ -105,19 +128,22 @@ QT_BEGIN_NAMESPACE const char *QCocoaTheme::name = "cocoa"; QCocoaTheme::QCocoaTheme() - : m_systemPalette(nullptr) + : m_systemPalette(nullptr), m_appearanceObserver(nil) { - m_notificationReceiver = [[QT_MANGLE_NAMESPACE(QCocoaThemeNotificationReceiver) alloc] initWithPrivate:this]; - [[NSNotificationCenter defaultCenter] addObserver:m_notificationReceiver - selector:@selector(systemColorsDidChange:) - name:NSSystemColorsDidChangeNotification - object:nil]; + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave) + m_appearanceObserver = [[QCocoaThemeAppAppearanceObserver alloc] initWithTheme:this]; + + [[NSNotificationCenter defaultCenter] addObserverForName:NSSystemColorsDidChangeNotification + object:nil queue:nil usingBlock:^(NSNotification *) { + handleSystemThemeChange(); + }]; } QCocoaTheme::~QCocoaTheme() { - [[NSNotificationCenter defaultCenter] removeObserver:m_notificationReceiver]; - [m_notificationReceiver release]; + if (m_appearanceObserver) + [m_appearanceObserver release]; + reset(); qDeleteAll(m_fonts); } @@ -130,6 +156,15 @@ void QCocoaTheme::reset() m_palettes.clear(); } +void QCocoaTheme::handleSystemThemeChange() +{ + reset(); + m_systemPalette = qt_mac_createSystemPalette(); + m_palettes = qt_mac_createRolePalettes(); + + QWindowSystemInterface::handleThemeChange(nullptr); +} + bool QCocoaTheme::usePlatformNativeDialog(DialogType dialogType) const { if (dialogType == QPlatformTheme::FileDialog) -- cgit v1.2.3