AutoDarkMode / Windows-Auto-Night-Mode

Automatically switches between the dark and light theme of Windows 10 and Windows 11
GNU General Public License v3.0
7.3k stars 260 forks source link

Usage of SecureUXTheme #567

Open namazso opened 1 year ago

namazso commented 1 year ago

Hey!

I see you're starting to use a SecureUXTheme fork for managing themes, but removed all the special parts (signaturte adder, signature bypass, etc..)

If that's all you need, I posted a gist better suited for that: https://gist.github.com/namazso/0fde102c2fc56049c7c37f7fdf9ac3cd

namazso commented 1 year ago

also feel free to consider this as my help in https://github.com/AutoDarkMode/Windows-Auto-Night-Mode/issues/103

Spiritreader commented 1 year ago

You are a wonderful person, thank you!!

In case you don't mind, you're a lot more knowledgeable than I am so I have a few questions.

I tried keeping an IThemeManager2 instance alive within ADM at first. (before I wrote a bridging executable) That way I discovered that the themes are internally tracked and not updated if there are any changes on disk. I only have a very basic understanding of this, so my assumptions could be wrong. But I believe either

a) this is due to creating ITheme instances that need to be released and retrieved again to update or b) the IThemeManager class itself has an active state of theme data in memory.

For case a) I figured that releasing memory for retrieved IThemes may allow a refresh. And for b) I thought that maybe freeing and re-initializing the IThemeManager2 may resolve the issue because it's forced to refresh its internal list of themes.

Have you had any experiences with how that might behave?

Also, there's an OpenTheme signature that you've mentioned in one of your replies in your repo. I might try this out now and see if maybe that works.


also feel free to consider this as my help in https://github.com/AutoDarkMode/Windows-Auto-Night-Mode/issues/103

You have been a huge help! This is an awesome step forward. It's a real shame that Microsoft has a new private api that fixes issues with theme switching on Win11. I was haivng more sucess with IThemeManager2, but it still fails occasionally to update UI elements properly.

namazso commented 1 year ago

a) this is due to creating ITheme instances that need to be released and retrieved again to update or

This is true, the class providing ITheme is actually called CThemeFile.

b) the IThemeManager class itself has an active state of theme data in memory.

This is also true; it stores the list of themes. call the Refresh() (or RefreshAsync(), upon completion the HWND will receive a 0x402 message) member.

It's a real shame that Microsoft has a new private api that fixes issues with theme switching on Win11.

I did not know about that existing. I'll look into this and maybe post the new api too.

Spiritreader commented 1 year ago

I did not know about that existing. I'll look into this and maybe post the new api too.

Well, I'm sorry I have to walk a bit back on my earlier statement. I think they have a new one. Theme switching on Win11 via ThemeManager2 is only reliable when changing the [Colors] section on Win11. When just toggling "AppsTheme" or "SystemTheme", the UI elements don't update correctly (~50-80% chance)

However, modifying the theme file without changing [Colors] and applying it via the settings CPL doesn't exhibit this behavior, so my guess is that something must be different

This is true, the class providing ITheme is actually called CThemeFile.

Great, thanks

This is also true; it stores the list of themes. call the Refresh() (or RefreshAsync(), upon completion the HWND will receive a 0x402 message) member.

Awesome, I will play around with this!

Update: I realized that since the C# wrapper requires STA the IThemeManager2 COM object seems to get disposed, so I have to re-intiailize ThemeManager2 after every call. I generally don't really know much about COM so I don't know if that approach causes memory leaks.

namazso commented 1 year ago

Well, I'm sorry I have to walk a bit back on my earlier statement. I think they have a new one. Theme switching on Win11 via ThemeManager2 is only reliable when changing the [Colors] section on Win11. When just toggling "AppsTheme" or "SystemTheme", the UI elements don't update correctly (~50-80% chance)

I see what you mean, just reproduced it:

image

Funny thing is this is without any sort of third party software, the old Personalization panel that only relies on IThemeManager2 also reproduces it (you can test it by going to shell:::{ED834ED6-4B5A-4bfe-8F11-A626DCB6A921} in explorer)

Spiritreader commented 1 year ago

Interesting that you mention the old personalization panel. I actually happened to test that a few days ago when trying to solve the issue. Didn't know it also used IThemeManager2.

Before switching to your IThemeManager2 implementation, we had IThemeManager (https://github.com/AutoDarkMode/Windows-Auto-Night-Mode/blob/master/AutoDarkModeSvc/Handlers/IThemeManager/Interfaces.cs) which uses another way of setting themes via path. Unsurprisingly though, it also fails. So maybe internally they're doing the same? It is different from OpenTheme in IThemeManager2 though. I tested that, and while it does work, it always ignored the silent flag and opens the new settings.

The Screenshot you posted has tabbed file explorer? Is that an insider build? We found out that theme switching there ist just always broken, even with the new settings, whereas it works fine in 22H2.

Funnily enough, the latest beta build of Auto Dark Mode now works better with insider than Microsofts own settings menu.

And the workaround is one of the dumbest things I've ever written https://github.com/AutoDarkMode/Windows-Auto-Night-Mode/blob/3e03e0ef29ca8adca9224fa16a7816082cdf4931/AutoDarkModeSvc/Handlers/ThemeFiles/ThemeFile.cs#L469

namazso commented 1 year ago

The Screenshot you posted has tabbed file explorer? Is that an insider build? We found out that theme switching there ist just always broken, even with the new settings, whereas it works fine in 22H2.

No, this is Win11 22H2

And the workaround is one do the dumbest things I've ever written

Interesting. themeui.dll actually decides whether to reapply theme based on a function that's meant to tell if the current theme matches the one to be set or not. Maybe there's a bug in Microsoft's code that causes misdetections? I'll try debugging it a bit.

Spiritreader commented 1 year ago

No, this is Win11 22H2

Oh interesting, didn't know tabbed file explorer is there / can be enabled yet. Given what I know from @Armin2208's insider build testing, It seemingly causes more issues than the non-tabbed version. At least on my two 22H2 test machines without tabbed explorer, the new settings menu works quite reliable when switching themes.

Maybe there's a bug in Microsoft's code that causes misdetections?

In versions prior to 22H2, SystemTheme and AppTheme could be toggled on/off with a registry key (found under Computer\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize), which worked fine. Now, changing the regkey for System bugs the taskbar, and for Apps it only applies when re-opening UI elements such as explorer. In addition, Accent color for window borders and titlebars could also be toggled with a regkey. (Computer\HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM) When modifying the regkey, from my testing, a full theme switch has to be performed for windows to update this now. But toggling it in the new settings menu is instant. So maybe something to do with DWM?

When switching themes, does themeui.dll also dynamically determine which UI elements need to be updated? AppsTheme and SystemTheme appear to need some sort of refresh now that wasn't the case before, so what you say sounds very plausible.

In any case, thanks for all your help in this again!

namazso commented 1 year ago

When switching themes, does themeui.dll also dynamically determine which UI elements need to be updated?

No, it does not as far as I'm aware. The function CThemeManager2::_ThemeMatchesCurrentState only returns whether a change is needed or not. For dark/light mode it determines this by comparing results of UxTheme!ShouldAppsUseDarkMode and UxTheme!ShouldSystemUseDarkMode to the values given in the theme file. I suspect that maybe these return old values or something.

Also, I just tried with the "normal" personalization, and it also broke:

image

image

Wonder if it's just a Windows bug in general

edit: now it even crashed the whole Settings app. High quality as always

Spiritreader commented 1 year ago

Also, I just tried with the "normal" personalization, and it also broke:

Ah Yes you are right, my bad. I just didn't do it often enough. If I switch around often enough between default Win11 light and dark modes it also breaks for me.

Wonder if it's just a Windows bug in general

In that case I think ADM currently has the best possible mitigation for this bug. Maybe the finding of having to update the [Colors] section is of use for UxSecurePatcher / people that create theme files in general as well.

Also, any idea what could be different with this method of swapping dark/light? image I also have trouble getting this to fail (at least for the tasbar and untabbed explorer). Is that related to UxTheme!ShouldAppsUseDarkMode and UxTheme!ShouldSystemUseDarkMode?

https://user-images.githubusercontent.com/18438899/196676796-55d7f5d5-1cbd-47eb-a48a-2c4dcd6f28bd.mp4

namazso commented 1 year ago

I'm not sure how but i managed to bug this one out too image

image

I'll try to investigate a bit more, it's probably fixable somehow

Spiritreader commented 1 year ago

I have made a new discovery. Double clicking a theme via the Windows Explorer seems to perform some sort of DWM update.

If the "Use accent color for titlebars and window color" option in the "Personalization -> Color" section is enabled and two themes have differing colorization colors

[VisualStyles]
Path=%SystemRoot%\resources\themes\Aero\Aero.msstyles
ColorStyle=NormalColor
Size=NormalSize
AutoColorization=0
ColorizationColor=0XC4FF8C00 <-- this setting right here
VisualStyleVersion=10
AppMode=Dark
SystemMode=Dark

it will update the DWM state. However, setting the theme in IThemeManager2 will not.

Maybe this is in part a reason why theme switching is more unreliable.

namazso commented 1 year ago

Interesting! I might take another look at what's going on on Windows 11, check what's exactly the chain of calls is. Just debugging is a pain because the only way to debug this is with kernel debugger, as your screen is obstructed by the big theme changing loading screen

Spiritreader commented 1 year ago

Interesting! I might take another look at what's going on on Windows 11, check what's exactly the chain of calls is. Just debugging is a pain because the only way to debug this is with kernel debugger, as your screen is obstructed by the big theme changing loading screen

With how flawless the API works I can only imagine how wonderful it is to do kernel debugging on that. I've since managed to get Windows to update DWM by means of changing the colorization color with IThemeManager2 and IThemeManager. It's a bit weird and also involves a fix similar to the explorer issue, buuut it works! Of course would be nice to know how Windows is doing it without juggling values in the theme file but for now I think it's resolvable with current means.

boromyr commented 1 year ago

+1 for using di SecureUXTheme

BinToss commented 1 year ago

I use a set of Win11 22H2 community themes (Win11Redux) patched via SecureUxTheme's ThemeTool. ADM's apply-theme behavior is different than ThemeTool's behavior. Namely, some text colors are not updated when ADM applies a theme. After an ADM theme switch (wherein a "Please Wait" screen is shown), applying the same theme via ThemeTool will again show the "Please Wait" screen and to a dark theme's light text color or a light theme's dark text color. themeSwitchComparison.webm

Spiritreader commented 1 year ago

I use a set of Win11 22H2 community themes (Win11Redux) patched via SecureUxTheme's ThemeTool. ADM's apply-theme behavior is different than ThemeTool's behavior. Namely, some text colors are not updated when ADM applies a theme. After an ADM theme switch (wherein a "Please Wait" screen is shown), applying the same theme via ThemeTool will again show the "Please Wait" screen and to a dark theme's light text color or a light theme's dark text color. themeSwitchComparison.webm

I am unsure if ADM is able to set patched themes properly at all. My guess is that it happens because there is no signature verification bypass in what we use. I assume that the theme gets applied, but not the rest of the visual styles.

@namazso can maybe tell you more about whether patched themes work with the originally provided gist.

BinToss commented 1 year ago

In the meantime, I'll write an ADM script to call ThemeTool to set patched themes. It will require some manual set up because the SecureUxTheme Scoop package doesn't create a shim for ThemeTool and because the user will need to specify the filenames of their dark and light themes.