11using System ;
2+ using System . Collections . Generic ;
3+ using System . IO ;
24using System . Linq ;
35using System . Runtime . InteropServices ;
4- using System . Text ;
5- using System . Windows . Documents ;
6+ using System . Windows ;
67using System . Windows . Media ;
8+ using System . Windows . Media . Imaging ;
79using Microsoft . Win32 ;
810using Windows . Win32 ;
911using Windows . Win32 . UI . WindowsAndMessaging ;
@@ -13,8 +15,70 @@ namespace Flow.Launcher.Helper;
1315public static class WallpaperPathRetrieval
1416{
1517 private static readonly int MAX_PATH = 260 ;
18+ private static readonly int MAX_CACHE_SIZE = 3 ;
1619
17- public static unsafe string GetWallpaperPath ( )
20+ private static readonly Dictionary < ( string , DateTime ) , ImageBrush > wallpaperCache = new ( ) ;
21+
22+ public static Brush GetWallpaperBrush ( )
23+ {
24+ // Invoke the method on the UI thread
25+ if ( ! Application . Current . Dispatcher . CheckAccess ( ) )
26+ {
27+ return Application . Current . Dispatcher . Invoke ( GetWallpaperBrush ) ;
28+ }
29+
30+ try
31+ {
32+ var wallpaperPath = GetWallpaperPath ( ) ;
33+ if ( wallpaperPath is not null && File . Exists ( wallpaperPath ) )
34+ {
35+ // Since the wallpaper file name can be the same (TranscodedWallpaper),
36+ // we need to add the last modified date to differentiate them
37+ var dateModified = File . GetLastWriteTime ( wallpaperPath ) ;
38+ wallpaperCache . TryGetValue ( ( wallpaperPath , dateModified ) , out var cachedWallpaper ) ;
39+ if ( cachedWallpaper != null )
40+ {
41+ return cachedWallpaper ;
42+ }
43+
44+ // We should not dispose the memory stream since the bitmap is still in use
45+ var memStream = new MemoryStream ( File . ReadAllBytes ( wallpaperPath ) ) ;
46+ var bitmap = new BitmapImage ( ) ;
47+ bitmap . BeginInit ( ) ;
48+ bitmap . StreamSource = memStream ;
49+ bitmap . DecodePixelWidth = 800 ;
50+ bitmap . DecodePixelHeight = 600 ;
51+ bitmap . EndInit ( ) ;
52+ bitmap . Freeze ( ) ; // Make the bitmap thread-safe
53+ var wallpaperBrush = new ImageBrush ( bitmap ) { Stretch = Stretch . UniformToFill } ;
54+ wallpaperBrush . Freeze ( ) ; // Make the brush thread-safe
55+
56+ // Manage cache size
57+ if ( wallpaperCache . Count >= MAX_CACHE_SIZE )
58+ {
59+ // Remove the oldest wallpaper from the cache
60+ var oldestCache = wallpaperCache . Keys . OrderBy ( k => k . Item2 ) . FirstOrDefault ( ) ;
61+ if ( oldestCache != default )
62+ {
63+ wallpaperCache . Remove ( oldestCache ) ;
64+ }
65+ }
66+
67+ wallpaperCache . Add ( ( wallpaperPath , dateModified ) , wallpaperBrush ) ;
68+ return wallpaperBrush ;
69+ }
70+
71+ var wallpaperColor = GetWallpaperColor ( ) ;
72+ return new SolidColorBrush ( wallpaperColor ) ;
73+ }
74+ catch ( Exception ex )
75+ {
76+ App . API . LogException ( nameof ( WallpaperPathRetrieval ) , "Error retrieving wallpaper" , ex ) ;
77+ return new SolidColorBrush ( Colors . Transparent ) ;
78+ }
79+ }
80+
81+ private static unsafe string GetWallpaperPath ( )
1882 {
1983 var wallpaperPtr = stackalloc char [ MAX_PATH ] ;
2084 PInvoke . SystemParametersInfo ( SYSTEM_PARAMETERS_INFO_ACTION . SPI_GETDESKWALLPAPER , ( uint ) MAX_PATH ,
@@ -25,7 +89,7 @@ public static unsafe string GetWallpaperPath()
2589 return wallpaper . ToString ( ) ;
2690 }
2791
28- public static Color GetWallpaperColor ( )
92+ private static Color GetWallpaperColor ( )
2993 {
3094 RegistryKey key = Registry . CurrentUser . OpenSubKey ( @"Control Panel\Colors" , true ) ;
3195 var result = key ? . GetValue ( "Background" , null ) ;
0 commit comments