Cocoa Port: Fix some bugs related to macOS Mojave's Dark Mode.
- Fix a bug where running DeSmuME on a Mac with a non-Haswell 64-bit Intel CPU would fail to switch the GUI icons into Dark Mode, despite the user running Mojave or later. - Fix a bug where the GUI icons would occasionally fail to correctly switch between Light Mode and Dark Mode if the user changed the system appearance in System Preferences while running Mojave or Catalina. - Add a new menu option in "Tools > App Appearance Mode" to manually force DeSmuME's app appearance to reflect Light Mode or Dark Mode. (Only available on dev+ builds.)
This commit is contained in:
parent
680b3c16a3
commit
84e98a0c49
|
@ -14,6 +14,8 @@
|
|||
<true/>
|
||||
<key>CoreControl_SpeedScalar</key>
|
||||
<real>1</real>
|
||||
<key>Debug_AppAppearanceMode</key>
|
||||
<integer>0</integer>
|
||||
<key>Debug_DisableMetal</key>
|
||||
<false/>
|
||||
<key>Debug_GDBStubEnableARM9</key>
|
||||
|
|
|
@ -215,6 +215,13 @@
|
|||
#define RUMBLE_ITERATIONS_ENABLE 1
|
||||
#define RUMBLE_ITERATIONS_TEST 3
|
||||
|
||||
enum
|
||||
{
|
||||
APP_APPEARANCEMODE_AUTOMATIC = 0,
|
||||
APP_APPEARANCEMODE_LIGHT = 1,
|
||||
APP_APPEARANCEMODE_DARK = 2
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ROMAUTOLOADOPTION_LOAD_LAST = 0,
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
+ (NSString *) appInternalNameAndVersionString;
|
||||
+ (NSString *) appCompilerDetailString;
|
||||
|
||||
+ (BOOL) determineDarkModeAppearance;
|
||||
|
||||
+ (NSString *) operatingSystemString;
|
||||
+ (NSString *) modelIdentifierString;
|
||||
+ (uint32_t) hostIP4AddressAsUInt32;
|
||||
|
|
|
@ -156,6 +156,42 @@
|
|||
return [NSString stringWithCString:EMU_DESMUME_COMPILER_DETAIL() encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
+ (BOOL) determineDarkModeAppearance
|
||||
{
|
||||
const NSInteger appAppearanceMode = [[NSUserDefaults standardUserDefaults] integerForKey:@"Debug_AppAppearanceMode"];
|
||||
BOOL darkModeState = NO; // Default to Light Mode appearance
|
||||
|
||||
if ( (appAppearanceMode == APP_APPEARANCEMODE_AUTOMATIC) && IsOSXVersionSupported(10, 10, 0) )
|
||||
{
|
||||
// We're doing a Yosemite-style check for Dark Mode by reading the AppleInterfaceStyle key from NSGlobalDomain.
|
||||
//
|
||||
// Apple recommends using [[NSView effectiveAppearance] name] to check for Dark Mode, which requires Mojave.
|
||||
// While this Mojave method may be the "correct" method according to Apple, we would be forcing the user to
|
||||
// run Mojave or later, with this method only being useful if DeSmuME's GUI uses a mix of both Light Mode and
|
||||
// Dark Mode windows. We want to keep DeSmuME's GUI simple by only using a single appearance mode for the
|
||||
// entire app, and so the Mojave method gives no benefits to DeSmuME over the Yosemite method, and because we
|
||||
// don't want DeSmuME to be limited to running only on the more advanced versions of macOS.
|
||||
//
|
||||
// And so we call this method in response to the "AppleInterfaceThemeChangedNotification" notification from
|
||||
// NSDistributedNotificationCenter. Doing this causes a serious technical problem to occur for the Mojave
|
||||
// method, in which macOS Mojave and Cataline experience a race condition if you try to call
|
||||
// [[NSView effectiveAppearance] name] when the user switches appearance modes in System Preferences. This
|
||||
// race condition causes an unreliable read of the Dark Mode state on Mojave and Catalina.
|
||||
//
|
||||
// With the aforementioned reliability issue being the final straw on top of the previously mentioned reasons,
|
||||
// this makes the Yosemite method for checking the Dark Mode state the correct choice.
|
||||
const NSDictionary *globalPersistentDomain = [[NSUserDefaults standardUserDefaults] persistentDomainForName:NSGlobalDomain];
|
||||
const NSString *interfaceStyle = [globalPersistentDomain valueForKey:@"AppleInterfaceStyle"];
|
||||
darkModeState = (interfaceStyle != nil) && [interfaceStyle isEqualToString:@"Dark"] && IsOSXVersionSupported(10, 14, 0);
|
||||
}
|
||||
else if (appAppearanceMode == APP_APPEARANCEMODE_DARK)
|
||||
{
|
||||
darkModeState = YES; // Force Dark Mode appearance
|
||||
}
|
||||
|
||||
return darkModeState;
|
||||
}
|
||||
|
||||
+ (NSString *) operatingSystemString
|
||||
{
|
||||
NSDictionary *systemDict = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"];
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -301,7 +301,6 @@ class AudioSampleBlockGenerator;
|
|||
- (BOOL) handleUnloadRom:(NSInteger)reasonID romToLoad:(NSURL *)romURL;
|
||||
- (BOOL) loadRomByURL:(NSURL *)romURL asynchronous:(BOOL)willLoadAsync;
|
||||
- (void) loadRomDidFinish:(NSNotification *)aNotification;
|
||||
- (void) handleSystemThemeChange:(NSNotification *) notification;
|
||||
- (BOOL) unloadRom;
|
||||
|
||||
- (void) addOutputToCore:(CocoaDSOutput *)theOutput;
|
||||
|
@ -330,5 +329,6 @@ class AudioSampleBlockGenerator;
|
|||
- (void) writeUserDefaults;
|
||||
- (void) restoreDisplayWindowStates;
|
||||
- (void) saveDisplayWindowStates;
|
||||
- (void) handleAppearanceChange;
|
||||
|
||||
@end
|
||||
|
|
|
@ -124,25 +124,7 @@
|
|||
mainWindow = nil;
|
||||
windowList = [[NSMutableArray alloc] initWithCapacity:32];
|
||||
|
||||
isRunningDarkMode = NO;
|
||||
|
||||
#if HAVE_OSAVAILABLE && defined(MAC_OS_X_VERSION_10_14) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14)
|
||||
if (IsOSXVersionSupported(10, 14, 0))
|
||||
{
|
||||
if (@available(macOS 10.14, *))
|
||||
{
|
||||
NSAppearanceName currentAppearanceName = [[NSApp effectiveAppearance] name];
|
||||
|
||||
if ( (currentAppearanceName == NSAppearanceNameDarkAqua) ||
|
||||
(currentAppearanceName == NSAppearanceNameVibrantDark) ||
|
||||
(currentAppearanceName == NSAppearanceNameAccessibilityHighContrastDarkAqua) ||
|
||||
(currentAppearanceName == NSAppearanceNameAccessibilityHighContrastVibrantDark) )
|
||||
{
|
||||
isRunningDarkMode = YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
isRunningDarkMode = [CocoaDSUtil determineDarkModeAppearance];
|
||||
|
||||
_displayRotationPanelTitle = nil;
|
||||
_displaySeparationPanelTitle = nil;
|
||||
|
@ -216,8 +198,6 @@
|
|||
name:@"org.desmume.DeSmuME.handleEmulatorExecutionState"
|
||||
object:nil];
|
||||
|
||||
[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(handleSystemThemeChange:) name:@"AppleInterfaceThemeChangedNotification" object:nil];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -2217,45 +2197,6 @@
|
|||
[cdsCore setFrameStatus:frameStatusString];
|
||||
}
|
||||
|
||||
- (void) handleSystemThemeChange:(NSNotification *) notification
|
||||
{
|
||||
BOOL newDarkModeState = NO;
|
||||
|
||||
#if HAVE_OSAVAILABLE && defined(MAC_OS_X_VERSION_10_14) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14)
|
||||
if (IsOSXVersionSupported(10, 14, 0))
|
||||
{
|
||||
if (@available(macOS 10.14, *))
|
||||
{
|
||||
NSAppearanceName currentAppearanceName = nil;
|
||||
|
||||
if (mainWindow != nil)
|
||||
{
|
||||
currentAppearanceName = [[[mainWindow view] effectiveAppearance] name];
|
||||
}
|
||||
else
|
||||
{
|
||||
currentAppearanceName = [[NSApp effectiveAppearance] name];
|
||||
}
|
||||
|
||||
if ( (currentAppearanceName == NSAppearanceNameDarkAqua) ||
|
||||
(currentAppearanceName == NSAppearanceNameVibrantDark) ||
|
||||
(currentAppearanceName == NSAppearanceNameAccessibilityHighContrastDarkAqua) ||
|
||||
(currentAppearanceName == NSAppearanceNameAccessibilityHighContrastVibrantDark) )
|
||||
{
|
||||
newDarkModeState = YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (newDarkModeState != [self isRunningDarkMode])
|
||||
{
|
||||
[self setIsRunningDarkMode:newDarkModeState];
|
||||
[self setCurrentVolumeValue:[self currentVolumeValue]];
|
||||
[self updateMicStatusIcon];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) addOutputToCore:(CocoaDSOutput *)theOutput
|
||||
{
|
||||
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
|
||||
|
@ -2940,6 +2881,18 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void) handleAppearanceChange
|
||||
{
|
||||
const BOOL newDarkModeState = [CocoaDSUtil determineDarkModeAppearance];
|
||||
|
||||
if (newDarkModeState != [self isRunningDarkMode])
|
||||
{
|
||||
[self setIsRunningDarkMode:newDarkModeState];
|
||||
[self setCurrentVolumeValue:[self currentVolumeValue]];
|
||||
[self updateMicStatusIcon];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark NSUserInterfaceValidations Protocol
|
||||
|
||||
- (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)theItem
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2011 Roger Manuel
|
||||
Copyright (C) 2011-2018 DeSmuME Team
|
||||
Copyright (C) 2011-2022 DeSmuME Team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -25,9 +25,9 @@
|
|||
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate, NSUserInterfaceValidations>
|
||||
#else
|
||||
@interface AppDelegate : NSObject
|
||||
@interface AppDelegate : NSObject<NSUserInterfaceValidations>
|
||||
#endif
|
||||
{
|
||||
NSObject *dummyObject;
|
||||
|
@ -77,9 +77,11 @@
|
|||
- (IBAction) launchForums:(id)sender;
|
||||
- (IBAction) supportRequest:(id)sender;
|
||||
- (IBAction) bugReport:(id)sender;
|
||||
- (IBAction) changeAppAppearance:(id)sender;
|
||||
|
||||
- (void) setupSlotMenuItems;
|
||||
- (NSMenuItem *) addSlotMenuItem:(NSMenu *)menu slotNumber:(NSUInteger)slotNumber;
|
||||
- (void) setupUserDefaults;
|
||||
- (void) handleSystemAppearanceThemeChange:(NSNotification *) notification;
|
||||
|
||||
@end
|
||||
|
|
|
@ -86,6 +86,8 @@
|
|||
RGBA8888ToNSColorValueTransformer *nsColorTransformer = [[[RGBA8888ToNSColorValueTransformer alloc] init] autorelease];
|
||||
[NSValueTransformer setValueTransformer:nsColorTransformer forName:@"RGBA8888ToNSColorValueTransformer"];
|
||||
|
||||
[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(handleSystemAppearanceThemeChange:) name:@"AppleInterfaceThemeChangedNotification" object:nil];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -459,6 +461,15 @@
|
|||
[troubleshootingWindow makeKeyAndOrderFront:sender];
|
||||
}
|
||||
|
||||
- (IBAction) changeAppAppearance:(id)sender
|
||||
{
|
||||
const NSInteger appAppearanceMode = [CocoaDSUtil getIBActionSenderTag:sender];
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:appAppearanceMode forKey:@"Debug_AppAppearanceMode"];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
|
||||
[self handleSystemAppearanceThemeChange:nil];
|
||||
}
|
||||
|
||||
#pragma mark Class Methods
|
||||
- (void) setupSlotMenuItems
|
||||
{
|
||||
|
@ -707,4 +718,33 @@
|
|||
[prefWindowDelegate setupUserDefaults];
|
||||
}
|
||||
|
||||
- (void) handleSystemAppearanceThemeChange:(NSNotification *) notification
|
||||
{
|
||||
EmuControllerDelegate *emuControl = (EmuControllerDelegate *)[emuControlController content];
|
||||
PreferencesWindowDelegate *prefWindowDelegate = (PreferencesWindowDelegate *)[prefWindow delegate];
|
||||
|
||||
[emuControl handleAppearanceChange];
|
||||
[prefWindowDelegate handleAppearanceChange];
|
||||
}
|
||||
|
||||
#pragma mark NSUserInterfaceValidations Protocol
|
||||
|
||||
- (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)theItem
|
||||
{
|
||||
BOOL enable = YES;
|
||||
const SEL theAction = [theItem action];
|
||||
|
||||
if (theAction == @selector(changeAppAppearance:))
|
||||
{
|
||||
const NSInteger appAppearanceMode = [[NSUserDefaults standardUserDefaults] integerForKey:@"Debug_AppAppearanceMode"];
|
||||
|
||||
if ([(id)theItem isMemberOfClass:[NSMenuItem class]])
|
||||
{
|
||||
[(NSMenuItem*)theItem setState:([theItem tag] == appAppearanceMode) ? GUI_STATE_ON : GUI_STATE_OFF];
|
||||
}
|
||||
}
|
||||
|
||||
return enable;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -173,5 +173,6 @@ class OGLImage;
|
|||
- (void) switchContentView:(NSView *)theView;
|
||||
- (void) markUnsupportedOpenGLMSAAMenuItems;
|
||||
- (void) setupUserDefaults;
|
||||
- (void) handleAppearanceChange;
|
||||
|
||||
@end
|
||||
|
|
|
@ -344,25 +344,7 @@
|
|||
subnetMaskString_AP2 = @"0.0.0.0";
|
||||
subnetMaskString_AP3 = @"0.0.0.0";
|
||||
|
||||
_isRunningDarkMode = NO;
|
||||
|
||||
#if HAVE_OSAVAILABLE && defined(MAC_OS_X_VERSION_10_14) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14)
|
||||
if (IsOSXVersionSupported(10, 14, 0))
|
||||
{
|
||||
if (@available(macOS 10.14, *))
|
||||
{
|
||||
NSAppearanceName currentAppearanceName = [[NSApp effectiveAppearance] name];
|
||||
|
||||
if ( (currentAppearanceName == NSAppearanceNameDarkAqua) ||
|
||||
(currentAppearanceName == NSAppearanceNameVibrantDark) ||
|
||||
(currentAppearanceName == NSAppearanceNameAccessibilityHighContrastDarkAqua) ||
|
||||
(currentAppearanceName == NSAppearanceNameAccessibilityHighContrastVibrantDark) )
|
||||
{
|
||||
_isRunningDarkMode = YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
_isRunningDarkMode = [CocoaDSUtil determineDarkModeAppearance];
|
||||
|
||||
// Load the volume icons.
|
||||
iconVolumeFull = [[NSImage imageNamed:@"Icon_VolumeFull_16x16"] retain];
|
||||
|
@ -377,8 +359,6 @@
|
|||
|
||||
prefViewDict = nil;
|
||||
|
||||
[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(handleSystemThemeChange:) name:@"AppleInterfaceThemeChangedNotification" object:nil];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -1161,28 +1141,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void) handleSystemThemeChange:(NSNotification *) notification
|
||||
- (void) handleAppearanceChange
|
||||
{
|
||||
BOOL newDarkModeState = NO;
|
||||
|
||||
#if HAVE_OSAVAILABLE && defined(MAC_OS_X_VERSION_10_14) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14)
|
||||
if (IsOSXVersionSupported(10, 14, 0))
|
||||
{
|
||||
if (@available(macOS 10.14, *))
|
||||
{
|
||||
NSAppearanceName currentAppearanceName = [[[self viewSound] effectiveAppearance] name];
|
||||
|
||||
if ( (currentAppearanceName == NSAppearanceNameDarkAqua) ||
|
||||
(currentAppearanceName == NSAppearanceNameVibrantDark) ||
|
||||
(currentAppearanceName == NSAppearanceNameAccessibilityHighContrastDarkAqua) ||
|
||||
(currentAppearanceName == NSAppearanceNameAccessibilityHighContrastVibrantDark) )
|
||||
{
|
||||
newDarkModeState = YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
const BOOL newDarkModeState = [CocoaDSUtil determineDarkModeAppearance];
|
||||
if (newDarkModeState != _isRunningDarkMode)
|
||||
{
|
||||
_isRunningDarkMode = newDarkModeState;
|
||||
|
|
Loading…
Reference in New Issue