fix: make the OS title bar follow the active theme - #1718
Merged
Conversation
Closes #1622. ApplyDarkTitleBar passed a hardcoded `int value = 1` to DWMWA_USE_IMMERSIVE_DARK_MODE and ran exactly once from OnSourceInitialized, with no second call site and no theme subscription. So the title bar stayed dark for the life of the process: on any of the six light presets the app was a near-white window wearing a black strip — the one piece of chrome the user could not theme, and the last surface still pinned to dark after every brush, chart paint and control template had been migrated to invert per preset. Renamed to ApplyTitleBarTheme(hwnd, dark) passing `dark ? 1 : 0` (0 is the documented default), called with ThemeService.Instance.CurrentTheme.IsDark, and subscribed to ThemeChanged so a switch re-applies immediately instead of waiting for a restart. Unsubscribed in OnClosed: ThemeService is a singleton that outlives the window, so a surviving handler would keep this instance alive and fire against a dead handle. Verified the signal the fix depends on rather than trusting it: IsDark classifies all 12 presets correctly against the same `R+G+B < 384` threshold the record applies to custom themes, and it is 6 dark / 6 light — so the old hardcoded 1 was giving six presets the wrong title bar. Pinned as a theory over every preset plus a guard that both kinds ship, because if every preset were dark that theory would be silently vacuous. The DwmSetWindowAttribute call itself needs a real window, so the on-screen result is deferred to the secondary workstation; what is checkable here is the decision feeding it, which the tests cover. Return value stays discarded — the attribute is unsupported before Windows 10 1809 and failing to tint a title bar must never take the window down. All four projects rebuild with 0 warnings.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1622.
The problem
ApplyDarkTitleBarpassed a hardcodedint value = 1toDWMWA_USE_IMMERSIVE_DARK_MODEand ran exactly once fromOnSourceInitialized— no second call site, no theme subscription. So the title bar stayed dark for the life of the process.On any of the six light presets the app was a near-white window wearing a black strip: the one piece of chrome the user could not theme away, and the last surface still pinned to dark after every brush, chart paint and control template had already been migrated to invert per preset.
The fix
ApplyTitleBarTheme(hwnd, dark)passingdark ? 1 : 0(0 is the documented default), called withThemeService.Instance.CurrentTheme.IsDark, plus aThemeChangedsubscription so a switch re-applies immediately rather than waiting for a restart.Unsubscribed in
OnClosed:ThemeServiceis a singleton that outlives the window, so a surviving handler would keep this instance alive and fire against a dead handle.Verification
I checked the signal the fix depends on rather than trusting it.
IsDarkclassifies all 12 presets correctly against the sameR+G+B < 384threshold the record applies to custom themes — and the split is 6 dark / 6 light, so the old hardcoded1was giving six presets the wrong title bar:15/15 on that harness. Pinned in the suite as a theory over every preset, plus a guard that both dark and light presets ship — if every preset were dark the theory would be silently vacuous and pass while testing nothing.
All four projects rebuild
--no-incrementalwith 0 errors, 0 warnings.Scope
DwmSetWindowAttributeneeds a real window, so the on-screen result is deferred to the secondary workstation — what's checkable here is the decision feeding it. The return value stays discarded: the attribute is unsupported before Windows 10 1809, and failing to tint a title bar must never take the window down.MainWindowis the onlyWindowin the project, so this is the only affected frame.