Dark Mode under Windows
The OS-drawn controls aren't working properly when DrRacket is in dark mode.
This issue was created by culling the specific comments from https://github.com/racket/drracket/issues/235.
@jcolivo wrote
Hello Racket Team, I appreciate all the hard work on trying to improve the dark mode in DrRacket. Thank you.
Just hoping that you won't forget us Windows users. ;-) My issues are as pointed out in this thread: https://groups.google.com/forum/#!topic/racket-dev/xYjE9JCe9u0
If there is anything I can do to help (I'm not a programmer, but can certainly help with testing), please let me know.
Have a wonderful weekend!
@alex-hhh wrote
The registry key AppsUseLightTheme in HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize, will be 1 or missing if applications use the "light" theme and will be 0 if the applications should use a dark theme.
I verified that AppsUseLightTheme changes to 0 if I select "dark" mode in my preferences on my Windows 10 machine. The key is missing if "Dark" mode was never selected on a machine.
white-on-black-panel-scheme? could just look for this key on Windows?
Source: https://stackoverflow.com/questions/51334674/how-to-detect-windows-10-light-dark-mode-in-win32-application
@mflatt wrote:
More ideas for dark mode on Windows based on various undocumented flags and functions: mflatt/gui@fd38e76
Last time I looked at this, I concluded that system Win32 control classes like buttons or checkboxes (I forget which, but I think it was buttons) don't support dark mode.
@jcolivo wrote
I found the Windows Registry Key as @default-kramer mentioned above referencing the StackOverflow thread: https://stackoverflow.com/questions/51334674/how-to-detect-windows-10-light-dark-mode-in-win32-application
If you want the "Choose your default app mode" setting, I'm pretty sure that I can find it in the Windows registry somewhere. (In fact, this looks like it: https://stackoverflow.com/questions/51334674/how-to-detect-windows-10-light-dark-mode-in-win32-application) I can try to make a PR for mrlib if this is the desired behavior. I don't have any older versions of Windows handy, so it will likely support Win10 only.
On my system (64 bit Windows 10, latest version), I verified the location of the registry key:
Computer\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\PersonalizeThis is a screenshot of the key when light theme is chosen. Notice the ApsUseLightTheme value set at 0x00000001 (1)
This is a screenshot of the key when dark theme is chosen. Notice the ApsUseLightTheme value now set at 0x00000000 (0)
Would this feature require Racket code to look for this specific registry key value, or would the code be written at a lower level?
I switched my Windows machine to Dark mode, and only some of the applications changed to Dark mode. In particular, most of the Windows tools, such as control panel property boxes remained to the default "light" mode.
I suspect the registry setting and the windows message about the mode change is more an "advisory" setting. Applications built on .Net technologies will use it because the .Net libraries use it, but the Win32 controls don't. As such, if DrRacket (and the Racket GUI library) would like to implement Dark mode, it would either have to change to use the .Net GUI libraries, or do their own drawing of controls such as buttons, and consult the registry to determine if dark mode is enabled or not.
Dark mode in the preferences of DrRacket may be the easy route to go ?
It looks like there has been some movement in the Windows API documentation related to dark mode. Here's an article from the end of 2022: Support Dark and Light themes in Win32 apps.
Currently the get-label-{background,foreground}-color functions are implemented using GetSysColor and the results do not seem to change when changing my Windows 10 VM into dark mode as described here.
The article above seems to suggest using UISettings.GetColorValue(UIColorType::Foreground) but I don't know how to make that call from our FFI. This seems to be the docs for UISettings.GetColorValue. Does anyone know how to call that function and get its value back into Racketdom?
Would that be helpful? Ref: https://learn.microsoft.com/en-us/answers/questions/715081/how-to-detect-windows-dark-mode
It depends on Windows versions On recent OS (>= Windows 10 1903) :
[DllImport("UXTheme.dll", SetLastError = true, EntryPoint = "#138")]
public static extern bool ShouldSystemUseDarkMode();
test :
bool bRet = ShouldSystemUseDarkMode();
Another uglier option: wrapping around PowerShell. I found this, but it doesn't work on my system. Maybe there's a way:
(New-Object Windows.UI.ViewManagement.UISettings).GetColorValue("background")
Ref: https://stackoverflow.com/questions/38734615/how-can-i-detect-windows-10-light-dark-mode
Also, according to this, Visual Styles have to be enabled for GetThemeSysColor to work.
Ref: https://stackoverflow.com/questions/63159666/get-windows-10-theme-color-in-classic-c-winapi-win32-application
Found the header file for the windows.ui.viewmanagement class for accessing UISettings, but for WinRT. Maybe these constants can help us with the FFI? Ref: https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/winrt/windows.ui.viewmanagement.h
Here's a hack that uses an undocumented dark mode API introduced in Windows 10 1809: https://github.com/ysc3839/win32-darkmode I wouldn't use it, but it's a start?
Another example in low(er) level C, using uxtheme.dll: https://github.com/ysc3839/VCMPBrowser/blob/darkmode/DarkMode.h
Cheers
I was reminded of this by a Discourse thread. I haven't thought about this in the last year, but I'll consolidate thoughts I had then into this issue.
In https://github.com/racket/gui/pull/293#issuecomment-1482080488 I wrote:
On Windows, the de facto way seems to be using
RegNotifyChangeKeyValueto detect changes to theAppsUseLightThemevalue ofHKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize(which may not exist).
In https://github.com/racket/gui/pull/293#issuecomment-1482100580 I wrote:
I've looked into windows (and there is an issue discussing it somewhere, I think) and the OS doesn't seem to provide a way to detect the theme.
That's my understanding, too, as far as detecting the theme. There's a Microsoft article recommending basically the same strategy
white-on-black-panel-scheme?uses, but using a Windows-specific API. The registry key I mentioned is undocumented, but seems to be used by a number of projects, like Chromium, to detect changes to the theme.
This issue has been mentioned on Racket Discourse. There might be relevant details there:
https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965/2

