Skip to content

Commit 98eb6b4

Browse files
0x5bfayaira2
authored andcommitted
Code Quality: Introduced IWindowsWallpaperService (#15811)
1 parent f7cac70 commit 98eb6b4

9 files changed

+170
-87
lines changed

src/Files.App/Actions/Content/Background/BaseSetAsAction.cs

+18
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// Copyright (c) 2024 Files Community
22
// Licensed under the MIT License. See the LICENSE.
33

4+
using Microsoft.UI.Xaml.Controls;
5+
using Windows.Foundation.Metadata;
6+
47
namespace Files.App.Actions
58
{
69
internal abstract class BaseSetAsAction : ObservableObject, IAction
@@ -28,6 +31,21 @@ public BaseSetAsAction()
2831

2932
public abstract Task ExecuteAsync(object? parameter = null);
3033

34+
protected async void ShowErrorDialog(string message)
35+
{
36+
var errorDialog = new ContentDialog()
37+
{
38+
Title = "FailedToSetBackground".GetLocalizedResource(),
39+
Content = message,
40+
PrimaryButtonText = "OK".GetLocalizedResource(),
41+
};
42+
43+
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
44+
errorDialog.XamlRoot = MainWindow.Instance.Content.XamlRoot;
45+
46+
await errorDialog.TryShowAsync();
47+
}
48+
3149
private void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)
3250
{
3351
switch (e.PropertyName)

src/Files.App/Actions/Content/Background/SetAsLockscreenBackgroundAction.cs

+14-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ namespace Files.App.Actions
55
{
66
internal sealed class SetAsLockscreenBackgroundAction : BaseSetAsAction
77
{
8+
private readonly IWindowsWallpaperService WindowsWallpaperService = Ioc.Default.GetRequiredService<IWindowsWallpaperService>();
9+
810
public override string Label
911
=> "SetAsLockscreen".GetLocalizedResource();
1012

@@ -20,10 +22,19 @@ public override RichGlyph Glyph
2022

2123
public override Task ExecuteAsync(object? parameter = null)
2224
{
23-
if (context.SelectedItem is not null)
24-
return WallpaperHelpers.SetAsBackgroundAsync(WallpaperType.LockScreen, context.SelectedItem.ItemPath);
25+
if (context.SelectedItem is null)
26+
return Task.CompletedTask;
27+
28+
try
29+
{
30+
return WindowsWallpaperService.SetLockScreenWallpaper(context.SelectedItem.ItemPath);
31+
}
32+
catch (Exception ex)
33+
{
34+
ShowErrorDialog(ex.Message);
2535

26-
return Task.CompletedTask;
36+
return Task.CompletedTask;
37+
}
2738
}
2839
}
2940
}

src/Files.App/Actions/Content/Background/SetAsSlideshowBackgroundAction.cs

+11-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ namespace Files.App.Actions
55
{
66
internal sealed class SetAsSlideshowBackgroundAction : BaseSetAsAction
77
{
8+
private readonly IWindowsWallpaperService WindowsWallpaperService = Ioc.Default.GetRequiredService<IWindowsWallpaperService>();
9+
810
public override string Label
911
=> "SetAsSlideshow".GetLocalizedResource();
1012

@@ -21,7 +23,15 @@ public override RichGlyph Glyph
2123
public override Task ExecuteAsync(object? parameter = null)
2224
{
2325
var paths = context.SelectedItems.Select(item => item.ItemPath).ToArray();
24-
WallpaperHelpers.SetSlideshow(paths);
26+
27+
try
28+
{
29+
WindowsWallpaperService.SetDesktopSlideshow(paths);
30+
}
31+
catch (Exception ex)
32+
{
33+
ShowErrorDialog(ex.Message);
34+
}
2535

2636
return Task.CompletedTask;
2737
}

src/Files.App/Actions/Content/Background/SetAsWallpaperBackgroundAction.cs

+13-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ namespace Files.App.Actions
55
{
66
internal sealed class SetAsWallpaperBackgroundAction : BaseSetAsAction
77
{
8+
private readonly IWindowsWallpaperService WindowsWallpaperService = Ioc.Default.GetRequiredService<IWindowsWallpaperService>();
9+
810
public override string Label
911
=> "SetAsBackground".GetLocalizedResource();
1012

@@ -20,8 +22,17 @@ public override RichGlyph Glyph
2022

2123
public override Task ExecuteAsync(object? parameter = null)
2224
{
23-
if (context.SelectedItem is not null)
24-
return WallpaperHelpers.SetAsBackgroundAsync(WallpaperType.Desktop, context.SelectedItem.ItemPath);
25+
if (context.SelectedItem is null)
26+
return Task.CompletedTask;
27+
28+
try
29+
{
30+
WindowsWallpaperService.SetDesktopWallpaper(context.SelectedItem.ItemPath);
31+
}
32+
catch (Exception ex)
33+
{
34+
ShowErrorDialog(ex.Message);
35+
}
2536

2637
return Task.CompletedTask;
2738
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (c) 2024 Files Community
2+
// Licensed under the MIT License. See the LICENSE.
3+
4+
namespace Files.App.Data.Contracts
5+
{
6+
/// <summary>
7+
/// Provides service for manipulating shell wallpapers on Windows.
8+
/// </summary>
9+
public interface IWindowsWallpaperService
10+
{
11+
/// <summary>
12+
/// Sets desktop wallpaper using the specified image path.
13+
/// </summary>
14+
/// <param name="szPath">The image path to assign as the desktop wallpaper.</param>
15+
void SetDesktopWallpaper(string szPath);
16+
17+
/// <summary>
18+
/// Sets desktop slideshow using the specified image paths.
19+
/// </summary>
20+
/// <param name="aszPaths">The image paths to use to set as slideshow.</param>
21+
void SetDesktopSlideshow(string[] aszPaths);
22+
23+
/// <summary>
24+
/// Gets lock screen wallpaper using the specified image path.
25+
/// </summary>
26+
/// <param name="szPath">The image path to use to set as lock screen wallpaper.</param>
27+
Task SetLockScreenWallpaper(string szPath);
28+
}
29+
}

src/Files.App/Helpers/Application/AppLifecycleHelper.cs

+1
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ public static IHost ConfigureHost()
165165
.AddSingleton<ISidebarContext, SidebarContext>()
166166
// Services
167167
.AddSingleton<IWindowsIniService, WindowsIniService>()
168+
.AddSingleton<IWindowsWallpaperService, WindowsWallpaperService>()
168169
.AddSingleton<IAppThemeModeService, AppThemeModeService>()
169170
.AddSingleton<IDialogService, DialogService>()
170171
.AddSingleton<ICommonDialogService, CommonDialogService>()

src/Files.App/NativeMethods.txt

+5
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,8 @@ LocalAlloc
8989
InitializeAcl
9090
AddAce
9191
LocalFree
92+
IDesktopWallpaper
93+
DesktopWallpaper
94+
SHCreateShellItemArrayFromIDLists
95+
ILCreateFromPath
96+
CLSIDFromString
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright (c) 2024 Files Community
2+
// Licensed under the MIT License. See the LICENSE.
3+
4+
using Windows.Storage;
5+
using Windows.System.UserProfile;
6+
using Windows.Win32;
7+
using Windows.Win32.Foundation;
8+
using Windows.Win32.System.Com;
9+
using Windows.Win32.UI.Shell;
10+
using Windows.Win32.UI.Shell.Common;
11+
12+
namespace Files.App.Services
13+
{
14+
/// <inheritdoc cref="IWindowsWallpaperService"/>
15+
public sealed class WindowsWallpaperService : IWindowsWallpaperService
16+
{
17+
/// <inheritdoc/>
18+
public unsafe void SetDesktopWallpaper(string szPath)
19+
{
20+
PInvoke.CoCreateInstance(
21+
new Guid("{C2CF3110-460E-4fc1-B9D0-8A1C0C9CC4BD}"),
22+
null,
23+
CLSCTX.CLSCTX_LOCAL_SERVER,
24+
out IDesktopWallpaper desktopWallpaper)
25+
.ThrowOnFailure();
26+
27+
desktopWallpaper.GetMonitorDevicePathCount(out var dwMonitorCount);
28+
29+
fixed (char* pszPath = szPath)
30+
{
31+
var pwszPath = new PWSTR(pszPath);
32+
33+
for (uint dwIndex = 0; dwIndex < dwMonitorCount; dwIndex++)
34+
{
35+
desktopWallpaper.GetMonitorDevicePathAt(dwIndex, out var pMonitorID);
36+
desktopWallpaper.SetWallpaper(pMonitorID, pwszPath);
37+
}
38+
}
39+
}
40+
41+
/// <inheritdoc/>
42+
public unsafe void SetDesktopSlideshow(string[] aszPaths)
43+
{
44+
PInvoke.CoCreateInstance(
45+
new Guid("{C2CF3110-460E-4fc1-B9D0-8A1C0C9CC4BD}"),
46+
null,
47+
CLSCTX.CLSCTX_LOCAL_SERVER,
48+
out IDesktopWallpaper desktopWallpaper)
49+
.ThrowOnFailure();
50+
51+
var dwCount = (uint)aszPaths.Length;
52+
53+
fixed (ITEMIDLIST** idList = new ITEMIDLIST*[dwCount])
54+
{
55+
for (uint dwIndex = 0u; dwIndex < dwCount; dwIndex++)
56+
{
57+
var id = PInvoke.ILCreateFromPath(aszPaths[dwIndex]);
58+
idList[dwIndex] = id;
59+
}
60+
61+
// Get shell item array from images to use for slideshow
62+
PInvoke.SHCreateShellItemArrayFromIDLists(dwCount, idList, out var shellItemArray);
63+
64+
// Set slideshow
65+
desktopWallpaper.SetSlideshow(shellItemArray);
66+
}
67+
68+
// Set wallpaper to fill desktop.
69+
desktopWallpaper.SetPosition(DESKTOP_WALLPAPER_POSITION.DWPOS_FILL);
70+
}
71+
72+
/// <inheritdoc/>
73+
public async Task SetLockScreenWallpaper(string szPath)
74+
{
75+
IStorageFile sourceFile = await StorageFile.GetFileFromPathAsync(szPath);
76+
await LockScreen.SetImageFileAsync(sourceFile);
77+
}
78+
}
79+
}

src/Files.App/Utils/Global/WallpaperHelpers.cs

-81
This file was deleted.

0 commit comments

Comments
 (0)