@@ -72,6 +72,11 @@ public class MacPlatformService : PlatformService
7272
7373 static bool initedGlobal ;
7474 bool setupFail , initedApp ;
75+ // hold a reference on all observer objects generated by the notification center
76+ // NOTE: these objects should not be actively disposed on macOS 10.11 and later, unless removed manually
77+ // not keeping a reference might cause a runtime crash when observers are added:
78+ // KVO_IS_RETAINING_ALL_OBSERVERS_OF_THIS_OBJECT_IF_IT_CRASHES_AN_OBSERVER_WAS_OVERRELEASED_OR_SMASHED
79+ List < IDisposable > notificationObservers = new List < IDisposable > ( ) ;
7580
7681 readonly Lazy < Dictionary < string , string > > mimemap = new Lazy < Dictionary < string , string > > ( LoadMimeMap ) ;
7782
@@ -317,12 +322,12 @@ public override Xwt.Toolkit LoadNativeToolkit ()
317322 SwizzleNSApplication ( ) ;
318323
319324 var nc = NSNotificationCenter . DefaultCenter ;
320- nc . AddObserver ( ( NSString ) "AtkCocoaAccessibilityEnabled" , ( NSNotification ) => {
325+ notificationObservers . Add ( nc . AddObserver ( ( NSString ) "AtkCocoaAccessibilityEnabled" , ( NSNotification ) => {
321326 LoggingService . LogInfo ( $ "VoiceOver on { IdeTheme . AccessibilityEnabled } ") ;
322327 if ( ! IdeTheme . AccessibilityEnabled ) {
323328 ShowVoiceOverNotice ( ) ;
324329 }
325- } , NSApplication . SharedApplication ) ;
330+ } , NSApplication . SharedApplication ) ) ;
326331
327332 // Now that Cocoa has been initialized we can check whether the keyboard focus mode is turned on
328333 // See System Preferences - Keyboard - Shortcuts - Full Keyboard Access
@@ -568,12 +573,23 @@ void InitApp (CommandManager commandManager)
568573 } ;
569574
570575 PatchGtkTheme ( ) ;
571- NSNotificationCenter . DefaultCenter . AddObserver ( NSCell . ControlTintChangedNotification , notif => Core . Runtime . RunInMainThread (
572- delegate {
573- Styles . LoadStyle ( ) ;
574- PatchGtkTheme ( ) ;
575- } ) ) ;
576576
577+ if ( MacSystemInformation . OsVersion >= MacSystemInformation . Mojave ) {
578+ IdeTheme . HighContrastThemeEnabled = GetIsHighContrastActive ( ) ;
579+ notificationObservers . Add ( NSApplication . SharedApplication . AddObserver ( "effectiveAppearance" , NSKeyValueObservingOptions . New , notif =>
580+ Core . Runtime . RunInMainThread ( ( ) => {
581+ IdeTheme . HighContrastThemeEnabled = GetIsHighContrastActive ( ) ;
582+ PatchGtkTheme ( ) ;
583+ } )
584+ ) ) ;
585+ } else {
586+ IdeTheme . HighContrastThemeEnabled = false ;
587+ notificationObservers . Add ( NSNotificationCenter . DefaultCenter . AddObserver ( NSCell . ControlTintChangedNotification , notif => Core . Runtime . RunInMainThread (
588+ delegate {
589+ Styles . LoadStyle ( ) ;
590+ PatchGtkTheme ( ) ;
591+ } ) ) ) ;
592+ }
577593
578594 if ( MacSystemInformation . OsVersion < MacSystemInformation . Mojave ) { // the shared color panel has full automatic theme support on Mojave
579595 Styles . Changed += ( s , a ) => {
@@ -594,6 +610,18 @@ void InitApp (CommandManager commandManager)
594610 //IdeApp.Preferences.UserInterfaceTheme.Changed += (s,a) => PatchGtkTheme ();
595611 }
596612
613+ static bool GetIsHighContrastActive ( )
614+ {
615+ var highContrastAppearances = new string [ ] {
616+ NSAppearance . NameAccessibilityHighContrastAqua ,
617+ NSAppearance . NameAccessibilityHighContrastDarkAqua ,
618+ NSAppearance . NameAccessibilityHighContrastVibrantDark ,
619+ NSAppearance . NameAccessibilityHighContrastVibrantLight ,
620+ } ;
621+ // FindBestMatch will return the best matching a11y appearance or null if no high contrast appearance is in use
622+ return NSApplication . SharedApplication . EffectiveAppearance . FindBestMatch ( highContrastAppearances ) != null ;
623+ }
624+
597625 static void UpdateColorPanelSubviewsAppearance ( NSView view , NSAppearance appearance )
598626 {
599627 if ( view . Class . Name == "NSPageableTableView" )
0 commit comments