Skip to content

Commit

Permalink
Add ThemeWatcher
Browse files Browse the repository at this point in the history
  • Loading branch information
AlpyneDreams committed Sep 6, 2023
1 parent 33b2661 commit 16dc4df
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 17 deletions.
33 changes: 16 additions & 17 deletions skiffWindowsApp/Skiff Desktop/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using System.Net.Http.Headers;
using System.Runtime.InteropServices;
using System.Windows.Interop;
using Skiff_Desktop.Utilities;

namespace Skiff_Desktop
{
Expand All @@ -34,23 +35,19 @@ public partial class MainWindow : Window

#region Dark Theme

private ThemeWatcher _themeWatcher;

[DllImport("dwmapi.dll", PreserveSig = true)]
static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
const int DWMWA_CAPTION_COLOR = 35;

[DllImport("UXTheme.dll", SetLastError = true, EntryPoint = "#138")]
static extern bool ShouldSystemUseDarkMode();

private void SetDarkMode(bool darkMode)
{
var value = darkMode;

WindowInteropHelper hwnd = new WindowInteropHelper(this);

if (hwnd.Handle == IntPtr.Zero)
return;

// Sidebar color
// Match sidebar color
int color = darkMode ? 0x1A1A1A : 0xF5F5F5;
try
{
Expand All @@ -70,16 +67,7 @@ public void SetTheme(string? theme)
{
bool darkMode = false;
if (theme == null || theme.Contains("system"))
{
try
{
darkMode = ShouldSystemUseDarkMode();
}
catch (EntryPointNotFoundException)
{
// Not supported (old Windows version?)
}
}
darkMode = _themeWatcher.GetCurrentTheme() == ThemeMode.Dark;
else
darkMode = (theme.Contains("dark"));

Expand Down Expand Up @@ -205,6 +193,17 @@ private async Task InitializeBrowser()
WebView2.CoreWebView2.Settings.IsGeneralAutofillEnabled = true;
WebView2.CoreWebView2.Settings.IsStatusBarEnabled = false;

// Watch for system theme changes
_themeWatcher = new ThemeWatcher();
_themeWatcher.ThemeChanged += (sender, theme) => Dispatcher.Invoke(() =>
{
// Update WebView default theme
WebView2.CoreWebView2.Profile.PreferredColorScheme =
(theme == ThemeMode.Dark) ? CoreWebView2PreferredColorScheme.Dark : CoreWebView2PreferredColorScheme.Light;

});
_themeWatcher.Start();

// this is needed to allow the webview to communicate with the app
// right now, only for sending notifications
WebView2.CoreWebView2.WebMessageReceived += _messageProcessor.CoreWebView2_WebMessageReceived;
Expand Down
1 change: 1 addition & 0 deletions skiffWindowsApp/Skiff Desktop/Skiff Desktop.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1988-prerelease" />
<PackageReference Include="System.Management" Version="7.0.2" />
<PackageReference Include="ToastNotifications" Version="2.5.1" />
<PackageReference Include="ToastNotifications.Messages" Version="2.5.1" />
</ItemGroup>
Expand Down
88 changes: 88 additions & 0 deletions skiffWindowsApp/Skiff Desktop/Utilities/ThemeWatcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.Globalization;
using System.Management;
using System.Security.Principal;

namespace Skiff_Desktop.Utilities
{
public enum ThemeMode
{
Light = 0,
Dark = 1,
}

public class ThemeWatcher
{
public ThemeMode Theme
{
get => _theme;
private set {
_theme = value;
ThemeChanged?.Invoke(this, value);
}
}
public event EventHandler<ThemeMode>? ThemeChanged;

private const string RegistryPath = @"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize";
private const string RegistryValueName = "AppsUseLightTheme";
private ManagementEventWatcher? watcher;
private ThemeMode _theme;

public void Start()
{
var currentUser = WindowsIdentity.GetCurrent();

// Based on https://stackoverflow.com/a/69604613
string query = string.Format(
CultureInfo.InvariantCulture,
@"SELECT * FROM RegistryValueChangeEvent WHERE Hive = 'HKEY_USERS' AND KeyPath = '{0}\\{1}' AND ValueName = '{2}'",
currentUser.User?.Value,
RegistryPath.Replace(@"\", @"\\"),
RegistryValueName);

try
{
Theme = GetCurrentTheme();

// Listen for events
watcher = new ManagementEventWatcher(query);
watcher.EventArrived += (sender, e) =>
{
Theme = GetCurrentTheme();
Debug.WriteLine("System theme changed: " + Theme);
};
watcher.Start();
}
catch (Exception)
{
// This can fail on Windows 7
Theme = ThemeMode.Light;
}
}

public ThemeMode GetCurrentTheme()
{
ThemeMode theme = ThemeMode.Light;

try
{
using (RegistryKey? key = Registry.CurrentUser?.OpenSubKey(RegistryPath))
{
object? value = key?.GetValue(RegistryValueName);
if (value == null)
return ThemeMode.Light;

theme = (int)value > 0 ? ThemeMode.Light : ThemeMode.Dark;
}

return theme;
}
catch (Exception)
{
return theme;
}
}
}
}

0 comments on commit 16dc4df

Please sign in to comment.