mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-06-07 09:28:03 +08:00
[FancyZones] Implement File Watcher (#8603)
* Implement File Watcher in FancyZones * Simplify code, address PR comments * Add check to result of CreateEventW * Rebase fix Removed unneeded newline. If we keep it now, VS will just remove it some other time.
This commit is contained in:
parent
540e16b179
commit
e2ca4177dd
@ -10,6 +10,7 @@
|
|||||||
#include "lib/ZoneWindow.h"
|
#include "lib/ZoneWindow.h"
|
||||||
#include "lib/FancyZonesData.h"
|
#include "lib/FancyZonesData.h"
|
||||||
#include "lib/ZoneSet.h"
|
#include "lib/ZoneSet.h"
|
||||||
|
#include "lib/FileWatcher.h"
|
||||||
#include "lib/WindowMoveHandler.h"
|
#include "lib/WindowMoveHandler.h"
|
||||||
#include "lib/FancyZonesWinHookEventIDs.h"
|
#include "lib/FancyZonesWinHookEventIDs.h"
|
||||||
#include "lib/util.h"
|
#include "lib/util.h"
|
||||||
@ -50,6 +51,9 @@ public:
|
|||||||
m_settings(settings),
|
m_settings(settings),
|
||||||
m_windowMoveHandler(settings, [this]() {
|
m_windowMoveHandler(settings, [this]() {
|
||||||
PostMessageW(m_window, WM_PRIV_LOCATIONCHANGE, NULL, NULL);
|
PostMessageW(m_window, WM_PRIV_LOCATIONCHANGE, NULL, NULL);
|
||||||
|
}),
|
||||||
|
m_fileWatcher(FancyZonesDataInstance().GetZonesSettingsFileName(), [this]() {
|
||||||
|
PostMessageW(m_window, WM_PRIV_FILE_UPDATE, NULL, NULL);
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
m_settings->SetCallback(this);
|
m_settings->SetCallback(this);
|
||||||
@ -221,6 +225,7 @@ private:
|
|||||||
void MoveWindowIntoZone(HWND window, winrt::com_ptr<IZoneWindow> zoneWindow, const std::vector<size_t>& zoneIndexSet) noexcept;
|
void MoveWindowIntoZone(HWND window, winrt::com_ptr<IZoneWindow> zoneWindow, const std::vector<size_t>& zoneIndexSet) noexcept;
|
||||||
|
|
||||||
void OnEditorExitEvent() noexcept;
|
void OnEditorExitEvent() noexcept;
|
||||||
|
void UpdateZoneSets() noexcept;
|
||||||
bool ShouldProcessSnapHotkey(DWORD vkCode) noexcept;
|
bool ShouldProcessSnapHotkey(DWORD vkCode) noexcept;
|
||||||
|
|
||||||
std::vector<std::pair<HMONITOR, RECT>> GetRawMonitorData() noexcept;
|
std::vector<std::pair<HMONITOR, RECT>> GetRawMonitorData() noexcept;
|
||||||
@ -232,6 +237,7 @@ private:
|
|||||||
HWND m_window{};
|
HWND m_window{};
|
||||||
WindowMoveHandler m_windowMoveHandler;
|
WindowMoveHandler m_windowMoveHandler;
|
||||||
MonitorWorkAreaHandler m_workAreaHandler;
|
MonitorWorkAreaHandler m_workAreaHandler;
|
||||||
|
FileWatcher m_fileWatcher;
|
||||||
|
|
||||||
winrt::com_ptr<IFancyZonesSettings> m_settings{};
|
winrt::com_ptr<IFancyZonesSettings> m_settings{};
|
||||||
GUID m_previousDesktopId{}; // UUID of previously active virtual desktop.
|
GUID m_previousDesktopId{}; // UUID of previously active virtual desktop.
|
||||||
@ -249,6 +255,7 @@ private:
|
|||||||
static UINT WM_PRIV_VD_SWITCH; // Scheduled when virtual desktop switch occurs
|
static UINT WM_PRIV_VD_SWITCH; // Scheduled when virtual desktop switch occurs
|
||||||
static UINT WM_PRIV_VD_UPDATE; // Scheduled on virtual desktops update (creation/deletion)
|
static UINT WM_PRIV_VD_UPDATE; // Scheduled on virtual desktops update (creation/deletion)
|
||||||
static UINT WM_PRIV_EDITOR; // Scheduled when the editor exits
|
static UINT WM_PRIV_EDITOR; // Scheduled when the editor exits
|
||||||
|
static UINT WM_PRIV_FILE_UPDATE; // Scheduled when the a watched file is updated
|
||||||
|
|
||||||
static UINT WM_PRIV_LOWLEVELKB; // Scheduled when we receive a key down press
|
static UINT WM_PRIV_LOWLEVELKB; // Scheduled when we receive a key down press
|
||||||
|
|
||||||
@ -266,6 +273,7 @@ UINT FancyZones::WM_PRIV_VD_INIT = RegisterWindowMessage(L"{469818a8-00fa-4069-b
|
|||||||
UINT FancyZones::WM_PRIV_VD_SWITCH = RegisterWindowMessage(L"{128c2cb0-6bdf-493e-abbe-f8705e04aa95}");
|
UINT FancyZones::WM_PRIV_VD_SWITCH = RegisterWindowMessage(L"{128c2cb0-6bdf-493e-abbe-f8705e04aa95}");
|
||||||
UINT FancyZones::WM_PRIV_VD_UPDATE = RegisterWindowMessage(L"{b8b72b46-f42f-4c26-9e20-29336cf2f22e}");
|
UINT FancyZones::WM_PRIV_VD_UPDATE = RegisterWindowMessage(L"{b8b72b46-f42f-4c26-9e20-29336cf2f22e}");
|
||||||
UINT FancyZones::WM_PRIV_EDITOR = RegisterWindowMessage(L"{87543824-7080-4e91-9d9c-0404642fc7b6}");
|
UINT FancyZones::WM_PRIV_EDITOR = RegisterWindowMessage(L"{87543824-7080-4e91-9d9c-0404642fc7b6}");
|
||||||
|
UINT FancyZones::WM_PRIV_FILE_UPDATE = RegisterWindowMessage(L"{632f17a9-55a7-45f1-a4db-162e39271d92}");
|
||||||
UINT FancyZones::WM_PRIV_LOWLEVELKB = RegisterWindowMessage(L"{763c03a3-03d9-4cde-8d71-f0358b0b4b52}");
|
UINT FancyZones::WM_PRIV_LOWLEVELKB = RegisterWindowMessage(L"{763c03a3-03d9-4cde-8d71-f0358b0b4b52}");
|
||||||
|
|
||||||
// IFancyZones
|
// IFancyZones
|
||||||
@ -856,6 +864,11 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
|
|||||||
auto hwnd = reinterpret_cast<HWND>(wparam);
|
auto hwnd = reinterpret_cast<HWND>(wparam);
|
||||||
WindowCreated(hwnd);
|
WindowCreated(hwnd);
|
||||||
}
|
}
|
||||||
|
else if (message == WM_PRIV_FILE_UPDATE)
|
||||||
|
{
|
||||||
|
FancyZonesDataInstance().LoadFancyZonesData();
|
||||||
|
UpdateZoneSets();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return DefWindowProc(window, message, wparam, lparam);
|
return DefWindowProc(window, message, wparam, lparam);
|
||||||
@ -1296,7 +1309,11 @@ void FancyZones::OnEditorExitEvent() noexcept
|
|||||||
{
|
{
|
||||||
// Collect information about changes in zone layout after editor exited.
|
// Collect information about changes in zone layout after editor exited.
|
||||||
FancyZonesDataInstance().ParseDataFromTmpFiles();
|
FancyZonesDataInstance().ParseDataFromTmpFiles();
|
||||||
|
UpdateZoneSets();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FancyZones::UpdateZoneSets() noexcept
|
||||||
|
{
|
||||||
for (auto workArea : m_workAreaHandler.GetAllWorkAreas())
|
for (auto workArea : m_workAreaHandler.GetAllWorkAreas())
|
||||||
{
|
{
|
||||||
workArea->UpdateActiveZoneSet();
|
workArea->UpdateActiveZoneSet();
|
||||||
|
@ -59,6 +59,11 @@ public:
|
|||||||
return appZoneHistoryMap;
|
return appZoneHistoryMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const std::wstring& GetZonesSettingsFileName() const
|
||||||
|
{
|
||||||
|
return zonesSettingsFileName;
|
||||||
|
}
|
||||||
|
|
||||||
bool AddDevice(const std::wstring& deviceId);
|
bool AddDevice(const std::wstring& deviceId);
|
||||||
void CloneDeviceInfo(const std::wstring& source, const std::wstring& destination);
|
void CloneDeviceInfo(const std::wstring& source, const std::wstring& destination);
|
||||||
void UpdatePrimaryDesktopData(const std::wstring& desktopId);
|
void UpdatePrimaryDesktopData(const std::wstring& desktopId);
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
<ClInclude Include="FancyZones.h" />
|
<ClInclude Include="FancyZones.h" />
|
||||||
<ClInclude Include="FancyZonesDataTypes.h" />
|
<ClInclude Include="FancyZonesDataTypes.h" />
|
||||||
<ClInclude Include="FancyZonesWinHookEventIDs.h" />
|
<ClInclude Include="FancyZonesWinHookEventIDs.h" />
|
||||||
|
<ClInclude Include="FileWatcher.h" />
|
||||||
<ClInclude Include="GenericKeyHook.h" />
|
<ClInclude Include="GenericKeyHook.h" />
|
||||||
<ClInclude Include="FancyZonesData.h" />
|
<ClInclude Include="FancyZonesData.h" />
|
||||||
<ClInclude Include="JsonHelpers.h" />
|
<ClInclude Include="JsonHelpers.h" />
|
||||||
@ -64,6 +65,7 @@
|
|||||||
<ClCompile Include="FancyZonesDataTypes.cpp" />
|
<ClCompile Include="FancyZonesDataTypes.cpp" />
|
||||||
<ClCompile Include="FancyZonesWinHookEventIDs.cpp" />
|
<ClCompile Include="FancyZonesWinHookEventIDs.cpp" />
|
||||||
<ClCompile Include="FancyZonesData.cpp" />
|
<ClCompile Include="FancyZonesData.cpp" />
|
||||||
|
<ClCompile Include="FileWatcher.cpp" />
|
||||||
<ClCompile Include="JsonHelpers.cpp" />
|
<ClCompile Include="JsonHelpers.cpp" />
|
||||||
<ClCompile Include="MonitorWorkAreaHandler.cpp" />
|
<ClCompile Include="MonitorWorkAreaHandler.cpp" />
|
||||||
<ClCompile Include="OnThreadExecutor.cpp" />
|
<ClCompile Include="OnThreadExecutor.cpp" />
|
||||||
|
@ -78,6 +78,9 @@
|
|||||||
<ClInclude Include="ZoneWindowDrawing.h">
|
<ClInclude Include="ZoneWindowDrawing.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="FileWatcher.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="pch.cpp">
|
<ClCompile Include="pch.cpp">
|
||||||
@ -134,6 +137,9 @@
|
|||||||
<ClCompile Include="OnThreadExecutor.cpp">
|
<ClCompile Include="OnThreadExecutor.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="FileWatcher.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
|
68
src/modules/fancyzones/lib/FileWatcher.cpp
Normal file
68
src/modules/fancyzones/lib/FileWatcher.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "FileWatcher.h"
|
||||||
|
|
||||||
|
std::optional<FILETIME> FileWatcher::MyFileTime()
|
||||||
|
{
|
||||||
|
HANDLE hFile = CreateFileW(m_path.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||||
|
std::optional<FILETIME> result;
|
||||||
|
if (hFile != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
FILETIME lastWrite;
|
||||||
|
if (GetFileTime(hFile, nullptr, nullptr, &lastWrite))
|
||||||
|
{
|
||||||
|
result = lastWrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(hFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileWatcher::Run()
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
auto lastWrite = MyFileTime();
|
||||||
|
if (!m_lastWrite.has_value())
|
||||||
|
{
|
||||||
|
m_lastWrite = lastWrite;
|
||||||
|
}
|
||||||
|
else if (lastWrite.has_value())
|
||||||
|
{
|
||||||
|
if (m_lastWrite->dwHighDateTime != lastWrite->dwHighDateTime ||
|
||||||
|
m_lastWrite->dwLowDateTime != lastWrite->dwLowDateTime)
|
||||||
|
{
|
||||||
|
m_lastWrite = lastWrite;
|
||||||
|
m_callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WaitForSingleObject(m_abortEvent, m_refreshPeriod) == WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileWatcher::FileWatcher(const std::wstring& path, std::function<void()> callback, DWORD refreshPeriod) :
|
||||||
|
m_refreshPeriod(refreshPeriod),
|
||||||
|
m_path(path),
|
||||||
|
m_callback(callback)
|
||||||
|
{
|
||||||
|
m_abortEvent = CreateEventW(nullptr, TRUE, FALSE, nullptr);
|
||||||
|
if (m_abortEvent)
|
||||||
|
{
|
||||||
|
m_thread = std::thread([this]() { Run(); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileWatcher::~FileWatcher()
|
||||||
|
{
|
||||||
|
if (m_abortEvent)
|
||||||
|
{
|
||||||
|
SetEvent(m_abortEvent);
|
||||||
|
m_thread.join();
|
||||||
|
CloseHandle(m_abortEvent);
|
||||||
|
}
|
||||||
|
}
|
19
src/modules/fancyzones/lib/FileWatcher.h
Normal file
19
src/modules/fancyzones/lib/FileWatcher.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
class FileWatcher
|
||||||
|
{
|
||||||
|
DWORD m_refreshPeriod;
|
||||||
|
std::wstring m_path;
|
||||||
|
std::optional<FILETIME> m_lastWrite;
|
||||||
|
std::function<void()> m_callback;
|
||||||
|
HANDLE m_abortEvent;
|
||||||
|
std::thread m_thread;
|
||||||
|
|
||||||
|
std::optional<FILETIME> MyFileTime();
|
||||||
|
void Run();
|
||||||
|
public:
|
||||||
|
FileWatcher(const std::wstring& path, std::function<void()> callback, DWORD refreshPeriod = 1000);
|
||||||
|
~FileWatcher();
|
||||||
|
};
|
@ -21,6 +21,7 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <ShObjIdl.h>
|
#include <ShObjIdl.h>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#pragma comment(lib, "windowsapp")
|
#pragma comment(lib, "windowsapp")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user