Skip to content

Commit 45887e0

Browse files
committed
Update
1 parent 6a85db5 commit 45887e0

File tree

4 files changed

+91
-41
lines changed

4 files changed

+91
-41
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright (c) Files Community
2+
// Licensed under the MIT License.
3+
4+
using Windows.Foundation;
5+
6+
namespace Files.App.Storage
7+
{
8+
public interface IWindowsFolderWatcher : IFolderWatcher
9+
{
10+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? EventOccurred;
11+
12+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? ItemAssocChanged; // SHCNE_ASSOCCHANGED
13+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? ItemAttributesChanged; // SHCNE_ATTRIBUTES
14+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? ItemImageUpdated; // SHCNE_UPDATEIMAGE
15+
16+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? FileRenamed; // SHCNE_RENAMEITEM
17+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? FileCreated; // SHCNE_CREATE
18+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? FileDeleted; // SHCNE_DELETE
19+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? FileUpdated; // SHCNE_UPDATEITEM
20+
21+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? FolderRenamed; // SHCNE_RENAMEFOLDER
22+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? FolderCreated; // SHCNE_MKDIR
23+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? FolderDeleted; // SHCNE_RMDIR
24+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? FolderUpdated; // SHCNE_UPDATEDIR
25+
26+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? MediaInserted; // SHCNE_MEDIAINSERTED
27+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? MediaRemoved; // SHCNE_MEDIAREMOVED
28+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? DriveRemoved; // SHCNE_DRIVEREMOVED
29+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? DriveAdded; // SHCNE_DRIVEADD
30+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? DriveAddedViaGUI; // SHCNE_DRIVEADDGUI
31+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? FreeSpaceUpdated; // SHCNE_FREESPACE
32+
33+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? SharingStarted; // SHCNE_NETSHARE
34+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? SharingStopped; // SHCNE_NETUNSHARE
35+
36+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? DisconnectedFromServer; // SHCNE_SERVERDISCONNECT
37+
38+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? ExtendedEventOccurred; // SHCNE_EXTENDED_EVENT
39+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? SystemInterruptOccurred; // SHCNE_INTERRUPT
40+
}
41+
}

src/Files.App.Storage/Storables/WindowsStorage/WindowsFolderWatcher.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ namespace Files.App.Storage
1616
/// <summary>
1717
/// Represents an implementation of <see cref="IFolderWatcher"/> that uses Windows Shell notifications to watch for changes in a folder.
1818
/// </summary>
19-
public unsafe partial class WindowsFolderWatcher : IFolderWatcher
19+
public unsafe partial class WindowsFolderWatcher : IWindowsFolderWatcher
2020
{
2121
// Fields
2222

2323
private const uint WM_NOTIFYFOLDERCHANGE = PInvoke.WM_APP | 0x0001U;
2424
private readonly WNDPROC _wndProc;
2525

2626
private uint _watcherRegID = 0U;
27-
private ITEMIDLIST* _targetItemPIDL = default;
27+
private ITEMIDLIST* _folderPidl = default;
2828

2929
// Properties
3030

@@ -34,6 +34,8 @@ public unsafe partial class WindowsFolderWatcher : IFolderWatcher
3434

3535
public event NotifyCollectionChangedEventHandler? CollectionChanged;
3636

37+
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? EventOccurred;
38+
3739
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? ItemAssocChanged; // SHCNE_ASSOCCHANGED
3840
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? ItemAttributesChanged; // SHCNE_ATTRIBUTES
3941
public event TypedEventHandler<WindowsFolderWatcher, WindowsFolderWatcherEventArgs>? ItemImageUpdated; // SHCNE_UPDATEIMAGE
@@ -86,6 +88,8 @@ public WindowsFolderWatcher(WindowsFolder folder)
8688
}
8789
}
8890

91+
// Methods
92+
8993
private unsafe LRESULT WndProc(HWND hWnd, uint uMessage, WPARAM wParam, LPARAM lParam)
9094
{
9195
switch (uMessage)
@@ -97,7 +101,7 @@ private unsafe LRESULT WndProc(HWND hWnd, uint uMessage, WPARAM wParam, LPARAM l
97101
ITEMIDLIST* pidl = default;
98102
IWindowsFolder folder = (IWindowsFolder)Folder;
99103
PInvoke.SHGetIDListFromObject((IUnknown*)folder.ThisPtr.Get(), &pidl);
100-
_targetItemPIDL = pidl;
104+
_folderPidl = pidl;
101105

102106
SHChangeNotifyEntry changeNotifyEntry = default;
103107
changeNotifyEntry.pidl = pidl;
@@ -123,7 +127,7 @@ private unsafe LRESULT WndProc(HWND hWnd, uint uMessage, WPARAM wParam, LPARAM l
123127
if (hLock.IsNull)
124128
break;
125129

126-
// TODO: Fire events
130+
FireEvent((SHCNE_ID)lEvent, ppidl);
127131

128132
PInvoke.SHChangeNotification_Unlock(hLock);
129133
}
@@ -140,6 +144,11 @@ private unsafe LRESULT WndProc(HWND hWnd, uint uMessage, WPARAM wParam, LPARAM l
140144

141145
private void FireEvent(SHCNE_ID eventType, ITEMIDLIST** ppidl)
142146
{
147+
//ITEMIDLIST* pOldPidl = ppidl[0];
148+
//ITEMIDLIST* pNewPidl = ppidl[1];
149+
150+
EventOccurred?.Invoke(this, new(eventType, null, null)); // WindowsStorable.TryParse(pOldPidl), WindowsStorable.TryParse(pNewPidl)
151+
143152
switch (eventType)
144153
{
145154
case SHCNE_ID.SHCNE_ASSOCCHANGED:
@@ -255,10 +264,12 @@ private void FireEvent(SHCNE_ID eventType, ITEMIDLIST** ppidl)
255264
}
256265
}
257266

267+
// Disposers
268+
258269
public void Dispose()
259270
{
260271
PInvoke.SHChangeNotifyDeregister(_watcherRegID);
261-
PInvoke.CoTaskMemFree(_targetItemPIDL);
272+
PInvoke.CoTaskMemFree(_folderPidl);
262273
PInvoke.CoUninitialize();
263274
PInvoke.PostQuitMessage(0);
264275
}

src/Files.App.Storage/Storables/WindowsStorage/WindowsStorable.cs

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Windows.Win32.Foundation;
66
using Windows.Win32.System.SystemServices;
77
using Windows.Win32.UI.Shell;
8+
using Windows.Win32.UI.Shell.Common;
89

910
namespace Files.App.Storage
1011
{
@@ -19,46 +20,59 @@ public abstract class WindowsStorable : IWindowsStorable
1920
public static unsafe WindowsStorable? TryParse(string parsablePath)
2021
{
2122
HRESULT hr = default;
22-
ComPtr<IShellItem> pShellItem = default;
23-
var IID_IShellItem = typeof(IShellItem).GUID;
23+
IShellItem* pShellItem = default;
2424

2525
fixed (char* pszParsablePath = parsablePath)
2626
{
2727
hr = PInvoke.SHCreateItemFromParsingName(
2828
pszParsablePath,
2929
null,
30-
&IID_IShellItem,
31-
(void**)pShellItem.GetAddressOf());
30+
IID.IID_IShellItem,
31+
(void**)&pShellItem);
3232
}
3333

34-
if (pShellItem.IsNull)
34+
if (hr.ThrowIfFailedOnDebug().Failed)
3535
return null;
3636

37-
return pShellItem.HasShellAttributes(SFGAO_FLAGS.SFGAO_FOLDER)
38-
? new WindowsFolder(pShellItem)
39-
: new WindowsFile(pShellItem);
37+
bool isFolder =
38+
pShellItem->GetAttributes(SFGAO_FLAGS.SFGAO_FOLDER, out var returnedAttributes).Succeeded &&
39+
returnedAttributes is SFGAO_FLAGS.SFGAO_FOLDER;
40+
41+
return isFolder ? new WindowsFolder(pShellItem) : new WindowsFile(pShellItem);
4042
}
4143

4244
public static unsafe WindowsStorable? TryParse(IShellItem* ptr)
4345
{
44-
ComPtr<IShellItem> pShellItem = default;
45-
pShellItem.Attach(ptr);
46+
bool isFolder =
47+
ptr->GetAttributes(SFGAO_FLAGS.SFGAO_FOLDER, out var returnedAttributes).Succeeded &&
48+
returnedAttributes is SFGAO_FLAGS.SFGAO_FOLDER;
49+
50+
return isFolder ? new WindowsFolder(ptr) : new WindowsFile(ptr);
51+
}
52+
53+
public static unsafe WindowsStorable? TryParse(ITEMIDLIST* pidl)
54+
{
55+
IShellItem* pShellItem = default;
56+
HRESULT hr = PInvoke.SHCreateItemFromIDList(pidl, IID.IID_IShellItem, (void**)&pShellItem);
57+
if (hr.ThrowIfFailedOnDebug().Failed || pShellItem is null)
58+
return null;
4659

47-
return pShellItem.HasShellAttributes(SFGAO_FLAGS.SFGAO_FOLDER)
48-
? new WindowsFolder(pShellItem)
49-
: new WindowsFile(pShellItem);
60+
bool isFolder =
61+
pShellItem->GetAttributes(SFGAO_FLAGS.SFGAO_FOLDER, out var returnedAttributes).Succeeded &&
62+
returnedAttributes is SFGAO_FLAGS.SFGAO_FOLDER;
63+
64+
return isFolder ? new WindowsFolder(pShellItem) : new WindowsFile(pShellItem);
5065
}
5166

5267
public unsafe Task<IFolder?> GetParentAsync(CancellationToken cancellationToken = default)
5368
{
5469
cancellationToken.ThrowIfCancellationRequested();
5570

56-
ComPtr<IShellItem> pParentFolder = default;
57-
HRESULT hr = ThisPtr.Get()->GetParent(pParentFolder.GetAddressOf());
71+
IShellItem* pParentFolder = default;
72+
HRESULT hr = ThisPtr.Get()->GetParent(&pParentFolder);
5873
if (hr.Failed)
5974
{
60-
if (!pParentFolder.IsNull) pParentFolder.Dispose();
61-
75+
if (pParentFolder is not null) pParentFolder->Release();
6276
return Task.FromResult<IFolder?>(null);
6377
}
6478

src/Files.App/ViewModels/UserControls/Widgets/QuickAccessWidgetViewModel.cs

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,7 @@ public sealed partial class QuickAccessWidgetViewModel : BaseWidgetViewModel, IW
3333

3434
// Fields
3535

36-
// TODO: Replace with IMutableFolder.GetWatcherAsync() once it gets implemented in IWindowsStorable
37-
private readonly SystemIO.FileSystemWatcher _quickAccessFolderWatcher;
38-
39-
private readonly IFolderWatcher _watcher;
36+
private readonly IWindowsFolderWatcher _watcher;
4037

4138
// Constructor
4239

@@ -49,21 +46,8 @@ public QuickAccessWidgetViewModel()
4946
UnpinFromSidebarCommand = new AsyncRelayCommand<WidgetFolderCardItem>(ExecuteUnpinFromSidebarCommand);
5047

5148
var quickAccessFolder = new WindowsFolder(new Guid("3936e9e4-d92c-4eee-a85a-bc16d5ea0819"));
52-
_watcher = quickAccessFolder.GetFolderWatcherAsync(default).Result;
53-
54-
//_quickAccessFolderWatcher = new()
55-
//{
56-
// Path = SystemIO.Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Microsoft", "Windows", "Recent", "AutomaticDestinations"),
57-
// Filter = "f01b4d95cf55d32a.automaticDestinations-ms",
58-
// NotifyFilter = SystemIO.NotifyFilters.LastAccess | SystemIO.NotifyFilters.LastWrite | SystemIO.NotifyFilters.FileName
59-
//};
60-
61-
//_quickAccessFolderWatcher.Changed += async (s, e) =>
62-
//{
63-
// await RefreshWidgetAsync();
64-
//};
65-
66-
//_quickAccessFolderWatcher.EnableRaisingEvents = true;
49+
_watcher = (IWindowsFolderWatcher)quickAccessFolder.GetFolderWatcherAsync(default).Result;
50+
_watcher.EventOccurred += async (s, e) => { await RefreshWidgetAsync(); };
6751
}
6852

6953
// Methods

0 commit comments

Comments
 (0)