Skip to content

Commit 2b03dad

Browse files
Fix UseHighContrast to use UISettings.ColorValuesChanged instead of broken API
AccessibilitySettings.HighContrastChanged always throws COMException 0x80070490 (ERROR_NOT_FOUND) in WinUI 3 desktop apps because it requires a CoreWindow that doesn't exist in the HWND-based window model. Replace with UISettings.ColorValuesChanged which fires reliably for high-contrast toggles and palette changes. This is the same approach ReactorHost.OnColorValuesChanged already uses for charting state. Also: - Remove redundant HighContrastChanged subscription from ReactorHost (OnColorValuesChanged already re-reads high contrast state) - Delete RenderContextUserCallbackEtwBridgeTests (test removed swallowing behavior) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 7eccb9c commit 2b03dad

3 files changed

Lines changed: 21 additions & 150 deletions

File tree

src/Reactor/Core/RenderContext.cs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -800,30 +800,39 @@ private HighContrastState UseHighContrastState()
800800
{
801801
var (state, _) = UseState(new HighContrastState());
802802

803-
// Subscribe once to HighContrastChanged and re-render when it fires.
803+
// AccessibilitySettings.HighContrastChanged throws ERROR_NOT_FOUND
804+
// (0x80070490) in WinUI 3 desktop apps because it requires a CoreWindow.
805+
// Instead, use UISettings.ColorValuesChanged which fires reliably for
806+
// system theme changes including high contrast toggles.
804807
UseEffect(() =>
805808
{
806-
state.Settings ??= new global::Windows.UI.ViewManagement.AccessibilitySettings();
809+
state.A11ySettings ??= new global::Windows.UI.ViewManagement.AccessibilitySettings();
810+
state.UiSettings ??= new global::Windows.UI.ViewManagement.UISettings();
807811
var rerender = _requestRerender;
808-
void OnChanged(global::Windows.UI.ViewManagement.AccessibilitySettings sender, object args)
812+
813+
void OnColorValuesChanged(global::Windows.UI.ViewManagement.UISettings sender, object args)
809814
{
810-
state.IsHighContrast = sender.HighContrast;
811-
state.HighContrastScheme = sender.HighContrast ? sender.HighContrastScheme : null;
815+
var a11y = state.A11ySettings;
816+
state.IsHighContrast = a11y.HighContrast;
817+
state.HighContrastScheme = a11y.HighContrast ? a11y.HighContrastScheme : null;
812818
rerender?.Invoke();
813819
}
814-
state.Settings.HighContrastChanged += OnChanged;
820+
821+
state.UiSettings.ColorValuesChanged += OnColorValuesChanged;
822+
815823
// Sync initial value
816-
state.IsHighContrast = state.Settings.HighContrast;
817-
state.HighContrastScheme = state.Settings.HighContrast ? state.Settings.HighContrastScheme : null;
818-
return () => state.Settings.HighContrastChanged -= OnChanged;
824+
state.IsHighContrast = state.A11ySettings.HighContrast;
825+
state.HighContrastScheme = state.A11ySettings.HighContrast ? state.A11ySettings.HighContrastScheme : null;
826+
return () => state.UiSettings.ColorValuesChanged -= OnColorValuesChanged;
819827
});
820828

821829
return state;
822830
}
823831

824832
private sealed class HighContrastState
825833
{
826-
public global::Windows.UI.ViewManagement.AccessibilitySettings? Settings;
834+
public global::Windows.UI.ViewManagement.AccessibilitySettings? A11ySettings;
835+
public global::Windows.UI.ViewManagement.UISettings? UiSettings;
827836
public bool IsHighContrast;
828837
public string? HighContrastScheme;
829838
}

src/Reactor/Hosting/ReactorHost.cs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -407,14 +407,15 @@ private void InitChartingState()
407407
_isForcedColors = _accessibilitySettings.HighContrast;
408408
if (_isForcedColors)
409409
_forcedColorsTheme = Charting.ForcedColorsTheme.FromSystem();
410-
_accessibilitySettings.HighContrastChanged += OnHighContrastChanged;
411410
}
412411
catch { /* headless / unit-test host — no accessibility settings */ }
413412

414413
try
415414
{
416415
_uiSettings = new global::Windows.UI.ViewManagement.UISettings();
417416
_isReducedMotion = !_uiSettings.AnimationsEnabled;
417+
// ColorValuesChanged fires for high-contrast toggles, palette
418+
// changes, and AnimationsEnabled changes — covers all charting signals.
418419
_uiSettings.ColorValuesChanged += OnColorValuesChanged;
419420
}
420421
catch { /* headless / unit-test host — no UI settings */ }
@@ -859,15 +860,6 @@ private void OnActualThemeChanged(FrameworkElement sender, object args)
859860
RequestRender();
860861
}
861862

862-
private void OnHighContrastChanged(
863-
global::Windows.UI.ViewManagement.AccessibilitySettings sender, object args)
864-
{
865-
_isForcedColors = sender.HighContrast;
866-
_forcedColorsTheme = _isForcedColors ? Charting.ForcedColorsTheme.FromSystem() : null;
867-
_logger?.LogDebug("High-contrast changed to {IsHighContrast} — re-rendering", _isForcedColors);
868-
RequestRender();
869-
}
870-
871863
private void OnColorValuesChanged(
872864
global::Windows.UI.ViewManagement.UISettings sender, object args)
873865
{
@@ -929,8 +921,6 @@ public void Dispose()
929921
});
930922

931923
// Accessibility listener cleanup
932-
if (_accessibilitySettings is not null)
933-
_accessibilitySettings.HighContrastChanged -= OnHighContrastChanged;
934924
if (_uiSettings is not null)
935925
_uiSettings.ColorValuesChanged -= OnColorValuesChanged;
936926

tests/Reactor.Tests/Diagnostics/RenderContextUserCallbackEtwBridgeTests.cs

Lines changed: 0 additions & 128 deletions
This file was deleted.

0 commit comments

Comments
 (0)