Skip to content

fix: make the OS title bar follow the active theme - #1718

Merged
laurentiu021 merged 1 commit into
mainfrom
fix/title-bar-follows-theme
Aug 6, 2026
Merged

fix: make the OS title bar follow the active theme#1718
laurentiu021 merged 1 commit into
mainfrom
fix/title-bar-follows-theme

Conversation

@laurentiu021

Copy link
Copy Markdown
Owner

Closes #1622.

The problem

ApplyDarkTitleBar passed a hardcoded int value = 1 to DWMWA_USE_IMMERSIVE_DARK_MODE and ran exactly once from OnSourceInitialized — 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) passing dark ? 1 : 0 (0 is the documented default), called with ThemeService.Instance.CurrentTheme.IsDark, plus a ThemeChanged subscription so a switch re-applies immediately rather than 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.

Verification

I checked 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 the split is 6 dark / 6 light, so the old hardcoded 1 was giving six presets the wrong title bar:

deep-ocean       bg=#050D1A sum= 44  IsDark=True  -> DWM 1
lavender         bg=#FAF5FF sum=750  IsDark=False -> DWM 0
midnight-indigo  bg=#070A0F sum= 32  IsDark=True  -> DWM 1
mint-fresh       bg=#F0FDF4 sum=737  IsDark=False -> DWM 0
neon-rose        bg=#120508 sum= 31  IsDark=True  -> DWM 1
sky-breeze       bg=#F8FAFC sum=750  IsDark=False -> DWM 0
soft-blossom     bg=#FDF2F8 sum=743  IsDark=False -> DWM 0
violet-night     bg=#0A0515 sum= 36  IsDark=True  -> DWM 1
warm-ember       bg=#0F0A04 sum= 29  IsDark=True  -> DWM 1
warm-sand        bg=#FFFBEB sum=741  IsDark=False -> DWM 0

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-incremental with 0 errors, 0 warnings.

Scope

DwmSetWindowAttribute needs 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.

MainWindow is the only Window in the project, so this is the only affected frame.

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.
@laurentiu021
laurentiu021 merged commit 28e327e into main Aug 6, 2026
5 of 6 checks passed
@laurentiu021
laurentiu021 deleted the fix/title-bar-follows-theme branch August 6, 2026 15:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Shell - Window title bar is forced dark forever

1 participant