[FancyZones] Split zones-settings: layout hotkeys (#15514)

This commit is contained in:
Seraphima Zykova 2022-01-17 11:50:24 +03:00 committed by GitHub
parent a96187bd04
commit ba431c5bfd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 524 additions and 153 deletions

View File

@ -1951,6 +1951,7 @@ textblock
TEXTINCLUDE
THICKFRAME
THISCOMPONENT
THotkey
thre
TILEDWINDOW
timedate

View File

@ -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();

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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();
}

View File

@ -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;
};

View File

@ -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" />

View File

@ -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" />

View File

@ -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}");

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -0,0 +1,6 @@
#pragma once
namespace NonLocalizable
{
const inline wchar_t ModuleKey[] = L"FancyZones";
}

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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());
}
};
}

View File

@ -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>

View File

@ -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">

View File

@ -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()
{
}

View File

@ -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)
{

View File

@ -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
{

View File

@ -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 {

View File

@ -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>

View File

@ -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;