mirror of
https://github.com/microsoft/PowerToys.git
synced 2024-11-27 14:59:16 +08:00
[FancyZones] Split zones-settings: layout hotkeys (#15514)
This commit is contained in:
parent
a96187bd04
commit
ba431c5bfd
1
.github/actions/spell-check/expect.txt
vendored
1
.github/actions/spell-check/expect.txt
vendored
@ -1951,6 +1951,7 @@ textblock
|
||||
TEXTINCLUDE
|
||||
THICKFRAME
|
||||
THISCOMPONENT
|
||||
THotkey
|
||||
thre
|
||||
TILEDWINDOW
|
||||
timedate
|
||||
|
@ -12,8 +12,8 @@
|
||||
#include <common/utils/resources.h>
|
||||
|
||||
#include <FancyZonesLib/FancyZones.h>
|
||||
#include <FancyZonesLib/FancyZonesData.h>
|
||||
#include <FancyZonesLib/FancyZonesWinHookEventIDs.h>
|
||||
#include <FancyZonesLib/ModuleConstants.h>
|
||||
|
||||
#include <FancyZonesApp.h>
|
||||
|
||||
@ -61,7 +61,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
|
||||
|
||||
Trace::RegisterProvider();
|
||||
|
||||
FancyZonesApp app(GET_RESOURCE_STRING(IDS_FANCYZONES), NonLocalizable::FancyZonesStr);
|
||||
FancyZonesApp app(GET_RESOURCE_STRING(IDS_FANCYZONES), NonLocalizable::ModuleKey);
|
||||
app.Run();
|
||||
|
||||
run_message_loop();
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <common/SettingsAPI/FileWatcher.h>
|
||||
|
||||
#include <FancyZonesLib/FancyZonesData.h>
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutHotkeys.h>
|
||||
#include <FancyZonesLib/FancyZonesWindowProperties.h>
|
||||
#include <FancyZonesLib/FancyZonesWinHookEventIDs.h>
|
||||
#include <FancyZonesLib/MonitorUtils.h>
|
||||
@ -68,6 +69,9 @@ public:
|
||||
})
|
||||
{
|
||||
this->disableModuleCallback = std::move(disableModuleCallback);
|
||||
|
||||
FancyZonesDataInstance().ReplaceZoneSettingsFileFromOlderVersions();
|
||||
LayoutHotkeys::instance().LoadData();
|
||||
}
|
||||
|
||||
// IFancyZones
|
||||
@ -486,8 +490,8 @@ FancyZones::OnKeyDown(PKBDLLHOOKSTRUCT info) noexcept
|
||||
|
||||
if (changeLayoutWhileNotDragging || changeLayoutWhileDragging)
|
||||
{
|
||||
auto quickKeysMap = FancyZonesDataInstance().GetLayoutQuickKeys();
|
||||
if (std::any_of(quickKeysMap.begin(), quickKeysMap.end(), [=](auto item) { return item.second == digitPressed; }))
|
||||
auto layoutId = LayoutHotkeys::instance().GetLayoutId(digitPressed);
|
||||
if (layoutId.has_value())
|
||||
{
|
||||
PostMessageW(m_window, WM_PRIV_QUICK_LAYOUT_KEY, 0, static_cast<LPARAM>(digitPressed));
|
||||
Trace::FancyZones::QuickLayoutSwitched(changeLayoutWhileNotDragging);
|
||||
@ -767,6 +771,10 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
|
||||
FancyZonesDataInstance().LoadFancyZonesData();
|
||||
UpdateZoneSets();
|
||||
}
|
||||
else if (message == WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE)
|
||||
{
|
||||
LayoutHotkeys::instance().LoadData();
|
||||
}
|
||||
else if (message == WM_PRIV_QUICK_LAYOUT_KEY)
|
||||
{
|
||||
ApplyQuickLayout(static_cast<int>(lparam));
|
||||
@ -1293,13 +1301,16 @@ bool FancyZones::ShouldProcessSnapHotkey(DWORD vkCode) noexcept
|
||||
|
||||
void FancyZones::ApplyQuickLayout(int key) noexcept
|
||||
{
|
||||
std::wstring uuid;
|
||||
for (auto [layoutUuid, hotkey] : FancyZonesDataInstance().GetLayoutQuickKeys())
|
||||
auto layoutId = LayoutHotkeys::instance().GetLayoutId(key);
|
||||
if (!layoutId)
|
||||
{
|
||||
if (hotkey == key)
|
||||
{
|
||||
uuid = layoutUuid;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
auto uuidStr = FancyZonesUtils::GuidToString(layoutId.value());
|
||||
if (!uuidStr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto workArea = m_workAreaHandler.GetWorkAreaFromCursor(m_currentDesktopId);
|
||||
@ -1307,12 +1318,12 @@ void FancyZones::ApplyQuickLayout(int key) noexcept
|
||||
// Find a custom zone set with this uuid and apply it
|
||||
auto customZoneSets = FancyZonesDataInstance().GetCustomZoneSetsMap();
|
||||
|
||||
if (!customZoneSets.contains(uuid))
|
||||
if (!customZoneSets.contains(uuidStr.value()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FancyZonesDataTypes::ZoneSetData data{ .uuid = uuid, .type = FancyZonesDataTypes::ZoneSetLayoutType::Custom };
|
||||
FancyZonesDataTypes::ZoneSetData data{ .uuid = uuidStr.value(), .type = FancyZonesDataTypes::ZoneSetLayoutType::Custom };
|
||||
FancyZonesDataInstance().SetActiveZoneSet(workArea->UniqueId(), data);
|
||||
FancyZonesDataInstance().SaveZoneSettings();
|
||||
UpdateZoneSets();
|
||||
|
@ -22,6 +22,9 @@
|
||||
#include <common/utils/process_path.h>
|
||||
#include <common/logger/logger.h>
|
||||
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutHotkeys.h>
|
||||
#include <FancyZonesLib/ModuleConstants.h>
|
||||
|
||||
// Non-localizable strings
|
||||
namespace NonLocalizable
|
||||
{
|
||||
@ -149,7 +152,7 @@ FancyZonesData& FancyZonesDataInstance()
|
||||
|
||||
FancyZonesData::FancyZonesData()
|
||||
{
|
||||
std::wstring saveFolderPath = PTSettingsHelper::get_module_save_folder_location(NonLocalizable::FancyZonesStr);
|
||||
std::wstring saveFolderPath = PTSettingsHelper::get_module_save_folder_location(NonLocalizable::ModuleKey);
|
||||
|
||||
settingsFileName = saveFolderPath + L"\\" + std::wstring(NonLocalizable::FancyZonesSettingsFile);
|
||||
zonesSettingsFileName = saveFolderPath + L"\\" + std::wstring(NonLocalizable::FancyZonesDataFile);
|
||||
@ -157,6 +160,26 @@ FancyZonesData::FancyZonesData()
|
||||
editorParametersFileName = saveFolderPath + L"\\" + std::wstring(NonLocalizable::FancyZonesEditorParametersFile);
|
||||
}
|
||||
|
||||
void FancyZonesData::ReplaceZoneSettingsFileFromOlderVersions()
|
||||
{
|
||||
if (std::filesystem::exists(zonesSettingsFileName))
|
||||
{
|
||||
json::JsonObject fancyZonesDataJSON = GetPersistFancyZonesJSON();
|
||||
|
||||
//appZoneHistoryMap = JSONHelpers::ParseAppZoneHistory(fancyZonesDataJSON);
|
||||
//deviceInfoMap = JSONHelpers::ParseDeviceInfos(fancyZonesDataJSON);
|
||||
//customZoneSetsMap = JSONHelpers::ParseCustomZoneSets(fancyZonesDataJSON);
|
||||
|
||||
auto quickKeysMap = JSONHelpers::ParseQuickKeys(fancyZonesDataJSON);
|
||||
if (quickKeysMap)
|
||||
{
|
||||
JSONHelpers::SaveLayoutHotkeys(quickKeysMap.value());
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: remove zone-settings.json after getting all info from it
|
||||
}
|
||||
|
||||
void FancyZonesData::SetVirtualDesktopCheckCallback(std::function<bool(GUID)> callback)
|
||||
{
|
||||
m_virtualDesktopCheckCallback = callback;
|
||||
@ -616,8 +639,7 @@ void FancyZonesData::LoadFancyZonesData()
|
||||
|
||||
appZoneHistoryMap = JSONHelpers::ParseAppZoneHistory(fancyZonesDataJSON);
|
||||
deviceInfoMap = JSONHelpers::ParseDeviceInfos(fancyZonesDataJSON);
|
||||
customZoneSetsMap = JSONHelpers::ParseCustomZoneSets(fancyZonesDataJSON);
|
||||
quickKeysMap = JSONHelpers::ParseQuickKeys(fancyZonesDataJSON);
|
||||
customZoneSetsMap = JSONHelpers::ParseCustomZoneSets(fancyZonesDataJSON);
|
||||
}
|
||||
}
|
||||
|
||||
@ -651,11 +673,11 @@ void FancyZonesData::SaveZoneSettings() const
|
||||
|
||||
if (dirtyFlag)
|
||||
{
|
||||
JSONHelpers::SaveZoneSettings(zonesSettingsFileName, updatedDeviceInfoMap, customZoneSetsMap, quickKeysMap);
|
||||
JSONHelpers::SaveZoneSettings(zonesSettingsFileName, updatedDeviceInfoMap, customZoneSetsMap);
|
||||
}
|
||||
else
|
||||
{
|
||||
JSONHelpers::SaveZoneSettings(zonesSettingsFileName, deviceInfoMap, customZoneSetsMap, quickKeysMap);
|
||||
JSONHelpers::SaveZoneSettings(zonesSettingsFileName, deviceInfoMap, customZoneSetsMap);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,12 +13,6 @@
|
||||
#include <winnt.h>
|
||||
#include <FancyZonesLib/JsonHelpers.h>
|
||||
|
||||
// Non-localizable strings
|
||||
namespace NonLocalizable
|
||||
{
|
||||
const wchar_t FancyZonesStr[] = L"FancyZones";
|
||||
}
|
||||
|
||||
namespace FancyZonesDataTypes
|
||||
{
|
||||
struct ZoneSetData;
|
||||
@ -36,6 +30,7 @@ namespace FancyZonesUnitTests
|
||||
class ZoneSetCalculateZonesUnitTests;
|
||||
class WorkAreaUnitTests;
|
||||
class WorkAreaCreationUnitTests;
|
||||
class LayoutHotkeysUnitTests;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -44,6 +39,8 @@ class FancyZonesData
|
||||
public:
|
||||
FancyZonesData();
|
||||
|
||||
void ReplaceZoneSettingsFileFromOlderVersions();
|
||||
|
||||
void SetVirtualDesktopCheckCallback(std::function<bool(GUID)> callback);
|
||||
|
||||
std::optional<FancyZonesDataTypes::DeviceInfoData> FindDeviceInfo(const FancyZonesDataTypes::DeviceIdData& id) const;
|
||||
@ -53,12 +50,6 @@ public:
|
||||
const JSONHelpers::TCustomZoneSetsMap& GetCustomZoneSetsMap() const;
|
||||
const std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>>& GetAppZoneHistoryMap() const;
|
||||
|
||||
inline const JSONHelpers::TLayoutQuickKeysMap& GetLayoutQuickKeys() const
|
||||
{
|
||||
std::scoped_lock lock{ dataLock };
|
||||
return quickKeysMap;
|
||||
}
|
||||
|
||||
inline const std::wstring& GetZonesSettingsFileName() const
|
||||
{
|
||||
return zonesSettingsFileName;
|
||||
@ -98,6 +89,7 @@ private:
|
||||
friend class FancyZonesUnitTests::WorkAreaUnitTests;
|
||||
friend class FancyZonesUnitTests::WorkAreaCreationUnitTests;
|
||||
friend class FancyZonesUnitTests::ZoneSetCalculateZonesUnitTests;
|
||||
friend class FancyZonesUnitTests::LayoutHotkeysUnitTests;
|
||||
|
||||
inline void SetDeviceInfo(const FancyZonesDataTypes::DeviceIdData& deviceId, FancyZonesDataTypes::DeviceInfoData data)
|
||||
{
|
||||
@ -128,6 +120,12 @@ private:
|
||||
zonesSettingsFileName = result + L"\\" + std::wstring(L"zones-settings.json");
|
||||
appZoneHistoryFileName = result + L"\\" + std::wstring(L"app-zone-history.json");
|
||||
}
|
||||
|
||||
inline std::wstring GetZoneSettingsPath(std::wstring_view moduleName)
|
||||
{
|
||||
std::wstring result = PTSettingsHelper::get_module_save_folder_location(moduleName);
|
||||
return result + L"\\" + std::wstring(L"zones-settings.json");
|
||||
}
|
||||
#endif
|
||||
void RemoveDesktopAppZoneHistory(GUID desktopId);
|
||||
|
||||
@ -137,8 +135,6 @@ private:
|
||||
JSONHelpers::TDeviceInfoMap deviceInfoMap{};
|
||||
// Maps custom zoneset UUID to it's data
|
||||
JSONHelpers::TCustomZoneSetsMap customZoneSetsMap{};
|
||||
// Maps zoneset UUID with quick access keys
|
||||
JSONHelpers::TLayoutQuickKeysMap quickKeysMap{};
|
||||
|
||||
std::wstring settingsFileName;
|
||||
std::wstring zonesSettingsFileName;
|
||||
|
@ -0,0 +1,110 @@
|
||||
#include "pch.h"
|
||||
#include "LayoutHotkeys.h"
|
||||
|
||||
#include <common/logger/logger.h>
|
||||
|
||||
#include <FancyZonesLib/FancyZonesWinHookEventIDs.h>
|
||||
#include <FancyZonesLib/JsonHelpers.h>
|
||||
#include <FancyZonesLib/util.h>
|
||||
|
||||
namespace JsonUtils
|
||||
{
|
||||
struct LayoutHotkeysJSON
|
||||
{
|
||||
GUID uuid;
|
||||
int key;
|
||||
|
||||
static std::optional<LayoutHotkeysJSON> FromJson(const json::JsonObject& json)
|
||||
{
|
||||
try
|
||||
{
|
||||
LayoutHotkeysJSON result;
|
||||
|
||||
std::wstring uuidStr = json.GetNamedString(NonLocalizable::LayoutHotkeysIds::LayoutUuidID).c_str();
|
||||
auto uuidOpt = FancyZonesUtils::GuidFromString(uuidStr);
|
||||
if (!uuidOpt)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
result.uuid = uuidOpt.value();
|
||||
result.key = static_cast<int>(json.GetNamedNumber(NonLocalizable::LayoutHotkeysIds::KeyID));
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
LayoutHotkeys::THotkeyMap ParseJson(const json::JsonObject& json)
|
||||
{
|
||||
LayoutHotkeys::THotkeyMap map{};
|
||||
auto layoutHotkeys = json.GetNamedArray(NonLocalizable::LayoutHotkeysIds::LayoutHotkeysArrayID);
|
||||
|
||||
for (uint32_t i = 0; i < layoutHotkeys.Size(); ++i)
|
||||
{
|
||||
if (auto obj = LayoutHotkeysJSON::FromJson(layoutHotkeys.GetObjectAt(i)); obj.has_value())
|
||||
{
|
||||
map[obj->key] = obj->uuid;
|
||||
}
|
||||
}
|
||||
|
||||
return std::move(map);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LayoutHotkeys::LayoutHotkeys()
|
||||
{
|
||||
const std::wstring& settingsFileName = LayoutHotkeysFileName();
|
||||
m_fileWatcher = std::make_unique<FileWatcher>(settingsFileName, [&]() {
|
||||
PostMessageW(HWND_BROADCAST, WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE, NULL, NULL);
|
||||
});
|
||||
}
|
||||
|
||||
LayoutHotkeys& LayoutHotkeys::instance()
|
||||
{
|
||||
static LayoutHotkeys self;
|
||||
return self;
|
||||
}
|
||||
|
||||
void LayoutHotkeys::LoadData()
|
||||
{
|
||||
auto data = json::from_file(LayoutHotkeysFileName());
|
||||
|
||||
try
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
m_hotkeyMap = JsonUtils::ParseJson(data.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hotkeyMap.clear();
|
||||
Logger::info(L"layout-hotkeys.json file is missing or malformed");
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error& e)
|
||||
{
|
||||
Logger::error(L"Parsing layout-hotkeys error: {}", e.message());
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<GUID> LayoutHotkeys::GetLayoutId(int key) const noexcept
|
||||
{
|
||||
auto iter = m_hotkeyMap.find(key);
|
||||
if (iter != m_hotkeyMap.end())
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
size_t LayoutHotkeys::GetHotkeysCount() const noexcept
|
||||
{
|
||||
return m_hotkeyMap.size();
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <guiddef.h>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include <FancyZonesLib/ModuleConstants.h>
|
||||
|
||||
#include <common/SettingsAPI/FileWatcher.h>
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
|
||||
namespace NonLocalizable
|
||||
{
|
||||
namespace LayoutHotkeysIds
|
||||
{
|
||||
const static wchar_t* LayoutHotkeysArrayID = L"layout-hotkeys";
|
||||
const static wchar_t* LayoutUuidID = L"layout-id";
|
||||
const static wchar_t* KeyID = L"key";
|
||||
}
|
||||
}
|
||||
|
||||
class LayoutHotkeys
|
||||
{
|
||||
public:
|
||||
using THotkeyMap = std::map<int, GUID>;
|
||||
|
||||
static LayoutHotkeys& instance();
|
||||
|
||||
inline static std::wstring LayoutHotkeysFileName()
|
||||
{
|
||||
std::wstring saveFolderPath = PTSettingsHelper::get_module_save_folder_location(NonLocalizable::ModuleKey);
|
||||
#if defined(UNIT_TESTS)
|
||||
return saveFolderPath + L"\\test-layout-hotkeys.json";
|
||||
#endif
|
||||
return saveFolderPath + L"\\layout-hotkeys.json";
|
||||
}
|
||||
|
||||
void LoadData();
|
||||
|
||||
std::optional<GUID> GetLayoutId(int key) const noexcept;
|
||||
size_t GetHotkeysCount() const noexcept;
|
||||
|
||||
private:
|
||||
LayoutHotkeys();
|
||||
~LayoutHotkeys() = default;
|
||||
|
||||
THotkeyMap m_hotkeyMap;
|
||||
std::unique_ptr<FileWatcher> m_fileWatcher;
|
||||
};
|
@ -45,6 +45,8 @@
|
||||
<ClInclude Include="GuidUtils.h" />
|
||||
<ClInclude Include="JsonHelpers.h" />
|
||||
<ClInclude Include="KeyState.h" />
|
||||
<ClInclude Include="FancyZonesData\LayoutHotkeys.h" />
|
||||
<ClInclude Include="ModuleConstants.h" />
|
||||
<ClInclude Include="MonitorUtils.h" />
|
||||
<ClInclude Include="MonitorWorkAreaHandler.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
@ -69,6 +71,7 @@
|
||||
<ClCompile Include="FancyZonesWinHookEventIDs.cpp" />
|
||||
<ClCompile Include="FancyZonesData.cpp" />
|
||||
<ClCompile Include="JsonHelpers.cpp" />
|
||||
<ClCompile Include="FancyZonesData\LayoutHotkeys.cpp" />
|
||||
<ClCompile Include="MonitorUtils.cpp" />
|
||||
<ClCompile Include="MonitorWorkAreaHandler.cpp" />
|
||||
<ClCompile Include="OnThreadExecutor.cpp" />
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
@ -90,6 +90,12 @@
|
||||
<ClInclude Include="GuidUtils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\LayoutHotkeys.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ModuleConstants.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp">
|
||||
@ -149,6 +155,9 @@
|
||||
<ClCompile Include="MonitorUtils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesData\LayoutHotkeys.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
@ -12,6 +12,7 @@ UINT WM_PRIV_VD_SWITCH;
|
||||
UINT WM_PRIV_VD_UPDATE;
|
||||
UINT WM_PRIV_EDITOR;
|
||||
UINT WM_PRIV_FILE_UPDATE;
|
||||
UINT WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE;
|
||||
UINT WM_PRIV_SNAP_HOTKEY;
|
||||
UINT WM_PRIV_QUICK_LAYOUT_KEY;
|
||||
UINT WM_PRIV_SETTINGS_CHANGED;
|
||||
@ -31,6 +32,7 @@ void InitializeWinhookEventIds()
|
||||
WM_PRIV_VD_UPDATE = RegisterWindowMessage(L"{b8b72b46-f42f-4c26-9e20-29336cf2f22e}");
|
||||
WM_PRIV_EDITOR = RegisterWindowMessage(L"{87543824-7080-4e91-9d9c-0404642fc7b6}");
|
||||
WM_PRIV_FILE_UPDATE = RegisterWindowMessage(L"{632f17a9-55a7-45f1-a4db-162e39271d92}");
|
||||
WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE = RegisterWindowMessage(L"{07229b7e-4f22-4357-b136-33c289be2295}");
|
||||
WM_PRIV_SNAP_HOTKEY = RegisterWindowMessage(L"{72f4fd8e-23f1-43ab-bbbc-029363df9a84}");
|
||||
WM_PRIV_QUICK_LAYOUT_KEY = RegisterWindowMessage(L"{15baab3d-c67b-4a15-aFF0-13610e05e947}");
|
||||
WM_PRIV_SETTINGS_CHANGED = RegisterWindowMessage(L"{89ca3Daa-bf2d-4e73-9f3f-c60716364e27}");
|
||||
|
@ -9,7 +9,8 @@ extern UINT WM_PRIV_VD_INIT; // Scheduled when FancyZones is initialized
|
||||
extern UINT WM_PRIV_VD_SWITCH; // Scheduled when virtual desktop switch occurs
|
||||
extern UINT WM_PRIV_VD_UPDATE; // Scheduled on virtual desktops update (creation/deletion)
|
||||
extern UINT WM_PRIV_EDITOR; // Scheduled when the editor exits
|
||||
extern UINT WM_PRIV_FILE_UPDATE; // Scheduled when the a watched zone-settings file is updated
|
||||
extern UINT WM_PRIV_FILE_UPDATE; // Scheduled when the watched zone-settings file is updated
|
||||
extern UINT WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE; // Scheduled when the watched layout-hotkeys.json file is updated
|
||||
extern UINT WM_PRIV_SNAP_HOTKEY; // Scheduled when we receive a snap hotkey key down press
|
||||
extern UINT WM_PRIV_QUICK_LAYOUT_KEY; // Scheduled when we receive a key down press to quickly apply a layout
|
||||
extern UINT WM_PRIV_SETTINGS_CHANGED; // Scheduled when the a watched settings file is updated
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include "trace.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutHotkeys.h>
|
||||
|
||||
#include <common/logger/logger.h>
|
||||
|
||||
#include <filesystem>
|
||||
@ -576,7 +578,7 @@ namespace JSONHelpers
|
||||
}
|
||||
}
|
||||
|
||||
void SaveZoneSettings(const std::wstring& zonesSettingsFileName, const TDeviceInfoMap& deviceInfoMap, const TCustomZoneSetsMap& customZoneSetsMap, const TLayoutQuickKeysMap& quickKeysMap)
|
||||
void SaveZoneSettings(const std::wstring& zonesSettingsFileName, const TDeviceInfoMap& deviceInfoMap, const TCustomZoneSetsMap& customZoneSetsMap)
|
||||
{
|
||||
auto before = json::from_file(zonesSettingsFileName);
|
||||
|
||||
@ -598,7 +600,6 @@ namespace JSONHelpers
|
||||
root.SetNamedValue(NonLocalizable::DevicesStr, JSONHelpers::SerializeDeviceInfos(deviceInfoMap));
|
||||
root.SetNamedValue(NonLocalizable::CustomZoneSetsStr, JSONHelpers::SerializeCustomZoneSets(customZoneSetsMap));
|
||||
root.SetNamedValue(NonLocalizable::Templates, templates);
|
||||
root.SetNamedValue(NonLocalizable::QuickLayoutKeys, JSONHelpers::SerializeQuickKeys(quickKeysMap));
|
||||
|
||||
if (!before.has_value() || before.value().Stringify() != root.Stringify())
|
||||
{
|
||||
@ -726,7 +727,7 @@ namespace JSONHelpers
|
||||
return customZoneSetsJSON;
|
||||
}
|
||||
|
||||
TLayoutQuickKeysMap ParseQuickKeys(const json::JsonObject& fancyZonesDataJSON)
|
||||
std::optional<TLayoutQuickKeysMap> ParseQuickKeys(const json::JsonObject& fancyZonesDataJSON)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -746,19 +747,26 @@ namespace JSONHelpers
|
||||
catch (const winrt::hresult_error& e)
|
||||
{
|
||||
Logger::error(L"Parsing quick keys error: {}", e.message());
|
||||
return {};
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
json::JsonArray SerializeQuickKeys(const TLayoutQuickKeysMap& quickKeysMap)
|
||||
void SaveLayoutHotkeys(const TLayoutQuickKeysMap& quickKeysMap)
|
||||
{
|
||||
json::JsonArray quickKeysJSON{};
|
||||
json::JsonObject root{};
|
||||
json::JsonArray keysArray{};
|
||||
|
||||
for (const auto& [uuid, key] : quickKeysMap)
|
||||
{
|
||||
quickKeysJSON.Append(LayoutQuickKeyJSON::ToJson(LayoutQuickKeyJSON{ uuid, key }));
|
||||
json::JsonObject keyJson{};
|
||||
|
||||
keyJson.SetNamedValue(NonLocalizable::LayoutHotkeysIds::LayoutUuidID, json::value(uuid));
|
||||
keyJson.SetNamedValue(NonLocalizable::LayoutHotkeysIds::KeyID, json::value(key));
|
||||
|
||||
keysArray.Append(keyJson);
|
||||
}
|
||||
|
||||
return quickKeysJSON;
|
||||
root.SetNamedValue(NonLocalizable::LayoutHotkeysIds::LayoutHotkeysArrayID, keysArray);
|
||||
json::to_file(LayoutHotkeys::LayoutHotkeysFileName(), root);
|
||||
}
|
||||
}
|
@ -93,7 +93,7 @@ namespace JSONHelpers
|
||||
|
||||
json::JsonObject GetPersistFancyZonesJSON(const std::wstring& zonesSettingsFileName, const std::wstring& appZoneHistoryFileName);
|
||||
|
||||
void SaveZoneSettings(const std::wstring& zonesSettingsFileName, const TDeviceInfoMap& deviceInfoMap, const TCustomZoneSetsMap& customZoneSetsMap, const TLayoutQuickKeysMap& quickKeysMap);
|
||||
void SaveZoneSettings(const std::wstring& zonesSettingsFileName, const TDeviceInfoMap& deviceInfoMap, const TCustomZoneSetsMap& customZoneSetsMap);
|
||||
void SaveAppZoneHistory(const std::wstring& appZoneHistoryFileName, const TAppZoneHistoryMap& appZoneHistoryMap);
|
||||
|
||||
TAppZoneHistoryMap ParseAppZoneHistory(const json::JsonObject& fancyZonesDataJSON);
|
||||
@ -105,6 +105,7 @@ namespace JSONHelpers
|
||||
TCustomZoneSetsMap ParseCustomZoneSets(const json::JsonObject& fancyZonesDataJSON);
|
||||
json::JsonArray SerializeCustomZoneSets(const TCustomZoneSetsMap& customZoneSetsMap);
|
||||
|
||||
TLayoutQuickKeysMap ParseQuickKeys(const json::JsonObject& fancyZonesDataJSON);
|
||||
json::JsonArray SerializeQuickKeys(const TLayoutQuickKeysMap& quickKeysMap);
|
||||
// replace zone-settings: layout hotkeys
|
||||
std::optional<TLayoutQuickKeysMap> ParseQuickKeys(const json::JsonObject& fancyZonesDataJSON);
|
||||
void SaveLayoutHotkeys(const TLayoutQuickKeysMap& quickKeysMap);
|
||||
}
|
||||
|
6
src/modules/fancyzones/FancyZonesLib/ModuleConstants.h
Normal file
6
src/modules/fancyzones/FancyZonesLib/ModuleConstants.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace NonLocalizable
|
||||
{
|
||||
const inline wchar_t ModuleKey[] = L"FancyZones";
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
#include "FancyZonesLib/ZoneSet.h"
|
||||
#include "FancyZonesLib/Settings.h"
|
||||
#include "FancyZonesLib/FancyZonesData.h"
|
||||
#include "FancyZonesLib/FancyZonesData/LayoutHotkeys.h"
|
||||
#include "FancyZonesLib/FancyZonesDataTypes.h"
|
||||
|
||||
// Telemetry strings should not be localized.
|
||||
@ -145,7 +146,7 @@ void Trace::FancyZones::DataChanged() noexcept
|
||||
int appsHistorySize = static_cast<int>(data.GetAppZoneHistoryMap().size());
|
||||
const auto& customZones = data.GetCustomZoneSetsMap();
|
||||
const auto& devices = data.GetDeviceInfoMap();
|
||||
const auto& quickKeys = data.GetLayoutQuickKeys();
|
||||
auto quickKeysCount = LayoutHotkeys::instance().GetHotkeysCount();
|
||||
|
||||
std::unique_ptr<INT32[]> customZonesArray(new (std::nothrow) INT32[customZones.size()]);
|
||||
if (!customZonesArray)
|
||||
@ -220,7 +221,7 @@ void Trace::FancyZones::DataChanged() noexcept
|
||||
TraceLoggingInt32Array(customZonesArray.get(), static_cast<int>(customZones.size()), NumberOfZonesForEachCustomZoneSetKey),
|
||||
TraceLoggingInt32(static_cast<int>(devices.size()), ActiveZoneSetsCountKey),
|
||||
TraceLoggingWideString(activeZoneSetInfo.c_str(), ActiveZoneSetsListKey),
|
||||
TraceLoggingInt32(static_cast<int>(quickKeys.size()), LayoutUsingQuickKeyCountKey));
|
||||
TraceLoggingInt32(static_cast<int>(quickKeysCount), LayoutUsingQuickKeyCountKey));
|
||||
}
|
||||
|
||||
void Trace::FancyZones::EditorLaunched(int value) noexcept
|
||||
|
@ -550,6 +550,17 @@ namespace FancyZonesUtils
|
||||
return SUCCEEDED(CLSIDFromString(str.c_str(), &id));
|
||||
}
|
||||
|
||||
std::optional<GUID> GuidFromString(const std::wstring& str) noexcept
|
||||
{
|
||||
GUID id;
|
||||
if (SUCCEEDED(CLSIDFromString(str.c_str(), &id)))
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::wstring> GuidToString(const GUID& guid) noexcept
|
||||
{
|
||||
wil::unique_cotaskmem_string guidString;
|
||||
|
@ -207,6 +207,7 @@ namespace FancyZonesUtils
|
||||
void RestoreWindowOrigin(HWND window) noexcept;
|
||||
|
||||
bool IsValidGuid(const std::wstring& str);
|
||||
std::optional<GUID> GuidFromString(const std::wstring& str) noexcept;
|
||||
std::optional<std::wstring> GuidToString(const GUID& guid) noexcept;
|
||||
|
||||
std::wstring GenerateUniqueId(HMONITOR monitor, const std::wstring& devideId, const std::wstring& virtualDesktopId);
|
||||
|
@ -8,9 +8,9 @@
|
||||
#include <common/utils/winapi_error.h>
|
||||
|
||||
#include <FancyZonesLib/Generated Files/resource.h>
|
||||
#include <FancyZonesLib/FancyZonesData.h>
|
||||
#include <FancyZonesLib/trace.h>
|
||||
#include <FancyZonesLib/Settings.h>
|
||||
#include <FancyZonesLib/ModuleConstants.h>
|
||||
|
||||
#include <shellapi.h>
|
||||
|
||||
@ -117,7 +117,7 @@ public:
|
||||
FancyZonesModuleInterface()
|
||||
{
|
||||
app_name = GET_RESOURCE_STRING(IDS_FANCYZONES);
|
||||
app_key = NonLocalizable::FancyZonesStr;
|
||||
app_key = NonLocalizable::ModuleKey;
|
||||
m_settings = MakeFancyZonesSettings(reinterpret_cast<HINSTANCE>(&__ImageBase), FancyZonesModuleInterface::get_name(), FancyZonesModuleInterface::get_key());
|
||||
|
||||
m_toggleEditorEvent = CreateDefaultEvent(CommonSharedConstants::FANCY_ZONES_EDITOR_TOGGLE_EVENT);
|
||||
|
@ -1556,73 +1556,6 @@ namespace FancyZonesUnitTests
|
||||
auto actual = SerializeCustomZoneSets(customZoneSetsMap);
|
||||
compareJsonArrays(expected, actual);
|
||||
}
|
||||
|
||||
TEST_METHOD(QuickLayoutKeysParse)
|
||||
{
|
||||
const std::wstring zoneUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}";
|
||||
LayoutQuickKeyJSON expected{ zoneUuid, 2 };
|
||||
json::JsonArray array;
|
||||
array.Append(LayoutQuickKeyJSON::ToJson(expected));
|
||||
|
||||
json::JsonObject json;
|
||||
json.SetNamedValue(L"quick-layout-keys", json::JsonValue::Parse(array.Stringify()));
|
||||
|
||||
const auto& quickKeysMap = ParseQuickKeys(json);
|
||||
|
||||
Assert::AreEqual((size_t)array.Size(), quickKeysMap.size());
|
||||
|
||||
Assert::IsTrue(quickKeysMap.find(zoneUuid) != quickKeysMap.end());
|
||||
int actualKey = quickKeysMap.find(zoneUuid)->second;
|
||||
Assert::AreEqual((int)expected.key, actualKey);
|
||||
}
|
||||
|
||||
TEST_METHOD (QuickLayoutKeysParseEmpty)
|
||||
{
|
||||
json::JsonArray array;
|
||||
json::JsonObject json;
|
||||
json.SetNamedValue(L"quick-layout-keys", json::JsonValue::Parse(array.Stringify()));
|
||||
|
||||
const auto& quickKeysMap = ParseQuickKeys(json);
|
||||
|
||||
Assert::IsTrue(quickKeysMap.empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (QuickLayoutKeysParseInvalid)
|
||||
{
|
||||
const std::wstring invalidZoneUuid = L"{33A2B101-06E0-437B-}";
|
||||
LayoutQuickKeyJSON expected{ invalidZoneUuid, 2 };
|
||||
json::JsonArray array;
|
||||
array.Append(LayoutQuickKeyJSON::ToJson(expected));
|
||||
|
||||
json::JsonObject json;
|
||||
json.SetNamedValue(L"quick-layout-keys", json::JsonValue::Parse(array.Stringify()));
|
||||
|
||||
const auto& quickKeysMap = ParseQuickKeys(json);
|
||||
|
||||
Assert::IsTrue(quickKeysMap.empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (QuickLayoutKeysParseMissed)
|
||||
{
|
||||
json::JsonObject json;
|
||||
|
||||
const auto& quickKeysMap = ParseQuickKeys(json);
|
||||
|
||||
Assert::IsTrue(quickKeysMap.empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (QuickLayoutKeysSerialize)
|
||||
{
|
||||
json::JsonArray expected;
|
||||
expected.Append(LayoutQuickKeyJSON::ToJson(LayoutQuickKeyJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", 3}));
|
||||
json::JsonObject json;
|
||||
json.SetNamedValue(L"quick-layout-keys", json::JsonValue::Parse(expected.Stringify()));
|
||||
|
||||
const auto& quickKeysMap = ParseQuickKeys(json);
|
||||
|
||||
auto actual = SerializeQuickKeys(quickKeysMap);
|
||||
compareJsonArrays(expected, actual);
|
||||
}
|
||||
|
||||
TEST_METHOD (SetActiveZoneSet)
|
||||
{
|
||||
@ -1754,7 +1687,6 @@ namespace FancyZonesUnitTests
|
||||
Assert::IsFalse(fancyZonesData.GetCustomZoneSetsMap().empty());
|
||||
Assert::IsFalse(fancyZonesData.GetCustomZoneSetsMap().empty());
|
||||
Assert::IsFalse(fancyZonesData.GetCustomZoneSetsMap().empty());
|
||||
Assert::IsFalse(fancyZonesData.GetLayoutQuickKeys().empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (LoadFancyZonesDataFromCroppedJson)
|
||||
|
@ -0,0 +1,126 @@
|
||||
#include "pch.h"
|
||||
#include <filesystem>
|
||||
|
||||
#include <FancyZonesLib/FancyZonesData.h>
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutHotkeys.h>
|
||||
#include <FancyZonesLib/util.h>
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
|
||||
namespace FancyZonesUnitTests
|
||||
{
|
||||
TEST_CLASS (LayoutHotkeysUnitTests)
|
||||
{
|
||||
FancyZonesData& m_fzData = FancyZonesDataInstance();
|
||||
std::wstring m_testFolder = L"FancyZonesUnitTests";
|
||||
|
||||
TEST_METHOD_INITIALIZE(Init)
|
||||
{
|
||||
m_fzData.clear_data();
|
||||
m_fzData.SetSettingsModulePath(L"FancyZonesUnitTests");
|
||||
}
|
||||
|
||||
TEST_METHOD_CLEANUP(CleanUp)
|
||||
{
|
||||
std::filesystem::remove_all(LayoutHotkeys::LayoutHotkeysFileName());
|
||||
std::filesystem::remove_all(PTSettingsHelper::get_module_save_folder_location(m_testFolder));
|
||||
}
|
||||
|
||||
TEST_METHOD (LayoutHotkeysParse)
|
||||
{
|
||||
// prepare
|
||||
json::JsonObject root{};
|
||||
json::JsonArray keysArray{};
|
||||
|
||||
{
|
||||
json::JsonObject keyJson{};
|
||||
keyJson.SetNamedValue(NonLocalizable::LayoutHotkeysIds::LayoutUuidID, json::value(L"{33A2B101-06E0-437B-A61E-CDBECF502906}"));
|
||||
keyJson.SetNamedValue(NonLocalizable::LayoutHotkeysIds::KeyID, json::value(1));
|
||||
|
||||
keysArray.Append(keyJson);
|
||||
}
|
||||
{
|
||||
json::JsonObject keyJson{};
|
||||
keyJson.SetNamedValue(NonLocalizable::LayoutHotkeysIds::LayoutUuidID, json::value(L"{33A2B101-06E0-437B-A61E-CDBECF502907}"));
|
||||
keyJson.SetNamedValue(NonLocalizable::LayoutHotkeysIds::KeyID, json::value(2));
|
||||
|
||||
keysArray.Append(keyJson);
|
||||
}
|
||||
|
||||
root.SetNamedValue(NonLocalizable::LayoutHotkeysIds::LayoutHotkeysArrayID, keysArray);
|
||||
json::to_file(LayoutHotkeys::LayoutHotkeysFileName(), root);
|
||||
|
||||
// test
|
||||
LayoutHotkeys::instance().LoadData();
|
||||
Assert::AreEqual((size_t)2, LayoutHotkeys::instance().GetHotkeysCount());
|
||||
Assert::AreEqual(L"{33A2B101-06E0-437B-A61E-CDBECF502906}", FancyZonesUtils::GuidToString(LayoutHotkeys::instance().GetLayoutId(1).value()).value().c_str());
|
||||
Assert::AreEqual(L"{33A2B101-06E0-437B-A61E-CDBECF502907}", FancyZonesUtils::GuidToString(LayoutHotkeys::instance().GetLayoutId(2).value()).value().c_str());
|
||||
}
|
||||
|
||||
TEST_METHOD (LayoutHotkeysParseEmpty)
|
||||
{
|
||||
// prepare
|
||||
json::JsonObject root{};
|
||||
json::JsonArray keysArray{};
|
||||
root.SetNamedValue(NonLocalizable::LayoutHotkeysIds::LayoutHotkeysArrayID, keysArray);
|
||||
json::to_file(LayoutHotkeys::LayoutHotkeysFileName(), root);
|
||||
|
||||
// test
|
||||
LayoutHotkeys::instance().LoadData();
|
||||
Assert::AreEqual((size_t)0, LayoutHotkeys::instance().GetHotkeysCount());
|
||||
}
|
||||
|
||||
TEST_METHOD (LayoutHotkeysNoFile)
|
||||
{
|
||||
// test
|
||||
LayoutHotkeys::instance().LoadData();
|
||||
Assert::AreEqual((size_t)0, LayoutHotkeys::instance().GetHotkeysCount());
|
||||
}
|
||||
|
||||
TEST_METHOD (MoveLayoutHotkeysFromZonesSettings)
|
||||
{
|
||||
// prepare
|
||||
json::JsonObject root{};
|
||||
json::JsonArray devicesArray{}, customLayoutsArray{}, templateLayoutsArray{}, quickLayoutKeysArray{};
|
||||
root.SetNamedValue(L"devices", devicesArray);
|
||||
root.SetNamedValue(L"custom-zone-sets", customLayoutsArray);
|
||||
root.SetNamedValue(L"templates", templateLayoutsArray);
|
||||
json::JsonObject layoutKeyObj{};
|
||||
layoutKeyObj.SetNamedValue(L"uuid", json::value(L"{BF7DD882-AB90-4AB8-88A0-96CCFCEC538C}"));
|
||||
layoutKeyObj.SetNamedValue(L"key", json::value(1));
|
||||
quickLayoutKeysArray.Append(layoutKeyObj);
|
||||
root.SetNamedValue(L"quick-layout-keys", quickLayoutKeysArray);
|
||||
json::to_file(m_fzData.GetZoneSettingsPath(m_testFolder), root);
|
||||
|
||||
// test
|
||||
m_fzData.ReplaceZoneSettingsFileFromOlderVersions();
|
||||
LayoutHotkeys::instance().LoadData();
|
||||
Assert::AreEqual((size_t)1, LayoutHotkeys::instance().GetHotkeysCount());
|
||||
Assert::AreEqual(L"{BF7DD882-AB90-4AB8-88A0-96CCFCEC538C}", FancyZonesUtils::GuidToString(LayoutHotkeys::instance().GetLayoutId(1).value()).value().c_str());
|
||||
}
|
||||
|
||||
TEST_METHOD (MoveLayoutHotkeysFromZonesSettingsNoQuickLayoutKeys)
|
||||
{
|
||||
// prepare
|
||||
json::JsonObject root{};
|
||||
json::JsonArray devicesArray{}, customLayoutsArray{}, templateLayoutsArray{};
|
||||
root.SetNamedValue(L"devices", devicesArray);
|
||||
root.SetNamedValue(L"custom-zone-sets", customLayoutsArray);
|
||||
root.SetNamedValue(L"templates", templateLayoutsArray);
|
||||
json::to_file(m_fzData.GetZoneSettingsPath(m_testFolder), root);
|
||||
|
||||
// test
|
||||
m_fzData.ReplaceZoneSettingsFileFromOlderVersions();
|
||||
LayoutHotkeys::instance().LoadData();
|
||||
Assert::AreEqual((size_t)0, LayoutHotkeys::instance().GetHotkeysCount());
|
||||
}
|
||||
|
||||
TEST_METHOD (MoveLayoutHotkeysFromZonesSettingsNoFile)
|
||||
{
|
||||
// test
|
||||
m_fzData.ReplaceZoneSettingsFileFromOlderVersions();
|
||||
LayoutHotkeys::instance().LoadData();
|
||||
Assert::AreEqual((size_t)0, LayoutHotkeys::instance().GetHotkeysCount());
|
||||
}
|
||||
};
|
||||
}
|
@ -44,6 +44,7 @@
|
||||
<ClCompile Include="FancyZones.Spec.cpp" />
|
||||
<ClCompile Include="FancyZonesSettings.Spec.cpp" />
|
||||
<ClCompile Include="JsonHelpers.Tests.cpp" />
|
||||
<ClCompile Include="LayoutHotkeysTests.Spec.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(CIBuild)'!='true'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
|
@ -42,6 +42,9 @@
|
||||
<ClCompile Include="WorkArea.Spec.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="LayoutHotkeysTests.Spec.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
|
@ -9,7 +9,7 @@ using System.Runtime.CompilerServices;
|
||||
|
||||
namespace FancyZonesEditor.Models
|
||||
{
|
||||
public class QuickKeysModel : INotifyPropertyChanged
|
||||
public class LayoutHotkeysModel : INotifyPropertyChanged
|
||||
{
|
||||
public SortedDictionary<string, string> SelectedKeys { get; } = new SortedDictionary<string, string>()
|
||||
{
|
||||
@ -26,7 +26,7 @@ namespace FancyZonesEditor.Models
|
||||
{ "9", string.Empty },
|
||||
};
|
||||
|
||||
public QuickKeysModel()
|
||||
public LayoutHotkeysModel()
|
||||
{
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ namespace FancyZonesEditor.Models
|
||||
get
|
||||
{
|
||||
List<string> result = new List<string>();
|
||||
foreach (var pair in MainWindowSettingsModel.QuickKeys.SelectedKeys)
|
||||
foreach (var pair in MainWindowSettingsModel.LayoutHotkeys.SelectedKeys)
|
||||
{
|
||||
if (string.IsNullOrEmpty(pair.Value) || pair.Value == Uuid)
|
||||
{
|
||||
@ -195,11 +195,11 @@ namespace FancyZonesEditor.Models
|
||||
|
||||
if (intValue != -1)
|
||||
{
|
||||
MainWindowSettingsModel.QuickKeys.SelectKey(value, Uuid);
|
||||
MainWindowSettingsModel.LayoutHotkeys.SelectKey(value, Uuid);
|
||||
}
|
||||
else
|
||||
{
|
||||
MainWindowSettingsModel.QuickKeys.FreeKey(prev);
|
||||
MainWindowSettingsModel.LayoutHotkeys.FreeKey(prev);
|
||||
}
|
||||
|
||||
FirePropertyChanged(nameof(QuickKey));
|
||||
@ -253,7 +253,7 @@ namespace FancyZonesEditor.Models
|
||||
{
|
||||
if (_quickKey != -1)
|
||||
{
|
||||
MainWindowSettingsModel.QuickKeys.FreeKey(QuickKey);
|
||||
MainWindowSettingsModel.LayoutHotkeys.FreeKey(QuickKey);
|
||||
}
|
||||
|
||||
var customModels = MainWindowSettingsModel.CustomModels;
|
||||
@ -298,9 +298,9 @@ namespace FancyZonesEditor.Models
|
||||
PersistData();
|
||||
}
|
||||
|
||||
public void QuickSwitchKeys_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
public void LayoutHotkeys_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
foreach (var pair in MainWindowSettingsModel.QuickKeys.SelectedKeys)
|
||||
foreach (var pair in MainWindowSettingsModel.LayoutHotkeys.SelectedKeys)
|
||||
{
|
||||
if (pair.Value == Uuid)
|
||||
{
|
||||
|
@ -143,7 +143,7 @@ namespace FancyZonesEditor
|
||||
{
|
||||
foreach (LayoutModel model in _customModels)
|
||||
{
|
||||
QuickKeys.PropertyChanged -= model.QuickSwitchKeys_PropertyChanged;
|
||||
LayoutHotkeys.PropertyChanged -= model.LayoutHotkeys_PropertyChanged;
|
||||
}
|
||||
|
||||
_customModels.Clear();
|
||||
@ -151,7 +151,7 @@ namespace FancyZonesEditor
|
||||
|
||||
foreach (LayoutModel model in _customModels)
|
||||
{
|
||||
QuickKeys.PropertyChanged += model.QuickSwitchKeys_PropertyChanged;
|
||||
LayoutHotkeys.PropertyChanged += model.LayoutHotkeys_PropertyChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -166,7 +166,7 @@ namespace FancyZonesEditor
|
||||
}
|
||||
}
|
||||
|
||||
public static QuickKeysModel QuickKeys { get; } = new QuickKeysModel();
|
||||
public static LayoutHotkeysModel LayoutHotkeys { get; } = new LayoutHotkeysModel();
|
||||
|
||||
public LayoutModel SelectedModel
|
||||
{
|
||||
|
@ -384,6 +384,15 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to An error occurred while parsing layout hotkeys..
|
||||
/// </summary>
|
||||
public static string Error_Parsing_Layout_Hotkeys_Message {
|
||||
get {
|
||||
return ResourceManager.GetString("Error_Parsing_Layout_Hotkeys_Message", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to A layout that contained invalid data has been removed..
|
||||
/// </summary>
|
||||
@ -394,7 +403,7 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Editor settings parsing error..
|
||||
/// Looks up a localized string similar to Editor data parsing error..
|
||||
/// </summary>
|
||||
public static string Error_Parsing_Zones_Settings_Title {
|
||||
get {
|
||||
|
@ -305,7 +305,7 @@
|
||||
<comment>A tooltip on a button that allows the user to delete a zone</comment>
|
||||
</data>
|
||||
<data name="Error_Parsing_Zones_Settings_Title" xml:space="preserve">
|
||||
<value>Editor settings parsing error.</value>
|
||||
<value>Editor data parsing error.</value>
|
||||
</data>
|
||||
<data name="Error_Parsing_Zones_Settings_Message" xml:space="preserve">
|
||||
<value>A layout that contained invalid data has been removed.</value>
|
||||
@ -383,4 +383,7 @@
|
||||
<data name="OpenSettings" xml:space="preserve">
|
||||
<value>Open settings</value>
|
||||
</data>
|
||||
<data name="Error_Parsing_Layout_Hotkeys_Message" xml:space="preserve">
|
||||
<value>An error occurred while parsing layout hotkeys.</value>
|
||||
</data>
|
||||
</root>
|
@ -29,6 +29,7 @@ namespace FancyZonesEditor.Utils
|
||||
|
||||
// Non-localizable strings: Files
|
||||
private const string ZonesSettingsFile = "\\Microsoft\\PowerToys\\FancyZones\\zones-settings.json";
|
||||
private const string LayoutHotkeysFile = "\\Microsoft\\PowerToys\\FancyZones\\layout-hotkeys.json";
|
||||
private const string ParamsFile = "\\Microsoft\\PowerToys\\FancyZones\\editor-parameters.json";
|
||||
|
||||
// Non-localizable string: Multi-monitor id
|
||||
@ -49,6 +50,8 @@ namespace FancyZonesEditor.Utils
|
||||
|
||||
public string FancyZonesSettingsFile { get; private set; }
|
||||
|
||||
public string FancyZonesLayoutHotkeysFile { get; private set; }
|
||||
|
||||
public string FancyZonesEditorParamsFile { get; private set; }
|
||||
|
||||
private enum CmdArgs
|
||||
@ -193,12 +196,18 @@ namespace FancyZonesEditor.Utils
|
||||
public int SensitivityRadius { get; set; }
|
||||
}
|
||||
|
||||
// zones-settings: quick-layout-keys-wrapper
|
||||
private struct QuickLayoutKeysWrapper
|
||||
// layout-hotkeys: layout-hotkeys-wrapper
|
||||
private struct LayoutHotkeyWrapper
|
||||
{
|
||||
public int Key { get; set; }
|
||||
|
||||
public string Uuid { get; set; }
|
||||
public string LayoutId { get; set; }
|
||||
}
|
||||
|
||||
// layout-hotkeys: layout-hotkeys-wrapper
|
||||
private struct LayoutHotkeysWrapper
|
||||
{
|
||||
public List<LayoutHotkeyWrapper> LayoutHotkeys { get; set; }
|
||||
}
|
||||
|
||||
// zones-settings
|
||||
@ -209,8 +218,6 @@ namespace FancyZonesEditor.Utils
|
||||
public List<CustomLayoutWrapper> CustomZoneSets { get; set; }
|
||||
|
||||
public List<TemplateLayoutWrapper> Templates { get; set; }
|
||||
|
||||
public List<QuickLayoutKeysWrapper> QuickLayoutKeys { get; set; }
|
||||
}
|
||||
|
||||
private struct EditorParams
|
||||
@ -242,6 +249,7 @@ namespace FancyZonesEditor.Utils
|
||||
{
|
||||
var localAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||
FancyZonesSettingsFile = localAppDataDir + ZonesSettingsFile;
|
||||
FancyZonesLayoutHotkeysFile = localAppDataDir + LayoutHotkeysFile;
|
||||
FancyZonesEditorParamsFile = localAppDataDir + ParamsFile;
|
||||
}
|
||||
|
||||
@ -516,7 +524,6 @@ namespace FancyZonesEditor.Utils
|
||||
bool devicesParsingResult = SetDevices(zoneSettings.Devices);
|
||||
bool customZonesParsingResult = SetCustomLayouts(zoneSettings.CustomZoneSets);
|
||||
bool templatesParsingResult = SetTemplateLayouts(zoneSettings.Templates);
|
||||
bool quickLayoutSwitchKeysParsingResult = SetQuickLayoutSwitchKeys(zoneSettings.QuickLayoutKeys);
|
||||
|
||||
if (!devicesParsingResult || !customZonesParsingResult)
|
||||
{
|
||||
@ -530,6 +537,51 @@ namespace FancyZonesEditor.Utils
|
||||
}
|
||||
}
|
||||
|
||||
var parsingHotkeysResult = ParseLayoutHotkeys();
|
||||
if (!parsingHotkeysResult.Result)
|
||||
{
|
||||
return parsingHotkeysResult;
|
||||
}
|
||||
|
||||
return new ParsingResult(true);
|
||||
}
|
||||
|
||||
public ParsingResult ParseLayoutHotkeys()
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
if (_fileSystem.File.Exists(FancyZonesLayoutHotkeysFile))
|
||||
{
|
||||
LayoutHotkeysWrapper layoutHotkeys;
|
||||
string dataString = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
dataString = ReadFile(FancyZonesLayoutHotkeysFile);
|
||||
layoutHotkeys = JsonSerializer.Deserialize<LayoutHotkeysWrapper>(dataString, _options);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Layout hotkeys parsing error", ex);
|
||||
return new ParsingResult(false, ex.Message, dataString);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
bool layoutHotkeysParsingResult = SetLayoutHotkeys(layoutHotkeys);
|
||||
|
||||
if (!layoutHotkeysParsingResult)
|
||||
{
|
||||
return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Layout_Hotkeys_Message, dataString);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Layout hotkeys parsing error", ex);
|
||||
return new ParsingResult(false, ex.Message, dataString);
|
||||
}
|
||||
}
|
||||
|
||||
return new ParsingResult(true);
|
||||
}
|
||||
|
||||
@ -541,7 +593,6 @@ namespace FancyZonesEditor.Utils
|
||||
zoneSettings.Devices = new List<DeviceWrapper>();
|
||||
zoneSettings.CustomZoneSets = new List<CustomLayoutWrapper>();
|
||||
zoneSettings.Templates = new List<TemplateLayoutWrapper>();
|
||||
zoneSettings.QuickLayoutKeys = new List<QuickLayoutKeysWrapper>();
|
||||
|
||||
// Serialize used devices
|
||||
foreach (var monitor in App.Overlay.Monitors)
|
||||
@ -678,20 +729,38 @@ namespace FancyZonesEditor.Utils
|
||||
zoneSettings.Templates.Add(wrapper);
|
||||
}
|
||||
|
||||
// Serialize quick layout switch keys
|
||||
foreach (var pair in MainWindowSettingsModel.QuickKeys.SelectedKeys)
|
||||
try
|
||||
{
|
||||
string jsonString = JsonSerializer.Serialize(zoneSettings, _options);
|
||||
_fileSystem.File.WriteAllText(FancyZonesSettingsFile, jsonString);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Serialize zone settings error", ex);
|
||||
App.ShowExceptionMessageBox(Properties.Resources.Error_Applying_Layout, ex);
|
||||
}
|
||||
|
||||
SerializeLayoutHotkeys();
|
||||
}
|
||||
|
||||
private void SerializeLayoutHotkeys()
|
||||
{
|
||||
LayoutHotkeysWrapper hotkeys = new LayoutHotkeysWrapper { };
|
||||
hotkeys.LayoutHotkeys = new List<LayoutHotkeyWrapper>();
|
||||
|
||||
foreach (var pair in MainWindowSettingsModel.LayoutHotkeys.SelectedKeys)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(pair.Value))
|
||||
{
|
||||
try
|
||||
{
|
||||
QuickLayoutKeysWrapper wrapper = new QuickLayoutKeysWrapper
|
||||
LayoutHotkeyWrapper wrapper = new LayoutHotkeyWrapper
|
||||
{
|
||||
Key = int.Parse(pair.Key),
|
||||
Uuid = pair.Value,
|
||||
LayoutId = pair.Value,
|
||||
};
|
||||
|
||||
zoneSettings.QuickLayoutKeys.Add(wrapper);
|
||||
hotkeys.LayoutHotkeys.Add(wrapper);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -702,12 +771,12 @@ namespace FancyZonesEditor.Utils
|
||||
|
||||
try
|
||||
{
|
||||
string jsonString = JsonSerializer.Serialize(zoneSettings, _options);
|
||||
_fileSystem.File.WriteAllText(FancyZonesSettingsFile, jsonString);
|
||||
string jsonString = JsonSerializer.Serialize(hotkeys, _options);
|
||||
_fileSystem.File.WriteAllText(FancyZonesLayoutHotkeysFile, jsonString);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Serialize zone settings error", ex);
|
||||
Logger.LogError("Serialize layout hotkeys error", ex);
|
||||
App.ShowExceptionMessageBox(Properties.Resources.Error_Applying_Layout, ex);
|
||||
}
|
||||
}
|
||||
@ -862,19 +931,14 @@ namespace FancyZonesEditor.Utils
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool SetQuickLayoutSwitchKeys(List<QuickLayoutKeysWrapper> quickSwitchKeys)
|
||||
private bool SetLayoutHotkeys(LayoutHotkeysWrapper layoutHotkeys)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
if (quickSwitchKeys == null)
|
||||
MainWindowSettingsModel.LayoutHotkeys.CleanUp();
|
||||
foreach (var wrapper in layoutHotkeys.LayoutHotkeys)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
MainWindowSettingsModel.QuickKeys.CleanUp();
|
||||
foreach (var wrapper in quickSwitchKeys)
|
||||
{
|
||||
MainWindowSettingsModel.QuickKeys.SelectKey(wrapper.Key.ToString(), wrapper.Uuid);
|
||||
MainWindowSettingsModel.LayoutHotkeys.SelectKey(wrapper.Key.ToString(), wrapper.LayoutId);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
Loading…
Reference in New Issue
Block a user