@@ -12,9 +12,9 @@ namespace Flow.Launcher.Helper;
12
12
13
13
public static class WallpaperPathRetrieval
14
14
{
15
- private static readonly int MAX_CACHE_SIZE = 3 ;
16
-
17
- private static readonly Dictionary < ( string , DateTime ) , ImageBrush > wallpaperCache = new ( ) ;
15
+ private const int MaxCacheSize = 3 ;
16
+ private static readonly Dictionary < ( string , DateTime ) , ImageBrush > WallpaperCache = new ( ) ;
17
+ private static readonly object CacheLock = new ( ) ;
18
18
19
19
public static Brush GetWallpaperBrush ( )
20
20
{
@@ -27,46 +27,71 @@ public static Brush GetWallpaperBrush()
27
27
try
28
28
{
29
29
var wallpaperPath = Win32Helper . GetWallpaperPath ( ) ;
30
- if ( wallpaperPath is not null && File . Exists ( wallpaperPath ) )
30
+ if ( string . IsNullOrEmpty ( wallpaperPath ) || ! File . Exists ( wallpaperPath ) )
31
+ {
32
+ App . API . LogInfo ( nameof ( WallpaperPathRetrieval ) , $ "Wallpaper path is invalid: { wallpaperPath } ") ;
33
+ var wallpaperColor = GetWallpaperColor ( ) ;
34
+ return new SolidColorBrush ( wallpaperColor ) ;
35
+ }
36
+
37
+ // Since the wallpaper file name can be the same (TranscodedWallpaper),
38
+ // we need to add the last modified date to differentiate them
39
+ var dateModified = File . GetLastWriteTime ( wallpaperPath ) ;
40
+ lock ( CacheLock )
31
41
{
32
- // Since the wallpaper file name can be the same (TranscodedWallpaper),
33
- // we need to add the last modified date to differentiate them
34
- var dateModified = File . GetLastWriteTime ( wallpaperPath ) ;
35
- wallpaperCache . TryGetValue ( ( wallpaperPath , dateModified ) , out var cachedWallpaper ) ;
42
+ WallpaperCache . TryGetValue ( ( wallpaperPath , dateModified ) , out var cachedWallpaper ) ;
36
43
if ( cachedWallpaper != null )
37
44
{
38
45
return cachedWallpaper ;
39
46
}
47
+ }
48
+
49
+ using var fileStream = File . OpenRead ( wallpaperPath ) ;
50
+ var decoder = BitmapDecoder . Create ( fileStream , BitmapCreateOptions . DelayCreation , BitmapCacheOption . None ) ;
51
+ var frame = decoder . Frames [ 0 ] ;
52
+ var originalWidth = frame . PixelWidth ;
53
+ var originalHeight = frame . PixelHeight ;
40
54
41
- // We should not dispose the memory stream since the bitmap is still in use
42
- var memStream = new MemoryStream ( File . ReadAllBytes ( wallpaperPath ) ) ;
43
- var bitmap = new BitmapImage ( ) ;
44
- bitmap . BeginInit ( ) ;
45
- bitmap . StreamSource = memStream ;
46
- bitmap . DecodePixelWidth = 800 ;
47
- bitmap . DecodePixelHeight = 600 ;
48
- bitmap . EndInit ( ) ;
49
- bitmap . Freeze ( ) ; // Make the bitmap thread-safe
50
- var wallpaperBrush = new ImageBrush ( bitmap ) { Stretch = Stretch . UniformToFill } ;
51
- wallpaperBrush . Freeze ( ) ; // Make the brush thread-safe
55
+ if ( originalWidth == 0 || originalHeight == 0 )
56
+ {
57
+ App . API . LogInfo ( nameof ( WallpaperPathRetrieval ) , $ "Failed to load bitmap: Width={ originalWidth } , Height={ originalHeight } ") ;
58
+ return new SolidColorBrush ( Colors . Transparent ) ;
59
+ }
60
+
61
+ // Calculate the scaling factor to fit the image within 800x600 while preserving aspect ratio
62
+ var widthRatio = 800.0 / originalWidth ;
63
+ var heightRatio = 600.0 / originalHeight ;
64
+ var scaleFactor = Math . Min ( widthRatio , heightRatio ) ;
65
+ var decodedPixelWidth = ( int ) ( originalWidth * scaleFactor ) ;
66
+ var decodedPixelHeight = ( int ) ( originalHeight * scaleFactor ) ;
67
+
68
+ // Set DecodePixelWidth and DecodePixelHeight to resize the image while preserving aspect ratio
69
+ var bitmap = new BitmapImage ( ) ;
70
+ bitmap . BeginInit ( ) ;
71
+ bitmap . UriSource = new Uri ( wallpaperPath ) ;
72
+ bitmap . DecodePixelWidth = decodedPixelWidth ;
73
+ bitmap . DecodePixelHeight = decodedPixelHeight ;
74
+ bitmap . EndInit ( ) ;
75
+ bitmap . Freeze ( ) ; // Make the bitmap thread-safe
76
+ var wallpaperBrush = new ImageBrush ( bitmap ) { Stretch = Stretch . UniformToFill } ;
77
+ wallpaperBrush . Freeze ( ) ; // Make the brush thread-safe
52
78
53
- // Manage cache size
54
- if ( wallpaperCache . Count >= MAX_CACHE_SIZE )
79
+ // Manage cache size
80
+ lock ( CacheLock )
81
+ {
82
+ if ( WallpaperCache . Count >= MaxCacheSize )
55
83
{
56
84
// Remove the oldest wallpaper from the cache
57
- var oldestCache = wallpaperCache . Keys . OrderBy ( k => k . Item2 ) . FirstOrDefault ( ) ;
85
+ var oldestCache = WallpaperCache . Keys . OrderBy ( k => k . Item2 ) . FirstOrDefault ( ) ;
58
86
if ( oldestCache != default )
59
87
{
60
- wallpaperCache . Remove ( oldestCache ) ;
88
+ WallpaperCache . Remove ( oldestCache ) ;
61
89
}
62
90
}
63
91
64
- wallpaperCache . Add ( ( wallpaperPath , dateModified ) , wallpaperBrush ) ;
92
+ WallpaperCache . Add ( ( wallpaperPath , dateModified ) , wallpaperBrush ) ;
65
93
return wallpaperBrush ;
66
94
}
67
-
68
- var wallpaperColor = GetWallpaperColor ( ) ;
69
- return new SolidColorBrush ( wallpaperColor ) ;
70
95
}
71
96
catch ( Exception ex )
72
97
{
@@ -77,7 +102,7 @@ public static Brush GetWallpaperBrush()
77
102
78
103
private static Color GetWallpaperColor ( )
79
104
{
80
- RegistryKey key = Registry . CurrentUser . OpenSubKey ( @"Control Panel\Colors" , true ) ;
105
+ RegistryKey key = Registry . CurrentUser . OpenSubKey ( @"Control Panel\Colors" , false ) ;
81
106
var result = key ? . GetValue ( "Background" , null ) ;
82
107
if ( result is string strResult )
83
108
{
@@ -86,8 +111,9 @@ private static Color GetWallpaperColor()
86
111
var parts = strResult . Trim ( ) . Split ( new [ ] { ' ' } , 3 ) . Select ( byte . Parse ) . ToList ( ) ;
87
112
return Color . FromRgb ( parts [ 0 ] , parts [ 1 ] , parts [ 2 ] ) ;
88
113
}
89
- catch
114
+ catch ( Exception ex )
90
115
{
116
+ App . API . LogException ( nameof ( WallpaperPathRetrieval ) , "Error parsing wallpaper color" , ex ) ;
91
117
}
92
118
}
93
119
0 commit comments