Based on some forum code and PB IDE code, I have workarounds to detect Dark Mode, and get MacOS system colors.
(I should check the authors and thank them here!)
System colors are used for drawing custom gadgets, eg. CanvasGadgets.
If I start in Light Mode --> everything looks OK
If I start in Dark Mode --> everything looks OK
But if I toggle Dark/Light Mode while my PB programs are running...
(1) Window background colors update but StatusBar background colors don't
I posted about that here: viewtopic.php?f=24&t=76728&p=565922#p565922
(2) My procedure to get the system colors still returns the initial colors... it doesn't get the updated colors
(3) (Least important) I am polling to detect when Dark Mode toggles, which is OK. But an event-driven detection would be appreciated!
Any advice? Thanks to all you Cocoa experts!
Demo:
Code: Select all
CompilerIf #PB_Compiler_OS <> #PB_OS_MacOS
CompilerError "Please test on MacOS!"
CompilerEndIf
OpenWindow(0, 0, 0, 640, 480, "Dark Mode Test", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
CreateStatusBar(0, WindowID(0))
AddStatusBarField(#PB_Ignore)
StatusBarText(0, 0, "Status Bar Text")
Macro SetCanvasColor(Canvas, Color)
If StartDrawing(CanvasOutput(Canvas))
Box(0, 0, OutputWidth(), OutputHeight(), Color)
StopDrawing()
EndIf
EndMacro
y = 40
TextGadget(#PB_Any, 20, y, 200, 30, "windowBackgroundColor")
CanvasGadget(0, 220, y, 30, 30, #PB_Canvas_Border)
y + 30
TextGadget(#PB_Any, 20, y, 200, 30, "systemGrayColor")
CanvasGadget(1, 220, y, 30, 30, #PB_Canvas_Border)
y + 30
TextGadget(#PB_Any, 20, y, 200, 30, "controlBackgroundColor")
CanvasGadget(2, 220, y, 30, 30, #PB_Canvas_Border)
y + 30
TextGadget(#PB_Any, 20, y, 200, 30, "textColor")
CanvasGadget(3, 220, y, 30, 30, #PB_Canvas_Border)
y + 30
TextGadget(#PB_Any, 20, 420, 400, 30, "Toggle Dark Mode, and see if the Status Bar below changes color")
AddWindowTimer(0, 0, 1000)
DarkModeFlag.i = -1
Procedure.i Cocoa_IsDarkMode()
Protected *appearance = CocoaMessage(0, CocoaMessage(0, 0, "NSUserDefaults standardUserDefaults"), "stringForKey:$", @"AppleInterfaceStyle")
If (*appearance)
*appearance = CocoaMessage(0, *appearance, "UTF8String")
If (FindString(PeekS(*appearance, -1, #PB_UTF8), "Dark"))
ProcedureReturn (#True)
EndIf
EndIf
ProcedureReturn (#False)
EndProcedure
Procedure.i Cocoa_GetSysColor(NSColorName.s)
; "windowBackgroundColor"
; "systemGrayColor"
; "controlBackgroundColor"
; "textColor"
Protected.CGFloat r, g, b
Protected NSColor.i, NSColorSpace.i
; There is no controlAccentColor on macOS < 10.14
If ((NSColorName = "controlAccentColor") And (OSVersion() < #PB_OS_MacOSX_10_14))
ProcedureReturn ($D5ABAD)
EndIf
; There are no system colors on macOS < 10.10
If ((Left(NSColorName, 6) = "system") And (OSVersion() < #PB_OS_MacOSX_10_10))
NSColorName = LCase(Mid(NSColorName, 7, 1)) + Mid(NSColorName, 8)
EndIf
NSColorSpace = CocoaMessage(0, 0, "NSColorSpace deviceRGBColorSpace")
NSColor = CocoaMessage(0, CocoaMessage(0, 0, "NSColor " + NSColorName), "colorUsingColorSpace:", NSColorSpace)
If (NSColor)
CocoaMessage(@r, NSColor, "redComponent")
CocoaMessage(@g, NSColor, "greenComponent")
CocoaMessage(@b, NSColor, "blueComponent")
ProcedureReturn (RGB(r * 255.0, g * 255.0, b * 255.0))
EndIf
EndProcedure
Repeat
Event = WaitWindowEvent()
If (Event = #PB_Event_Timer)
NewDarkMode = Cocoa_IsDarkMode()
If NewDarkMode <> DarkModeFlag
DarkModeFlag = NewDarkMode
SetCanvasColor(0, Cocoa_GetSysColor("windowBackgroundColor"))
SetCanvasColor(1, Cocoa_GetSysColor("systemGrayColor"))
SetCanvasColor(2, Cocoa_GetSysColor("controlBackgroundColor"))
SetCanvasColor(3, Cocoa_GetSysColor("textColor"))
If (#True) ; Even if you re-create StatusBar, it remains in original color
FreeStatusBar(0)
CreateStatusBar(0, WindowID(0))
AddStatusBarField(#PB_Ignore)
StatusBarText(0, 0, "Status Bar Text")
EndIf
If DarkModeFlag
MessageRequester("", "Dark Mode!")
Else
MessageRequester("", "Light / Regular Mode")
EndIf
EndIf
EndIf
Until (Event = #PB_Event_CloseWindow) Or (Event = #PB_Event_Menu)