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.
This commit is contained in:
Jack251970 2026-03-01 13:59:32 +08:00
parent 5b6b7e728e
commit 9943b72839

View file

@ -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)