Repository navigation
Ensure that ActualThemeVariant always has a proper value - #21930
Conversation
|
@zdpcdt emm again |
cf0b2f1 to
074e7aa
Compare
|
You can test this PR using the following package version. |
There was a problem hiding this comment.
Pull request overview
This PR reworks theme-variant propagation so ActualThemeVariant is always resolved to a concrete value (typically Light/Dark) at theme roots (Application/TopLevel/etc.), and stops using platform “workarounds” (like raising ColorValuesChanged from SetFrameThemeVariant) that caused performance regressions.
Changes:
- Centralizes
RequestedThemeVariant→ActualThemeVariantresolution inThemeVariant.UpdateActualThemeVariantusing a newIThemeVariantRootmarker for platform-root resolution vs. parent inheritance. - Updates multiple platform backends to cache/compare
PlatformColorValuesand avoid spuriousColorValuesChangednotifications (notably Win32), plus Android-specific changes for night mode/config change handling. - Adds unit-test infrastructure and new tests validating
ActualThemeVariantbehavior for Application/TopLevel/ThemeVariantScope.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Avalonia.UnitTests/UnitTestApplication.cs | Allows injecting IPlatformSettings into test app and initializes theme variant resolution. |
| tests/Avalonia.UnitTests/TestServices.cs | Adds PlatformSettings to test service plumbing and With(...) builder. |
| tests/Avalonia.UnitTests/TestPlatformSettings.cs | New test IPlatformSettings implementation with controllable PlatformColorValues. |
| tests/Avalonia.Controls.UnitTests/ThemeVariantTests.cs | New tests covering Application/TopLevel/ThemeVariantScope theme-variant resolution and inheritance. |
| src/Windows/Avalonia.Win32/WindowImpl.cs | Removes unconditional OnColorValuesChanged() call from SetFrameThemeVariant. |
| src/Windows/Avalonia.Win32/Win32PlatformSettings.cs | Caches color values and only raises ColorValuesChanged when values actually change. |
| src/iOS/Avalonia.iOS/PlatformSettings.cs | Caches uncached color values and only raises when changed on trait changes. |
| src/iOS/Avalonia.iOS/AvaloniaView.cs | Removes “null themeVariant triggers platform settings refresh” behavior. |
| src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs | Removes platform-settings refresh trigger when themeVariant is null. |
| src/Browser/Avalonia.Browser/BrowserPlatformSettings.cs | Adds caching + change detection for browser platform color values. |
| src/Avalonia.X11/X11Window.cs | Removes DBus “request default theme” trigger from SetFrameThemeVariant and drops unnecessary async void. |
| src/Avalonia.Wayland/WindowImplBase.cs | Removes DBus “request default theme” trigger from SetFrameThemeVariant and drops unnecessary async void. |
| src/Avalonia.Native/WindowImplBase.cs | Stops forcing platform-settings refresh when themeVariant is null; falls back to platform theme if needed. |
| src/Avalonia.Native/NativePlatformSettings.cs | Caches color values and only raises ColorValuesChanged when values actually change. |
| src/Avalonia.FreeDesktop/DBusPlatformSettings.cs | Refactors DBus settings into cached _colorValues + update-on-change approach. |
| src/Avalonia.Controls/TopLevel.cs | Makes TopLevel a theme-variant root when no application theme host exists; removes old platform binding workaround. |
| src/Avalonia.Controls/Application.cs | Implements theme-variant root behavior and centralizes initialization via InitializeThemeVariant(). |
| src/Avalonia.Base/Styling/ThemeVariant.cs | Adds centralized update logic + class handler to keep ActualThemeVariant consistent and platform-resolved at roots. |
| src/Avalonia.Base/Styling/IThemeVariantRoot.cs | New internal interface to identify objects that resolve Default from platform settings. |
| src/Avalonia.Base/StyledElement.cs | Removes duplicated Requested→Actual theme-variant handling (now centralized in ThemeVariant). |
| src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs | Uses local night mode instead of global DefaultNightMode; stores context. |
| src/Android/Avalonia.Android/Platform/AndroidPlatformSettings.cs | Refactors to cached _colorValues and adds configuration-change receiver to update values. |
| src/Android/Avalonia.Android/AvaloniaView.cs | Removes direct forwarding of config changes into AndroidPlatformSettings. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
You can test this PR using the following package version. |
…21930) * Correctly set ActualThemeVariant * Don't call OnColorValuesChanged unnecessarily on Win32 * Don't call OnColorValuesChanged unnecessarily on macOS * Change iOS PlatformSettings to match other platforms * Don't call OnColorValuesChanged unnecessarily on Android * Android: set theme using SetLocalNightMode * Don't call OnColorValuesChanged unnecessarily on X11/Wayland * Don't call OnColorValuesChanged unnecessarily on Browser * Fix timer Start order * Remove dead code in DBusPlatformSettings
What does the pull request do?
This PR ensures that
ActualThemeVariantalways has a proper value (typicallyLight/Dark).Currently, there are cases where
ActualThemeVariantgets set to null.It was actually implemented in #16340 but caused several other problems. First, the fact that
ActualThemeVariantcould have an invalid value prevented the theme from propagating correctly. This led to workarounds like have to raisePlatformSettings.ColorValuesChangedto properly propagate the theme, even though the system settings didn't really change. Which caused in turn performance issues such as #21897.Instead, this PR sets
ActualThemeVariantproperly again onApplication/TopLevel/ThemeVariantScopewhenever theRequestedThemeVariantor the system settings change.Doing so actually regressed #16340 on Android though, as a non-null
ThemeVariantis now again always passed toITopLevelImpl.SetFrameThemeVariant(), causing the app to force a default mode, preventing system changes from happening (as documented). Instead, a local night mode is now set, and a custom receiver listens to configuration changes.Unit tests have been added for non-platform code (verifying
ActualThemeVariant).Windows, macOS, Android, iOS, X11, Wayland and Browser have all been modified and re-tested.
Fixed issues
ColorValuesChangedis raised on every TopLevel construction since 12.1.0, causing UI stalls proportional to visual-tree size #21897