diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs
index c3bb6190f01..77e1ea5b5bd 100644
--- a/Flow.Launcher.Core/Resource/Theme.cs
+++ b/Flow.Launcher.Core/Resource/Theme.cs
@@ -11,12 +11,12 @@
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Shell;
-using System.Windows.Threading;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedModels;
using Microsoft.Win32;
+using System.Windows.Threading;
namespace Flow.Launcher.Core.Resource
{
@@ -100,12 +100,6 @@ private void MakeSureThemeDirectoriesExist()
private void UpdateResourceDictionary(ResourceDictionary dictionaryToUpdate)
{
- // Add new resources
- if (!Application.Current.Resources.MergedDictionaries.Contains(dictionaryToUpdate))
- {
- Application.Current.Resources.MergedDictionaries.Add(dictionaryToUpdate);
- }
-
// Remove old resources
if (_oldResource != null && _oldResource != dictionaryToUpdate &&
Application.Current.Resources.MergedDictionaries.Contains(_oldResource))
@@ -113,7 +107,20 @@ private void UpdateResourceDictionary(ResourceDictionary dictionaryToUpdate)
Application.Current.Resources.MergedDictionaries.Remove(_oldResource);
}
- _oldResource = dictionaryToUpdate;
+ // Add new resources
+ try
+ {
+ if (!Application.Current.Resources.MergedDictionaries.Contains(dictionaryToUpdate))
+ {
+ Application.Current.Resources.MergedDictionaries.Add(dictionaryToUpdate);
+ }
+ _oldResource = dictionaryToUpdate;
+ }
+ catch (InvalidCastException)
+ {
+ // System.InvalidCastException: Unable to cast object of type 'System.Windows.Media.Color' to type 'System.Windows.Expression'.
+ _oldResource = null;
+ }
}
///
@@ -124,8 +131,8 @@ public void UpdateFonts()
try
{
// Load a ResourceDictionary for the specified theme.
- var themeName = _settings.Theme;
- var dict = GetThemeResourceDictionary(themeName);
+ var theme = _settings.Theme;
+ var dict = GetThemeResourceDictionary(theme);
// Apply font settings to the theme resource.
ApplyFontSettings(dict);
@@ -221,7 +228,13 @@ private static void SetFontProperties(Style style, FontFamily fontFamily, FontSt
var foregroundPropertyValue = style.Setters.OfType().Where(x => x.Property.Name == "Foreground")
.Select(x => x.Value).FirstOrDefault();
if (!caretBrushPropertyValue && foregroundPropertyValue != null)
- style.Setters.Add(new Setter(TextBoxBase.CaretBrushProperty, foregroundPropertyValue));
+ {
+ var newCaretValue = GetNewCaretValue(foregroundPropertyValue);
+ if (newCaretValue != null)
+ {
+ style.Setters.Add(new Setter(TextBoxBase.CaretBrushProperty, newCaretValue));
+ }
+ }
}
else
{
@@ -246,6 +259,37 @@ private static void SetFontProperties(Style style, FontFamily fontFamily, FontSt
}
}
+ private static object GetNewCaretValue(object foregroundPropertyValue)
+ {
+ object newCaretValue;
+ if (foregroundPropertyValue is DynamicResourceExtension dynamicResource)
+ {
+ newCaretValue = new DynamicResourceExtension(dynamicResource.ResourceKey);
+ }
+ else if (foregroundPropertyValue is SolidColorBrush solidBrush)
+ {
+ // Create a new brush to avoid sharing mutable freezables with potential expressions
+ if (solidBrush.IsFrozen)
+ {
+ newCaretValue = solidBrush;
+ }
+ else
+ {
+ var newBrush = new SolidColorBrush(solidBrush.Color)
+ {
+ Opacity = solidBrush.Opacity
+ };
+ if (newBrush.CanFreeze) newBrush.Freeze();
+ newCaretValue = newBrush;
+ }
+ }
+ else
+ {
+ newCaretValue = foregroundPropertyValue;
+ }
+ return newCaretValue;
+ }
+
private ResourceDictionary GetThemeResourceDictionary(string theme)
{
var uri = GetThemePath(theme);
@@ -275,10 +319,15 @@ private ResourceDictionary GetResourceDictionary(string theme)
queryBoxStyle.Setters.Add(new Setter(Control.FontStretchProperty, fontStretch));
var caretBrushPropertyValue = queryBoxStyle.Setters.OfType().Any(x => x.Property.Name == "CaretBrush");
- var foregroundPropertyValue = queryBoxStyle.Setters.OfType().Where(x => x.Property.Name == "Foreground")
- .Select(x => x.Value).FirstOrDefault();
+ var foregroundPropertyValue = queryBoxStyle.Setters.OfType().FirstOrDefault(x => x.Property.Name == "Foreground")?.Value;
if (!caretBrushPropertyValue && foregroundPropertyValue != null) //otherwise BaseQueryBoxStyle will handle styling
- queryBoxStyle.Setters.Add(new Setter(TextBoxBase.CaretBrushProperty, foregroundPropertyValue));
+ {
+ var newCaretValue = GetNewCaretValue(foregroundPropertyValue);
+ if (newCaretValue != null)
+ {
+ queryBoxStyle.Setters.Add(new Setter(TextBoxBase.CaretBrushProperty, newCaretValue));
+ }
+ }
// Query suggestion box's font style is aligned with query box
querySuggestionBoxStyle.Setters.Add(new Setter(Control.FontFamilyProperty, fontFamily));
@@ -419,20 +468,17 @@ public bool ChangeTheme(string theme = null)
if (string.IsNullOrEmpty(path))
throw new DirectoryNotFoundException($"Theme path can't be found <{path}>");
- // Retrieve theme resource – always use the resource with font settings applied.
- var resourceDict = GetResourceDictionary(theme);
-
- UpdateResourceDictionary(resourceDict);
-
_settings.Theme = theme;
- //always allow re-loading default theme, in case of failure of switching to a new theme from default theme
+ // Always allow re-loading default theme, in case of failure of switching to a new theme from default theme
if (_oldTheme != theme || theme == Constant.DefaultTheme)
{
_oldTheme = Path.GetFileNameWithoutExtension(_oldResource.Source.AbsolutePath);
}
- BlurEnabled = IsBlurTheme();
+ // Check if blur is enabled
+ var dict = GetThemeResourceDictionary(theme);
+ BlurEnabled = Win32Helper.IsBackdropSupported() && IsThemeBlurEnabled(dict);
// Apply blur and drop shadow effect so that we do not need to call it again
_ = RefreshFrameAsync();
@@ -477,76 +523,113 @@ public bool ChangeTheme(string theme = null)
public void AddDropShadowEffectToCurrentTheme()
{
- var dict = GetCurrentResourceDictionary();
+ // Get current theme's WindowBorderStyle
+ var theme = _settings.Theme;
+ var dict = GetThemeResourceDictionary(theme);
+ var windowBorderStyle = dict.Contains("WindowBorderStyle") ? dict["WindowBorderStyle"] as Style : null;
+ if (windowBorderStyle == null) return;
- var windowBorderStyle = dict["WindowBorderStyle"] as Style;
+ // Get a new unsealed style based on the old one, and copy Resources and Triggers
+ var newWindowBorderStyle = new Style(typeof(Border));
+ CopyStyle(windowBorderStyle, newWindowBorderStyle);
- var effectSetter = new Setter
+ // Identify existing Margin to calculate new Margin, and copy other setters
+ Setter existingMarginSetter = null;
+ foreach (var setterBase in windowBorderStyle.Setters)
{
- Property = UIElement.EffectProperty,
- Value = new DropShadowEffect
+ if (setterBase is Setter setter)
{
- Opacity = 0.3,
- ShadowDepth = 12,
- Direction = 270,
- BlurRadius = 30
+ // Skip existing Margin (we'll replace it)
+ if (setter.Property == FrameworkElement.MarginProperty)
+ {
+ existingMarginSetter = setter;
+ continue;
+ }
+
+ // Skip existing Effect (we'll ensure strictly one is added)
+ if (setter.Property == UIElement.EffectProperty) continue;
}
- };
- if (windowBorderStyle.Setters.FirstOrDefault(setterBase => setterBase is Setter setter && setter.Property == FrameworkElement.MarginProperty) is not Setter marginSetter)
- {
- var margin = new Thickness(ShadowExtraMargin, 12, ShadowExtraMargin, ShadowExtraMargin);
- marginSetter = new Setter()
- {
- Property = FrameworkElement.MarginProperty,
- Value = margin,
- };
- windowBorderStyle.Setters.Add(marginSetter);
+ // Add other setters (e.g. Background, BorderThickness)
+ newWindowBorderStyle.Setters.Add(setterBase);
+ }
- SetResizeBoarderThickness(margin);
+ // Calculate new Margin
+ Thickness newMargin;
+ if (existingMarginSetter == null)
+ {
+ newMargin = new Thickness(ShadowExtraMargin, 12, ShadowExtraMargin, ShadowExtraMargin);
}
else
{
- var baseMargin = (Thickness)marginSetter.Value;
- var newMargin = new Thickness(
+ var baseMargin = (Thickness)existingMarginSetter.Value;
+ newMargin = new Thickness(
baseMargin.Left + ShadowExtraMargin,
baseMargin.Top + ShadowExtraMargin,
baseMargin.Right + ShadowExtraMargin,
baseMargin.Bottom + ShadowExtraMargin);
- marginSetter.Value = newMargin;
-
- SetResizeBoarderThickness(newMargin);
}
- windowBorderStyle.Setters.Add(effectSetter);
+ // Add new Margin Setter
+ newWindowBorderStyle.Setters.Add(new Setter(FrameworkElement.MarginProperty, newMargin));
- UpdateResourceDictionary(dict);
+ // Add Drop Shadow Effect Setter
+ newWindowBorderStyle.Setters.Add(new Setter
+ {
+ Property = UIElement.EffectProperty,
+ Value = new DropShadowEffect
+ {
+ Opacity = 0.3,
+ ShadowDepth = 12,
+ Direction = 270,
+ BlurRadius = 30
+ }
+ });
+
+ SetResizeBoarderThickness(newMargin);
+
+ Application.Current.Resources["WindowBorderStyle"] = newWindowBorderStyle;
}
public void RemoveDropShadowEffectFromCurrentTheme()
{
- var dict = GetCurrentResourceDictionary();
- var windowBorderStyle = dict["WindowBorderStyle"] as Style;
+ // Get current theme's WindowBorderStyle
+ var theme = _settings.Theme;
+ var dict = GetThemeResourceDictionary(theme);
+ var windowBorderStyle = dict.Contains("WindowBorderStyle") ? dict["WindowBorderStyle"] as Style : null;
+ if (windowBorderStyle == null) return;
- if (windowBorderStyle.Setters.FirstOrDefault(setterBase => setterBase is Setter setter && setter.Property == UIElement.EffectProperty) is Setter effectSetter)
- {
- windowBorderStyle.Setters.Remove(effectSetter);
- }
+ // Get a new unsealed style based on the old one, and copy Resources and Triggers
+ var newWindowBorderStyle = new Style(typeof(Border));
+ CopyStyle(windowBorderStyle, newWindowBorderStyle);
- if (windowBorderStyle.Setters.FirstOrDefault(setterBase => setterBase is Setter setter && setter.Property == FrameworkElement.MarginProperty) is Setter marginSetter)
+ // Copy Setters, excluding the Effect setter and updating the Margin setter
+ foreach (var setterBase in windowBorderStyle.Setters)
{
- var currentMargin = (Thickness)marginSetter.Value;
- var newMargin = new Thickness(
- currentMargin.Left - ShadowExtraMargin,
- currentMargin.Top - ShadowExtraMargin,
- currentMargin.Right - ShadowExtraMargin,
- currentMargin.Bottom - ShadowExtraMargin);
- marginSetter.Value = newMargin;
+ if (setterBase is Setter setter)
+ {
+ // Skip existing Effect (We'll remove it)
+ if (setter.Property == UIElement.EffectProperty) continue;
+
+ // Update Margin by subtracting the extra margin we added for the shadow
+ if (setter.Property == FrameworkElement.MarginProperty)
+ {
+ var currentMargin = (Thickness)setter.Value;
+ var newMargin = new Thickness(
+ currentMargin.Left - ShadowExtraMargin,
+ currentMargin.Top - ShadowExtraMargin,
+ currentMargin.Right - ShadowExtraMargin,
+ currentMargin.Bottom - ShadowExtraMargin);
+ newWindowBorderStyle.Setters.Add(new Setter(FrameworkElement.MarginProperty, newMargin));
+ continue;
+ }
+ }
+ newWindowBorderStyle.Setters.Add(setterBase);
}
SetResizeBoarderThickness(null);
- UpdateResourceDictionary(dict);
+ Application.Current.Resources["WindowBorderStyle"] = newWindowBorderStyle;
}
public void SetResizeBorderThickness(WindowChrome windowChrome, bool fixedWindowSize)
@@ -596,26 +679,33 @@ private void SetResizeBoarderThickness(Thickness? effectMargin)
///
public async Task RefreshFrameAsync()
{
- await Application.Current.Dispatcher.InvokeAsync(() =>
+ if (Application.Current == null) return;
+ if (!Application.Current.Dispatcher.CheckAccess())
{
- // Get the actual backdrop type and drop shadow effect settings
- var (backdropType, useDropShadowEffect) = GetActualValue();
+ await Application.Current?.Dispatcher.InvokeAsync(RefreshFrameAsync, DispatcherPriority.Render);
+ return;
+ }
- // Remove OS minimizing/maximizing animation
- // Methods.SetWindowAttribute(new WindowInteropHelper(mainWindow).Handle, DWMWINDOWATTRIBUTE.DWMWA_TRANSITIONS_FORCEDISABLED, 3);
+ // Get the actual backdrop type and drop shadow effect settings
+ var (backdropType, useDropShadowEffect) = GetActualValue();
- // The timing of adding the shadow effect should vary depending on whether the theme is transparent.
- if (BlurEnabled)
- {
- AutoDropShadow(useDropShadowEffect);
- }
- SetBlurForWindow(_settings.Theme, backdropType);
+ // Remove OS minimizing/maximizing animation
+ // Methods.SetWindowAttribute(new WindowInteropHelper(mainWindow).Handle, DWMWINDOWATTRIBUTE.DWMWA_TRANSITIONS_FORCEDISABLED, 3);
- if (!BlurEnabled)
- {
- AutoDropShadow(useDropShadowEffect);
- }
- }, DispatcherPriority.Render);
+ // The timing of adding the shadow effect should vary depending on whether the theme is transparent.
+ if (BlurEnabled)
+ {
+ AutoDropShadow(useDropShadowEffect);
+ }
+
+#pragma warning disable VSTHRD103 // Call async methods when in an async method
+ SetBlurForWindow(_settings.Theme, backdropType);
+#pragma warning restore VSTHRD103 // Call async methods when in an async method
+
+ if (!BlurEnabled)
+ {
+ AutoDropShadow(useDropShadowEffect);
+ }
}
///
@@ -623,13 +713,17 @@ await Application.Current.Dispatcher.InvokeAsync(() =>
///
public async Task SetBlurForWindowAsync()
{
- await Application.Current.Dispatcher.InvokeAsync(() =>
+ if (Application.Current == null) return;
+ if (!Application.Current.Dispatcher.CheckAccess())
{
- // Get the actual backdrop type and drop shadow effect settings
- var (backdropType, _) = GetActualValue();
+ await Application.Current?.Dispatcher.InvokeAsync(SetBlurForWindowAsync, DispatcherPriority.Render);
+ return;
+ }
- SetBlurForWindow(_settings.Theme, backdropType);
- }, DispatcherPriority.Render);
+ // Get the actual backdrop type and drop shadow effect settings
+ var (backdropType, _) = GetActualValue();
+
+ SetBlurForWindow(_settings.Theme, backdropType);
}
///
@@ -667,21 +761,25 @@ private void SetBlurForWindow(string theme, BackdropTypes backdropType)
if (mainWindow == null) return;
// Check if the theme supports blur
- bool hasBlur = dict.Contains("ThemeBlurEnabled") && dict["ThemeBlurEnabled"] is bool b && b;
+ var hasBlur = IsThemeBlurEnabled(dict);
if (BlurEnabled && hasBlur && Win32Helper.IsBackdropSupported())
{
// If the BackdropType is Mica or MicaAlt, set the windowborderstyle's background to transparent
if (backdropType == BackdropTypes.Mica || backdropType == BackdropTypes.MicaAlt)
{
windowBorderStyle.Setters.Remove(windowBorderStyle.Setters.OfType().FirstOrDefault(x => x.Property.Name == "Background"));
- windowBorderStyle.Setters.Add(new Setter(Border.BackgroundProperty, new SolidColorBrush(Color.FromArgb(1, 0, 0, 0))));
+ var brush = new SolidColorBrush(Color.FromArgb(1, 0, 0, 0));
+ brush.Freeze();
+ windowBorderStyle.Setters.Add(new Setter(Border.BackgroundProperty, brush));
}
else if (backdropType == BackdropTypes.Acrylic)
{
windowBorderStyle.Setters.Remove(windowBorderStyle.Setters.OfType().FirstOrDefault(x => x.Property.Name == "Background"));
- windowBorderStyle.Setters.Add(new Setter(Border.BackgroundProperty, new SolidColorBrush(Colors.Transparent)));
+ var brush = new SolidColorBrush(Colors.Transparent);
+ brush.Freeze();
+ windowBorderStyle.Setters.Add(new Setter(Border.BackgroundProperty, brush));
}
-
+
// For themes with blur enabled, the window border is rendered by the system, so it's treated as a simple rectangle regardless of thickness.
//(This is to avoid issues when the window is forcibly changed to a rectangular shape during snap scenarios.)
var cornerRadiusSetter = windowBorderStyle.Setters.OfType().FirstOrDefault(x => x.Property == Border.CornerRadiusProperty);
@@ -689,7 +787,7 @@ private void SetBlurForWindow(string theme, BackdropTypes backdropType)
cornerRadiusSetter.Value = new CornerRadius(0);
else
windowBorderStyle.Setters.Add(new Setter(Border.CornerRadiusProperty, new CornerRadius(0)));
-
+
// Apply the blur effect
Win32Helper.DWMSetBackdropForWindow(mainWindow, backdropType);
ColorizeWindow(theme, backdropType);
@@ -706,13 +804,12 @@ private void SetBlurForWindow(string theme, BackdropTypes backdropType)
private void AutoDropShadow(bool useDropShadowEffect)
{
- SetWindowCornerPreference("Default");
- RemoveDropShadowEffectFromCurrentTheme();
if (useDropShadowEffect)
{
if (BlurEnabled && Win32Helper.IsBackdropSupported())
{
SetWindowCornerPreference("Round");
+ RemoveDropShadowEffectFromCurrentTheme();
}
else
{
@@ -725,9 +822,11 @@ private void AutoDropShadow(bool useDropShadowEffect)
if (BlurEnabled && Win32Helper.IsBackdropSupported())
{
SetWindowCornerPreference("Default");
+ RemoveDropShadowEffectFromCurrentTheme();
}
else
{
+ SetWindowCornerPreference("Default");
RemoveDropShadowEffectFromCurrentTheme();
}
}
@@ -746,8 +845,9 @@ private static void SetWindowCornerPreference(string cornerType)
// for theme has not "LightBG" or "DarkBG" case.
private Color GetWindowBorderStyleBackground(string theme)
{
- var Resources = GetThemeResourceDictionary(theme);
- var windowBorderStyle = (Style)Resources["WindowBorderStyle"];
+ var dict = GetThemeResourceDictionary(theme);
+ var windowBorderStyle = dict.Contains("WindowBorderStyle") ? dict["WindowBorderStyle"] as Style : null;
+ if (windowBorderStyle == null) return Colors.Transparent; // Default is transparent
var backgroundSetter = windowBorderStyle.Setters
.OfType()
@@ -765,12 +865,12 @@ private Color GetWindowBorderStyleBackground(string theme)
else if (backgroundValue is DynamicResourceExtension dynamicResource)
{
// When DynamicResource Extension it is, Key is resource's name.
- var resourceKey = backgroundSetter.Value.ToString();
+ var resourceKey = dynamicResource.ResourceKey.ToString();
// find key in resource and return color.
- if (Resources.Contains(resourceKey))
+ if (dict.Contains(resourceKey))
{
- var colorResource = Resources[resourceKey];
+ var colorResource = dict[resourceKey];
if (colorResource is SolidColorBrush colorBrush)
{
return colorBrush.Color;
@@ -803,7 +903,9 @@ private void ApplyPreviewBackground(Color? bgColor = null)
// Apply background color (remove transparency in color)
Color backgroundColor = Color.FromRgb(bgColor.Value.R, bgColor.Value.G, bgColor.Value.B);
- previewStyle.Setters.Add(new Setter(Border.BackgroundProperty, new SolidColorBrush(backgroundColor)));
+ var brush = new SolidColorBrush(backgroundColor);
+ brush.Freeze();
+ previewStyle.Setters.Add(new Setter(Border.BackgroundProperty, brush));
// The blur theme keeps the corner round fixed (applying DWM code to modify it causes rendering issues).
// The non-blur theme retains the previously set WindowBorderStyle.
@@ -817,7 +919,7 @@ private void ApplyPreviewBackground(Color? bgColor = null)
Application.Current.Resources["PreviewWindowBorderStyle"] = previewStyle;
}
- private void CopyStyle(Style originalStyle, Style targetStyle)
+ private static void CopyStyle(Style originalStyle, Style targetStyle)
{
// If the style is based on another style, copy the base style first
if (originalStyle.BasedOn != null)
@@ -841,20 +943,16 @@ private void ColorizeWindow(string theme, BackdropTypes backdropType)
if (mainWindow == null) return;
// Check if the theme supports blur
- bool hasBlur = dict.Contains("ThemeBlurEnabled") && dict["ThemeBlurEnabled"] is bool b && b;
+ var hasBlur = IsThemeBlurEnabled(dict);
// SystemBG value check (Auto, Light, Dark)
- string systemBG = dict.Contains("SystemBG") ? dict["SystemBG"] as string : "Auto"; // 기본값 Auto
+ var systemBG = dict.Contains("SystemBG") ? dict["SystemBG"] as string : "Auto"; // 기본값 Auto
// Check the user's ColorScheme setting
- string colorScheme = _settings.ColorScheme;
-
- // Check system dark mode setting (read AppsUseLightTheme value)
- int themeValue = (int)Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", "AppsUseLightTheme", 1);
- bool isSystemDark = themeValue == 0;
+ var colorScheme = _settings.ColorScheme;
// Final decision on whether to use dark mode
- bool useDarkMode = false;
+ var useDarkMode = false;
// If systemBG is not "Auto", prioritize it over ColorScheme and set the mode based on systemBG value
if (systemBG == "Dark")
@@ -869,11 +967,20 @@ private void ColorizeWindow(string theme, BackdropTypes backdropType)
{
// If systemBG is "Auto", decide based on ColorScheme
if (colorScheme == "Dark")
+ {
useDarkMode = true;
+ }
else if (colorScheme == "Light")
+ {
useDarkMode = false;
+ }
else
+ {
+ // Check system dark mode setting (read AppsUseLightTheme value)
+ var themeValue = (int)Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", "AppsUseLightTheme", 1);
+ var isSystemDark = themeValue == 0;
useDarkMode = isSystemDark; // Auto (based on system setting)
+ }
}
// Apply DWM Dark Mode
@@ -906,8 +1013,8 @@ private void ColorizeWindow(string theme, BackdropTypes backdropType)
Color selectedBG = useDarkMode ? DarkBG : LightBG;
ApplyPreviewBackground(selectedBG);
- bool isBlurAvailable = hasBlur && Win32Helper.IsBackdropSupported(); // Windows 11 미만이면 hasBlur를 강제 false
-
+ // If Windows does not support backdrop, treat as blur unavailable
+ var isBlurAvailable = hasBlur && Win32Helper.IsBackdropSupported();
if (!isBlurAvailable)
{
mainWindow.Background = Brushes.Transparent;
@@ -917,23 +1024,22 @@ private void ColorizeWindow(string theme, BackdropTypes backdropType)
// Only set the background to transparent if the theme supports blur
if (backdropType == BackdropTypes.Mica || backdropType == BackdropTypes.MicaAlt)
{
- mainWindow.Background = new SolidColorBrush(Color.FromArgb(1, 0, 0, 0));
+ var backgroundBrush = new SolidColorBrush(Color.FromArgb(1, 0, 0, 0));
+ backgroundBrush.Freeze();
+ mainWindow.Background = backgroundBrush;
}
else
{
- mainWindow.Background = new SolidColorBrush(selectedBG);
+ var backgroundBrush = new SolidColorBrush(selectedBG);
+ backgroundBrush.Freeze();
+ mainWindow.Background = backgroundBrush;
}
}
}
- private static bool IsBlurTheme()
+ private static bool IsThemeBlurEnabled(ResourceDictionary dict)
{
- if (!Win32Helper.IsBackdropSupported()) // Windows 11 미만이면 무조건 false
- return false;
-
- var resource = Application.Current.TryFindResource("ThemeBlurEnabled");
-
- return resource is bool b && b;
+ return dict.Contains("ThemeBlurEnabled") && dict["ThemeBlurEnabled"] is bool enabled && enabled;
}
#endregion