From 9943b728390533a90a6024e59bbf5111d2ff3baa Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 1 Mar 2026 13:59:32 +0800 Subject: [PATCH] Refactor drop shadow handling for window border style Reworked how drop shadow effects are added and removed by creating new unsealed Style instances instead of modifying sealed ones. Resources, triggers, and setters are copied, with margin adjustments and effect setter management to ensure reliability. Introduced GetNewWindowBorderStyle helper for style copying. --- Flow.Launcher.Core/Resource/Theme.cs | 140 ++++++++++++++++++--------- 1 file changed, 94 insertions(+), 46 deletions(-) diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs index 43814800b..e0f3368f8 100644 --- a/Flow.Launcher.Core/Resource/Theme.cs +++ b/Flow.Launcher.Core/Resource/Theme.cs @@ -522,11 +522,56 @@ namespace Flow.Launcher.Core.Resource public void AddDropShadowEffectToCurrentTheme() { - var dict = GetCurrentResourceDictionary(); + // Get current theme's WindowBorderStyle + var theme = _settings.Theme; + var dict = GetThemeResourceDictionary(theme); + if (dict["WindowBorderStyle"] is not Style windowBorderStyle) return; - var windowBorderStyle = dict["WindowBorderStyle"] as Style; + // Get a new unsealed style based on the old one, and copy Resources and Triggers + var newWindowBorderStyle = GetNewWindowBorderStyle(windowBorderStyle); - var effectSetter = new Setter + // Identify existing Margin to calculate new Margin, and copy other setters + Setter existingMarginSetter = null; + foreach (var setterBase in windowBorderStyle.Setters) + { + if (setterBase is Setter setter) + { + // 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; + } + + // Add other setters (e.g. Background, BorderThickness) + newWindowBorderStyle.Setters.Add(setterBase); + } + + // Calculate new Margin + Thickness newMargin; + if (existingMarginSetter == null) + { + newMargin = new Thickness(ShadowExtraMargin, 12, ShadowExtraMargin, ShadowExtraMargin); + } + else + { + var baseMargin = (Thickness)existingMarginSetter.Value; + newMargin = new Thickness( + baseMargin.Left + ShadowExtraMargin, + baseMargin.Top + ShadowExtraMargin, + baseMargin.Right + ShadowExtraMargin, + baseMargin.Bottom + ShadowExtraMargin); + } + + // Add new Margin Setter + newWindowBorderStyle.Setters.Add(new Setter(FrameworkElement.MarginProperty, newMargin)); + + // Add Drop Shadow Effect Setter + newWindowBorderStyle.Setters.Add(new Setter { Property = UIElement.EffectProperty, Value = new DropShadowEffect @@ -536,62 +581,65 @@ namespace Flow.Launcher.Core.Resource Direction = 270, BlurRadius = 30 } - }; + }); - 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); + SetResizeBoarderThickness(newMargin); - SetResizeBoarderThickness(margin); - } - else - { - var baseMargin = (Thickness)marginSetter.Value; - var newMargin = new Thickness( - baseMargin.Left + ShadowExtraMargin, - baseMargin.Top + ShadowExtraMargin, - baseMargin.Right + ShadowExtraMargin, - baseMargin.Bottom + ShadowExtraMargin); - marginSetter.Value = newMargin; - - SetResizeBoarderThickness(newMargin); - } - - windowBorderStyle.Setters.Add(effectSetter); - - UpdateResourceDictionary(dict); + _oldResource["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); + if (dict["WindowBorderStyle"] is not Style windowBorderStyle) 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 = GetNewWindowBorderStyle(windowBorderStyle); - 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); + _oldResource["WindowBorderStyle"] = newWindowBorderStyle; + } + + private static Style GetNewWindowBorderStyle(Style windowBorderStyle) + { + // Create a new unsealed style based on the old one + var newWindowBorderStyle = new Style(windowBorderStyle.TargetType, windowBorderStyle.BasedOn); + + // Copy Resources and Triggers + foreach (var key in windowBorderStyle.Resources.Keys) + newWindowBorderStyle.Resources.Add(key, windowBorderStyle.Resources[key]); + + foreach (var trigger in windowBorderStyle.Triggers) + newWindowBorderStyle.Triggers.Add(trigger); + + return newWindowBorderStyle; } public void SetResizeBorderThickness(WindowChrome windowChrome, bool fixedWindowSize)