Skip to content

Fix Preview in Welcome Window & Wallpaper Retriever Improvement #3398

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 55 additions & 29 deletions Flow.Launcher/Helper/WallpaperPathRetrieval.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ namespace Flow.Launcher.Helper;

public static class WallpaperPathRetrieval
{
private static readonly int MAX_CACHE_SIZE = 3;

private static readonly Dictionary<(string, DateTime), ImageBrush> wallpaperCache = new();
private const int MaxCacheSize = 3;
private static readonly Dictionary<(string, DateTime), ImageBrush> WallpaperCache = new();
private static readonly object CacheLock = new();

public static Brush GetWallpaperBrush()
{
Expand All @@ -27,46 +27,71 @@ public static Brush GetWallpaperBrush()
try
{
var wallpaperPath = Win32Helper.GetWallpaperPath();
if (wallpaperPath is not null && File.Exists(wallpaperPath))
if (string.IsNullOrEmpty(wallpaperPath) || !File.Exists(wallpaperPath))
{
App.API.LogInfo(nameof(WallpaperPathRetrieval), $"Wallpaper path is invalid: {wallpaperPath}");
var wallpaperColor = GetWallpaperColor();
return new SolidColorBrush(wallpaperColor);
}

// Since the wallpaper file name can be the same (TranscodedWallpaper),
// we need to add the last modified date to differentiate them
var dateModified = File.GetLastWriteTime(wallpaperPath);
lock (CacheLock)
{
// Since the wallpaper file name can be the same (TranscodedWallpaper),
// we need to add the last modified date to differentiate them
var dateModified = File.GetLastWriteTime(wallpaperPath);
wallpaperCache.TryGetValue((wallpaperPath, dateModified), out var cachedWallpaper);
WallpaperCache.TryGetValue((wallpaperPath, dateModified), out var cachedWallpaper);
if (cachedWallpaper != null)
{
return cachedWallpaper;
}
}

using var fileStream = File.OpenRead(wallpaperPath);
var decoder = BitmapDecoder.Create(fileStream, BitmapCreateOptions.DelayCreation, BitmapCacheOption.None);
var frame = decoder.Frames[0];
var originalWidth = frame.PixelWidth;
var originalHeight = frame.PixelHeight;

// We should not dispose the memory stream since the bitmap is still in use
var memStream = new MemoryStream(File.ReadAllBytes(wallpaperPath));
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = memStream;
bitmap.DecodePixelWidth = 800;
bitmap.DecodePixelHeight = 600;
bitmap.EndInit();
bitmap.Freeze(); // Make the bitmap thread-safe
var wallpaperBrush = new ImageBrush(bitmap) { Stretch = Stretch.UniformToFill };
wallpaperBrush.Freeze(); // Make the brush thread-safe
if (originalWidth == 0 || originalHeight == 0)
{
App.API.LogInfo(nameof(WallpaperPathRetrieval), $"Failed to load bitmap: Width={originalWidth}, Height={originalHeight}");
return new SolidColorBrush(Colors.Transparent);
}

// Calculate the scaling factor to fit the image within 800x600 while preserving aspect ratio
var widthRatio = 800.0 / originalWidth;
var heightRatio = 600.0 / originalHeight;
var scaleFactor = Math.Min(widthRatio, heightRatio);
var decodedPixelWidth = (int)(originalWidth * scaleFactor);
var decodedPixelHeight = (int)(originalHeight * scaleFactor);

// Set DecodePixelWidth and DecodePixelHeight to resize the image while preserving aspect ratio
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = new Uri(wallpaperPath);
bitmap.DecodePixelWidth = decodedPixelWidth;
bitmap.DecodePixelHeight = decodedPixelHeight;
bitmap.EndInit();
bitmap.Freeze(); // Make the bitmap thread-safe
var wallpaperBrush = new ImageBrush(bitmap) { Stretch = Stretch.UniformToFill };
wallpaperBrush.Freeze(); // Make the brush thread-safe

// Manage cache size
if (wallpaperCache.Count >= MAX_CACHE_SIZE)
// Manage cache size
lock (CacheLock)
{
if (WallpaperCache.Count >= MaxCacheSize)
{
// Remove the oldest wallpaper from the cache
var oldestCache = wallpaperCache.Keys.OrderBy(k => k.Item2).FirstOrDefault();
var oldestCache = WallpaperCache.Keys.OrderBy(k => k.Item2).FirstOrDefault();
if (oldestCache != default)
{
wallpaperCache.Remove(oldestCache);
WallpaperCache.Remove(oldestCache);
}
}

wallpaperCache.Add((wallpaperPath, dateModified), wallpaperBrush);
WallpaperCache.Add((wallpaperPath, dateModified), wallpaperBrush);
return wallpaperBrush;
}

var wallpaperColor = GetWallpaperColor();
return new SolidColorBrush(wallpaperColor);
}
catch (Exception ex)
{
Expand All @@ -77,7 +102,7 @@ public static Brush GetWallpaperBrush()

private static Color GetWallpaperColor()
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Colors", true);
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Colors", false);
var result = key?.GetValue("Background", null);
if (result is string strResult)
{
Expand All @@ -86,8 +111,9 @@ private static Color GetWallpaperColor()
var parts = strResult.Trim().Split(new[] { ' ' }, 3).Select(byte.Parse).ToList();
return Color.FromRgb(parts[0], parts[1], parts[2]);
}
catch
catch (Exception ex)
{
App.API.LogException(nameof(WallpaperPathRetrieval), "Error parsing wallpaper color", ex);
}
}

Expand Down
4 changes: 2 additions & 2 deletions Flow.Launcher/Resources/Pages/WelcomePage1.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@
<Border.Background>
<LinearGradientBrush StartPoint="0 0" EndPoint="1 1">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.0" Color="#1494df" />
<GradientStop Offset="1.0" Color="#1073bd" />
<GradientStop Offset="0.0" Color="#2A4D8C" />
<GradientStop Offset="1.0" Color="#1E3160" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
Expand Down
2 changes: 1 addition & 1 deletion Flow.Launcher/Resources/Pages/WelcomePage2.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Width="450" Style="{DynamicResource WindowBorderStyle}">
<Border Width="450" Style="{DynamicResource PreviewWindowBorderStyle}">
<Border Style="{DynamicResource WindowRadius}">
<Grid>
<Grid.RowDefinitions>
Expand Down
6 changes: 3 additions & 3 deletions Flow.Launcher/Resources/Pages/WelcomePage5.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@

<Border Grid.Row="0" HorizontalAlignment="Stretch">
<Border.Background>
<LinearGradientBrush StartPoint="0 0" EndPoint="1 1">
<LinearGradientBrush StartPoint="0 1" EndPoint="0 0">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.0" Color="#7b83eb" />
<GradientStop Offset="1.0" Color="#555dc0" />
<GradientStop Offset="0.0" Color="#E5F3F7" />
<GradientStop Offset="1.0" Color="#FAFAFD" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
Expand Down
Loading