Skip to content

Conversation

@Koichi-Kobayashi
Copy link
Contributor

@Koichi-Kobayashi Koichi-Kobayashi commented Dec 14, 2025

Pull request type

  • Update
  • Bugfix
  • Feature
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • Documentation content changes

What is the current behavior?

  1. Have a program with changed theme and/or accent color running
  2. Lock Windows via Win + L
  3. Wait a minute (or until the screen turns black)
  4. Log in again
  5. Theme and Accent color gets reset to default values

Issue Number: #1467 #1267

What is the new behavior?

The code from the initial pull request is no longer needed, so I reverted it.

WM_DWMCOLORIZATIONCOLORCHANGED
Meaning: Sent when the DWM (Desktop Window Manager) color settings change
Timing: When Windows accent colors or DWM color settings change
Purpose: Detect accent color changes

WM_THEMECHANGED
Meaning: Sent when the theme changes
Timing: When switching between light/dark mode or changing the Windows theme
Purpose: Detect theme changes

WM_SYSCOLORCHANGE
Meaning: Sent when system colors change
Timing: When system colors (window background, text, etc.) change
Purpose: Detect system color changes

Other information

Before locking
image

After unlocking
2025-12-14_17h01_22

- Add session switch event handling to restore theme and accent color after unlock
- Store current theme and accent color before session lock
- Ignore WM_WININICHANGE messages during unlock restore period (5 seconds)
- Preserve stored theme when it differs from system theme
- Optimize code by removing unnecessary operations and using switch expressions
- Remove debug output statements
@apachezy
Copy link
Contributor

Hi @Koichi-Kobayashi

Thanks for the detailed PR! I've reviewed the changes and have some thoughts on the approach.

1. Current behavior might be intentional
When developers call SystemThemeWatcher.Watch(), they're explicitly opting into system theme synchronization. The theme reset on unlock is actually the expected behavior - if an app doesn't want to follow system theme, they shouldn't call Watch(). The issues #1467 and #1267 might be cases where developers didn't realize this.

2. Flexibility concern
The current design allows apps to implement their own theme strategies (like having "Light"/"Dark"/"Follow System" options). Automatically overriding this could reduce that flexibility.

3. Simpler alternative if needed
If we do decide to "fix" this, a lighter approach might be:

  • Listen for WM_WTSSESSION_CHANGE/SystemEvents.SessionSwitch
  • Temporarily pause theme sync during lock, resume after unlock
  • Much simpler than storing/restoring colors and ignoring WM_WININICHANGE

Question:
Are we sure this is a bug rather than expected behavior when using Watch()? Maybe we should clarify this in documentation instead of changing the behavior?

Just my thoughts - what do you think about this approach?

@Devin-goBILDA
Copy link

Hi @Koichi-Kobayashi

Thanks for the detailed PR! I've reviewed the changes and have some thoughts on the approach.

1. Current behavior might be intentional

When developers call SystemThemeWatcher.Watch(), they're explicitly opting into system theme synchronization. The theme reset on unlock is actually the expected behavior - if an app doesn't want to follow system theme, they shouldn't call Watch(). The issues #1467 and #1267 might be cases where developers didn't realize this.

2. Flexibility concern

The current design allows apps to implement their own theme strategies (like having "Light"/"Dark"/"Follow System" options). Automatically overriding this could reduce that flexibility.

3. Simpler alternative if needed

If we do decide to "fix" this, a lighter approach might be:

  • Listen for WM_WTSSESSION_CHANGE/SystemEvents.SessionSwitch

  • Temporarily pause theme sync during lock, resume after unlock

  • Much simpler than storing/restoring colors and ignoring WM_WININICHANGE

Question:

Are we sure this is a bug rather than expected behavior when using Watch()? Maybe we should clarify this in documentation instead of changing the behavior?

Just my thoughts - what do you think about this approach?

I was one of the original people that complained about this issue. I do believe that this is an actual issue instead of expected behavior. When I manually select dark mode (not follow system theme) there would be times when the application would randomly change back to white after the computer was idling for a while or even when accidentally activating the voice access when trying to take a screenshot (CTRL + Win + S). Idk, but to me there is no way on earth that that is an expected/desired behavior.

@apachezy
Copy link
Contributor

Hi @[username], after careful consideration, I believe we should address the root cause rather than applying temporary fixes that may obscure the underlying issue.

The Core Problem:
SystemThemeWatcher currently listens to WM_WININICHANGE—a message that fires for almost any system setting change, including unrelated events like screensaver updates (as mentioned in #1267). This over-broad listening approach leads to unnecessary triggers and the "false reset" behavior you observed.

A More Targeted Approach (for your consideration):
Since UpdateObservedWindow() only calls:

  • ApplicationThemeManager.ApplySystemTheme
  • WindowBackgroundManager.UpdateBackground

...which handle application theme colors and main window background, we might only need to listen to three specific messages instead:

  1. WM_THEMECHANGED – for system theme changes
  2. WM_DWMCOLORIZATIONCOLORCHANGED – for accent/colorization changes
  3. WM_SYSCOLORCHANGE – for legacy system color changes (fallback)

Potential benefits:

  • Reduces false triggers from unrelated system changes
  • Less unnecessary re-renders and logic execution
  • More precise control over what we're actually watching

These are just my thoughts for your reference—hopefully they can provide some useful insight for your work on this PR.

@apachezy
Copy link
Contributor

Hi @Devin-goBILDA , I took some time drafting a new response and didn't notice your message earlier—my apologies.

Regarding the issue you mentioned where the application randomly switches theme colors when Ctrl + Win + S activates voice control, have you tried disabling the theme watcher by commenting out any calls to Appearance.SystemThemeWatcher.Watch()?

@apachezy
Copy link
Contributor

@Koichi-Kobayashi,

My apologies—I’m not very familiar with PR communication workflows, so I used AI to help translate and polish my message, and I forgot to update the placeholder "@[username]".

Yes, I have just reproduced the issue described by @Devin-goBILDA where pressing Ctrl + Win + S (activating voice control) causes the application theme to reset. The approach I mentioned in my second reply does avoid this problem:

if (msg == (int)PInvoke.WM_DWMCOLORIZATIONCOLORCHANGED ||
    msg == (int)PInvoke.WM_THEMECHANGED ||
    msg == (int)PInvoke.WM_SYSCOLORCHANGE)
//if (msg == (int)PInvoke.WM_WININICHANGE)
{
    UpdateObservedWindow(hWnd);
}

@apachezy
Copy link
Contributor

@Koichi-Kobayashi

If you are able to reproduce the lock screen → black screen → login → theme reset issue, could you please try whether the approach I suggested resolves it? I haven't been able to reproduce this problem under any test conditions on my end…

@Koichi-Kobayashi
Copy link
Contributor Author

@apachezy
It's 11 PM on Sunday in Japan, so please allow me a little time.

@Koichi-Kobayashi
Copy link
Contributor Author

@apachezy
That's amazing! It fixed itself just like that!
Dark mode remained active both when unlocking the device and when pressing Ctrl + Win + S (activating voice control).
It also remained active even after changing the mode in System Settings.
I apologize for submitting an incorrect pull request.

@Koichi-Kobayashi
Copy link
Contributor Author

@apachezy
Thank you for your proposal.

@apachezy
Copy link
Contributor

@Koichi-Kobayashi 👍nice!

@apachezy
Copy link
Contributor

@Koichi-Kobayashi

Could you please update the PR description to include:

- Fixed #1467
- Fixed #1267

These issues will be automatically closed when the PR is merged.👌

Copy link
Collaborator

@Nuklon Nuklon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is OK to merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dotnet PR Pull request release themes Topic is related to managing themes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Color theme and accent color gets reset after logging in Dark Theme Flickering To Light Theme Randomly

4 participants