From 98268cc10aecca2f4e412c801c46ba0b05660de2 Mon Sep 17 00:00:00 2001 From: Seraphima Zykova Date: Thu, 7 Apr 2022 11:48:29 +0200 Subject: [PATCH] [FancyZones] Remove resolution from "device-id" (#17412) * removed resolution from device id * update applied layouts device id * app zone history device id updated * moved old device id parsing * updated tests * remove resolution in the editor * remove resolution from device id generation * update editor params --- .../fancyzones/FancyZonesLib/FancyZones.cpp | 13 - .../FancyZonesLib/FancyZonesData.cpp | 11 +- .../FancyZonesData/AppZoneHistory.cpp | 207 +++++++- .../FancyZonesData/AppZoneHistory.h | 16 + .../FancyZonesData/AppliedLayouts.cpp | 83 ++- .../FancyZonesData/AppliedLayouts.h | 3 + .../FancyZonesLib/FancyZonesDataTypes.cpp | 166 +----- .../FancyZonesLib/FancyZonesDataTypes.h | 10 +- .../fancyzones/FancyZonesLib/JsonHelpers.cpp | 320 +++++++----- .../fancyzones/FancyZonesLib/JsonHelpers.h | 64 ++- src/modules/fancyzones/FancyZonesLib/util.cpp | 4 - .../UnitTests/AppZoneHistoryTests.Spec.cpp | 181 +++++++ .../UnitTests/AppliedLayoutsTests.Spec.cpp | 176 ++++++- .../UnitTests/JsonHelpers.Tests.cpp | 492 +----------------- .../FancyZonesTests/UnitTests/Util.Spec.cpp | 25 +- .../UnitTests/WorkArea.Spec.cpp | 26 +- .../editor/FancyZonesEditor/Models/Device.cs | 12 +- .../editor/FancyZonesEditor/Models/Monitor.cs | 4 +- .../Utils/FancyZonesEditorIO.cs | 84 ++- 19 files changed, 969 insertions(+), 928 deletions(-) diff --git a/src/modules/fancyzones/FancyZonesLib/FancyZones.cpp b/src/modules/fancyzones/FancyZonesLib/FancyZones.cpp index 8dee473c80..0b6032abbd 100644 --- a/src/modules/fancyzones/FancyZonesLib/FancyZones.cpp +++ b/src/modules/fancyzones/FancyZonesLib/FancyZones.cpp @@ -862,23 +862,10 @@ void FancyZones::AddWorkArea(HMONITOR monitor, const std::wstring& deviceId) noe if (monitor) { uniqueId.deviceName = FancyZonesUtils::TrimDeviceId(deviceId); - - MONITORINFOEXW mi; - mi.cbSize = sizeof(mi); - if (GetMonitorInfo(monitor, &mi)) - { - const FancyZonesUtils::Rect monitorRect(mi.rcMonitor); - uniqueId.width = monitorRect.width(); - uniqueId.height = monitorRect.height(); - } } else { uniqueId.deviceName = ZonedWindowProperties::MultiMonitorDeviceID; - - RECT combinedResolution = FancyZonesUtils::GetAllMonitorsCombinedRect<&MONITORINFO::rcMonitor>(); - uniqueId.width = combinedResolution.right - combinedResolution.left; - uniqueId.height = combinedResolution.bottom - combinedResolution.top; } FancyZonesDataTypes::DeviceIdData parentId{}; diff --git a/src/modules/fancyzones/FancyZonesLib/FancyZonesData.cpp b/src/modules/fancyzones/FancyZonesLib/FancyZonesData.cpp index 1ee3092a62..e67b405571 100644 --- a/src/modules/fancyzones/FancyZonesLib/FancyZonesData.cpp +++ b/src/modules/fancyzones/FancyZonesLib/FancyZonesData.cpp @@ -9,6 +9,7 @@ #include #include +#include #include // Non-localizable strings @@ -81,10 +82,10 @@ void FancyZonesData::SaveFancyZonesEditorParameters(bool spanZonesAcrossMonitors if (spanZonesAcrossMonitors) { auto monitorRect = FancyZonesUtils::GetAllMonitorsCombinedRect<&MONITORINFOEX::rcWork>(); - std::wstring monitorId = FancyZonesUtils::GenerateUniqueIdAllMonitorsArea(virtualDesktopId); JSONHelpers::MonitorInfo monitorJson; - monitorJson.id = monitorId; + monitorJson.monitorName = ZonedWindowProperties::MultiMonitorDeviceID; + monitorJson.virtualDesktop = virtualDesktopId; monitorJson.top = monitorRect.top; monitorJson.left = monitorRect.left; monitorJson.width = monitorRect.right - monitorRect.left; @@ -107,14 +108,14 @@ void FancyZonesData::SaveFancyZonesEditorParameters(bool spanZonesAcrossMonitors JSONHelpers::MonitorInfo monitorJson; std::wstring deviceId = FancyZonesUtils::GetDisplayDeviceId(monitorInfo.szDevice, displayDeviceIdxMap); - std::wstring monitorId = FancyZonesUtils::GenerateUniqueId(monitor, deviceId, virtualDesktopId); - + if (monitor == targetMonitor) { monitorJson.isSelected = true; /* Is monitor selected for the main editor window opening */ } - monitorJson.id = monitorId; /* Monitor id */ + monitorJson.monitorName = FancyZonesUtils::TrimDeviceId(deviceId); /* Monitor name */ + monitorJson.virtualDesktop = virtualDesktopId; /* Virtual desktop id */ UINT dpi = 0; if (DPIAware::GetScreenDPIForMonitor(monitor, dpi) != S_OK) diff --git a/src/modules/fancyzones/FancyZonesLib/FancyZonesData/AppZoneHistory.cpp b/src/modules/fancyzones/FancyZonesLib/FancyZonesData/AppZoneHistory.cpp index 9e5b825285..8e7a157745 100644 --- a/src/modules/fancyzones/FancyZonesLib/FancyZonesData/AppZoneHistory.cpp +++ b/src/modules/fancyzones/FancyZonesLib/FancyZonesData/AppZoneHistory.cpp @@ -10,6 +10,207 @@ #include #include +namespace JsonUtils +{ + struct AppZoneHistoryJSON + { + private: + static std::optional DeviceIdFromJson(const json::JsonObject& json) + { + try + { + if (json.HasKey(NonLocalizable::AppZoneHistoryIds::DeviceID)) + { + json::JsonObject device = json.GetNamedObject(NonLocalizable::AppZoneHistoryIds::DeviceID); + std::wstring monitor = device.GetNamedString(NonLocalizable::AppZoneHistoryIds::MonitorID).c_str(); + std::wstring virtualDesktop = device.GetNamedString(NonLocalizable::AppZoneHistoryIds::VirtualDesktopID).c_str(); + + auto virtualDesktopGuid = FancyZonesUtils::GuidFromString(virtualDesktop); + if (!virtualDesktopGuid) + { + return std::nullopt; + } + + return FancyZonesDataTypes::DeviceIdData{ + .deviceName = monitor, + .virtualDesktopId = virtualDesktopGuid.value(), + }; + } + else + { + std::wstring deviceIdStr = json.GetNamedString(NonLocalizable::AppZoneHistoryIds::DeviceIdID).c_str(); + auto bcDeviceId = BackwardsCompatibility::DeviceIdData::ParseDeviceId(deviceIdStr); + if (!bcDeviceId) + { + return std::nullopt; + } + + return FancyZonesDataTypes::DeviceIdData{ + .deviceName = bcDeviceId->deviceName, + .virtualDesktopId = bcDeviceId->virtualDesktopId, + }; + } + } + catch (const winrt::hresult_error&) + { + return std::nullopt; + } + } + + static std::optional ParseSingleAppZoneHistoryItem(const json::JsonObject& json) + { + FancyZonesDataTypes::AppZoneHistoryData data; + if (json.HasKey(NonLocalizable::AppZoneHistoryIds::LayoutIndexesID)) + { + data.zoneIndexSet = {}; + for (const auto& value : json.GetNamedArray(NonLocalizable::AppZoneHistoryIds::LayoutIndexesID)) + { + data.zoneIndexSet.push_back(static_cast(value.GetNumber())); + } + } + else if (json.HasKey(NonLocalizable::AppZoneHistoryIds::LayoutIndexesID)) + { + data.zoneIndexSet = { static_cast(json.GetNamedNumber(NonLocalizable::AppZoneHistoryIds::LayoutIndexesID)) }; + } + + auto deviceIdOpt = DeviceIdFromJson(json); + if (!deviceIdOpt) + { + return std::nullopt; + } + + data.deviceId = deviceIdOpt.value(); + data.zoneSetUuid = json.GetNamedString(NonLocalizable::AppZoneHistoryIds::LayoutIdID); + + if (!FancyZonesUtils::IsValidGuid(data.zoneSetUuid)) + { + return std::nullopt; + } + + return data; + } + + public: + std::wstring appPath; + std::vector data; + + static std::optional FromJson(const json::JsonObject& json) + { + try + { + AppZoneHistoryJSON result; + + result.appPath = json.GetNamedString(NonLocalizable::AppZoneHistoryIds::AppPathID); + if (json.HasKey(NonLocalizable::AppZoneHistoryIds::HistoryID)) + { + auto appHistoryArray = json.GetNamedArray(NonLocalizable::AppZoneHistoryIds::HistoryID); + for (uint32_t i = 0; i < appHistoryArray.Size(); ++i) + { + json::JsonObject json = appHistoryArray.GetObjectAt(i); + if (auto data = ParseSingleAppZoneHistoryItem(json); data.has_value()) + { + result.data.push_back(std::move(data.value())); + } + } + } + else + { + // handle previous file format, with single desktop layout information per application + if (auto data = ParseSingleAppZoneHistoryItem(json); data.has_value()) + { + result.data.push_back(std::move(data.value())); + } + } + if (result.data.empty()) + { + return std::nullopt; + } + + return result; + } + catch (const winrt::hresult_error&) + { + return std::nullopt; + } + } + + static json::JsonObject ToJson(const AppZoneHistoryJSON& appZoneHistory) + { + json::JsonObject result{}; + + result.SetNamedValue(NonLocalizable::AppZoneHistoryIds::AppPathID, json::value(appZoneHistory.appPath)); + + json::JsonArray appHistoryArray; + for (const auto& data : appZoneHistory.data) + { + json::JsonObject desktopData; + json::JsonArray jsonIndexSet; + for (ZoneIndex index : data.zoneIndexSet) + { + jsonIndexSet.Append(json::value(static_cast(index))); + } + + json::JsonObject device{}; + device.SetNamedValue(NonLocalizable::AppZoneHistoryIds::MonitorID, json::value(data.deviceId.deviceName)); + auto virtualDesktopStr = FancyZonesUtils::GuidToString(data.deviceId.virtualDesktopId); + if (virtualDesktopStr) + { + device.SetNamedValue(NonLocalizable::AppZoneHistoryIds::VirtualDesktopID, json::value(virtualDesktopStr.value())); + } + + desktopData.SetNamedValue(NonLocalizable::AppZoneHistoryIds::LayoutIndexesID, jsonIndexSet); + desktopData.SetNamedValue(NonLocalizable::AppZoneHistoryIds::DeviceID, device); + desktopData.SetNamedValue(NonLocalizable::AppZoneHistoryIds::LayoutIdID, json::value(data.zoneSetUuid)); + + appHistoryArray.Append(desktopData); + } + + result.SetNamedValue(NonLocalizable::AppZoneHistoryIds::HistoryID, appHistoryArray); + + return result; + } + }; + + AppZoneHistory::TAppZoneHistoryMap ParseAppZoneHistory(const json::JsonObject& fancyZonesDataJSON) + { + try + { + AppZoneHistory::TAppZoneHistoryMap appZoneHistoryMap{}; + auto appLastZones = fancyZonesDataJSON.GetNamedArray(NonLocalizable::AppZoneHistoryIds::AppZoneHistoryID); + + for (uint32_t i = 0; i < appLastZones.Size(); ++i) + { + json::JsonObject appLastZone = appLastZones.GetObjectAt(i); + if (auto appZoneHistory = AppZoneHistoryJSON::FromJson(appLastZone); appZoneHistory.has_value()) + { + appZoneHistoryMap[appZoneHistory->appPath] = std::move(appZoneHistory->data); + } + } + + return std::move(appZoneHistoryMap); + } + catch (const winrt::hresult_error&) + { + return {}; + } + } + + json::JsonObject SerializeJson(const AppZoneHistory::TAppZoneHistoryMap& map) + { + json::JsonObject root{}; + json::JsonArray appHistoryArray{}; + + for (const auto& [appPath, appZoneHistoryData] : map) + { + appHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ appPath, appZoneHistoryData })); + } + + root.SetNamedValue(NonLocalizable::AppZoneHistoryIds::AppZoneHistoryID, appHistoryArray); + return root; + } +} + + AppZoneHistory::AppZoneHistory() { } @@ -34,7 +235,7 @@ void AppZoneHistory::LoadData() { if (data) { - m_history = JSONHelpers::ParseAppZoneHistory(data.value()); + m_history = JsonUtils::ParseAppZoneHistory(data.value()); } else { @@ -72,11 +273,11 @@ void AppZoneHistory::SaveData() if (dirtyFlag) { - JSONHelpers::SaveAppZoneHistory(AppZoneHistoryFileName(), updatedHistory); + json::to_file(AppZoneHistoryFileName(), JsonUtils::SerializeJson(updatedHistory)); } else { - JSONHelpers::SaveAppZoneHistory(AppZoneHistoryFileName(), m_history); + json::to_file(AppZoneHistoryFileName(), JsonUtils::SerializeJson(m_history)); } } diff --git a/src/modules/fancyzones/FancyZonesLib/FancyZonesData/AppZoneHistory.h b/src/modules/fancyzones/FancyZonesLib/FancyZonesData/AppZoneHistory.h index 3eab15fdae..5c59f6cb43 100644 --- a/src/modules/fancyzones/FancyZonesLib/FancyZonesData/AppZoneHistory.h +++ b/src/modules/fancyzones/FancyZonesLib/FancyZonesData/AppZoneHistory.h @@ -5,6 +5,22 @@ #include +namespace NonLocalizable +{ + namespace AppZoneHistoryIds + { + const static wchar_t* AppZoneHistoryID = L"app-zone-history"; + const static wchar_t* AppPathID = L"app-path"; + const static wchar_t* HistoryID = L"history"; + const static wchar_t* LayoutIndexesID = L"zone-index-set"; + const static wchar_t* LayoutIdID = L"zoneset-uuid"; + const static wchar_t* DeviceIdID = L"device-id"; + const static wchar_t* DeviceID = L"device"; + const static wchar_t* MonitorID = L"monitor"; + const static wchar_t* VirtualDesktopID = L"virtual-desktop"; + } +} + class AppZoneHistory { public: diff --git a/src/modules/fancyzones/FancyZonesLib/FancyZonesData/AppliedLayouts.cpp b/src/modules/fancyzones/FancyZonesLib/FancyZonesData/AppliedLayouts.cpp index 3fb23fe4da..bd963b7577 100644 --- a/src/modules/fancyzones/FancyZonesLib/FancyZonesData/AppliedLayouts.cpp +++ b/src/modules/fancyzones/FancyZonesLib/FancyZonesData/AppliedLayouts.cpp @@ -11,6 +11,19 @@ #include #include +namespace +{ + // didn't use default constants since if they'll be changed later, it'll break this function + bool isLayoutDefault(const Layout& layout) + { + return layout.type == FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid && + layout.zoneCount == 3 && + layout.spacing == 16 && + layout.showSpacing == true && + layout.sensitivityRadius == 20; + } +} + namespace JsonUtils { struct LayoutJSON @@ -57,6 +70,50 @@ namespace JsonUtils struct AppliedLayoutsJSON { + private: + static std::optional DeviceIdFromJson(const json::JsonObject& json) + { + try + { + if (json.HasKey(NonLocalizable::AppliedLayoutsIds::DeviceID)) + { + json::JsonObject device = json.GetNamedObject(NonLocalizable::AppliedLayoutsIds::DeviceID); + std::wstring monitor = device.GetNamedString(NonLocalizable::AppliedLayoutsIds::MonitorID).c_str(); + std::wstring virtualDesktop = device.GetNamedString(NonLocalizable::AppliedLayoutsIds::VirtualDesktopID).c_str(); + + auto virtualDesktopGuid = FancyZonesUtils::GuidFromString(virtualDesktop); + if (!virtualDesktopGuid) + { + return std::nullopt; + } + + return FancyZonesDataTypes::DeviceIdData{ + .deviceName = monitor, + .virtualDesktopId = virtualDesktopGuid.value(), + }; + } + else + { + std::wstring deviceIdStr = json.GetNamedString(NonLocalizable::AppliedLayoutsIds::DeviceIdID).c_str(); + auto bcDeviceId = BackwardsCompatibility::DeviceIdData::ParseDeviceId(deviceIdStr); + if (!bcDeviceId) + { + return std::nullopt; + } + + return FancyZonesDataTypes::DeviceIdData{ + .deviceName = bcDeviceId->deviceName, + .virtualDesktopId = bcDeviceId->virtualDesktopId, + }; + } + } + catch (const winrt::hresult_error&) + { + return std::nullopt; + } + } + + public: FancyZonesDataTypes::DeviceIdData deviceId; Layout data; @@ -66,9 +123,8 @@ namespace JsonUtils { AppliedLayoutsJSON result; - std::wstring deviceIdStr = json.GetNamedString(NonLocalizable::AppliedLayoutsIds::DeviceIdID).c_str(); - auto deviceId = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(deviceIdStr); - if (!deviceId.has_value()) + auto deviceIdOpt = DeviceIdFromJson(json); + if (!deviceIdOpt.has_value()) { return std::nullopt; } @@ -79,7 +135,7 @@ namespace JsonUtils return std::nullopt; } - result.deviceId = std::move(deviceId.value()); + result.deviceId = std::move(deviceIdOpt.value()); result.data = std::move(layout.value()); return result; } @@ -91,9 +147,17 @@ namespace JsonUtils static json::JsonObject ToJson(const AppliedLayoutsJSON& value) { - json::JsonObject result{}; + json::JsonObject device{}; + device.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorID, json::value(value.deviceId.deviceName)); - result.SetNamedValue(NonLocalizable::AppliedLayoutsIds::DeviceIdID, json::value(value.deviceId.toString())); + auto virtualDesktopStr = FancyZonesUtils::GuidToString(value.deviceId.virtualDesktopId); + if (virtualDesktopStr) + { + device.SetNamedValue(NonLocalizable::AppliedLayoutsIds::VirtualDesktopID, json::value(virtualDesktopStr.value())); + } + + json::JsonObject result{}; + result.SetNamedValue(NonLocalizable::AppliedLayoutsIds::DeviceID, device); result.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutID, JsonUtils::LayoutJSON::ToJson(value.data)); return result; @@ -109,7 +173,12 @@ namespace JsonUtils { if (auto obj = AppliedLayoutsJSON::FromJson(layouts.GetObjectAt(i)); obj.has_value()) { - map[obj->deviceId] = std::move(obj->data); + // skip default layouts in case if they were applied to different resolutions on the same monitor. + // NOTE: keep the default layout check for users who update PT version from the v0.57 + if (!map.contains(obj->deviceId) && !isLayoutDefault(obj->data)) + { + map[obj->deviceId] = std::move(obj->data); + } } } diff --git a/src/modules/fancyzones/FancyZonesLib/FancyZonesData/AppliedLayouts.h b/src/modules/fancyzones/FancyZonesLib/FancyZonesData/AppliedLayouts.h index 579b14d042..3b93c11218 100644 --- a/src/modules/fancyzones/FancyZonesLib/FancyZonesData/AppliedLayouts.h +++ b/src/modules/fancyzones/FancyZonesLib/FancyZonesData/AppliedLayouts.h @@ -16,6 +16,9 @@ namespace NonLocalizable { const static wchar_t* AppliedLayoutsArrayID = L"applied-layouts"; const static wchar_t* DeviceIdID = L"device-id"; + const static wchar_t* DeviceID = L"device"; + const static wchar_t* MonitorID = L"monitor"; + const static wchar_t* VirtualDesktopID = L"virtual-desktop"; const static wchar_t* AppliedLayoutID = L"applied-layout"; const static wchar_t* UuidID = L"uuid"; const static wchar_t* TypeID = L"type"; diff --git a/src/modules/fancyzones/FancyZonesLib/FancyZonesDataTypes.cpp b/src/modules/fancyzones/FancyZonesLib/FancyZonesDataTypes.cpp index bf79eb46b1..f066dd1ea2 100644 --- a/src/modules/fancyzones/FancyZonesLib/FancyZonesDataTypes.cpp +++ b/src/modules/fancyzones/FancyZonesLib/FancyZonesDataTypes.cpp @@ -129,166 +129,6 @@ namespace FancyZonesDataTypes return high + 1; } - std::optional DeviceIdData::ParseDeviceId(const std::wstring& str) - { - FancyZonesDataTypes::DeviceIdData data; - - std::wstring temp; - std::wstringstream wss(str); - - /* - Important fix for device info that contains a '_' in the name: - 1. first search for '#' - 2. Then split the remaining string by '_' - */ - - // Step 1: parse the name until the #, then to the '_' - if (str.find(L'#') != std::string::npos) - { - std::getline(wss, temp, L'#'); - - data.deviceName = temp; - - if (!std::getline(wss, temp, L'_')) - { - return std::nullopt; - } - - data.deviceName += L"#" + temp; - } - else if (std::getline(wss, temp, L'_') && !temp.empty()) - { - data.deviceName = temp; - } - else - { - return std::nullopt; - } - - // Step 2: parse the rest of the id - std::vector parts; - while (std::getline(wss, temp, L'_')) - { - parts.push_back(temp); - } - - if (parts.size() != 3 && parts.size() != 4) - { - return std::nullopt; - } - - /* - Refer to FancyZonesUtils::GenerateUniqueId parts contain: - 1. monitor id [string] - 2. width of device [int] - 3. height of device [int] - 4. virtual desktop id (GUID) [string] - */ - try - { - for (const auto& c : parts[0]) - { - std::ignore = std::stoi(std::wstring(&c)); - } - - for (const auto& c : parts[1]) - { - std::ignore = std::stoi(std::wstring(&c)); - } - - data.width = std::stoi(parts[0]); - data.height = std::stoi(parts[1]); - } - catch (const std::exception&) - { - return std::nullopt; - } - - if (!SUCCEEDED(CLSIDFromString(parts[2].c_str(), &data.virtualDesktopId))) - { - return std::nullopt; - } - - if (parts.size() == 4) - { - data.monitorId = parts[3]; //could be empty - } - - return data; - } - - bool DeviceIdData::IsValidDeviceId(const std::wstring& str) - { - std::wstring monitorName; - std::wstring temp; - std::vector parts; - std::wstringstream wss(str); - - /* - Important fix for device info that contains a '_' in the name: - 1. first search for '#' - 2. Then split the remaining string by '_' - */ - - // Step 1: parse the name until the #, then to the '_' - if (str.find(L'#') != std::string::npos) - { - std::getline(wss, temp, L'#'); - - monitorName = temp; - - if (!std::getline(wss, temp, L'_')) - { - return false; - } - - monitorName += L"#" + temp; - parts.push_back(monitorName); - } - - // Step 2: parse the rest of the id - while (std::getline(wss, temp, L'_')) - { - parts.push_back(temp); - } - - if (parts.size() != 4) - { - return false; - } - - /* - Refer to FancyZonesUtils::GenerateUniqueId parts contain: - 1. monitor id [string] - 2. width of device [int] - 3. height of device [int] - 4. virtual desktop id (GUID) [string] - */ - try - { - //check if resolution contain only digits - for (const auto& c : parts[1]) - { - std::ignore = std::stoi(std::wstring(&c)); - } - for (const auto& c : parts[2]) - { - std::ignore = std::stoi(std::wstring(&c)); - } - } - catch (const std::exception&) - { - return false; - } - - if (!FancyZonesUtils::IsValidGuid(parts[3]) || parts[0].empty()) - { - return false; - } - - return true; - } - std::wstring DeviceIdData::toString() const { wil::unique_cotaskmem_string virtualDesktopIdStr; @@ -297,11 +137,7 @@ namespace FancyZonesDataTypes return std::wstring(); } - std::wstring result = deviceName + L"_" + std::to_wstring(width) + L"_" + std::to_wstring(height) + L"_" + virtualDesktopIdStr.get(); - if (!monitorId.empty()) - { - result += L"_" + monitorId; - } + std::wstring result = deviceName + L"_" + virtualDesktopIdStr.get(); return result; } diff --git a/src/modules/fancyzones/FancyZonesLib/FancyZonesDataTypes.h b/src/modules/fancyzones/FancyZonesLib/FancyZonesDataTypes.h index 26d34b5982..6790c3ac4b 100644 --- a/src/modules/fancyzones/FancyZonesLib/FancyZonesDataTypes.h +++ b/src/modules/fancyzones/FancyZonesLib/FancyZonesDataTypes.h @@ -116,14 +116,8 @@ namespace FancyZonesDataTypes struct DeviceIdData { std::wstring deviceName = L"FallbackDevice"; - int width; - int height; GUID virtualDesktopId; - std::wstring monitorId; - static std::optional ParseDeviceId(const std::wstring& str); - static bool IsValidDeviceId(const std::wstring& str); - std::wstring toString() const; }; @@ -152,7 +146,7 @@ namespace FancyZonesDataTypes inline bool operator==(const DeviceIdData& lhs, const DeviceIdData& rhs) { - return lhs.deviceName.compare(rhs.deviceName) == 0 && lhs.width == rhs.width && lhs.height == rhs.height && (lhs.virtualDesktopId == rhs.virtualDesktopId || lhs.virtualDesktopId == GUID_NULL || rhs.virtualDesktopId == GUID_NULL) && lhs.monitorId.compare(rhs.monitorId) == 0; + return lhs.deviceName.compare(rhs.deviceName) == 0 && (lhs.virtualDesktopId == rhs.virtualDesktopId || lhs.virtualDesktopId == GUID_NULL || rhs.virtualDesktopId == GUID_NULL); } inline bool operator!=(const DeviceIdData& lhs, const DeviceIdData& rhs) @@ -162,7 +156,7 @@ namespace FancyZonesDataTypes inline bool operator<(const DeviceIdData& lhs, const DeviceIdData& rhs) { - return lhs.deviceName.compare(rhs.deviceName) < 0 || lhs.width < rhs.width || lhs.height < rhs.height || lhs.monitorId.compare(rhs.monitorId) < 0; + return lhs.deviceName.compare(rhs.deviceName) < 0; } inline bool operator==(const DeviceInfoData& lhs, const DeviceInfoData& rhs) diff --git a/src/modules/fancyzones/FancyZonesLib/JsonHelpers.cpp b/src/modules/fancyzones/FancyZonesLib/JsonHelpers.cpp index 0d19491b9e..efcfa9aa70 100644 --- a/src/modules/fancyzones/FancyZonesLib/JsonHelpers.cpp +++ b/src/modules/fancyzones/FancyZonesLib/JsonHelpers.cpp @@ -63,7 +63,8 @@ namespace NonLocalizable // Editor arguments const wchar_t Dpi[] = L"dpi"; - const wchar_t MonitorId[] = L"monitor-id"; + const wchar_t MonitorNameId[] = L"monitor"; + const wchar_t VirtualDesktopId[] = L"virtual-desktop"; const wchar_t TopCoordinate[] = L"top-coordinate"; const wchar_t LeftCoordinate[] = L"left-coordinate"; const wchar_t Width[] = L"width"; @@ -74,6 +75,169 @@ namespace NonLocalizable const wchar_t Monitors[] = L"monitors"; } +namespace BackwardsCompatibility +{ + std::optional DeviceIdData::ParseDeviceId(const std::wstring& str) + { + DeviceIdData data; + + std::wstring temp; + std::wstringstream wss(str); + + /* + Important fix for device info that contains a '_' in the name: + 1. first search for '#' + 2. Then split the remaining string by '_' + */ + + // Step 1: parse the name until the #, then to the '_' + if (str.find(L'#') != std::string::npos) + { + std::getline(wss, temp, L'#'); + + data.deviceName = temp; + + if (!std::getline(wss, temp, L'_')) + { + return std::nullopt; + } + + data.deviceName += L"#" + temp; + } + else if (std::getline(wss, temp, L'_') && !temp.empty()) + { + data.deviceName = temp; + } + else + { + return std::nullopt; + } + + // Step 2: parse the rest of the id + std::vector parts; + while (std::getline(wss, temp, L'_')) + { + parts.push_back(temp); + } + + if (parts.size() != 3 && parts.size() != 4) + { + return std::nullopt; + } + + /* + Refer to FancyZonesUtils::GenerateUniqueId parts contain: + 1. monitor id [string] + 2. width of device [int] + 3. height of device [int] + 4. virtual desktop id (GUID) [string] + */ + try + { + for (const auto& c : parts[0]) + { + std::ignore = std::stoi(std::wstring(&c)); + } + + for (const auto& c : parts[1]) + { + std::ignore = std::stoi(std::wstring(&c)); + } + + data.width = std::stoi(parts[0]); + data.height = std::stoi(parts[1]); + } + catch (const std::exception&) + { + return std::nullopt; + } + + if (!SUCCEEDED(CLSIDFromString(parts[2].c_str(), &data.virtualDesktopId))) + { + return std::nullopt; + } + + if (parts.size() == 4) + { + data.monitorId = parts[3]; //could be empty + } + + return data; + } + + bool DeviceIdData::IsValidDeviceId(const std::wstring& str) + { + std::wstring monitorName; + std::wstring temp; + std::vector parts; + std::wstringstream wss(str); + + /* + Important fix for device info that contains a '_' in the name: + 1. first search for '#' + 2. Then split the remaining string by '_' + */ + + // Step 1: parse the name until the #, then to the '_' + if (str.find(L'#') != std::string::npos) + { + std::getline(wss, temp, L'#'); + + monitorName = temp; + + if (!std::getline(wss, temp, L'_')) + { + return false; + } + + monitorName += L"#" + temp; + parts.push_back(monitorName); + } + + // Step 2: parse the rest of the id + while (std::getline(wss, temp, L'_')) + { + parts.push_back(temp); + } + + if (parts.size() != 4) + { + return false; + } + + /* + Refer to FancyZonesUtils::GenerateUniqueId parts contain: + 1. monitor id [string] + 2. width of device [int] + 3. height of device [int] + 4. virtual desktop id (GUID) [string] + */ + try + { + //check if resolution contain only digits + for (const auto& c : parts[1]) + { + std::ignore = std::stoi(std::wstring(&c)); + } + for (const auto& c : parts[2]) + { + std::ignore = std::stoi(std::wstring(&c)); + } + } + catch (const std::exception&) + { + return false; + } + + if (!FancyZonesUtils::IsValidGuid(parts[3]) || parts[0].empty()) + { + return false; + } + + return true; + } +} + namespace { json::JsonArray NumVecToJsonArray(const std::vector& vec) @@ -115,13 +279,16 @@ namespace } std::wstring deviceIdStr = json.GetNamedString(NonLocalizable::DeviceIdStr).c_str(); - auto deviceId = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(deviceIdStr); + auto deviceId = BackwardsCompatibility::DeviceIdData::ParseDeviceId(deviceIdStr); if (!deviceId.has_value()) { return std::nullopt; } - data.deviceId = *deviceId; + data.deviceId = FancyZonesDataTypes::DeviceIdData{ + .deviceName = deviceId->deviceName, + .virtualDesktopId = deviceId->virtualDesktopId + }; data.zoneSetUuid = json.GetNamedString(NonLocalizable::ZoneSetUuidStr); if (!FancyZonesUtils::IsValidGuid(data.zoneSetUuid)) @@ -372,88 +539,6 @@ namespace JSONHelpers } } - json::JsonObject AppZoneHistoryJSON::ToJson(const AppZoneHistoryJSON& appZoneHistory) - { - json::JsonObject result{}; - - result.SetNamedValue(NonLocalizable::AppPathStr, json::value(appZoneHistory.appPath)); - - json::JsonArray appHistoryArray; - for (const auto& data : appZoneHistory.data) - { - json::JsonObject desktopData; - json::JsonArray jsonIndexSet; - for (ZoneIndex index : data.zoneIndexSet) - { - jsonIndexSet.Append(json::value(static_cast(index))); - } - - desktopData.SetNamedValue(NonLocalizable::ZoneIndexSetStr, jsonIndexSet); - desktopData.SetNamedValue(NonLocalizable::DeviceIdStr, json::value(data.deviceId.toString())); - desktopData.SetNamedValue(NonLocalizable::ZoneSetUuidStr, json::value(data.zoneSetUuid)); - - appHistoryArray.Append(desktopData); - } - - result.SetNamedValue(NonLocalizable::HistoryStr, appHistoryArray); - - return result; - } - - std::optional AppZoneHistoryJSON::FromJson(const json::JsonObject& zoneSet) - { - try - { - AppZoneHistoryJSON result; - - result.appPath = zoneSet.GetNamedString(NonLocalizable::AppPathStr); - if (zoneSet.HasKey(NonLocalizable::HistoryStr)) - { - auto appHistoryArray = zoneSet.GetNamedArray(NonLocalizable::HistoryStr); - for (uint32_t i = 0; i < appHistoryArray.Size(); ++i) - { - json::JsonObject json = appHistoryArray.GetObjectAt(i); - if (auto data = ParseSingleAppZoneHistoryItem(json); data.has_value()) - { - result.data.push_back(std::move(data.value())); - } - } - } - else - { - // handle previous file format, with single desktop layout information per application - if (auto data = ParseSingleAppZoneHistoryItem(zoneSet); data.has_value()) - { - result.data.push_back(std::move(data.value())); - } - } - if (result.data.empty()) - { - return std::nullopt; - } - - return result; - } - catch (const winrt::hresult_error&) - { - return std::nullopt; - } - } - - json::JsonObject DeviceInfoJSON::ToJson(const DeviceInfoJSON& device) - { - json::JsonObject result{}; - - result.SetNamedValue(NonLocalizable::DeviceIdStr, json::value(device.deviceId.toString())); - result.SetNamedValue(NonLocalizable::ActiveZoneSetStr, JSONHelpers::ZoneSetDataJSON::ToJson(device.data.activeZoneSet)); - result.SetNamedValue(NonLocalizable::EditorShowSpacingStr, json::value(device.data.showSpacing)); - result.SetNamedValue(NonLocalizable::EditorSpacingStr, json::value(device.data.spacing)); - result.SetNamedValue(NonLocalizable::EditorZoneCountStr, json::value(device.data.zoneCount)); - result.SetNamedValue(NonLocalizable::EditorSensitivityRadiusStr, json::value(device.data.sensitivityRadius)); - - return result; - } - std::optional DeviceInfoJSON::FromJson(const json::JsonObject& device) { try @@ -461,7 +546,7 @@ namespace JSONHelpers DeviceInfoJSON result; std::wstring deviceIdStr = device.GetNamedString(NonLocalizable::DeviceIdStr).c_str(); - auto deviceId = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(deviceIdStr); + auto deviceId = BackwardsCompatibility::DeviceIdData::ParseDeviceId(deviceIdStr); if (!deviceId.has_value()) { return std::nullopt; @@ -527,8 +612,9 @@ namespace JSONHelpers { json::JsonObject result{}; + result.SetNamedValue(NonLocalizable::MonitorNameId, json::value(monitor.monitorName)); + result.SetNamedValue(NonLocalizable::VirtualDesktopId, json::value(monitor.virtualDesktop)); result.SetNamedValue(NonLocalizable::Dpi, json::value(monitor.dpi)); - result.SetNamedValue(NonLocalizable::MonitorId, json::value(monitor.id)); result.SetNamedValue(NonLocalizable::TopCoordinate, json::value(monitor.top)); result.SetNamedValue(NonLocalizable::LeftCoordinate, json::value(monitor.left)); result.SetNamedValue(NonLocalizable::Width, json::value(monitor.width)); @@ -581,55 +667,6 @@ namespace JSONHelpers } } - void SaveAppZoneHistory(const std::wstring& appZoneHistoryFileName, const TAppZoneHistoryMap& appZoneHistoryMap) - { - json::JsonObject root{}; - - root.SetNamedValue(NonLocalizable::AppZoneHistoryStr, JSONHelpers::SerializeAppZoneHistory(appZoneHistoryMap)); - - auto before = json::from_file(appZoneHistoryFileName); - if (!before.has_value() || before.value().Stringify() != root.Stringify()) - { - json::to_file(appZoneHistoryFileName, root); - } - } - - TAppZoneHistoryMap ParseAppZoneHistory(const json::JsonObject& fancyZonesDataJSON) - { - try - { - TAppZoneHistoryMap appZoneHistoryMap{}; - auto appLastZones = fancyZonesDataJSON.GetNamedArray(NonLocalizable::AppZoneHistoryStr); - - for (uint32_t i = 0; i < appLastZones.Size(); ++i) - { - json::JsonObject appLastZone = appLastZones.GetObjectAt(i); - if (auto appZoneHistory = AppZoneHistoryJSON::FromJson(appLastZone); appZoneHistory.has_value()) - { - appZoneHistoryMap[appZoneHistory->appPath] = std::move(appZoneHistory->data); - } - } - - return std::move(appZoneHistoryMap); - } - catch (const winrt::hresult_error&) - { - return {}; - } - } - - json::JsonArray SerializeAppZoneHistory(const TAppZoneHistoryMap& appZoneHistoryMap) - { - json::JsonArray appHistoryArray; - - for (const auto& [appPath, appZoneHistoryData] : appZoneHistoryMap) - { - appHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ appPath, appZoneHistoryData })); - } - - return appHistoryArray; - } - std::optional ParseDeviceInfos(const json::JsonObject& fancyZonesDataJSON) { try @@ -670,7 +707,16 @@ namespace JSONHelpers layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SensitivityRadiusID, json::value(data.sensitivityRadius)); json::JsonObject obj{}; - obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::DeviceIdID, json::value(deviceID.toString())); + json::JsonObject device{}; + device.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorID, json::value(deviceID.deviceName)); + + auto virtualDesktopStr = FancyZonesUtils::GuidToString(deviceID.virtualDesktopId); + if (virtualDesktopStr) + { + device.SetNamedValue(NonLocalizable::AppliedLayoutsIds::VirtualDesktopID, json::value(virtualDesktopStr.value())); + } + + obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::DeviceID, device); obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutID, layout); layoutsArray.Append(obj); diff --git a/src/modules/fancyzones/FancyZonesLib/JsonHelpers.h b/src/modules/fancyzones/FancyZonesLib/JsonHelpers.h index 0bfe583f60..270fc45106 100644 --- a/src/modules/fancyzones/FancyZonesLib/JsonHelpers.h +++ b/src/modules/fancyzones/FancyZonesLib/JsonHelpers.h @@ -8,6 +8,36 @@ #include #include +namespace BackwardsCompatibility +{ + struct DeviceIdData + { + std::wstring deviceName = L"FallbackDevice"; + int width; + int height; + GUID virtualDesktopId; + std::wstring monitorId; + + static std::optional ParseDeviceId(const std::wstring& str); + static bool IsValidDeviceId(const std::wstring& str); + }; + + inline bool operator==(const BackwardsCompatibility::DeviceIdData& lhs, const BackwardsCompatibility::DeviceIdData& rhs) + { + return lhs.deviceName.compare(rhs.deviceName) == 0 && lhs.width == rhs.width && lhs.height == rhs.height && (lhs.virtualDesktopId == rhs.virtualDesktopId || lhs.virtualDesktopId == GUID_NULL || rhs.virtualDesktopId == GUID_NULL) && lhs.monitorId.compare(rhs.monitorId) == 0; + } + + inline bool operator!=(const BackwardsCompatibility::DeviceIdData& lhs, const BackwardsCompatibility::DeviceIdData& rhs) + { + return !(lhs == rhs); + } + + inline bool operator<(const BackwardsCompatibility::DeviceIdData& lhs, const BackwardsCompatibility::DeviceIdData& rhs) + { + return lhs.deviceName.compare(rhs.deviceName) < 0 || lhs.width < rhs.width || lhs.height < rhs.height || lhs.monitorId.compare(rhs.monitorId) < 0; + } +} + namespace JSONHelpers { namespace CanvasLayoutInfoJSON @@ -37,21 +67,11 @@ namespace JSONHelpers std::optional FromJson(const json::JsonObject& zoneSet); }; - struct AppZoneHistoryJSON - { - std::wstring appPath; - std::vector data; - - static json::JsonObject ToJson(const AppZoneHistoryJSON& appZoneHistory); - static std::optional FromJson(const json::JsonObject& zoneSet); - }; - struct DeviceInfoJSON { - FancyZonesDataTypes::DeviceIdData deviceId; + BackwardsCompatibility::DeviceIdData deviceId; FancyZonesDataTypes::DeviceInfoData data; - static json::JsonObject ToJson(const DeviceInfoJSON& device); static std::optional FromJson(const json::JsonObject& device); }; @@ -64,15 +84,15 @@ namespace JSONHelpers static std::optional FromJson(const json::JsonObject& device); }; - using TAppZoneHistoryMap = std::unordered_map>; - using TDeviceInfoMap = std::unordered_map; + using TDeviceInfoMap = std::unordered_map; using TCustomZoneSetsMap = std::unordered_map; using TLayoutQuickKeysMap = std::unordered_map; struct MonitorInfo { + std::wstring monitorName; + std::wstring virtualDesktop; int dpi; - std::wstring id; int top; int left; int width; @@ -93,10 +113,6 @@ namespace JSONHelpers json::JsonObject GetPersistFancyZonesJSON(const std::wstring& zonesSettingsFileName, const std::wstring& appZoneHistoryFileName); - TAppZoneHistoryMap ParseAppZoneHistory(const json::JsonObject& fancyZonesDataJSON); - json::JsonArray SerializeAppZoneHistory(const TAppZoneHistoryMap& appZoneHistoryMap); - void SaveAppZoneHistory(const std::wstring& appZoneHistoryFileName, const TAppZoneHistoryMap& appZoneHistoryMap); - // replace zones-settings: applied layouts std::optional ParseDeviceInfos(const json::JsonObject& fancyZonesDataJSON); void SaveAppliedLayouts(const TDeviceInfoMap& deviceInfoMap); @@ -113,3 +129,15 @@ namespace JSONHelpers std::optional ParseCustomZoneSets(const json::JsonObject& fancyZonesDataJSON); void SaveCustomLayouts(const TCustomZoneSetsMap& map); } + +namespace std +{ + template<> + struct hash + { + size_t operator()(const BackwardsCompatibility::DeviceIdData& Value) const + { + return 0; + } + }; +} \ No newline at end of file diff --git a/src/modules/fancyzones/FancyZonesLib/util.cpp b/src/modules/fancyzones/FancyZonesLib/util.cpp index 1bc541a1ef..f0347800da 100644 --- a/src/modules/fancyzones/FancyZonesLib/util.cpp +++ b/src/modules/fancyzones/FancyZonesLib/util.cpp @@ -215,10 +215,6 @@ namespace FancyZonesUtils Rect const monitorRect(mi.rcMonitor); // Unique identifier format: ___ return TrimDeviceId(deviceId) + - L'_' + - std::to_wstring(monitorRect.width()) + - L'_' + - std::to_wstring(monitorRect.height()) + L'_' + virtualDesktopId; } diff --git a/src/modules/fancyzones/FancyZonesTests/UnitTests/AppZoneHistoryTests.Spec.cpp b/src/modules/fancyzones/FancyZonesTests/UnitTests/AppZoneHistoryTests.Spec.cpp index d843048617..7902a9de66 100644 --- a/src/modules/fancyzones/FancyZonesTests/UnitTests/AppZoneHistoryTests.Spec.cpp +++ b/src/modules/fancyzones/FancyZonesTests/UnitTests/AppZoneHistoryTests.Spec.cpp @@ -4,6 +4,7 @@ #include #include "util.h" +#include using namespace Microsoft::VisualStudio::CppUnitTestFramework; @@ -24,6 +25,186 @@ namespace FancyZonesUnitTests std::filesystem::remove(AppZoneHistory::instance().AppZoneHistoryFileName()); } + TEST_METHOD (AppZoneHistoryParse) + { + // prepare + json::JsonObject root{}; + json::JsonArray appZoneHistoryArray{}; + + { + json::JsonArray history{}; + { + json::JsonObject device{}; + device.SetNamedValue(NonLocalizable::AppZoneHistoryIds::MonitorID, json::value(L"monitor-1")); + device.SetNamedValue(NonLocalizable::AppZoneHistoryIds::VirtualDesktopID, json::value(L"{72FA9FC0-26A6-4B37-A834-491C148DFC58}")); + + json::JsonArray zones{}; + zones.Append(json::value(0)); + zones.Append(json::value(1)); + + json::JsonObject historyObj{}; + historyObj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::LayoutIdID, json::value(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}")); + historyObj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::DeviceID, device); + historyObj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::LayoutIndexesID, zones); + + history.Append(historyObj); + } + { + json::JsonObject device{}; + device.SetNamedValue(NonLocalizable::AppZoneHistoryIds::MonitorID, json::value(L"monitor-2")); + device.SetNamedValue(NonLocalizable::AppZoneHistoryIds::VirtualDesktopID, json::value(L"{72FA9FC0-26A6-4B37-A834-491C148DFC58}")); + + json::JsonArray zones{}; + zones.Append(json::value(2)); + + json::JsonObject historyObj{}; + historyObj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::LayoutIdID, json::value(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}")); + historyObj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::DeviceID, device); + historyObj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::LayoutIndexesID, zones); + + history.Append(historyObj); + } + + json::JsonObject obj{}; + obj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::AppPathID, json::value(L"app-1")); + obj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::HistoryID, history); + appZoneHistoryArray.Append(obj); + } + { + json::JsonArray history{}; + { + json::JsonObject device{}; + device.SetNamedValue(NonLocalizable::AppZoneHistoryIds::MonitorID, json::value(L"monitor-1")); + device.SetNamedValue(NonLocalizable::AppZoneHistoryIds::VirtualDesktopID, json::value(L"{72FA9FC0-26A6-4B37-A834-491C148DFC58}")); + + json::JsonArray zones{}; + zones.Append(json::value(0)); + + json::JsonObject historyObj{}; + historyObj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::LayoutIdID, json::value(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}")); + historyObj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::DeviceID, device); + historyObj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::LayoutIndexesID, zones); + + history.Append(historyObj); + } + + json::JsonObject obj{}; + obj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::AppPathID, json::value(L"app-2")); + obj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::HistoryID, history); + appZoneHistoryArray.Append(obj); + } + + root.SetNamedValue(NonLocalizable::AppZoneHistoryIds::AppZoneHistoryID, appZoneHistoryArray); + json::to_file(AppZoneHistory::AppZoneHistoryFileName(), root); + + // test + AppZoneHistory::instance().LoadData(); + Assert::AreEqual((size_t)2, AppZoneHistory::instance().GetFullAppZoneHistory().size()); + + { + FancyZonesDataTypes::DeviceIdData id{ + .deviceName = L"monitor-1", + .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{72FA9FC0-26A6-4B37-A834-491C148DFC58}").value() + }; + Assert::IsTrue(AppZoneHistory::instance().GetZoneHistory(L"app-1", id).has_value()); + } + { + FancyZonesDataTypes::DeviceIdData id{ + .deviceName = L"monitor-2", + .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{72FA9FC0-26A6-4B37-A834-491C148DFC58}").value() + }; + Assert::IsTrue(AppZoneHistory::instance().GetZoneHistory(L"app-1", id).has_value()); + } + { + FancyZonesDataTypes::DeviceIdData id{ + .deviceName = L"monitor-1", + .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{72FA9FC0-26A6-4B37-A834-491C148DFC58}").value() + }; + Assert::IsTrue(AppZoneHistory::instance().GetZoneHistory(L"app-2", id).has_value()); + } + } + + TEST_METHOD (AppZoneHistoryParseEmpty) + { + // prepare + json::JsonObject root{}; + json::to_file(AppZoneHistory::AppZoneHistoryFileName(), root); + + // test + AppZoneHistory::instance().LoadData(); + Assert::IsTrue(AppZoneHistory::instance().GetFullAppZoneHistory().empty()); + } + + TEST_METHOD (AppZoneHistoryParseInvalid) + { + // prepare + json::JsonObject root{}; + json::JsonArray appZoneHistoryArray{}; + + { + json::JsonArray history{}; + { + json::JsonObject device{}; + device.SetNamedValue(NonLocalizable::AppZoneHistoryIds::MonitorID, json::value(L"monitor-1")); + device.SetNamedValue(NonLocalizable::AppZoneHistoryIds::VirtualDesktopID, json::value(L"{72FA9FC0-26A6-4B37-A834-491C148DFC58}")); + + json::JsonArray zones{}; + zones.Append(json::value(0)); + zones.Append(json::value(1)); + + json::JsonObject historyObj{}; + historyObj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::LayoutIdID, json::value(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}")); + historyObj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::DeviceID, device); + historyObj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::LayoutIndexesID, zones); + + history.Append(historyObj); + } + + json::JsonObject obj{}; + obj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::AppPathID, json::value(L"app-1")); + obj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::HistoryID, history); + appZoneHistoryArray.Append(obj); + } + { + json::JsonArray history{}; + { + json::JsonObject device{}; + device.SetNamedValue(NonLocalizable::AppZoneHistoryIds::MonitorID, json::value(L"monitor-1")); + device.SetNamedValue(NonLocalizable::AppZoneHistoryIds::VirtualDesktopID, json::value(L"{72FA9FC0-26A6-4B37-A834-}")); + + json::JsonArray zones{}; + zones.Append(json::value(0)); + + json::JsonObject historyObj{}; + historyObj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::LayoutIdID, json::value(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}")); + historyObj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::DeviceID, device); + historyObj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::LayoutIndexesID, zones); + + history.Append(historyObj); + } + + json::JsonObject obj{}; + obj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::AppPathID, json::value(L"app-2")); + obj.SetNamedValue(NonLocalizable::AppZoneHistoryIds::HistoryID, history); + appZoneHistoryArray.Append(obj); + } + + root.SetNamedValue(NonLocalizable::AppZoneHistoryIds::AppZoneHistoryID, appZoneHistoryArray); + json::to_file(AppZoneHistory::AppZoneHistoryFileName(), root); + + // test + AppZoneHistory::instance().LoadData(); + Assert::AreEqual((size_t)1, AppZoneHistory::instance().GetFullAppZoneHistory().size()); + + { + FancyZonesDataTypes::DeviceIdData id{ + .deviceName = L"monitor-1", + .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{72FA9FC0-26A6-4B37-A834-491C148DFC58}").value() + }; + Assert::IsTrue(AppZoneHistory::instance().GetZoneHistory(L"app-1", id).has_value()); + } + } + TEST_METHOD (AppLastZoneInvalidWindow) { const std::wstring zoneSetId = L"{2FEC41DA-3A0B-4E31-9CE1-9473C65D99F2}"; diff --git a/src/modules/fancyzones/FancyZonesTests/UnitTests/AppliedLayoutsTests.Spec.cpp b/src/modules/fancyzones/FancyZonesTests/UnitTests/AppliedLayoutsTests.Spec.cpp index f98b29f44b..9d8d422904 100644 --- a/src/modules/fancyzones/FancyZonesTests/UnitTests/AppliedLayoutsTests.Spec.cpp +++ b/src/modules/fancyzones/FancyZonesTests/UnitTests/AppliedLayoutsTests.Spec.cpp @@ -31,6 +31,46 @@ namespace FancyZonesUnitTests json::JsonObject root{}; json::JsonArray layoutsArray{}; + { + json::JsonObject layout{}; + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::UuidID, json::value(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}")); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::TypeID, json::value(FancyZonesDataTypes::TypeToString(FancyZonesDataTypes::ZoneSetLayoutType::Rows))); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ShowSpacingID, json::value(true)); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SpacingID, json::value(3)); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ZoneCountID, json::value(4)); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SensitivityRadiusID, json::value(22)); + + json::JsonObject device{}; + device.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorID, json::value(L"DELA026#5&10a58c63&0&UID16777488")); + device.SetNamedValue(NonLocalizable::AppliedLayoutsIds::VirtualDesktopID, json::value(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}")); + + json::JsonObject obj{}; + obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::DeviceID, device); + obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutID, layout); + + layoutsArray.Append(obj); + } + + root.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutsArrayID, layoutsArray); + json::to_file(AppliedLayouts::AppliedLayoutsFileName(), root); + + // test + AppliedLayouts::instance().LoadData(); + Assert::AreEqual((size_t)1, AppliedLayouts::instance().GetAppliedLayoutMap().size()); + + FancyZonesDataTypes::DeviceIdData id{ + .deviceName = L"DELA026#5&10a58c63&0&UID16777488", + .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}").value() + }; + Assert::IsTrue(AppliedLayouts::instance().GetDeviceLayout(id).has_value()); + } + + TEST_METHOD(AppliedLayoutsParseDataWithResolution) + { + // prepare + json::JsonObject root{}; + json::JsonArray layoutsArray{}; + { json::JsonObject layout{}; layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::UuidID, json::value(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}")); @@ -56,8 +96,114 @@ namespace FancyZonesUnitTests FancyZonesDataTypes::DeviceIdData id{ .deviceName = L"DELA026#5&10a58c63&0&UID16777488", - .width = 2194, - .height = 1234, + .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}").value() + }; + Assert::IsTrue(AppliedLayouts::instance().GetDeviceLayout(id).has_value()); + } + + TEST_METHOD (AppliedLayoutsParseDataWithResolution2) + { + // same monitor names and virtual desktop ids, but different resolution + // prepare + json::JsonObject root{}; + json::JsonArray layoutsArray{}; + + { + json::JsonObject layout{}; + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::UuidID, json::value(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}")); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::TypeID, json::value(FancyZonesDataTypes::TypeToString(FancyZonesDataTypes::ZoneSetLayoutType::Rows))); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ShowSpacingID, json::value(true)); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SpacingID, json::value(3)); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ZoneCountID, json::value(4)); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SensitivityRadiusID, json::value(22)); + + json::JsonObject obj{}; + obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::DeviceIdID, json::value(L"DELA026#5&10a58c63&0&UID16777488_2194_1234_{61FA9FC0-26A6-4B37-A834-491C148DFC57}")); + obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutID, layout); + + layoutsArray.Append(obj); + } + + { + json::JsonObject layout{}; + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::UuidID, json::value(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}")); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::TypeID, json::value(FancyZonesDataTypes::TypeToString(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid))); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ShowSpacingID, json::value(true)); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SpacingID, json::value(16)); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ZoneCountID, json::value(3)); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SensitivityRadiusID, json::value(20)); + + json::JsonObject obj{}; + obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::DeviceIdID, json::value(L"DELA026#5&10a58c63&0&UID16777488_1920_1080_{61FA9FC0-26A6-4B37-A834-491C148DFC57}")); + obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutID, layout); + + layoutsArray.Append(obj); + } + + root.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutsArrayID, layoutsArray); + json::to_file(AppliedLayouts::AppliedLayoutsFileName(), root); + + // test + AppliedLayouts::instance().LoadData(); + Assert::AreEqual((size_t)1, AppliedLayouts::instance().GetAppliedLayoutMap().size()); + + FancyZonesDataTypes::DeviceIdData id{ + .deviceName = L"DELA026#5&10a58c63&0&UID16777488", + .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}").value() + }; + Assert::IsTrue(AppliedLayouts::instance().GetDeviceLayout(id).has_value()); + } + + TEST_METHOD (AppliedLayoutsParseDataWithResolution3) + { + // same monitor names and virtual desktop ids, but different resolution + // non-default layouts applied + + // prepare + json::JsonObject root{}; + json::JsonArray layoutsArray{}; + + { + json::JsonObject layout{}; + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::UuidID, json::value(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}")); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::TypeID, json::value(FancyZonesDataTypes::TypeToString(FancyZonesDataTypes::ZoneSetLayoutType::Rows))); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ShowSpacingID, json::value(true)); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SpacingID, json::value(3)); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ZoneCountID, json::value(4)); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SensitivityRadiusID, json::value(22)); + + json::JsonObject obj{}; + obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::DeviceIdID, json::value(L"DELA026#5&10a58c63&0&UID16777488_2194_1234_{61FA9FC0-26A6-4B37-A834-491C148DFC57}")); + obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutID, layout); + + layoutsArray.Append(obj); + } + + { + json::JsonObject layout{}; + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::UuidID, json::value(L"{ACE817FD-2C51-4E13-903A-84CAB86FD178}")); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::TypeID, json::value(FancyZonesDataTypes::TypeToString(FancyZonesDataTypes::ZoneSetLayoutType::Columns))); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ShowSpacingID, json::value(true)); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SpacingID, json::value(3)); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ZoneCountID, json::value(4)); + layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SensitivityRadiusID, json::value(22)); + + json::JsonObject obj{}; + obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::DeviceIdID, json::value(L"DELA026#5&10a58c63&0&UID16777488_2194_1234_{61FA9FC0-26A6-4B37-A834-491C148DFC57}")); + obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutID, layout); + + layoutsArray.Append(obj); + } + + root.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutsArrayID, layoutsArray); + json::to_file(AppliedLayouts::AppliedLayoutsFileName(), root); + + // test + AppliedLayouts::instance().LoadData(); + Assert::AreEqual((size_t)1, AppliedLayouts::instance().GetAppliedLayoutMap().size()); + + FancyZonesDataTypes::DeviceIdData id{ + .deviceName = L"DELA026#5&10a58c63&0&UID16777488", .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}").value() }; Assert::IsTrue(AppliedLayouts::instance().GetDeviceLayout(id).has_value()); @@ -118,8 +264,6 @@ namespace FancyZonesUnitTests FancyZonesDataTypes::DeviceIdData id{ .deviceName = L"VSC9636#5&37ac4db&0&UID160005", - .width = 3840, - .height = 2160, .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value() }; Assert::IsTrue(AppliedLayouts::instance().GetDeviceLayout(id).has_value()); @@ -153,14 +297,10 @@ namespace FancyZonesUnitTests { FancyZonesDataTypes::DeviceIdData deviceSrc{ .deviceName = L"Device1", - .width = 200, - .height = 100, .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value() }; FancyZonesDataTypes::DeviceIdData deviceDst{ .deviceName = L"Device2", - .width = 300, - .height = 400, .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value() }; @@ -185,14 +325,10 @@ namespace FancyZonesUnitTests { FancyZonesDataTypes::DeviceIdData deviceSrc{ .deviceName = L"Device1", - .width = 200, - .height = 100, .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value() }; FancyZonesDataTypes::DeviceIdData deviceDst{ .deviceName = L"Device2", - .width = 300, - .height = 400, .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value() }; @@ -216,14 +352,10 @@ namespace FancyZonesUnitTests { FancyZonesDataTypes::DeviceIdData deviceSrc{ .deviceName = L"Device1", - .width = 200, - .height = 100, .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value() }; FancyZonesDataTypes::DeviceIdData deviceDst{ .deviceName = L"Device2", - .width = 300, - .height = 400, .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value() }; @@ -240,14 +372,10 @@ namespace FancyZonesUnitTests { FancyZonesDataTypes::DeviceIdData deviceSrc{ .deviceName = L"Device1", - .width = 200, - .height = 100, .virtualDesktopId = GUID_NULL }; FancyZonesDataTypes::DeviceIdData deviceDst{ .deviceName = L"Device2", - .width = 300, - .height = 400, .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value() }; @@ -273,8 +401,6 @@ namespace FancyZonesUnitTests // prepare FancyZonesDataTypes::DeviceIdData deviceId { .deviceName = L"DELA026#5&10a58c63&0&UID16777488", - .width = 2194, - .height = 1234, .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}").value() }; @@ -306,8 +432,6 @@ namespace FancyZonesUnitTests // prepare FancyZonesDataTypes::DeviceIdData deviceId{ .deviceName = L"DELA026#5&10a58c63&0&UID16777488", - .width = 2194, - .height = 1234, .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}").value() }; @@ -360,8 +484,6 @@ namespace FancyZonesUnitTests { FancyZonesDataTypes::DeviceIdData expected{ .deviceName = L"Device", - .width = 200, - .height = 100, .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value() }; @@ -377,8 +499,6 @@ namespace FancyZonesUnitTests { FancyZonesDataTypes::DeviceIdData expected{ .deviceName = L"Device", - .width = 200, - .height = 100, .virtualDesktopId = GUID_NULL }; diff --git a/src/modules/fancyzones/FancyZonesTests/UnitTests/JsonHelpers.Tests.cpp b/src/modules/fancyzones/FancyZonesTests/UnitTests/JsonHelpers.Tests.cpp index ba49b2ea2d..bc87154ccf 100644 --- a/src/modules/fancyzones/FancyZonesTests/UnitTests/JsonHelpers.Tests.cpp +++ b/src/modules/fancyzones/FancyZonesTests/UnitTests/JsonHelpers.Tests.cpp @@ -49,61 +49,61 @@ namespace FancyZonesUnitTests TEST_METHOD (DeviceId) { const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; - Assert::IsTrue(FancyZonesDataTypes::DeviceIdData::IsValidDeviceId(deviceId)); + Assert::IsTrue(BackwardsCompatibility::DeviceIdData::IsValidDeviceId(deviceId)); } TEST_METHOD (DeviceIdWithoutHashInName) { const auto deviceId = L"LOCALDISPLAY_5120_1440_{00000000-0000-0000-0000-000000000000}"; - Assert::IsTrue(FancyZonesDataTypes::DeviceIdData::IsValidDeviceId(deviceId)); + Assert::IsTrue(BackwardsCompatibility::DeviceIdData::IsValidDeviceId(deviceId)); } TEST_METHOD (DeviceIdWithoutHashInNameButWithUnderscores) { const auto deviceId = L"LOCAL_DISPLAY_5120_1440_{00000000-0000-0000-0000-000000000000}"; - Assert::IsFalse(FancyZonesDataTypes::DeviceIdData::IsValidDeviceId(deviceId)); + Assert::IsFalse(BackwardsCompatibility::DeviceIdData::IsValidDeviceId(deviceId)); } TEST_METHOD (DeviceIdWithUnderscoresInName) { const auto deviceId = L"Default_Monitor#1&1f0c3c2f&0&UID256_5120_1440_{00000000-0000-0000-0000-000000000000}"; - Assert::IsTrue(FancyZonesDataTypes::DeviceIdData::IsValidDeviceId(deviceId)); + Assert::IsTrue(BackwardsCompatibility::DeviceIdData::IsValidDeviceId(deviceId)); } TEST_METHOD (DeviceIdInvalidFormat) { const auto deviceId = L"_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; - Assert::IsFalse(FancyZonesDataTypes::DeviceIdData::IsValidDeviceId(deviceId)); + Assert::IsFalse(BackwardsCompatibility::DeviceIdData::IsValidDeviceId(deviceId)); } TEST_METHOD (DeviceIdInvalidFormat2) { const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_19201200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; - Assert::IsFalse(FancyZonesDataTypes::DeviceIdData::IsValidDeviceId(deviceId)); + Assert::IsFalse(BackwardsCompatibility::DeviceIdData::IsValidDeviceId(deviceId)); } TEST_METHOD (DeviceIdInvalidDecimals) { const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_aaaa_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; - Assert::IsFalse(FancyZonesDataTypes::DeviceIdData::IsValidDeviceId(deviceId)); + Assert::IsFalse(BackwardsCompatibility::DeviceIdData::IsValidDeviceId(deviceId)); } TEST_METHOD (DeviceIdInvalidDecimals2) { const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_19a0_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; - Assert::IsFalse(FancyZonesDataTypes::DeviceIdData::IsValidDeviceId(deviceId)); + Assert::IsFalse(BackwardsCompatibility::DeviceIdData::IsValidDeviceId(deviceId)); } TEST_METHOD (DeviceIdInvalidDecimals3) { const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_1900_120000000000000_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; - Assert::IsFalse(FancyZonesDataTypes::DeviceIdData::IsValidDeviceId(deviceId)); + Assert::IsFalse(BackwardsCompatibility::DeviceIdData::IsValidDeviceId(deviceId)); } TEST_METHOD (DeviceIdInvalidGuid) { const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-4B5D-8851-4791D66B1539}"; - Assert::IsFalse(FancyZonesDataTypes::DeviceIdData::IsValidDeviceId(deviceId)); + Assert::IsFalse(BackwardsCompatibility::DeviceIdData::IsValidDeviceId(deviceId)); } }; TEST_CLASS (ZoneSetLayoutTypeUnitTest) @@ -738,159 +738,26 @@ namespace FancyZonesUnitTests } }; - TEST_CLASS (AppZoneHistoryUnitTests) - { - TEST_METHOD (ToJson) - { - AppZoneHistoryData data{ - .zoneSetUuid = L"zoneset-uuid", .deviceId = L"device-id", .zoneIndexSet = { 54321 } - }; - AppZoneHistoryJSON appZoneHistory{ L"appPath", std::vector{ data } }; - json::JsonObject expected = json::JsonObject::Parse(L"{\"app-path\": \"appPath\", \"history\":[{\"zone-index-set\": [54321], \"device-id\": \"device-id_0_0_{00000000-0000-0000-0000-000000000000}\", \"zoneset-uuid\": \"zoneset-uuid\"}]}"); - - auto actual = AppZoneHistoryJSON::ToJson(appZoneHistory); - auto res = CustomAssert::CompareJsonObjects(expected, actual); - Assert::IsTrue(res.first, res.second.c_str()); - } - - TEST_METHOD (FromJson) - { - AppZoneHistoryData data{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = DeviceIdData::ParseDeviceId(L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}").value(), .zoneIndexSet = { - 54321 } - }; - AppZoneHistoryJSON expected{ L"appPath", std::vector{ data } }; - json::JsonObject json = json::JsonObject::Parse(L"{\"app-path\": \"appPath\", \"history\": [{\"device-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"zoneset-uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\", \"zone-index\": 54321}]}"); - - auto actual = AppZoneHistoryJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); - - Assert::AreEqual(expected.appPath.c_str(), actual->appPath.c_str()); - Assert::AreEqual(expected.data.size(), actual->data.size()); - Assert::IsTrue(expected.data[0].zoneIndexSet == actual->data[0].zoneIndexSet); - Assert::IsTrue(expected.data[0].deviceId == actual->data[0].deviceId); - Assert::AreEqual(expected.data[0].zoneSetUuid.c_str(), actual->data[0].zoneSetUuid.c_str()); - } - - TEST_METHOD (FromJsonInvalidUuid) - { - json::JsonObject json = json::JsonObject::Parse(L"{\"app-path\": \"appPath\", \"history\": [{\"device-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"zoneset-uuid\": \"zoneset-uuid\", \"zone-index\": 54321}]}"); - auto actual = AppZoneHistoryJSON::FromJson(json); - Assert::IsFalse(actual.has_value()); - } - - TEST_METHOD (FromJsonInvalidDeviceId) - { - json::JsonObject json = json::JsonObject::Parse(L"{\"app-path\": \"appPath\", \"history\": [{\"device-id\": \"device-id\", \"zoneset-uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\", \"zone-index\": 54321}]}"); - auto actual = AppZoneHistoryJSON::FromJson(json); - Assert::IsFalse(actual.has_value()); - } - - TEST_METHOD (FromJsonMissingKeys) - { - AppZoneHistoryData data{ - .zoneSetUuid = L"zoneset-uuid", .deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}", .zoneIndexSet = { 54321 } - }; - AppZoneHistoryJSON appZoneHistory{ L"appPath", std::vector{ data } }; - const auto json = AppZoneHistoryJSON::ToJson(appZoneHistory); - - auto iter = json.First(); - while (iter.HasCurrent()) - { - json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); - modifiedJson.Remove(iter.Current().Key()); - - auto actual = AppZoneHistoryJSON::FromJson(modifiedJson); - Assert::IsFalse(actual.has_value()); - - iter.MoveNext(); - } - } - - TEST_METHOD (FromJsonInvalidTypes) - { - json::JsonObject json = json::JsonObject::Parse(L"{\"app-path\": false, \"history\": [{\"device-id\": [], \"zoneset-uuid\": {}, \"zone-index\": \"54321\"}]}"); - Assert::IsFalse(AppZoneHistoryJSON::FromJson(json).has_value()); - } - - TEST_METHOD (ToJsonMultipleDesktopAppHistory) - { - AppZoneHistoryData data1{ - .zoneSetUuid = L"zoneset-uuid1", .deviceId = L"device-id1", .zoneIndexSet = { 54321 } - }; - AppZoneHistoryData data2{ - .zoneSetUuid = L"zoneset-uuid2", .deviceId = L"device-id2", .zoneIndexSet = { 12345 } - }; - AppZoneHistoryJSON appZoneHistory{ - L"appPath", std::vector{ data1, data2 } - }; - json::JsonObject expected = json::JsonObject::Parse(L"{\"app-path\": \"appPath\", \"history\": [{\"zone-index-set\": [54321], \"device-id\": \"device-id1_0_0_{00000000-0000-0000-0000-000000000000}\", \"zoneset-uuid\": \"zoneset-uuid1\"}, {\"zone-index-set\": [12345], \"device-id\": \"device-id2_0_0_{00000000-0000-0000-0000-000000000000}\", \"zoneset-uuid\": \"zoneset-uuid2\"}]}"); - - auto actual = AppZoneHistoryJSON::ToJson(appZoneHistory); - std::wstring s = actual.Stringify().c_str(); - auto res = CustomAssert::CompareJsonObjects(expected, actual); - Assert::IsTrue(res.first, res.second.c_str()); - } - - TEST_METHOD (FromJsonMultipleDesktopAppHistory) - { - AppZoneHistoryData data1{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = DeviceIdData::ParseDeviceId(L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}").value(), .zoneIndexSet = { 54321 } - }; - AppZoneHistoryData data2{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = DeviceIdData::ParseDeviceId(L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{8a0b9205-6128-45a2-934a-b97f5b271235}").value(), .zoneIndexSet = { - 12345 } - }; - AppZoneHistoryJSON expected{ - L"appPath", std::vector{ data1, data2 } - }; - json::JsonObject json = json::JsonObject::Parse(L"{\"app-path\": \"appPath\", \"history\": [{\"device-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"zoneset-uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\", \"zone-index-set\": [54321]}, {\"device-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1200_{8a0b9205-6128-45a2-934a-b97f5b271235}\", \"zoneset-uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\", \"zone-index-set\": [12345]}]}"); - - auto actual = AppZoneHistoryJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); - - Assert::AreEqual(expected.appPath.c_str(), actual->appPath.c_str()); - Assert::AreEqual(expected.data.size(), actual->data.size()); - - for (size_t i = 0; i < expected.data.size(); ++i) - { - Assert::IsTrue(expected.data[i].zoneIndexSet == actual->data[i].zoneIndexSet); - Assert::IsTrue(expected.data[i].deviceId == actual->data[i].deviceId); - Assert::AreEqual(expected.data[i].zoneSetUuid.c_str(), actual->data[i].zoneSetUuid.c_str()); - } - } - }; - TEST_CLASS (DeviceInfoUnitTests) { private: - FancyZonesDataTypes::DeviceIdData m_defaultDeviceId{ L"AOC2460#4&fe3a015&0&UID65793", 1920, 1200, }; - DeviceInfoJSON m_defaultDeviceInfo = DeviceInfoJSON{ m_defaultDeviceId, DeviceInfoData{ ZoneSetData{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Custom }, true, 16, 3 } }; + FancyZonesDataTypes::DeviceIdData m_defaultDeviceId{ .deviceName = L"AOC2460#4&fe3a015&0&UID65793", .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{33A2B101-06E0-437B-A61E-CDBECF502907}").value() }; + DeviceInfoJSON m_defaultDeviceInfo = DeviceInfoJSON{ BackwardsCompatibility::DeviceIdData::ParseDeviceId(L"AOC2460#4&fe3a015&0&UID65793_1920_1080_{33A2B101-06E0-437B-A61E-CDBECF502907}").value(), DeviceInfoData{ ZoneSetData{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Custom }, true, 16, 3 } }; json::JsonObject m_defaultJson = json::JsonObject::Parse(L"{\"device-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"active-zoneset\": {\"type\": \"custom\", \"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\"}, \"editor-show-spacing\": true, \"editor-spacing\": 16, \"editor-zone-count\": 3}"); TEST_METHOD_INITIALIZE(Init) { CLSIDFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}", &m_defaultDeviceId.virtualDesktopId); - m_defaultDeviceInfo.deviceId = m_defaultDeviceId; } public: - TEST_METHOD (ToJson) - { - DeviceInfoJSON deviceInfo = m_defaultDeviceInfo; - json::JsonObject expected = m_defaultJson; - - auto actual = DeviceInfoJSON::ToJson(deviceInfo); - auto res = CustomAssert::CompareJsonObjects(expected, actual); - Assert::IsTrue(res.first, res.second.c_str()); - } - TEST_METHOD (FromJson) { DeviceInfoJSON expected = m_defaultDeviceInfo; expected.data.spacing = true; - json::JsonObject json = DeviceInfoJSON::ToJson(expected); + json::JsonObject json = json::JsonObject::Parse(L"{\"device-id\":\"AOC2460#4&fe3a015&0&UID65793_1920_1080_{33A2B101-06E0-437B-A61E-CDBECF502907}\",\"active-zoneset\":{\"uuid\":\"{33A2B101-06E0-437B-A61E-CDBECF502906}\",\"type\":\"custom\"},\"editor-show-spacing\":true,\"editor-spacing\":16,\"editor-zone-count\":3, \"sensitivity-radius\":20}"); + auto actual = DeviceInfoJSON::FromJson(json); Assert::IsTrue(actual.has_value()); @@ -900,67 +767,6 @@ namespace FancyZonesUnitTests Assert::AreEqual(expected.data.activeZoneSet.uuid.c_str(), actual->data.activeZoneSet.uuid.c_str(), L"zone set uuid"); } - TEST_METHOD (FromJsonSpacingTrue) - { - DeviceInfoJSON expected = m_defaultDeviceInfo; - expected.data.spacing = true; - - json::JsonObject json = DeviceInfoJSON::ToJson(expected); - auto actual = DeviceInfoJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); - - Assert::AreEqual(expected.data.spacing, actual->data.spacing); - } - - TEST_METHOD (FromJsonSpacingFalse) - { - DeviceInfoJSON expected = m_defaultDeviceInfo; - expected.data.activeZoneSet.type = ZoneSetLayoutType::Custom; - - json::JsonObject json = DeviceInfoJSON::ToJson(expected); - auto actual = DeviceInfoJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); - - Assert::AreEqual(expected.data.spacing, actual->data.spacing); - } - - TEST_METHOD (FromJsonZoneGeneral) - { - DeviceInfoJSON expected = m_defaultDeviceInfo; - expected.data.activeZoneSet.type = ZoneSetLayoutType::PriorityGrid; - - json::JsonObject json = DeviceInfoJSON::ToJson(expected); - auto actual = DeviceInfoJSON::FromJson(json); - Assert::IsTrue(actual.has_value()); - - Assert::AreEqual((int)expected.data.activeZoneSet.type, (int)actual->data.activeZoneSet.type, L"zone set type"); - } - - TEST_METHOD (FromJsonMissingKeys) - { - DeviceInfoJSON deviceInfo{ m_defaultDeviceId, DeviceInfoData{ ZoneSetData{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Custom }, true, 16, 3, DefaultValues::SensitivityRadius } }; - const auto json = DeviceInfoJSON::ToJson(deviceInfo); - - auto iter = json.First(); - while (iter.HasCurrent()) - { - //this setting has been added later and gets a default value, so missing key still result is valid Json - if (iter.Current().Key() == L"editor-sensitivity-radius") - { - iter.MoveNext(); - continue; - } - - json::JsonObject modifiedJson = json::JsonObject::Parse(json.Stringify()); - modifiedJson.Remove(iter.Current().Key()); - - auto actual = DeviceInfoJSON::FromJson(modifiedJson); - Assert::IsFalse(actual.has_value()); - - iter.MoveNext(); - } - } - TEST_METHOD (FromJsonMissingSensitivityRadiusUsesDefault) { //json without "editor-sensitivity-radius" @@ -971,19 +777,7 @@ namespace FancyZonesUnitTests Assert::AreEqual(DefaultValues::SensitivityRadius, actual->data.sensitivityRadius); } - TEST_METHOD (FromJsonInvalidTypes) - { - json::JsonObject json = json::JsonObject::Parse(L"{\"device-id\": true, \"active-zoneset\": {\"type\": null, \"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\"}, \"editor-show-spacing\": true, \"editor-spacing\": 16, \"editor-zone-count\": 3}"); - Assert::IsFalse(DeviceInfoJSON::FromJson(json).has_value()); - } - - TEST_METHOD (FromJsonInvalidUuid) - { - json::JsonObject json = json::JsonObject::Parse(L"{\"device-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"active-zoneset\": {\"type\": \"custom\", \"uuid\": \"uuid\"}, \"editor-show-spacing\": true, \"editor-spacing\": 16, \"editor-zone-count\": 3}"); - Assert::IsFalse(DeviceInfoJSON::FromJson(json).has_value()); - } - - TEST_METHOD (FromJsonInvalidDeviceId) + TEST_METHOD (FromJsonInvalid) { json::JsonObject json = json::JsonObject::Parse(L"{\"device-id\": true, \"active-zoneset\": {\"type\": \"custom\", \"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\"}, \"editor-show-spacing\": true, \"editor-spacing\": 16, \"editor-zone-count\": 3}"); Assert::IsFalse(DeviceInfoJSON::FromJson(json).has_value()); @@ -994,27 +788,15 @@ namespace FancyZonesUnitTests { private: const std::wstring_view m_moduleName = L"FancyZonesUnitTests"; - const std::wstring m_defaultDeviceIdStr = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; const std::wstring m_defaultCustomDeviceStr = L"{\"device-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"active-zoneset\": {\"type\": \"custom\", \"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\"}, \"editor-show-spacing\": true, \"editor-spacing\": 16, \"editor-zone-count\": 3}"; const std::wstring m_defaultCustomLayoutStr = L"{\"device-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"applied-layout\": {\"type\": \"custom\", \"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\", \"show-spacing\": true, \"spacing\": 16, \"zone-count\": 3, \"sensitivity-radius\": 30}}"; const json::JsonValue m_defaultCustomDeviceValue = json::JsonValue::Parse(m_defaultCustomDeviceStr); - const json::JsonObject m_defaultCustomDeviceObj = json::JsonObject::Parse(m_defaultCustomDeviceStr); - const json::JsonObject m_defaultCustomLayoutObj = json::JsonObject::Parse(m_defaultCustomLayoutStr); - - const FancyZonesDataTypes::DeviceIdData m_defaultDeviceId = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(m_defaultDeviceIdStr).value(); - - GUID m_defaultVDId; - HINSTANCE m_hInst{}; - + const FancyZonesDataTypes::DeviceIdData m_defaultDeviceId = FancyZonesDataTypes::DeviceIdData{ .deviceName = L"AOC2460#4&fe3a015&0&UID65793", .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}").value() }; + TEST_METHOD_INITIALIZE(Init) { - m_hInst = (HINSTANCE)GetModuleHandleW(nullptr); std::filesystem::remove_all(PTSettingsHelper::get_module_save_folder_location(m_moduleName)); - - auto guid = Helpers::StringToGuid(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}"); - Assert::IsTrue(guid.has_value()); - m_defaultVDId = *guid; } TEST_METHOD_CLEANUP(CleanUp) @@ -1101,243 +883,15 @@ namespace FancyZonesUnitTests Assert::AreEqual((size_t)10, deviceInfoMap->size()); } - - TEST_METHOD (AppZoneHistoryParseSingle) - { - const std::wstring expectedAppPath = L"appPath"; - const auto expectedDeviceId = m_defaultDeviceId; - const std::wstring expectedZoneSetId = L"{33A2B101-06E0-437B-A61E-CDBECF502906}"; - const size_t expectedIndex = 54321; - - AppZoneHistoryData data{ - .zoneSetUuid = expectedZoneSetId, .deviceId = expectedDeviceId, .zoneIndexSet = { expectedIndex } - }; - AppZoneHistoryJSON expected{ expectedAppPath, std::vector{ data } }; - json::JsonArray zoneHistoryArray; - zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(expected)); - json::JsonObject json; - json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(zoneHistoryArray.Stringify())); - - const auto& appZoneHistoryMap = ParseAppZoneHistory(json); - - Assert::AreEqual((size_t)zoneHistoryArray.Size(), appZoneHistoryMap.size()); - - const auto& entry = appZoneHistoryMap.begin(); - Assert::AreEqual(expectedAppPath.c_str(), entry->first.c_str()); - - const auto entryData = entry->second; - Assert::AreEqual(expected.data.size(), entryData.size()); - Assert::AreEqual(expectedZoneSetId.c_str(), entryData[0].zoneSetUuid.c_str()); - Assert::IsTrue(expectedDeviceId == entryData[0].deviceId); - Assert::IsTrue(std::vector{ expectedIndex } == entryData[0].zoneIndexSet); - } - - TEST_METHOD (AppZoneHistoryParseManyApps) - { - json::JsonObject json; - json::JsonArray zoneHistoryArray; - AppZoneHistoryData data1{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502900}", .deviceId = DeviceIdData::ParseDeviceId(L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1530}").value(), .zoneIndexSet = { - 1 } - }; - AppZoneHistoryData data2{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502901}", .deviceId = DeviceIdData::ParseDeviceId(L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1531}").value(), .zoneIndexSet = { - 2 } - }; - AppZoneHistoryData data3{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502902}", .deviceId = DeviceIdData::ParseDeviceId(L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1532}").value(), .zoneIndexSet = { - 3 } - }; - AppZoneHistoryData data4{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502903}", .deviceId = DeviceIdData::ParseDeviceId(L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1533}").value(), .zoneIndexSet = { - 4 } - }; - zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-1", std::vector{ data1 } })); - zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-2", std::vector{ data2 } })); - zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-3", std::vector{ data3 } })); - zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ L"app-path-4", std::vector{ data4 } })); - - json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(zoneHistoryArray.Stringify())); - - const auto& appZoneHistoryMap = ParseAppZoneHistory(json); - - Assert::AreEqual((size_t)zoneHistoryArray.Size(), appZoneHistoryMap.size()); - - auto iter = zoneHistoryArray.First(); - while (iter.HasCurrent()) - { - auto expected = AppZoneHistoryJSON::FromJson(json::JsonObject::Parse(iter.Current().Stringify())); - - const auto& actual = appZoneHistoryMap.at(expected->appPath); - Assert::AreEqual(expected->data.size(), actual.size()); - Assert::IsTrue(expected->data[0].deviceId == actual[0].deviceId); - Assert::AreEqual(expected->data[0].zoneSetUuid.c_str(), actual[0].zoneSetUuid.c_str()); - Assert::IsTrue(expected->data[0].zoneIndexSet == actual[0].zoneIndexSet); - - iter.MoveNext(); - } - } - - TEST_METHOD (AppZoneHistoryParseManyZonesForSingleApp) - { - json::JsonObject json; - json::JsonArray zoneHistoryArray; - - const auto appPath = L"app-path"; - AppZoneHistoryData data1{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502900}", .deviceId = DeviceIdData::ParseDeviceId(L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1530}").value(), .zoneIndexSet = { - 1 } - }; - zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ appPath, std::vector{ data1 } })); - AppZoneHistoryData data2{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502901}", .deviceId = DeviceIdData::ParseDeviceId(L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1531}").value(), .zoneIndexSet = { - 2 } - }; - zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ appPath, std::vector{ data2 } })); - AppZoneHistoryData data3{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502902}", .deviceId = DeviceIdData::ParseDeviceId(L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1532}").value(), .zoneIndexSet = { - 3 } - }; - zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ appPath, std::vector{ data3 } })); - AppZoneHistoryData expected{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502903}", .deviceId = DeviceIdData::ParseDeviceId(L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1533}").value(), .zoneIndexSet = { - 4 } - }; - zoneHistoryArray.Append(AppZoneHistoryJSON::ToJson(AppZoneHistoryJSON{ appPath, std::vector{ expected } })); - json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(zoneHistoryArray.Stringify())); - - const auto& appZoneHistoryMap = ParseAppZoneHistory(json); - - Assert::AreEqual((size_t)1, appZoneHistoryMap.size()); - - const auto& actual = appZoneHistoryMap.at(appPath); - Assert::AreEqual((size_t)1, actual.size()); - Assert::IsTrue(expected.deviceId == actual[0].deviceId); - Assert::AreEqual(expected.zoneSetUuid.c_str(), actual[0].zoneSetUuid.c_str()); - Assert::IsTrue(expected.zoneIndexSet == actual[0].zoneIndexSet); - } - - TEST_METHOD (AppZoneHistoryParseEmpty) - { - const auto& appZoneHistoryMap = ParseAppZoneHistory(json::JsonObject()); - - Assert::IsTrue(appZoneHistoryMap.empty()); - } - - TEST_METHOD (AppZoneHistoryParseInvalid) - { - const std::wstring appPath = L"appPath"; - json::JsonObject json; - AppZoneHistoryData data{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = L"device-id", .zoneIndexSet = { 54321 } - }; - AppZoneHistoryJSON expected{ appPath, std::vector{ data } }; - json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(AppZoneHistoryJSON::ToJson(expected).Stringify())); - - const auto& appZoneHistoryMap = ParseAppZoneHistory(json); - - Assert::IsTrue(appZoneHistoryMap.empty()); - } - - TEST_METHOD (AppZoneHistoryParseInvalidUuid) - { - const std::wstring appPath = L"appPath"; - json::JsonObject json; - AppZoneHistoryData data{ - .zoneSetUuid = L"zoneset-uuid", .deviceId = L"device-id", .zoneIndexSet = { 54321 } - }; - AppZoneHistoryJSON expected{ appPath, std::vector{ data } }; - json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(AppZoneHistoryJSON::ToJson(expected).Stringify())); - - const auto& appZoneHistoryMap = ParseAppZoneHistory(json); - - Assert::IsTrue(appZoneHistoryMap.empty()); - } - - TEST_METHOD (AppZoneHistorySerializeSingle) - { - const std::wstring appPath = L"appPath"; - json::JsonArray expected; - AppZoneHistoryData data{ - .zoneSetUuid = L"{39B25DD2-130D-4B5D-8851-4791D66B1539}", .deviceId = m_defaultDeviceId, .zoneIndexSet = { 54321 } - }; - AppZoneHistoryJSON appZoneHistory{ - appPath, std::vector{ data } - }; - expected.Append(AppZoneHistoryJSON::ToJson(appZoneHistory)); - json::JsonObject json; - json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(expected.Stringify())); - - auto appZoneHistoryMap = ParseAppZoneHistory(json); - - const auto& actual = SerializeAppZoneHistory(appZoneHistoryMap); - auto res = CustomAssert::CompareJsonArrays(expected, actual); - Assert::IsTrue(res.first, res.second.c_str()); - } - - TEST_METHOD (AppZoneHistorySerializeMany) - { - json::JsonObject json; - json::JsonArray expected; - AppZoneHistoryData data1{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = m_defaultDeviceId, .zoneIndexSet = { 54321 } - }; - AppZoneHistoryJSON appZoneHistory1{ - L"app-path-1", std::vector{ data1 } - }; - AppZoneHistoryData data2{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = m_defaultDeviceId, .zoneIndexSet = { 54321 } - }; - AppZoneHistoryJSON appZoneHistory2{ - L"app-path-2", std::vector{ data2 } - }; - AppZoneHistoryData data3{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = m_defaultDeviceId, .zoneIndexSet = { 54321 } - }; - AppZoneHistoryJSON appZoneHistory3{ - L"app-path-3", std::vector{ data3 } - }; - AppZoneHistoryData data4{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = m_defaultDeviceId, .zoneIndexSet = { 54321 } - }; - AppZoneHistoryJSON appZoneHistory4{ - L"app-path-4", std::vector{ data4 } - }; - expected.Append(AppZoneHistoryJSON::ToJson(appZoneHistory1)); - expected.Append(AppZoneHistoryJSON::ToJson(appZoneHistory2)); - expected.Append(AppZoneHistoryJSON::ToJson(appZoneHistory3)); - expected.Append(AppZoneHistoryJSON::ToJson(appZoneHistory4)); - json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(expected.Stringify())); - - const auto& appZoneHistoryMap = ParseAppZoneHistory(json); - - const auto& actual = SerializeAppZoneHistory(appZoneHistoryMap); - auto res = CustomAssert::CompareJsonArrays(expected, actual); - Assert::IsTrue(res.first, res.second.c_str()); - } - - TEST_METHOD (AppZoneHistorySerializeEmpty) - { - json::JsonArray expected; - json::JsonObject json; - json.SetNamedValue(L"app-zone-history", json::JsonValue::Parse(expected.Stringify())); - - const auto& appZoneHistoryMap = ParseAppZoneHistory(json); - - const auto& actual = SerializeAppZoneHistory(appZoneHistoryMap); - auto res = CustomAssert::CompareJsonArrays(expected, actual); - Assert::IsTrue(res.first, res.second.c_str()); - } }; TEST_CLASS(EditorArgsUnitTests) { TEST_METHOD(MonitorToJson) { - const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; - MonitorInfo monitor{ 144, deviceId, -10, 0, 1920, 1080, true }; + MonitorInfo monitor{ L"AOC2460#4&fe3a015&0&UID65793", L"{39B25DD2-130D-4B5D-8851-4791D66B1539}", 144, -10, 0, 1920, 1080, true }; - const auto expectedStr = L"{\"dpi\": 144, \"monitor-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"top-coordinate\": -10, \"left-coordinate\": 0, \"width\": 1920, \"height\": 1080, \"is-selected\": true}"; + const auto expectedStr = L"{\"monitor\": \"AOC2460#4&fe3a015&0&UID65793\", \"virtual-desktop\": \"{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"dpi\": 144, \"top-coordinate\": -10, \"left-coordinate\": 0, \"width\": 1920, \"height\": 1080, \"is-selected\": true}"; const auto expected = json::JsonObject::Parse(expectedStr); const auto actual = MonitorInfo::ToJson(monitor); @@ -1348,14 +902,14 @@ namespace FancyZonesUnitTests TEST_METHOD(EditorArgsToJson) { - MonitorInfo monitor1{ 144, L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}", -10, 0, 1920, 1080, true }; - MonitorInfo monitor2{ 96, L"AOC2460#4&fe3a015&0&UID65793_1920_1080_{39B25DD2-130D-4B5D-8851-4791D66B1538}", 0, 1920, 1920, 1080, false }; + MonitorInfo monitor1{ L"AOC2460#4&fe3a015&0&UID65793", L"{39B25DD2-130D-4B5D-8851-4791D66B1539}", 144, -10, 0, 1920, 1080, true }; + MonitorInfo monitor2{ L"AOC2460#4&fe3a015&0&UID65793", L"{39B25DD2-130D-4B5D-8851-4791D66B1538}", 96, 0, 1920, 1920, 1080, false }; EditorArgs args{ 1, true, std::vector{ monitor1, monitor2 } }; - const std::wstring expectedMonitor1 = L"{\"dpi\": 144, \"monitor-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"top-coordinate\": -10, \"left-coordinate\": 0, \"width\": 1920, \"height\": 1080, \"is-selected\": true}"; - const std::wstring expectedMonitor2 = L"{\"dpi\": 96, \"monitor-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1080_{39B25DD2-130D-4B5D-8851-4791D66B1538}\", \"top-coordinate\": 0, \"left-coordinate\": 1920, \"width\": 1920, \"height\": 1080, \"is-selected\": false}"; + const std::wstring expectedMonitor1 = L"{\"monitor\": \"AOC2460#4&fe3a015&0&UID65793\", \"virtual-desktop\": \"{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"dpi\": 144, \"top-coordinate\": -10, \"left-coordinate\": 0, \"width\": 1920, \"height\": 1080, \"is-selected\": true}"; + const std::wstring expectedMonitor2 = L"{\"monitor\": \"AOC2460#4&fe3a015&0&UID65793\", \"virtual-desktop\": \"{39B25DD2-130D-4B5D-8851-4791D66B1538}\", \"dpi\": 96, \"top-coordinate\": 0, \"left-coordinate\": 1920, \"width\": 1920, \"height\": 1080, \"is-selected\": false}"; const std::wstring expectedStr = L"{\"process-id\": 1, \"span-zones-across-monitors\": true, \"monitors\": [" + expectedMonitor1 + L", " + expectedMonitor2 + L"]}"; const auto expected = json::JsonObject::Parse(expectedStr); diff --git a/src/modules/fancyzones/FancyZonesTests/UnitTests/Util.Spec.cpp b/src/modules/fancyzones/FancyZonesTests/UnitTests/Util.Spec.cpp index ba49aeaa0e..33f2dfd9a0 100644 --- a/src/modules/fancyzones/FancyZonesTests/UnitTests/Util.Spec.cpp +++ b/src/modules/fancyzones/FancyZonesTests/UnitTests/Util.Spec.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "Util.h" #include "FancyZonesLib\util.h" +#include "FancyZonesLib/JsonHelpers.h" using namespace Microsoft::VisualStudio::CppUnitTestFramework; @@ -69,9 +70,9 @@ namespace FancyZonesUnitTests GUID guid; const auto expectedGuidStr = L"{E0A2904E-889C-4532-95B1-28FE15C16F66}"; CLSIDFromString(expectedGuidStr, &guid); - const FancyZonesDataTypes::DeviceIdData expected{ L"AOC0001#5&37ac4db&0&UID160002", 1536, 960, guid }; + const BackwardsCompatibility::DeviceIdData expected{ L"AOC0001#5&37ac4db&0&UID160002", 1536, 960, guid }; - const auto actual = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(input); + const auto actual = BackwardsCompatibility::DeviceIdData::ParseDeviceId(input); Assert::IsTrue(actual.has_value()); Assert::AreEqual(expected.deviceName, actual->deviceName); @@ -91,9 +92,9 @@ namespace FancyZonesUnitTests GUID guid; const auto expectedGuidStr = L"{E0A2904E-889C-4532-95B1-28FE15C16F66}"; CLSIDFromString(expectedGuidStr, &guid); - const FancyZonesDataTypes::DeviceIdData expected{ L"AOC0001#5&37ac4db&0&UID160002", 1536, 960, guid, L"monitorId" }; + const BackwardsCompatibility::DeviceIdData expected{ L"AOC0001#5&37ac4db&0&UID160002", 1536, 960, guid, L"monitorId" }; - const auto actual = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(input); + const auto actual = BackwardsCompatibility::DeviceIdData::ParseDeviceId(input); Assert::IsTrue(actual.has_value()); Assert::AreEqual(expected.deviceName, actual->deviceName); @@ -114,9 +115,9 @@ namespace FancyZonesUnitTests GUID guid; const auto expectedGuidStr = L"{E0A2904E-889C-4532-95B1-28FE15C16F66}"; CLSIDFromString(expectedGuidStr, &guid); - const FancyZonesDataTypes::DeviceIdData expected{ L"AOC00015&37ac4db&0&UID160002", 1536, 960, guid }; + const BackwardsCompatibility::DeviceIdData expected{ L"AOC00015&37ac4db&0&UID160002", 1536, 960, guid }; - const auto actual = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(input); + const auto actual = BackwardsCompatibility::DeviceIdData::ParseDeviceId(input); Assert::IsTrue(actual.has_value()); Assert::AreEqual(expected.deviceName, actual->deviceName); @@ -133,7 +134,7 @@ namespace FancyZonesUnitTests { // no width or height const std::wstring input = L"AOC00015&37ac4db&0&UID160002_1536960_{E0A2904E-889C-4532-95B1-28FE15C16F66}"; - const auto actual = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(input); + const auto actual = BackwardsCompatibility::DeviceIdData::ParseDeviceId(input); Assert::IsFalse(actual.has_value()); } @@ -141,7 +142,7 @@ namespace FancyZonesUnitTests { // no width and height const std::wstring input = L"AOC00015&37ac4db&0&UID160002_{E0A2904E-889C-4532-95B1-28FE15C16F66}_monitorId"; - const auto actual = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(input); + const auto actual = BackwardsCompatibility::DeviceIdData::ParseDeviceId(input); Assert::IsFalse(actual.has_value()); } @@ -149,7 +150,7 @@ namespace FancyZonesUnitTests { // no guid const std::wstring input = L"AOC00015&37ac4db&0&UID160002_1536960_"; - const auto actual = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(input); + const auto actual = BackwardsCompatibility::DeviceIdData::ParseDeviceId(input); Assert::IsFalse(actual.has_value()); } @@ -157,7 +158,7 @@ namespace FancyZonesUnitTests { // invalid guid const std::wstring input = L"AOC00015&37ac4db&0&UID160002_1536960_{asdf}"; - const auto actual = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(input); + const auto actual = BackwardsCompatibility::DeviceIdData::ParseDeviceId(input); Assert::IsFalse(actual.has_value()); } @@ -165,7 +166,7 @@ namespace FancyZonesUnitTests { // invalid width/height const std::wstring input = L"AOC00015&37ac4db&0&UID160002_15a6_960_{E0A2904E-889C-4532-95B1-28FE15C16F66}"; - const auto actual = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(input); + const auto actual = BackwardsCompatibility::DeviceIdData::ParseDeviceId(input); Assert::IsFalse(actual.has_value()); } @@ -173,7 +174,7 @@ namespace FancyZonesUnitTests { // changed order const std::wstring input = L"AOC00015&37ac4db&0&UID160002_15a6_960_monitorId_{E0A2904E-889C-4532-95B1-28FE15C16F66}"; - const auto actual = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(input); + const auto actual = BackwardsCompatibility::DeviceIdData::ParseDeviceId(input); Assert::IsFalse(actual.has_value()); } diff --git a/src/modules/fancyzones/FancyZonesTests/UnitTests/WorkArea.Spec.cpp b/src/modules/fancyzones/FancyZonesTests/UnitTests/WorkArea.Spec.cpp index ba18404725..936a7a7d42 100644 --- a/src/modules/fancyzones/FancyZonesTests/UnitTests/WorkArea.Spec.cpp +++ b/src/modules/fancyzones/FancyZonesTests/UnitTests/WorkArea.Spec.cpp @@ -48,13 +48,9 @@ namespace FancyZonesUnitTests Assert::AreNotEqual(0, GetMonitorInfoW(m_monitor, &m_monitorInfo)); m_parentUniqueId.deviceName = L"DELA026#5&10a58c63&0&UID16777488"; - m_parentUniqueId.width = m_monitorInfo.rcMonitor.right - m_monitorInfo.rcMonitor.left; - m_parentUniqueId.height = m_monitorInfo.rcMonitor.bottom - m_monitorInfo.rcMonitor.top; CLSIDFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}", &m_parentUniqueId.virtualDesktopId); m_uniqueId.deviceName = L"DELA026#5&10a58c63&0&UID16777488"; - m_uniqueId.width = m_monitorInfo.rcMonitor.right - m_monitorInfo.rcMonitor.left; - m_uniqueId.height = m_monitorInfo.rcMonitor.bottom - m_monitorInfo.rcMonitor.top; CLSIDFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}", &m_uniqueId.virtualDesktopId); auto guid = Helpers::StringToGuid(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}"); @@ -116,19 +112,10 @@ namespace FancyZonesUnitTests FancyZonesDataTypes::DeviceIdData uniqueIdData; uniqueIdData.virtualDesktopId = m_virtualDesktopGuid; - MONITORINFOEXW mi; - mi.cbSize = sizeof(mi); - if (GetMonitorInfo(m_monitor, &mi)) - { - FancyZonesUtils::Rect const monitorRect(mi.rcMonitor); - uniqueIdData.width = monitorRect.width(); - uniqueIdData.height = monitorRect.height(); - } - auto workArea = MakeWorkArea(m_hInst, m_monitor, uniqueIdData, {}); const std::wstring expectedWorkArea = std::to_wstring(m_monitorInfo.rcMonitor.right) + L"_" + std::to_wstring(m_monitorInfo.rcMonitor.bottom); - const FancyZonesDataTypes::DeviceIdData expectedUniqueId{ L"FallbackDevice", m_monitorInfo.rcMonitor.right - m_monitorInfo.rcMonitor.left, m_monitorInfo.rcMonitor.bottom - m_monitorInfo.rcMonitor.top, m_virtualDesktopGuid }; + const FancyZonesDataTypes::DeviceIdData expectedUniqueId{ L"FallbackDevice", m_virtualDesktopGuid }; Assert::IsNotNull(workArea.get()); Assert::IsTrue(expectedUniqueId == workArea->UniqueId()); @@ -145,15 +132,6 @@ namespace FancyZonesUnitTests FancyZonesDataTypes::DeviceIdData uniqueId; uniqueId.deviceName = FancyZonesUtils::TrimDeviceId(m_deviceId); - MONITORINFOEXW mi; - mi.cbSize = sizeof(mi); - if (GetMonitorInfo(m_monitor, &mi)) - { - FancyZonesUtils::Rect const monitorRect(mi.rcMonitor); - uniqueId.width = monitorRect.width(); - uniqueId.height = monitorRect.height(); - } - auto workArea = MakeWorkArea(m_hInst, m_monitor, uniqueId, {}); const std::wstring expectedWorkArea = std::to_wstring(m_monitorInfo.rcMonitor.right) + L"_" + std::to_wstring(m_monitorInfo.rcMonitor.bottom); @@ -208,8 +186,6 @@ namespace FancyZonesUnitTests Assert::AreNotEqual(0, GetMonitorInfoW(m_monitor, &m_monitorInfo)); m_uniqueId.deviceName = L"DELA026#5&10a58c63&0&UID16777488"; - m_uniqueId.width = m_monitorInfo.rcMonitor.right - m_monitorInfo.rcMonitor.left; - m_uniqueId.height = m_monitorInfo.rcMonitor.bottom - m_monitorInfo.rcMonitor.top; CLSIDFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}", &m_uniqueId.virtualDesktopId); AppZoneHistory::instance().LoadData(); diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Models/Device.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Models/Device.cs index e874da2acd..6a17b582f2 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Models/Device.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Models/Device.cs @@ -11,7 +11,9 @@ namespace FancyZonesEditor.Utils { public class Device { - public string Id { get; set; } + public string MonitorName { get; set; } + + public string VirtualDesktopId { get; set; } public Rect UnscaledBounds { get; private set; } @@ -21,9 +23,10 @@ namespace FancyZonesEditor.Utils public int Dpi { get; set; } - public Device(string id, int dpi, Rect bounds, Rect workArea) + public Device(string monitorName, string virtualDesktopId, int dpi, Rect bounds, Rect workArea) { - Id = id; + MonitorName = monitorName; + VirtualDesktopId = virtualDesktopId; Dpi = dpi; WorkAreaRect = workArea; UnscaledBounds = bounds; @@ -55,7 +58,8 @@ namespace FancyZonesEditor.Utils { var sb = new StringBuilder(); - sb.AppendFormat(CultureInfo.InvariantCulture, "ID: {0}{1}", Id, Environment.NewLine); + sb.AppendFormat(CultureInfo.InvariantCulture, "MonitorName: {0}{1}", MonitorName, Environment.NewLine); + sb.AppendFormat(CultureInfo.InvariantCulture, "Virtual desktop: {0}{1}", VirtualDesktopId, Environment.NewLine); sb.AppendFormat(CultureInfo.InvariantCulture, "DPI: {0}{1}", Dpi, Environment.NewLine); string workArea = string.Format(CultureInfo.InvariantCulture, "({0}, {1}, {2}, {3})", WorkAreaRect.X, WorkAreaRect.Y, WorkAreaRect.Width, WorkAreaRect.Height); diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Models/Monitor.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Models/Monitor.cs index 7ce9186dd3..5977b58813 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Models/Monitor.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Models/Monitor.cs @@ -41,10 +41,10 @@ namespace FancyZonesEditor.Models Window.Height = workArea.Height; } - public Monitor(string id, int dpi, Rect bounds, Rect workArea) + public Monitor(string monitorName, string virtualDesktop, int dpi, Rect bounds, Rect workArea) : this(bounds, workArea) { - Device = new Device(id, dpi, bounds, workArea); + Device = new Device(monitorName, virtualDesktop, dpi, bounds, workArea); } public void Scale(double scaleFactor) diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs index 922d52ce6b..6c98e877d1 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs @@ -75,7 +75,9 @@ namespace FancyZonesEditor.Utils // parsing cmd args private struct NativeMonitorData { - public string MonitorId { get; set; } + public string Monitor { get; set; } + + public string VirtualDesktop { get; set; } public int Dpi { get; set; } @@ -94,8 +96,10 @@ namespace FancyZonesEditor.Utils var sb = new StringBuilder(); // using CultureInfo.InvariantCulture since this is internal data - sb.Append("ID: "); - sb.AppendLine(MonitorId); + sb.Append("Monitor: "); + sb.AppendLine(Monitor); + sb.Append("Virtual desktop: "); + sb.AppendLine(VirtualDesktop); sb.Append("DPI: "); sb.AppendLine(Dpi.ToString(CultureInfo.InvariantCulture)); @@ -111,6 +115,13 @@ namespace FancyZonesEditor.Utils // applied-layouts.json private struct AppliedLayoutWrapper { + public struct DeviceIdWrapper + { + public string Monitor { get; set; } + + public string VirtualDesktop { get; set; } + } + public struct LayoutWrapper { public string Uuid { get; set; } @@ -126,7 +137,7 @@ namespace FancyZonesEditor.Utils public int SensitivityRadius { get; set; } } - public string DeviceId { get; set; } + public DeviceIdWrapper Device { get; set; } public LayoutWrapper AppliedLayout { get; set; } } @@ -329,7 +340,7 @@ namespace FancyZonesEditor.Utils for (int i = 0; i < count; i++) { var nativeData = default(NativeMonitorData); - nativeData.MonitorId = argsParts[(int)CmdArgs.MonitorId + (i * monitorArgsCount)]; + nativeData.Monitor = argsParts[(int)CmdArgs.MonitorId + (i * monitorArgsCount)]; nativeData.Dpi = int.Parse(argsParts[(int)CmdArgs.DPI + (i * monitorArgsCount)], CultureInfo.InvariantCulture); nativeData.LeftCoordinate = int.Parse(argsParts[(int)CmdArgs.MonitorLeft + (i * monitorArgsCount)], CultureInfo.InvariantCulture); nativeData.TopCoordinate = int.Parse(argsParts[(int)CmdArgs.MonitorTop + (i * monitorArgsCount)], CultureInfo.InvariantCulture); @@ -346,14 +357,13 @@ namespace FancyZonesEditor.Utils { foreach (NativeMonitorData nativeData in nativeMonitorData) { - var splittedId = nativeData.MonitorId.Split('_'); - int width = int.Parse(splittedId[1], CultureInfo.InvariantCulture); - int height = int.Parse(splittedId[2], CultureInfo.InvariantCulture); + var splittedId = nativeData.Monitor.Split('_'); Rect bounds = new Rect(nativeData.LeftCoordinate, nativeData.TopCoordinate, nativeData.Width, nativeData.Height); Monitor monitor = new Monitor(bounds, bounds); - monitor.Device.Id = nativeData.MonitorId; + monitor.Device.MonitorName = nativeData.Monitor.Substring(0, nativeData.Monitor.LastIndexOf("_", StringComparison.Ordinal)); + monitor.Device.VirtualDesktopId = nativeData.Monitor.Substring(nativeData.Monitor.LastIndexOf("_", StringComparison.Ordinal) + 1); monitor.Device.Dpi = nativeData.Dpi; monitors.Add(monitor); @@ -366,11 +376,12 @@ namespace FancyZonesEditor.Utils Rect workArea = new Rect(nativeData.LeftCoordinate, nativeData.TopCoordinate, nativeData.Width, nativeData.Height); if (nativeData.IsSelected) { - targetMonitorName = nativeData.MonitorId; + targetMonitorName = nativeData.Monitor; } var monitor = new Monitor(workArea, workArea); - monitor.Device.Id = nativeData.MonitorId; + monitor.Device.MonitorName = nativeData.Monitor.Substring(0, nativeData.Monitor.LastIndexOf("_", StringComparison.Ordinal)); + monitor.Device.VirtualDesktopId = nativeData.Monitor.Substring(nativeData.Monitor.LastIndexOf("_", StringComparison.Ordinal) + 1); monitor.Device.Dpi = nativeData.Dpi; App.Overlay.AddMonitor(monitor); @@ -381,7 +392,11 @@ namespace FancyZonesEditor.Utils for (int i = 0; i < monitors.Count; i++) { var monitor = monitors[i]; - if (monitor.Device.Id == targetMonitorName) + + var monitorName = targetMonitorName.Substring(0, targetMonitorName.LastIndexOf("_", StringComparison.Ordinal)); + var virtualDesktop = targetMonitorName.Substring(targetMonitorName.LastIndexOf("_", StringComparison.Ordinal) + 1); + + if (monitor.Device.MonitorName == monitorName && monitor.Device.VirtualDesktopId == virtualDesktop) { App.Overlay.CurrentDesktop = i; break; @@ -399,7 +414,7 @@ namespace FancyZonesEditor.Utils for (int i = 0; i < count; i++) { var nativeData = default(NativeMonitorData); - nativeData.MonitorId = argsParts[(int)CmdArgs.MonitorId + (i * monitorArgsCount)]; + nativeData.Monitor = argsParts[(int)CmdArgs.MonitorId + (i * monitorArgsCount)]; nativeData.Dpi = int.Parse(argsParts[(int)CmdArgs.DPI + (i * monitorArgsCount)], CultureInfo.InvariantCulture); nativeData.LeftCoordinate = int.Parse(argsParts[(int)CmdArgs.MonitorLeft + (i * monitorArgsCount)], CultureInfo.InvariantCulture); nativeData.TopCoordinate = int.Parse(argsParts[(int)CmdArgs.MonitorTop + (i * monitorArgsCount)], CultureInfo.InvariantCulture); @@ -419,7 +434,11 @@ namespace FancyZonesEditor.Utils } var monitor = new Monitor(workAreaUnion, workAreaUnion); - monitor.Device.Id = targetMonitorName; + + var monitorName = targetMonitorName.Substring(0, targetMonitorName.LastIndexOf("_", StringComparison.Ordinal)); + var virtualDesktop = targetMonitorName.Substring(targetMonitorName.LastIndexOf("_", StringComparison.Ordinal) + 1); + monitor.Device.MonitorName = monitorName; + monitor.Device.VirtualDesktopId = virtualDesktop; App.Overlay.Monitors.Add(monitor); } @@ -453,18 +472,21 @@ namespace FancyZonesEditor.Utils if (!App.Overlay.SpanZonesAcrossMonitors) { - string targetMonitorName = string.Empty; + string targetMonitorId = string.Empty; + string targetVirtualDesktop = string.Empty; foreach (NativeMonitorData nativeData in editorParams.Monitors) { Rect workArea = new Rect(nativeData.LeftCoordinate, nativeData.TopCoordinate, nativeData.Width, nativeData.Height); if (nativeData.IsSelected) { - targetMonitorName = nativeData.MonitorId; + targetMonitorId = nativeData.Monitor; + targetVirtualDesktop = nativeData.VirtualDesktop; } var monitor = new Monitor(workArea, workArea); - monitor.Device.Id = nativeData.MonitorId; + monitor.Device.MonitorName = nativeData.Monitor; + monitor.Device.VirtualDesktopId = nativeData.VirtualDesktop; monitor.Device.Dpi = nativeData.Dpi; App.Overlay.AddMonitor(monitor); @@ -475,7 +497,7 @@ namespace FancyZonesEditor.Utils for (int i = 0; i < monitors.Count; i++) { var monitor = monitors[i]; - if (monitor.Device.Id == targetMonitorName) + if (monitor.Device.MonitorName == targetMonitorId && monitor.Device.VirtualDesktopId == targetVirtualDesktop) { App.Overlay.CurrentDesktop = i; break; @@ -493,7 +515,9 @@ namespace FancyZonesEditor.Utils Rect workArea = new Rect(nativeData.LeftCoordinate, nativeData.TopCoordinate, nativeData.Width, nativeData.Height); var monitor = new Monitor(workArea, workArea); - monitor.Device.Id = nativeData.MonitorId; + monitor.Device.MonitorName = nativeData.Monitor; + monitor.Device.VirtualDesktopId = nativeData.VirtualDesktop; + App.Overlay.AddMonitor(monitor); } } @@ -688,7 +712,12 @@ namespace FancyZonesEditor.Utils layouts.AppliedLayouts.Add(new AppliedLayoutWrapper { - DeviceId = monitor.Device.Id, + Device = new AppliedLayoutWrapper.DeviceIdWrapper + { + Monitor = monitor.Device.MonitorName, + VirtualDesktop = monitor.Device.VirtualDesktopId, + }, + AppliedLayout = new AppliedLayoutWrapper.LayoutWrapper { Uuid = zoneset.ZonesetUuid, @@ -936,7 +965,12 @@ namespace FancyZonesEditor.Utils var monitors = App.Overlay.Monitors; foreach (var layout in layouts) { - if (layout.DeviceId == null || layout.DeviceId.Length == 0 || layout.AppliedLayout.Uuid == null || layout.AppliedLayout.Uuid.Length == 0) + if (layout.Device.Monitor == null || + layout.Device.Monitor.Length == 0 || + layout.Device.VirtualDesktop == null || + layout.Device.VirtualDesktop.Length == 0 || + layout.AppliedLayout.Uuid == null || + layout.AppliedLayout.Uuid.Length == 0) { result = false; continue; @@ -945,13 +979,7 @@ namespace FancyZonesEditor.Utils bool unused = true; foreach (Monitor monitor in monitors) { - string deviceIdSaved = monitor.Device.Id.Substring(0, monitor.Device.Id.LastIndexOf("_", StringComparison.Ordinal)); - string deviceIdReadFromSettings = layout.DeviceId.Substring(0, layout.DeviceId.LastIndexOf("_", StringComparison.Ordinal)); - - string virtualDesktopIdSaved = monitor.Device.Id.Substring(monitor.Device.Id.LastIndexOf("_", StringComparison.Ordinal) + 1); - string virtualDesktopIdReadFromSettings = layout.DeviceId.Substring(layout.DeviceId.LastIndexOf("_", StringComparison.Ordinal) + 1); - - if (deviceIdSaved == deviceIdReadFromSettings && (virtualDesktopIdSaved == virtualDesktopIdReadFromSettings || virtualDesktopIdReadFromSettings == DefaultVirtualDesktopGuid)) + if (monitor.Device.MonitorName == layout.Device.Monitor && (monitor.Device.VirtualDesktopId == layout.Device.VirtualDesktop || layout.Device.VirtualDesktop == DefaultVirtualDesktopGuid)) { var settings = new LayoutSettings {