diff --git a/src/modules/PowerOCR/PowerOCR/OCROverlay.xaml.cs b/src/modules/PowerOCR/PowerOCR/OCROverlay.xaml.cs index cf516f9959..1c7f266169 100644 --- a/src/modules/PowerOCR/PowerOCR/OCROverlay.xaml.cs +++ b/src/modules/PowerOCR/PowerOCR/OCROverlay.xaml.cs @@ -50,15 +50,7 @@ public partial class OCROverlay : Window InitializeComponent(); - // workaround for #30177 - try - { - Wpf.Ui.Appearance.SystemThemeWatcher.Watch(this, Wpf.Ui.Controls.WindowBackdropType.None); - } - catch (Exception ex) - { - Logger.LogError($"Exception in SystemThemeWatcher.Watch, issue 30177. {ex.Message}"); - } + Wpf.Ui.Appearance.SystemThemeWatcher.Watch(this, Wpf.Ui.Controls.WindowBackdropType.None); PopulateLanguageMenu(); } diff --git a/src/modules/imageresizer/ui/Views/MainWindow.xaml.cs b/src/modules/imageresizer/ui/Views/MainWindow.xaml.cs index d9d75abb11..4389558a7d 100644 --- a/src/modules/imageresizer/ui/Views/MainWindow.xaml.cs +++ b/src/modules/imageresizer/ui/Views/MainWindow.xaml.cs @@ -7,7 +7,6 @@ using System.Collections.Generic; using System.Linq; using Common.UI; using ImageResizer.ViewModels; -using ManagedCommon; using Microsoft.Win32; using Wpf.Ui.Controls; using AppResources = ImageResizer.Properties.Resources; @@ -31,15 +30,7 @@ namespace ImageResizer.Views WindowBackdropType = WindowBackdropType.None; } - // workaround for #30177 - try - { - Wpf.Ui.Appearance.SystemThemeWatcher.Watch(this, WindowBackdropType); - } - catch (Exception ex) - { - Logger.LogError($"Exception in SystemThemeWatcher.Watch, issue 30177. {ex.Message}"); - } + Wpf.Ui.Appearance.SystemThemeWatcher.Watch(this, WindowBackdropType); } public IEnumerable OpenPictureFiles() diff --git a/src/modules/launcher/PowerLauncher/App.xaml b/src/modules/launcher/PowerLauncher/App.xaml index efbf8c7053..92a135daa3 100644 --- a/src/modules/launcher/PowerLauncher/App.xaml +++ b/src/modules/launcher/PowerLauncher/App.xaml @@ -2,13 +2,11 @@ x:Class="PowerLauncher.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:theming="clr-namespace:Common.UI;assembly=PowerToys.Common.UI" xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml" ShutdownMode="OnMainWindowClose" Startup="OnStartup"> - diff --git a/src/modules/launcher/PowerLauncher/App.xaml.cs b/src/modules/launcher/PowerLauncher/App.xaml.cs index 9c917ba7d4..04c395d40d 100644 --- a/src/modules/launcher/PowerLauncher/App.xaml.cs +++ b/src/modules/launcher/PowerLauncher/App.xaml.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation +// Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. @@ -9,7 +9,6 @@ using System.Linq; using System.Text; using System.Threading; using System.Windows; -using Common.UI; using interop; using ManagedCommon; using Microsoft.PowerLauncher.Telemetry; @@ -23,7 +22,6 @@ using Wox.Infrastructure.Image; using Wox.Infrastructure.UserSettings; using Wox.Plugin; using Wox.Plugin.Logger; -using Wpf.Ui.Appearance; using Stopwatch = Wox.Infrastructure.Stopwatch; namespace PowerLauncher @@ -82,7 +80,7 @@ namespace PowerLauncher { application.InitializeComponent(); - NativeEventWaiter.WaitForEventLoop( + Common.UI.NativeEventWaiter.WaitForEventLoop( Constants.RunExitEvent(), () => { @@ -122,8 +120,7 @@ namespace PowerLauncher RegisterAppDomainExceptions(); RegisterDispatcherUnhandledException(); - _themeManager = new ThemeManager(this); - ImageLoader.Initialize(_themeManager.GetCurrentTheme()); + ImageLoader.Initialize(); _settingsVM = new SettingWindowViewModel(); _settings = _settingsVM.Settings; @@ -136,6 +133,7 @@ namespace PowerLauncher _mainVM = new MainViewModel(_settings, NativeThreadCTS.Token); _mainWindow = new MainWindow(_settings, _mainVM, NativeThreadCTS.Token); + _themeManager = new ThemeManager(_settings, _mainWindow); API = new PublicAPIInstance(_settingsVM, _mainVM, _alphabet, _themeManager); _settingsReader = new SettingsReader(_settings, _themeManager); _settingsReader.ReadSettings(); @@ -152,10 +150,6 @@ namespace PowerLauncher _settingsReader.ReadSettingsOnChange(); - _themeManager.ThemeChanged += OnThemeChanged; - - OnThemeChanged(_settings.Theme, _settings.Theme); - textToLog.AppendLine("End PowerToys Run startup ---------------------------------------------------- "); bootTime.Stop(); @@ -214,48 +208,6 @@ namespace PowerLauncher }; } - /// - /// Callback when windows theme is changed. - /// - /// Previous Theme - /// Current Theme - private void OnThemeChanged(Theme oldTheme, Theme newTheme) - { - // If OS theme is high contrast, don't change theme. - if (SystemParameters.HighContrast) - { - return; - } - - ApplicationTheme theme = ApplicationTheme.Unknown; - - switch (newTheme) - { - case Theme.Dark: - theme = ApplicationTheme.Dark; break; - case Theme.Light: - theme = ApplicationTheme.Light; break; - case Theme.HighContrastWhite: - case Theme.HighContrastBlack: - case Theme.HighContrastOne: - case Theme.HighContrastTwo: - theme = ApplicationTheme.HighContrast; break; - default: - break; - } - - _mainWindow?.Dispatcher.Invoke(() => - { - if (theme != ApplicationTheme.Unknown) - { - ApplicationThemeManager.Apply(theme); - } - }); - - ImageLoader.UpdateIconPath(newTheme); - _mainVM.Query(); - } - /// /// let exception throw as normal is better for Debug /// @@ -302,19 +254,12 @@ namespace PowerLauncher Log.Info("Start PowerToys Run Exit---------------------------------------------------- ", GetType()); if (disposing) { - if (_themeManager != null) - { - _themeManager.ThemeChanged -= OnThemeChanged; - } - API?.SaveAppAllSettings(); PluginManager.Dispose(); // Dispose needs to be called on the main Windows thread, since some resources owned by the thread need to be disposed. _mainWindow?.Dispatcher.Invoke(Dispose); - API?.Dispose(); _mainVM?.Dispose(); - _themeManager?.Dispose(); } Log.Info("End PowerToys Run Exit ---------------------------------------------------- ", GetType()); diff --git a/src/modules/launcher/PowerLauncher/Helper/ThemeExtensions.cs b/src/modules/launcher/PowerLauncher/Helper/ThemeExtensions.cs new file mode 100644 index 0000000000..a2396b0288 --- /dev/null +++ b/src/modules/launcher/PowerLauncher/Helper/ThemeExtensions.cs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Linq; +using ManagedCommon; +using Microsoft.Win32; +using Wpf.Ui.Appearance; + +namespace PowerLauncher.Helper +{ + public static class ThemeExtensions + { + public static Theme ToTheme(this ApplicationTheme applicationTheme) + { + return applicationTheme switch + { + ApplicationTheme.Dark => Theme.Dark, + ApplicationTheme.Light => Theme.Light, + ApplicationTheme.HighContrast => GetHighContrastBaseType(), + _ => Theme.Light, + }; + } + + private static Theme GetHighContrastBaseType() + { + string registryKey = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes"; + string theme = (string)Registry.GetValue(registryKey, "CurrentTheme", string.Empty); + theme = theme.Split('\\').Last().Split('.').First().ToString(); + + switch (theme) + { + case "hc1": + return Theme.HighContrastOne; + case "hc2": + return Theme.HighContrastTwo; + case "hcwhite": + return Theme.HighContrastWhite; + case "hcblack": + return Theme.HighContrastBlack; + default: + return Theme.HighContrastOne; + } + } + } +} diff --git a/src/modules/launcher/PowerLauncher/Helper/ThemeManager.cs b/src/modules/launcher/PowerLauncher/Helper/ThemeManager.cs new file mode 100644 index 0000000000..923553a846 --- /dev/null +++ b/src/modules/launcher/PowerLauncher/Helper/ThemeManager.cs @@ -0,0 +1,90 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using ManagedCommon; +using Wox.Infrastructure.Image; +using Wox.Infrastructure.UserSettings; +using Wpf.Ui.Appearance; + +namespace PowerLauncher.Helper +{ + public class ThemeManager : IDisposable + { + private readonly PowerToysRunSettings _settings; + private readonly MainWindow _mainWindow; + private Theme _currentTheme; + private bool _disposed; + + public Theme CurrentTheme => _currentTheme; + + public event Common.UI.ThemeChangedHandler ThemeChanged; + + public ThemeManager(PowerToysRunSettings settings, MainWindow mainWindow) + { + _settings = settings; + _mainWindow = mainWindow; + _currentTheme = ApplicationThemeManager.GetAppTheme().ToTheme(); + SetTheme(false); + + ApplicationThemeManager.Changed += ApplicationThemeManager_Changed; + } + + public void SetTheme(bool fromSettings) + { + if (_settings.Theme == Theme.Light) + { + _currentTheme = Theme.Light; + _mainWindow?.Dispatcher.Invoke(() => ApplicationThemeManager.Apply(ApplicationTheme.Light, _mainWindow.WindowBackdropType)); + } + else if (_settings.Theme == Theme.Dark) + { + _currentTheme = Theme.Dark; + _mainWindow?.Dispatcher.Invoke(() => ApplicationThemeManager.Apply(ApplicationTheme.Dark, _mainWindow.WindowBackdropType)); + } + else if (fromSettings) + { + _mainWindow?.Dispatcher.Invoke(ApplicationThemeManager.ApplySystemTheme); + } + + ImageLoader.UpdateIconPath(_currentTheme); + + // oldTheme isn't used + ThemeChanged?.Invoke(_currentTheme, _currentTheme); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void ApplicationThemeManager_Changed(ApplicationTheme currentApplicationTheme, System.Windows.Media.Color systemAccent) + { + var newTheme = currentApplicationTheme.ToTheme(); + if (_currentTheme == newTheme) + { + return; + } + + _currentTheme = newTheme; + SetTheme(false); + } + + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + if (disposing) + { + ApplicationThemeManager.Changed -= ApplicationThemeManager_Changed; + } + + _disposed = true; + } + } +} diff --git a/src/modules/launcher/PowerLauncher/MainWindow.xaml.cs b/src/modules/launcher/PowerLauncher/MainWindow.xaml.cs index 103c2eb59d..e0512af085 100644 --- a/src/modules/launcher/PowerLauncher/MainWindow.xaml.cs +++ b/src/modules/launcher/PowerLauncher/MainWindow.xaml.cs @@ -24,6 +24,7 @@ using PowerLauncher.ViewModel; using Wox.Infrastructure.UserSettings; using Wox.Plugin; using Wox.Plugin.Interfaces; +using Wpf.Ui.Appearance; using CancellationToken = System.Threading.CancellationToken; using Image = Wox.Infrastructure.Image; using KeyEventArgs = System.Windows.Input.KeyEventArgs; @@ -65,15 +66,7 @@ namespace PowerLauncher WindowBackdropType = Wpf.Ui.Controls.WindowBackdropType.None; } - // workaround for #30217 - try - { - Wpf.Ui.Appearance.SystemThemeWatcher.Watch(this, WindowBackdropType); - } - catch (Exception ex) - { - Log.Exception("Exception in SystemThemeWatcher.Watch, issue 30217.", ex, GetType()); - } + SystemThemeWatcher.Watch(this, WindowBackdropType); _firstDeleteTimer.Elapsed += CheckForFirstDelete; _firstDeleteTimer.Interval = 1000; @@ -803,11 +796,7 @@ namespace PowerLauncher { if (disposing) { - if (_firstDeleteTimer != null) - { - _firstDeleteTimer.Dispose(); - } - + _firstDeleteTimer?.Dispose(); _hwndSource?.Dispose(); } diff --git a/src/modules/launcher/PowerLauncher/PowerLauncher.csproj b/src/modules/launcher/PowerLauncher/PowerLauncher.csproj index 471afe1198..56d463e9f3 100644 --- a/src/modules/launcher/PowerLauncher/PowerLauncher.csproj +++ b/src/modules/launcher/PowerLauncher/PowerLauncher.csproj @@ -80,7 +80,6 @@ - diff --git a/src/modules/launcher/PowerLauncher/PublicAPIInstance.cs b/src/modules/launcher/PowerLauncher/PublicAPIInstance.cs index c60ba20315..4357270a6b 100644 --- a/src/modules/launcher/PowerLauncher/PublicAPIInstance.cs +++ b/src/modules/launcher/PowerLauncher/PublicAPIInstance.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation +// Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. @@ -6,18 +6,12 @@ using System; using System.Collections.Generic; using System.Linq; using System.Windows; - -using Common.UI; - using ManagedCommon; - using Microsoft.Toolkit.Uwp.Notifications; - +using PowerLauncher.Helper; using PowerLauncher.Plugin; using PowerLauncher.ViewModel; - using Windows.UI.Notifications; - using Wox.Infrastructure; using Wox.Infrastructure.Image; using Wox.Plugin; @@ -32,7 +26,7 @@ namespace Wox private readonly ThemeManager _themeManager; private bool _disposed; - public event ThemeChangedHandler ThemeChanged; + public event Common.UI.ThemeChangedHandler ThemeChanged; public PublicAPIInstance(SettingWindowViewModel settingsVM, MainViewModel mainVM, Alphabet alphabet, ThemeManager themeManager) { @@ -108,7 +102,7 @@ namespace Wox public Theme GetCurrentTheme() { - return _themeManager.GetCurrentTheme(); + return _themeManager.CurrentTheme; } public void Dispose() diff --git a/src/modules/launcher/PowerLauncher/SettingsReader.cs b/src/modules/launcher/PowerLauncher/SettingsReader.cs index 229b3583a9..d32ca1f915 100644 --- a/src/modules/launcher/PowerLauncher/SettingsReader.cs +++ b/src/modules/launcher/PowerLauncher/SettingsReader.cs @@ -9,7 +9,6 @@ using System.IO.Abstractions; using System.Linq; using System.Threading; using System.Windows.Input; -using Common.UI; using global::PowerToys.GPOWrapper; using Microsoft.PowerToys.Settings.UI.Library; using PowerLauncher.Helper; @@ -44,9 +43,6 @@ namespace PowerLauncher var overloadSettings = _settingsUtils.GetSettingsOrDefault(PowerLauncherSettings.ModuleName); UpdateSettings(overloadSettings); _settingsUtils.SaveSettings(overloadSettings.ToJsonString(), PowerLauncherSettings.ModuleName); - - // Apply theme at startup - _themeManager.ChangeTheme(_settings.Theme, true); } public void CreateSettingsIfNotExists() @@ -161,7 +157,7 @@ namespace PowerLauncher if (_settings.Theme != overloadSettings.Properties.Theme) { _settings.Theme = overloadSettings.Properties.Theme; - _themeManager.ChangeTheme(_settings.Theme, true); + _themeManager.SetTheme(true); } if (_settings.StartupPosition != overloadSettings.Properties.Position) diff --git a/src/modules/launcher/Wox.Infrastructure/Image/ImageLoader.cs b/src/modules/launcher/Wox.Infrastructure/Image/ImageLoader.cs index 6a10753df0..1e3f2d8455 100644 --- a/src/modules/launcher/Wox.Infrastructure/Image/ImageLoader.cs +++ b/src/modules/launcher/Wox.Infrastructure/Image/ImageLoader.cs @@ -31,7 +31,7 @@ namespace Wox.Infrastructure.Image private static IImageHashGenerator _hashGenerator; - public static string ErrorIconPath { get; set; } + public static string ErrorIconPath { get; set; } = Constant.LightThemedErrorIcon; private static readonly string[] ImageExtensions = { @@ -54,7 +54,7 @@ namespace Wox.Infrastructure.Image return fs.Read(buffer, 0, buffer.Length) == buffer.Length && pngSignature.SequenceEqual(buffer); } - public static void Initialize(Theme theme) + public static void Initialize() { _hashGenerator = new ImageHashGenerator(); @@ -86,7 +86,6 @@ namespace Wox.Infrastructure.Image } } - UpdateIconPath(theme); Task.Run(() => { Stopwatch.Normal("ImageLoader.Initialize - Preload images cost", async () => diff --git a/src/modules/poweraccent/PowerAccent.UI/Selector.xaml.cs b/src/modules/poweraccent/PowerAccent.UI/Selector.xaml.cs index d7fab64210..05e3bb2d6d 100644 --- a/src/modules/poweraccent/PowerAccent.UI/Selector.xaml.cs +++ b/src/modules/poweraccent/PowerAccent.UI/Selector.xaml.cs @@ -5,7 +5,6 @@ using System; using System.ComponentModel; using System.Windows; -using ManagedCommon; using Wpf.Ui.Controls; using Point = PowerAccent.Core.Point; using Size = PowerAccent.Core.Size; @@ -40,15 +39,7 @@ public partial class Selector : FluentWindow, IDisposable, INotifyPropertyChange { InitializeComponent(); - // workaround for #30177 - try - { - Wpf.Ui.Appearance.SystemThemeWatcher.Watch(this); - } - catch (Exception ex) - { - Logger.LogError($"Exception in SystemThemeWatcher.Watch, issue 30177. {ex.Message}"); - } + Wpf.Ui.Appearance.SystemThemeWatcher.Watch(this); Application.Current.MainWindow.ShowActivated = false; Application.Current.MainWindow.Topmost = true;