|
|
|
|
@ -124,8 +124,8 @@ namespace Flow.Launcher.Core.Resource
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// Load a ResourceDictionary for the specified theme.
|
|
|
|
|
var theme = _settings.Theme;
|
|
|
|
|
var dict = GetThemeResourceDictionary(theme);
|
|
|
|
|
var themeName = _settings.Theme;
|
|
|
|
|
var dict = GetThemeResourceDictionary(themeName);
|
|
|
|
|
|
|
|
|
|
// Apply font settings to the theme resource.
|
|
|
|
|
ApplyFontSettings(dict);
|
|
|
|
|
@ -292,10 +292,10 @@ namespace Flow.Launcher.Core.Resource
|
|
|
|
|
dict["ItemHotkeyStyle"] is Style resultHotkeyItemStyle &&
|
|
|
|
|
dict["ItemHotkeySelectedStyle"] is Style resultHotkeyItemSelectedStyle)
|
|
|
|
|
{
|
|
|
|
|
var fontFamily = new Setter(TextBlock.FontFamilyProperty, new FontFamily(_settings.ResultFont));
|
|
|
|
|
var fontStyle = new Setter(TextBlock.FontStyleProperty, FontHelper.GetFontStyleFromInvariantStringOrNormal(_settings.ResultFontStyle));
|
|
|
|
|
var fontWeight = new Setter(TextBlock.FontWeightProperty, FontHelper.GetFontWeightFromInvariantStringOrNormal(_settings.ResultFontWeight));
|
|
|
|
|
var fontStretch = new Setter(TextBlock.FontStretchProperty, FontHelper.GetFontStretchFromInvariantStringOrNormal(_settings.ResultFontStretch));
|
|
|
|
|
Setter fontFamily = new Setter(TextBlock.FontFamilyProperty, new FontFamily(_settings.ResultFont));
|
|
|
|
|
Setter fontStyle = new Setter(TextBlock.FontStyleProperty, FontHelper.GetFontStyleFromInvariantStringOrNormal(_settings.ResultFontStyle));
|
|
|
|
|
Setter fontWeight = new Setter(TextBlock.FontWeightProperty, FontHelper.GetFontWeightFromInvariantStringOrNormal(_settings.ResultFontWeight));
|
|
|
|
|
Setter fontStretch = new Setter(TextBlock.FontStretchProperty, FontHelper.GetFontStretchFromInvariantStringOrNormal(_settings.ResultFontStretch));
|
|
|
|
|
|
|
|
|
|
Setter[] setters = { fontFamily, fontStyle, fontWeight, fontStretch };
|
|
|
|
|
Array.ForEach(
|
|
|
|
|
@ -307,10 +307,10 @@ namespace Flow.Launcher.Core.Resource
|
|
|
|
|
dict["ItemSubTitleStyle"] is Style resultSubItemStyle &&
|
|
|
|
|
dict["ItemSubTitleSelectedStyle"] is Style resultSubItemSelectedStyle)
|
|
|
|
|
{
|
|
|
|
|
var fontFamily = new Setter(TextBlock.FontFamilyProperty, new FontFamily(_settings.ResultSubFont));
|
|
|
|
|
var fontStyle = new Setter(TextBlock.FontStyleProperty, FontHelper.GetFontStyleFromInvariantStringOrNormal(_settings.ResultSubFontStyle));
|
|
|
|
|
var fontWeight = new Setter(TextBlock.FontWeightProperty, FontHelper.GetFontWeightFromInvariantStringOrNormal(_settings.ResultSubFontWeight));
|
|
|
|
|
var fontStretch = new Setter(TextBlock.FontStretchProperty, FontHelper.GetFontStretchFromInvariantStringOrNormal(_settings.ResultSubFontStretch));
|
|
|
|
|
Setter fontFamily = new Setter(TextBlock.FontFamilyProperty, new FontFamily(_settings.ResultSubFont));
|
|
|
|
|
Setter fontStyle = new Setter(TextBlock.FontStyleProperty, FontHelper.GetFontStyleFromInvariantStringOrNormal(_settings.ResultSubFontStyle));
|
|
|
|
|
Setter fontWeight = new Setter(TextBlock.FontWeightProperty, FontHelper.GetFontWeightFromInvariantStringOrNormal(_settings.ResultSubFontWeight));
|
|
|
|
|
Setter fontStretch = new Setter(TextBlock.FontStretchProperty, FontHelper.GetFontStretchFromInvariantStringOrNormal(_settings.ResultSubFontStretch));
|
|
|
|
|
|
|
|
|
|
Setter[] setters = { fontFamily, fontStyle, fontWeight, fontStretch };
|
|
|
|
|
Array.ForEach(
|
|
|
|
|
@ -395,7 +395,7 @@ namespace Flow.Launcher.Core.Resource
|
|
|
|
|
|
|
|
|
|
public List<ThemeData> GetAvailableThemes()
|
|
|
|
|
{
|
|
|
|
|
var themes = new List<ThemeData>();
|
|
|
|
|
List<ThemeData> themes = new List<ThemeData>();
|
|
|
|
|
foreach (var themeDirectory in _themeDirectories)
|
|
|
|
|
{
|
|
|
|
|
var filePaths = Directory
|
|
|
|
|
@ -410,7 +410,8 @@ namespace Flow.Launcher.Core.Resource
|
|
|
|
|
|
|
|
|
|
public bool ChangeTheme(string theme = null)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(theme)) theme = _settings.Theme;
|
|
|
|
|
if (string.IsNullOrEmpty(theme))
|
|
|
|
|
theme = _settings.Theme;
|
|
|
|
|
|
|
|
|
|
string path = GetThemePath(theme);
|
|
|
|
|
try
|
|
|
|
|
@ -425,14 +426,13 @@ namespace Flow.Launcher.Core.Resource
|
|
|
|
|
|
|
|
|
|
_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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if blur is enabled
|
|
|
|
|
BlurEnabled = Win32Helper.IsBackdropSupported() && IsThemeBlurEnabled(resourceDict);
|
|
|
|
|
BlurEnabled = IsBlurTheme();
|
|
|
|
|
|
|
|
|
|
// Apply blur and drop shadow effect so that we do not need to call it again
|
|
|
|
|
_ = RefreshFrameAsync();
|
|
|
|
|
@ -667,21 +667,21 @@ namespace Flow.Launcher.Core.Resource
|
|
|
|
|
if (mainWindow == null) return;
|
|
|
|
|
|
|
|
|
|
// Check if the theme supports blur
|
|
|
|
|
var hasBlur = IsThemeBlurEnabled(dict);
|
|
|
|
|
bool hasBlur = dict.Contains("ThemeBlurEnabled") && dict["ThemeBlurEnabled"] is bool b && b;
|
|
|
|
|
if (BlurEnabled && hasBlur && Win32Helper.IsBackdropSupported())
|
|
|
|
|
{
|
|
|
|
|
// If the BackdropType is Mica or MicaAlt, set the windowborderstyle's background to transparent
|
|
|
|
|
if (backdropType is BackdropTypes.Mica or BackdropTypes.MicaAlt)
|
|
|
|
|
if (backdropType == BackdropTypes.Mica || backdropType == BackdropTypes.MicaAlt)
|
|
|
|
|
{
|
|
|
|
|
windowBorderStyle.Setters.Remove(windowBorderStyle.Setters.OfType<Setter>().FirstOrDefault(x => x.Property == Control.BackgroundProperty));
|
|
|
|
|
windowBorderStyle.Setters.Add(new Setter(Border.BackgroundProperty, ThemeHelper.GetFrozenSolidColorBrush(Color.FromArgb(1, 0, 0, 0))));
|
|
|
|
|
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))));
|
|
|
|
|
}
|
|
|
|
|
else if (backdropType == BackdropTypes.Acrylic)
|
|
|
|
|
{
|
|
|
|
|
windowBorderStyle.Setters.Remove(windowBorderStyle.Setters.OfType<Setter>().FirstOrDefault(x => x.Property == Control.BackgroundProperty));
|
|
|
|
|
windowBorderStyle.Setters.Add(new Setter(Border.BackgroundProperty, Brushes.Transparent));
|
|
|
|
|
windowBorderStyle.Setters.Remove(windowBorderStyle.Setters.OfType<Setter>().FirstOrDefault(x => x.Property.Name == "Background"));
|
|
|
|
|
windowBorderStyle.Setters.Add(new Setter(Border.BackgroundProperty, new SolidColorBrush(Colors.Transparent)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 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 +689,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);
|
|
|
|
|
@ -798,12 +798,12 @@ namespace Flow.Launcher.Core.Resource
|
|
|
|
|
Application.Current.Resources["WindowBorderStyle"] is Style originalStyle)
|
|
|
|
|
{
|
|
|
|
|
// Copy the original style, including the base style if it exists
|
|
|
|
|
ThemeHelper.CopyStyle(originalStyle, previewStyle);
|
|
|
|
|
CopyStyle(originalStyle, previewStyle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Apply background color (remove transparency in color)
|
|
|
|
|
var backgroundColor = Color.FromRgb(bgColor.Value.R, bgColor.Value.G, bgColor.Value.B);
|
|
|
|
|
previewStyle.Setters.Add(new Setter(Border.BackgroundProperty, ThemeHelper.GetFrozenSolidColorBrush(backgroundColor)));
|
|
|
|
|
Color backgroundColor = Color.FromRgb(bgColor.Value.R, bgColor.Value.G, bgColor.Value.B);
|
|
|
|
|
previewStyle.Setters.Add(new Setter(Border.BackgroundProperty, new SolidColorBrush(backgroundColor)));
|
|
|
|
|
|
|
|
|
|
// 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,6 +817,21 @@ namespace Flow.Launcher.Core.Resource
|
|
|
|
|
Application.Current.Resources["PreviewWindowBorderStyle"] = previewStyle;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CopyStyle(Style originalStyle, Style targetStyle)
|
|
|
|
|
{
|
|
|
|
|
// If the style is based on another style, copy the base style first
|
|
|
|
|
if (originalStyle.BasedOn != null)
|
|
|
|
|
{
|
|
|
|
|
CopyStyle(originalStyle.BasedOn, targetStyle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Copy the setters from the original style
|
|
|
|
|
foreach (var setter in originalStyle.Setters.OfType<Setter>())
|
|
|
|
|
{
|
|
|
|
|
targetStyle.Setters.Add(new Setter(setter.Property, setter.Value));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ColorizeWindow(string theme, BackdropTypes backdropType)
|
|
|
|
|
{
|
|
|
|
|
var dict = GetThemeResourceDictionary(theme);
|
|
|
|
|
@ -826,16 +841,20 @@ namespace Flow.Launcher.Core.Resource
|
|
|
|
|
if (mainWindow == null) return;
|
|
|
|
|
|
|
|
|
|
// Check if the theme supports blur
|
|
|
|
|
var hasBlur = IsThemeBlurEnabled(dict);
|
|
|
|
|
bool hasBlur = dict.Contains("ThemeBlurEnabled") && dict["ThemeBlurEnabled"] is bool b && b;
|
|
|
|
|
|
|
|
|
|
// SystemBG value check (Auto, Light, Dark)
|
|
|
|
|
var systemBG = dict.Contains("SystemBG") ? dict["SystemBG"] as string : "Auto"; // 기본값 Auto
|
|
|
|
|
string systemBG = dict.Contains("SystemBG") ? dict["SystemBG"] as string : "Auto"; // 기본값 Auto
|
|
|
|
|
|
|
|
|
|
// Check the user's ColorScheme setting
|
|
|
|
|
var colorScheme = _settings.ColorScheme;
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
// Final decision on whether to use dark mode
|
|
|
|
|
var useDarkMode = false;
|
|
|
|
|
bool useDarkMode = false;
|
|
|
|
|
|
|
|
|
|
// If systemBG is not "Auto", prioritize it over ColorScheme and set the mode based on systemBG value
|
|
|
|
|
if (systemBG == "Dark")
|
|
|
|
|
@ -850,20 +869,11 @@ 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
|
|
|
|
|
@ -905,20 +915,25 @@ namespace Flow.Launcher.Core.Resource
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Only set the background to transparent if the theme supports blur
|
|
|
|
|
if (backdropType is BackdropTypes.Mica or BackdropTypes.MicaAlt)
|
|
|
|
|
if (backdropType == BackdropTypes.Mica || backdropType == BackdropTypes.MicaAlt)
|
|
|
|
|
{
|
|
|
|
|
mainWindow.Background = ThemeHelper.GetFrozenSolidColorBrush(Color.FromArgb(1, 0, 0, 0));
|
|
|
|
|
mainWindow.Background = new SolidColorBrush(Color.FromArgb(1, 0, 0, 0));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
mainWindow.Background = ThemeHelper.GetFrozenSolidColorBrush(selectedBG);
|
|
|
|
|
mainWindow.Background = new SolidColorBrush(selectedBG);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static bool IsThemeBlurEnabled(ResourceDictionary dict)
|
|
|
|
|
private static bool IsBlurTheme()
|
|
|
|
|
{
|
|
|
|
|
return dict.Contains("ThemeBlurEnabled") && dict["ThemeBlurEnabled"] is bool enabled && enabled;
|
|
|
|
|
if (!Win32Helper.IsBackdropSupported()) // Windows 11 미만이면 무조건 false
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
var resource = Application.Current.TryFindResource("ThemeBlurEnabled");
|
|
|
|
|
|
|
|
|
|
return resource is bool b && b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|