mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge 7476cdd894 into 5ef6a2b688
This commit is contained in:
commit
e2015c4b4f
1 changed files with 227 additions and 121 deletions
|
|
@ -11,12 +11,12 @@ using System.Windows.Markup;
|
|||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
|
||||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -124,8 +131,8 @@ namespace Flow.Launcher.Core.Resource
|
|||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
var foregroundPropertyValue = style.Setters.OfType<Setter>().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 @@ namespace Flow.Launcher.Core.Resource
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
queryBoxStyle.Setters.Add(new Setter(Control.FontStretchProperty, fontStretch));
|
||||
|
||||
var caretBrushPropertyValue = queryBoxStyle.Setters.OfType<Setter>().Any(x => x.Property.Name == "CaretBrush");
|
||||
var foregroundPropertyValue = queryBoxStyle.Setters.OfType<Setter>().Where(x => x.Property.Name == "Foreground")
|
||||
.Select(x => x.Value).FirstOrDefault();
|
||||
var foregroundPropertyValue = queryBoxStyle.Setters.OfType<Setter>().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 @@ namespace Flow.Launcher.Core.Resource
|
|||
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,11 +523,58 @@ namespace Flow.Launcher.Core.Resource
|
|||
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
|
@ -491,62 +584,52 @@ 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);
|
||||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -623,13 +713,17 @@ namespace Flow.Launcher.Core.Resource
|
|||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -667,21 +761,25 @@ namespace Flow.Launcher.Core.Resource
|
|||
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<Setter>().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<Setter>().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<Setter>().FirstOrDefault(x => x.Property == Border.CornerRadiusProperty);
|
||||
|
|
@ -689,7 +787,7 @@ namespace Flow.Launcher.Core.Resource
|
|||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
|
||||
private void AutoDropShadow(bool useDropShadowEffect)
|
||||
{
|
||||
SetWindowCornerPreference("Default");
|
||||
RemoveDropShadowEffectFromCurrentTheme();
|
||||
if (useDropShadowEffect)
|
||||
{
|
||||
if (BlurEnabled && Win32Helper.IsBackdropSupported())
|
||||
{
|
||||
SetWindowCornerPreference("Round");
|
||||
RemoveDropShadowEffectFromCurrentTheme();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -725,9 +822,11 @@ namespace Flow.Launcher.Core.Resource
|
|||
if (BlurEnabled && Win32Helper.IsBackdropSupported())
|
||||
{
|
||||
SetWindowCornerPreference("Default");
|
||||
RemoveDropShadowEffectFromCurrentTheme();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowCornerPreference("Default");
|
||||
RemoveDropShadowEffectFromCurrentTheme();
|
||||
}
|
||||
}
|
||||
|
|
@ -746,8 +845,9 @@ namespace Flow.Launcher.Core.Resource
|
|||
// 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<Setter>()
|
||||
|
|
@ -765,12 +865,12 @@ namespace Flow.Launcher.Core.Resource
|
|||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
|
||||
// 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 @@ namespace Flow.Launcher.Core.Resource
|
|||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
{
|
||||
// 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 @@ namespace Flow.Launcher.Core.Resource
|
|||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
// 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
|
||||
|
|
|
|||
Loading…
Reference in a new issue