Skip to content

Commit f1ea619

Browse files
committed
feat(WPF): Observe system theme during runtime
1 parent 287f978 commit f1ea619

File tree

3 files changed

+71
-2
lines changed

3 files changed

+71
-2
lines changed
Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,75 @@
11
using System;
2+
using Microsoft.Win32;
3+
using Uno.Helpers.Theming;
4+
using Uno.UI.Runtime.Skia.Wpf.WPF.Extensions.Helper.Theming;
25
using Uno.UI.Xaml;
36
using Windows.UI.Xaml;
47

58
namespace Uno.UI.Runtime.Skia.Wpf
69
{
7-
public class WpfApplicationExtension : IApplicationExtension
10+
public class WpfApplicationExtension : IApplicationExtension, IDisposable
811
{
912
private readonly Application _owner;
13+
private WpfSystemThemeHelperExtension _themeHelper;
14+
private SystemTheme _currentTheme;
15+
16+
private bool _disposedValue;
1017

1118
public WpfApplicationExtension(Application owner)
1219
{
1320
_owner = owner ?? throw new ArgumentNullException(nameof(owner));
21+
22+
_themeHelper = new WpfSystemThemeHelperExtension(null);
23+
_currentTheme = _themeHelper.GetSystemTheme();
24+
25+
SystemEvents.UserPreferenceChanged += SystemEvents_UserPreferenceChanged;
1426
}
1527

1628
public bool CanExit => true;
1729

1830
public void Exit() => System.Windows.Application.Current.Shutdown();
31+
32+
public event EventHandler SystemThemeChanged;
33+
34+
private void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
35+
{
36+
// This event is raised when the theme is changed,
37+
// but also for various other irrelevant reasons.
38+
// Check the registry first, before forcing the application
39+
// to refresh everything.
40+
var newTheme = _themeHelper.GetSystemTheme();
41+
42+
if (newTheme != _currentTheme)
43+
{
44+
_currentTheme = newTheme;
45+
SystemThemeChanged?.Invoke(this, EventArgs.Empty);
46+
}
47+
}
48+
49+
#region IDisposable
50+
protected virtual void Dispose(bool disposing)
51+
{
52+
if (!_disposedValue)
53+
{
54+
// According to Microsoft, https://docs.microsoft.com/en-us/dotnet/api/microsoft.win32.systemevents.userpreferencechanged,
55+
// this event must be manully unhooked when the application is disposed.
56+
SystemEvents.UserPreferenceChanged -= SystemEvents_UserPreferenceChanged;
57+
_disposedValue = true;
58+
}
59+
}
60+
61+
~WpfApplicationExtension()
62+
{
63+
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
64+
Dispose(disposing: false);
65+
}
66+
67+
public void Dispose()
68+
{
69+
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
70+
Dispose(disposing: true);
71+
GC.SuppressFinalize(this);
72+
}
73+
#endregion
1974
}
2075
}

src/Uno.UI/UI/Xaml/Application.skia.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,21 @@ private void Initialize()
7878
// Force init
7979
Window.Current.ToString();
8080

81+
InitializationCompleted();
82+
8183
OnLaunched(new LaunchActivatedEventArgs(ActivationKind.Launch, string.Join(";", _args)));
8284
}
8385
}
8486

8587
internal void ForceSetRequestedTheme(ApplicationTheme theme) => _requestedTheme = theme;
88+
89+
partial void ObserveSystemThemeChanges()
90+
{
91+
_applicationExtension.SystemThemeChanged += SystemThemeChanged;
92+
_systemThemeChangesObserved = true;
93+
}
94+
95+
private void SystemThemeChanged(object sender, EventArgs e) => OnSystemThemeChanged();
8696
}
8797

8898
internal interface IApplicationEvents
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
namespace Uno.UI.Xaml
1+
using System;
2+
3+
namespace Uno.UI.Xaml
24
{
35
internal interface IApplicationExtension
46
{
57
bool CanExit { get; }
68

79
void Exit();
10+
11+
event EventHandler SystemThemeChanged;
812
}
913
}

0 commit comments

Comments
 (0)