From 9ac9ec849741194d48a964c7b3032bc174e2b923 Mon Sep 17 00:00:00 2001 From: DB p Date: Sat, 29 Mar 2025 18:10:03 +0900 Subject: [PATCH 1/2] - Fix Preview in WelcomePage - Adjust BG Color - Fix aspect ratio wallpaper bitmap --- .../Helper/WallpaperPathRetrieval.cs | 99 ++++++++++++------- .../Resources/Pages/WelcomePage1.xaml | 4 +- .../Resources/Pages/WelcomePage2.xaml | 2 +- .../Resources/Pages/WelcomePage5.xaml | 6 +- 4 files changed, 69 insertions(+), 42 deletions(-) diff --git a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs index 151ce97dd83..47a77f398c6 100644 --- a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs +++ b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs @@ -13,7 +13,6 @@ 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(); public static Brush GetWallpaperBrush() @@ -27,46 +26,73 @@ public static Brush GetWallpaperBrush() try { var wallpaperPath = Win32Helper.GetWallpaperPath(); - if (wallpaperPath is not null && File.Exists(wallpaperPath)) + if (string.IsNullOrEmpty(wallpaperPath) || !File.Exists(wallpaperPath)) { - // 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); - if (cachedWallpaper != null) - { - return cachedWallpaper; - } + 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); + wallpaperCache.TryGetValue((wallpaperPath, dateModified), out var cachedWallpaper); + if (cachedWallpaper != null) + { + App.API.LogInfo(nameof(WallpaperPathRetrieval), "Using cached wallpaper"); + return cachedWallpaper; + } + + // 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.EndInit(); + + if (bitmap.PixelWidth == 0 || bitmap.PixelHeight == 0) + { + App.API.LogInfo(nameof(WallpaperPathRetrieval), $"Failed to load bitmap: Width={bitmap.PixelWidth}, Height={bitmap.PixelHeight}"); + return new SolidColorBrush(Colors.Transparent); + } + + var originalWidth = bitmap.PixelWidth; + var originalHeight = bitmap.PixelHeight; + + // Calculate the scaling factor to fit the image within 800x600 while preserving aspect ratio + double widthRatio = 800.0 / originalWidth; + double heightRatio = 600.0 / originalHeight; + double scaleFactor = Math.Min(widthRatio, heightRatio); + + int decodedPixelWidth = (int)(originalWidth * scaleFactor); + int decodedPixelHeight = (int)(originalHeight * scaleFactor); - // 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 - - // Manage cache size - if (wallpaperCache.Count >= MAX_CACHE_SIZE) + // Set DecodePixelWidth and DecodePixelHeight to resize the image while preserving aspect ratio + bitmap = new BitmapImage(); + bitmap.BeginInit(); + memStream.Seek(0, SeekOrigin.Begin); // Reset stream position + bitmap.StreamSource = memStream; + 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) + { + // Remove the oldest wallpaper from the cache + var oldestCache = wallpaperCache.Keys.OrderBy(k => k.Item2).FirstOrDefault(); + if (oldestCache != default) { - // Remove the oldest wallpaper from the cache - var oldestCache = wallpaperCache.Keys.OrderBy(k => k.Item2).FirstOrDefault(); - if (oldestCache != default) - { - wallpaperCache.Remove(oldestCache); - } + wallpaperCache.Remove(oldestCache); } - - wallpaperCache.Add((wallpaperPath, dateModified), wallpaperBrush); - return wallpaperBrush; } - var wallpaperColor = GetWallpaperColor(); - return new SolidColorBrush(wallpaperColor); + wallpaperCache.Add((wallpaperPath, dateModified), wallpaperBrush); + return wallpaperBrush; + } catch (Exception ex) { @@ -86,8 +112,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); } } diff --git a/Flow.Launcher/Resources/Pages/WelcomePage1.xaml b/Flow.Launcher/Resources/Pages/WelcomePage1.xaml index 1728195bde9..32fdb62fc71 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage1.xaml +++ b/Flow.Launcher/Resources/Pages/WelcomePage1.xaml @@ -110,8 +110,8 @@ - - + + diff --git a/Flow.Launcher/Resources/Pages/WelcomePage2.xaml b/Flow.Launcher/Resources/Pages/WelcomePage2.xaml index 04c76d0277f..f62cec3bf12 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage2.xaml +++ b/Flow.Launcher/Resources/Pages/WelcomePage2.xaml @@ -60,7 +60,7 @@ HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal"> - + diff --git a/Flow.Launcher/Resources/Pages/WelcomePage5.xaml b/Flow.Launcher/Resources/Pages/WelcomePage5.xaml index c898ac9a02e..3df4b506ed2 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage5.xaml +++ b/Flow.Launcher/Resources/Pages/WelcomePage5.xaml @@ -58,10 +58,10 @@ - + - - + + From c685075436f904bc3142d8f7f211a123fcf762cb Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sat, 29 Mar 2025 21:01:30 +0800 Subject: [PATCH 2/2] Code quality & Lock & Bitmap memory & Registry access improvement --- .../Helper/WallpaperPathRetrieval.cs | 77 +++++++++---------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs index 47a77f398c6..77bebe2d37d 100644 --- a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs +++ b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs @@ -12,8 +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() { @@ -36,42 +37,38 @@ public static Brush GetWallpaperBrush() // 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); - if (cachedWallpaper != null) + lock (CacheLock) { - App.API.LogInfo(nameof(WallpaperPathRetrieval), "Using cached wallpaper"); - return cachedWallpaper; + WallpaperCache.TryGetValue((wallpaperPath, dateModified), out var cachedWallpaper); + if (cachedWallpaper != null) + { + return cachedWallpaper; + } } - - // 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.EndInit(); - - if (bitmap.PixelWidth == 0 || bitmap.PixelHeight == 0) + + 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; + + if (originalWidth == 0 || originalHeight == 0) { - App.API.LogInfo(nameof(WallpaperPathRetrieval), $"Failed to load bitmap: Width={bitmap.PixelWidth}, Height={bitmap.PixelHeight}"); + App.API.LogInfo(nameof(WallpaperPathRetrieval), $"Failed to load bitmap: Width={originalWidth}, Height={originalHeight}"); return new SolidColorBrush(Colors.Transparent); } - var originalWidth = bitmap.PixelWidth; - var originalHeight = bitmap.PixelHeight; - // Calculate the scaling factor to fit the image within 800x600 while preserving aspect ratio - double widthRatio = 800.0 / originalWidth; - double heightRatio = 600.0 / originalHeight; - double scaleFactor = Math.Min(widthRatio, heightRatio); - - int decodedPixelWidth = (int)(originalWidth * scaleFactor); - int decodedPixelHeight = (int)(originalHeight * scaleFactor); + 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 - bitmap = new BitmapImage(); + var bitmap = new BitmapImage(); bitmap.BeginInit(); - memStream.Seek(0, SeekOrigin.Begin); // Reset stream position - bitmap.StreamSource = memStream; + bitmap.UriSource = new Uri(wallpaperPath); bitmap.DecodePixelWidth = decodedPixelWidth; bitmap.DecodePixelHeight = decodedPixelHeight; bitmap.EndInit(); @@ -80,19 +77,21 @@ public static Brush GetWallpaperBrush() wallpaperBrush.Freeze(); // Make the brush thread-safe // Manage cache size - if (wallpaperCache.Count >= MAX_CACHE_SIZE) + lock (CacheLock) { - // Remove the oldest wallpaper from the cache - var oldestCache = wallpaperCache.Keys.OrderBy(k => k.Item2).FirstOrDefault(); - if (oldestCache != default) + if (WallpaperCache.Count >= MaxCacheSize) { - wallpaperCache.Remove(oldestCache); + // Remove the oldest wallpaper from the cache + var oldestCache = WallpaperCache.Keys.OrderBy(k => k.Item2).FirstOrDefault(); + if (oldestCache != default) + { + WallpaperCache.Remove(oldestCache); + } } - } - - wallpaperCache.Add((wallpaperPath, dateModified), wallpaperBrush); - return wallpaperBrush; + WallpaperCache.Add((wallpaperPath, dateModified), wallpaperBrush); + return wallpaperBrush; + } } catch (Exception ex) { @@ -103,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) { @@ -114,7 +113,7 @@ private static Color GetWallpaperColor() } catch (Exception ex) { - App.API.LogException(nameof(WallpaperPathRetrieval), "Error parsing wallpaper color", ex); + App.API.LogException(nameof(WallpaperPathRetrieval), "Error parsing wallpaper color", ex); } }