diff --git a/src/modules/fancyzones/FancyZonesLib/FancyZones.cpp b/src/modules/fancyzones/FancyZonesLib/FancyZones.cpp index 9127cdada2..cf4df48a50 100644 --- a/src/modules/fancyzones/FancyZonesLib/FancyZones.cpp +++ b/src/modules/fancyzones/FancyZonesLib/FancyZones.cpp @@ -241,6 +241,8 @@ FancyZones::Run() noexcept PostMessage(m_window, WM_HOTKEY, 1, 0); } }); + + FancyZonesDataInstance().SetVirtualDesktopCheckCallback(std::bind(&VirtualDesktop::IsVirtualDesktopIdSavedInRegistry, &m_virtualDesktop, std::placeholders::_1)); } // IFancyZones @@ -683,7 +685,7 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa } else if (message == WM_PRIV_VD_UPDATE) { - RegisterVirtualDesktopUpdates(); + OnDisplayChange(DisplayChangeType::Initialization); } else if (message == WM_PRIV_EDITOR) { @@ -755,7 +757,14 @@ void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept changeType == DisplayChangeType::Initialization) { m_previousDesktopId = m_currentDesktopId; - auto currentVirtualDesktopId = m_virtualDesktop.GetCurrentVirtualDesktopId(); + + auto currentVirtualDesktopId = m_virtualDesktop.GetCurrentVirtualDesktopIdFromRegistry(); + if (!currentVirtualDesktopId.has_value()) + { + Logger::info("Virtual Desktop id from top level window"); + currentVirtualDesktopId = m_virtualDesktop.GetDesktopIdByTopLevelWindows(); + } + if (currentVirtualDesktopId.has_value()) { m_currentDesktopId = *currentVirtualDesktopId; @@ -792,33 +801,49 @@ void FancyZones::AddZoneWindow(HMONITOR monitor, const std::wstring& deviceId) n _TRACER_; if (m_workAreaHandler.IsNewWorkArea(m_currentDesktopId, monitor)) { - wil::unique_cotaskmem_string virtualDesktopId; - if (SUCCEEDED(StringFromCLSID(m_currentDesktopId, &virtualDesktopId))) + wil::unique_cotaskmem_string virtualDesktopIdStr; + if (!SUCCEEDED(StringFromCLSID(m_currentDesktopId, &virtualDesktopIdStr))) { - std::wstring uniqueId; + Logger::debug(L"Add new work area on virtual desktop {}", virtualDesktopIdStr.get()); + } + + FancyZonesDataTypes::DeviceIdData uniqueId; + uniqueId.virtualDesktopId = m_currentDesktopId; - if (monitor) - { - uniqueId = FancyZonesUtils::GenerateUniqueId(monitor, deviceId, virtualDesktopId.get()); - } - else - { - uniqueId = FancyZonesUtils::GenerateUniqueIdAllMonitorsArea(virtualDesktopId.get()); - } + if (monitor) + { + uniqueId.deviceName = FancyZonesUtils::TrimDeviceId(deviceId); - std::wstring parentId{}; - auto parentArea = m_workAreaHandler.GetWorkArea(m_previousDesktopId, monitor); - if (parentArea) + MONITORINFOEXW mi; + mi.cbSize = sizeof(mi); + if (GetMonitorInfo(monitor, &mi)) { - parentId = parentArea->UniqueId(); + 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; + } - auto workArea = MakeWorkArea(m_hinstance, monitor, uniqueId, parentId, GetZoneColors(), m_settings->GetSettings()->overlappingZonesAlgorithm); - if (workArea) - { - m_workAreaHandler.AddWorkArea(m_currentDesktopId, monitor, workArea); - FancyZonesDataInstance().SaveZoneSettings(); - } + FancyZonesDataTypes::DeviceIdData parentId{}; + auto parentArea = m_workAreaHandler.GetWorkArea(m_previousDesktopId, monitor); + if (parentArea) + { + parentId = parentArea->UniqueId(); + } + + auto workArea = MakeWorkArea(m_hinstance, monitor, uniqueId, parentId, GetZoneColors(), m_settings->GetSettings()->overlappingZonesAlgorithm); + if (workArea) + { + m_workAreaHandler.AddWorkArea(m_currentDesktopId, monitor, workArea); + FancyZonesDataInstance().SaveZoneSettings(); } } } @@ -839,34 +864,34 @@ LRESULT CALLBACK FancyZones::s_WndProc(HWND window, UINT message, WPARAM wparam, void FancyZones::UpdateZoneWindows() noexcept { - // Mapping between display device name and device index (operating system identifies each display device with an index value). - std::unordered_map displayDeviceIdxMap; - struct capture - { - FancyZones* fancyZones; - std::unordered_map* displayDeviceIdx; - }; - - auto callback = [](HMONITOR monitor, HDC, RECT*, LPARAM data) -> BOOL { - capture* params = reinterpret_cast(data); - MONITORINFOEX mi{ { .cbSize = sizeof(mi) } }; - if (GetMonitorInfoW(monitor, &mi)) - { - auto& displayDeviceIdxMap = *(params->displayDeviceIdx); - FancyZones* fancyZones = params->fancyZones; - - std::wstring deviceId = FancyZonesUtils::GetDisplayDeviceId(mi.szDevice, displayDeviceIdxMap); - fancyZones->AddZoneWindow(monitor, deviceId); - } - return TRUE; - }; - if (m_settings->GetSettings()->spanZonesAcrossMonitors) { AddZoneWindow(nullptr, {}); } else { + // Mapping between display device name and device index (operating system identifies each display device with an index value). + std::unordered_map displayDeviceIdxMap; + struct capture + { + FancyZones* fancyZones; + std::unordered_map* displayDeviceIdx; + }; + + auto callback = [](HMONITOR monitor, HDC, RECT*, LPARAM data) -> BOOL { + capture* params = reinterpret_cast(data); + MONITORINFOEX mi{ { .cbSize = sizeof(mi) } }; + if (GetMonitorInfoW(monitor, &mi)) + { + auto& displayDeviceIdxMap = *(params->displayDeviceIdx); + FancyZones* fancyZones = params->fancyZones; + + std::wstring deviceId = FancyZonesUtils::GetDisplayDeviceId(mi.szDevice, displayDeviceIdxMap); + fancyZones->AddZoneWindow(monitor, deviceId); + } + return TRUE; + }; + capture capture{ this, &displayDeviceIdxMap }; EnumDisplayMonitors(nullptr, nullptr, callback, reinterpret_cast(&capture)); } @@ -874,22 +899,15 @@ void FancyZones::UpdateZoneWindows() noexcept void FancyZones::UpdateWindowsPositions() noexcept { - auto callback = [](HWND window, LPARAM data) -> BOOL { + for (const auto [window, desktopId] : m_virtualDesktop.GetWindowsRelatedToDesktops()) + { auto zoneIndexSet = GetZoneIndexSet(window); - auto strongThis = reinterpret_cast(data); - auto desktopId = strongThis->m_virtualDesktop.GetWindowDesktopId(window); - if (desktopId.has_value()) + auto zoneWindow = m_workAreaHandler.GetWorkArea(window, desktopId); + if (zoneWindow) { - auto zoneWindow = strongThis->m_workAreaHandler.GetWorkArea(window, *desktopId); - if (zoneWindow) - { - strongThis->m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, zoneIndexSet, zoneWindow); - } + m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, zoneIndexSet, zoneWindow); } - - return TRUE; - }; - EnumWindows(callback, reinterpret_cast(this)); + } } bool FancyZones::OnSnapHotkeyBasedOnZoneNumber(HWND window, DWORD vkCode) noexcept @@ -1107,28 +1125,14 @@ void FancyZones::RegisterVirtualDesktopUpdates() noexcept { _TRACER_; - auto guids = m_virtualDesktop.GetVirtualDesktopIds(); - std::vector guidStrings{}; + auto guids = m_virtualDesktop.GetVirtualDesktopIdsFromRegistry(); if (guids.has_value()) { m_workAreaHandler.RegisterUpdates(*guids); - - for (auto& guid : *guids) - { - auto guidString = FancyZonesUtils::GuidToString(guid); - if (guidString.has_value()) - { - guidStrings.push_back(*guidString); - } - } - - if (!guidStrings.empty()) - { - FancyZonesDataInstance().UpdatePrimaryDesktopData(guidStrings[0]); - } - - FancyZonesDataInstance().RemoveDeletedDesktops(guidStrings); + FancyZonesDataInstance().RemoveDeletedDesktops(*guids); } + + FancyZonesDataInstance().SyncVirtualDesktops(m_currentDesktopId); } void FancyZones::OnSettingsChanged() noexcept @@ -1163,6 +1167,7 @@ void FancyZones::OnEditorExitEvent() noexcept { // Collect information about changes in zone layout after editor exited. FancyZonesDataInstance().LoadFancyZonesData(); + FancyZonesDataInstance().SyncVirtualDesktops(m_currentDesktopId); UpdateZoneSets(); } diff --git a/src/modules/fancyzones/FancyZonesLib/FancyZonesData.cpp b/src/modules/fancyzones/FancyZonesLib/FancyZonesData.cpp index bbb2a67ab1..f8be67c50b 100644 --- a/src/modules/fancyzones/FancyZonesLib/FancyZonesData.cpp +++ b/src/modules/fancyzones/FancyZonesLib/FancyZonesData.cpp @@ -5,6 +5,7 @@ #include "ZoneSet.h" #include "Settings.h" #include "CallTracer.h" +#include "GuidUtils.h" #include #include @@ -30,7 +31,6 @@ namespace NonLocalizable const wchar_t FancyZonesDataFile[] = L"zones-settings.json"; const wchar_t FancyZonesAppZoneHistoryFile[] = L"app-zone-history.json"; const wchar_t FancyZonesEditorParametersFile[] = L"editor-parameters.json"; - const wchar_t DefaultGuid[] = L"{00000000-0000-0000-0000-000000000000}"; const wchar_t RegistryPath[] = L"Software\\SuperFancyZones"; } @@ -157,6 +157,11 @@ FancyZonesData::FancyZonesData() editorParametersFileName = saveFolderPath + L"\\" + std::wstring(NonLocalizable::FancyZonesEditorParametersFile); } +void FancyZonesData::SetVirtualDesktopCheckCallback(std::function callback) +{ + m_virtualDesktopCheckCallback = callback; +} + const JSONHelpers::TDeviceInfoMap& FancyZonesData::GetDeviceInfoMap() const { std::scoped_lock lock{ dataLock }; @@ -175,7 +180,7 @@ const std::unordered_map FancyZonesData::FindDeviceInfo(const std::wstring& zoneWindowId) const +std::optional FancyZonesData::FindDeviceInfo(const FancyZonesDataTypes::DeviceIdData& zoneWindowId) const { std::scoped_lock lock{ dataLock }; auto it = deviceInfoMap.find(zoneWindowId); @@ -189,7 +194,7 @@ std::optional FancyZonesData::FindCustom return it != end(customZoneSetsMap) ? std::optional{ it->second } : std::nullopt; } -bool FancyZonesData::AddDevice(const std::wstring& deviceId) +bool FancyZonesData::AddDevice(const FancyZonesDataTypes::DeviceIdData& deviceId) { _TRACER_; using namespace FancyZonesDataTypes; @@ -197,6 +202,12 @@ bool FancyZonesData::AddDevice(const std::wstring& deviceId) std::scoped_lock lock{ dataLock }; if (!deviceInfoMap.contains(deviceId)) { + wil::unique_cotaskmem_string virtualDesktopId; + if (SUCCEEDED(StringFromCLSID(deviceId.virtualDesktopId, &virtualDesktopId))) + { + Logger::info(L"Create new device on virtual desktop {}", virtualDesktopId.get()); + } + // Creates default entry in map when WorkArea is created GUID guid; auto result{ CoCreateGuid(&guid) }; @@ -218,7 +229,7 @@ bool FancyZonesData::AddDevice(const std::wstring& deviceId) return false; } -void FancyZonesData::CloneDeviceInfo(const std::wstring& source, const std::wstring& destination) +void FancyZonesData::CloneDeviceInfo(const FancyZonesDataTypes::DeviceIdData& source, const FancyZonesDataTypes::DeviceIdData& destination) { if (source == destination) { @@ -235,7 +246,7 @@ void FancyZonesData::CloneDeviceInfo(const std::wstring& source, const std::wstr deviceInfoMap[destination] = deviceInfoMap[source]; } -void FancyZonesData::UpdatePrimaryDesktopData(const std::wstring& desktopId) +void FancyZonesData::SyncVirtualDesktops(GUID currentVirtualDesktopId) { _TRACER_; // Explorer persists current virtual desktop identifier to registry on a per session basis, @@ -244,9 +255,6 @@ void FancyZonesData::UpdatePrimaryDesktopData(const std::wstring& desktopId) // that case (00000000-0000-0000-0000-000000000000). // This method will go through all our persisted data with default GUID and update it with // valid one. - auto replaceDesktopId = [&desktopId](const std::wstring& deviceId) { - return deviceId.substr(0, deviceId.rfind('_') + 1) + desktopId; - }; std::scoped_lock lock{ dataLock }; bool dirtyFlag = false; @@ -255,53 +263,89 @@ void FancyZonesData::UpdatePrimaryDesktopData(const std::wstring& desktopId) { for (auto& data : perDesktopData) { - if (ExtractVirtualDesktopId(data.deviceId) == NonLocalizable::DefaultGuid) + if (data.deviceId.virtualDesktopId == GUID_NULL) { - data.deviceId = replaceDesktopId(data.deviceId); + data.deviceId.virtualDesktopId = currentVirtualDesktopId; + dirtyFlag = true; + } + else + { + if (m_virtualDesktopCheckCallback && !m_virtualDesktopCheckCallback(data.deviceId.virtualDesktopId)) + { + data.deviceId.virtualDesktopId = GUID_NULL; + dirtyFlag = true; + } + } + } + } + + std::vector replaceWithCurrentId{}; + std::vector replaceWithNullId{}; + + for (const auto& [desktopId, data] : deviceInfoMap) + { + if (desktopId.virtualDesktopId == GUID_NULL) + { + replaceWithCurrentId.push_back(desktopId); + dirtyFlag = true; + } + else + { + if (m_virtualDesktopCheckCallback && !m_virtualDesktopCheckCallback(desktopId.virtualDesktopId)) + { + replaceWithNullId.push_back(desktopId); dirtyFlag = true; } } } - std::vector toReplace{}; - - for (const auto& [id, data] : deviceInfoMap) - { - if (ExtractVirtualDesktopId(id) == NonLocalizable::DefaultGuid) - { - toReplace.push_back(id); - dirtyFlag = true; - } - } - - for (const auto& id : toReplace) + for (const auto& id : replaceWithCurrentId) { auto mapEntry = deviceInfoMap.extract(id); - mapEntry.key() = replaceDesktopId(id); + mapEntry.key().virtualDesktopId = currentVirtualDesktopId; + deviceInfoMap.insert(std::move(mapEntry)); + } + + for (const auto& id : replaceWithNullId) + { + auto mapEntry = deviceInfoMap.extract(id); + mapEntry.key().virtualDesktopId = GUID_NULL; deviceInfoMap.insert(std::move(mapEntry)); } - // TODO: when updating the primary desktop GUID, the app zone history also needs to be updated if (dirtyFlag) { - SaveZoneSettings(); + wil::unique_cotaskmem_string virtualDesktopIdStr; + if (SUCCEEDED(StringFromCLSID(currentVirtualDesktopId, &virtualDesktopIdStr))) + { + Logger::info(L"Update Virtual Desktop id to {}", virtualDesktopIdStr.get()); + } + + SaveAppZoneHistoryAndZoneSettings(); } } -void FancyZonesData::RemoveDeletedDesktops(const std::vector& activeDesktops) +void FancyZonesData::RemoveDeletedDesktops(const std::vector& activeDesktops) { - std::unordered_set active(std::begin(activeDesktops), std::end(activeDesktops)); + std::unordered_set active(std::begin(activeDesktops), std::end(activeDesktops)); std::scoped_lock lock{ dataLock }; bool dirtyFlag = false; for (auto it = std::begin(deviceInfoMap); it != std::end(deviceInfoMap);) { - std::wstring desktopId = ExtractVirtualDesktopId(it->first); - if (desktopId != NonLocalizable::DefaultGuid) + GUID desktopId = it->first.virtualDesktopId; + + if (desktopId != GUID_NULL) { auto foundId = active.find(desktopId); if (foundId == std::end(active)) { + wil::unique_cotaskmem_string virtualDesktopIdStr; + if (SUCCEEDED(StringFromCLSID(desktopId, &virtualDesktopIdStr))) + { + Logger::info(L"Remove Virtual Desktop id {}", virtualDesktopIdStr.get()); + } + RemoveDesktopAppZoneHistory(desktopId); it = deviceInfoMap.erase(it); dirtyFlag = true; @@ -317,7 +361,7 @@ void FancyZonesData::RemoveDeletedDesktops(const std::vector& acti } } -bool FancyZonesData::IsAnotherWindowOfApplicationInstanceZoned(HWND window, const std::wstring_view& deviceId) const +bool FancyZonesData::IsAnotherWindowOfApplicationInstanceZoned(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId) const { std::scoped_lock lock{ dataLock }; auto processPath = get_process_path(window); @@ -329,7 +373,7 @@ bool FancyZonesData::IsAnotherWindowOfApplicationInstanceZoned(HWND window, cons auto& perDesktopData = history->second; for (auto& data : perDesktopData) { - if (data.deviceId == deviceId) + if (data.deviceId.isEqualWithNullVirtualDesktopId(deviceId)) { DWORD processId = 0; GetWindowThreadProcessId(window, &processId); @@ -352,7 +396,7 @@ bool FancyZonesData::IsAnotherWindowOfApplicationInstanceZoned(HWND window, cons return false; } -void FancyZonesData::UpdateProcessIdToHandleMap(HWND window, const std::wstring_view& deviceId) +void FancyZonesData::UpdateProcessIdToHandleMap(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId) { std::scoped_lock lock{ dataLock }; auto processPath = get_process_path(window); @@ -364,7 +408,7 @@ void FancyZonesData::UpdateProcessIdToHandleMap(HWND window, const std::wstring_ auto& perDesktopData = history->second; for (auto& data : perDesktopData) { - if (data.deviceId == deviceId) + if (data.deviceId.isEqualWithNullVirtualDesktopId(deviceId)) { DWORD processId = 0; GetWindowThreadProcessId(window, &processId); @@ -376,7 +420,7 @@ void FancyZonesData::UpdateProcessIdToHandleMap(HWND window, const std::wstring_ } } -ZoneIndexSet FancyZonesData::GetAppLastZoneIndexSet(HWND window, const std::wstring_view& deviceId, const std::wstring_view& zoneSetId) const +ZoneIndexSet FancyZonesData::GetAppLastZoneIndexSet(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring_view& zoneSetId) const { std::scoped_lock lock{ dataLock }; auto processPath = get_process_path(window); @@ -388,7 +432,7 @@ ZoneIndexSet FancyZonesData::GetAppLastZoneIndexSet(HWND window, const std::wstr const auto& perDesktopData = history->second; for (const auto& data : perDesktopData) { - if (data.zoneSetUuid == zoneSetId && data.deviceId == deviceId) + if (data.zoneSetUuid == zoneSetId && data.deviceId.isEqualWithNullVirtualDesktopId(deviceId)) { return data.zoneIndexSet; } @@ -399,7 +443,7 @@ ZoneIndexSet FancyZonesData::GetAppLastZoneIndexSet(HWND window, const std::wstr return {}; } -bool FancyZonesData::RemoveAppLastZone(HWND window, const std::wstring_view& deviceId, const std::wstring_view& zoneSetId) +bool FancyZonesData::RemoveAppLastZone(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring_view& zoneSetId) { _TRACER_; std::scoped_lock lock{ dataLock }; @@ -412,7 +456,7 @@ bool FancyZonesData::RemoveAppLastZone(HWND window, const std::wstring_view& dev auto& perDesktopData = history->second; for (auto data = std::begin(perDesktopData); data != std::end(perDesktopData);) { - if (data->deviceId == deviceId && data->zoneSetUuid == zoneSetId) + if (data->deviceId.isEqualWithNullVirtualDesktopId(deviceId) && data->zoneSetUuid == zoneSetId) { if (!IsAnotherWindowOfApplicationInstanceZoned(window, deviceId)) { @@ -452,7 +496,7 @@ bool FancyZonesData::RemoveAppLastZone(HWND window, const std::wstring_view& dev return false; } -bool FancyZonesData::SetAppLastZones(HWND window, const std::wstring& deviceId, const std::wstring& zoneSetId, const ZoneIndexSet& zoneIndexSet) +bool FancyZonesData::SetAppLastZones(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring& zoneSetId, const ZoneIndexSet& zoneIndexSet) { _TRACER_; std::scoped_lock lock{ dataLock }; @@ -477,7 +521,7 @@ bool FancyZonesData::SetAppLastZones(HWND window, const std::wstring& deviceId, auto& perDesktopData = history->second; for (auto& data : perDesktopData) { - if (data.deviceId == deviceId) + if (data.deviceId.isEqualWithNullVirtualDesktopId(deviceId)) { // application already has history on this work area, update it with new window position data.processIdToHandleMap[processId] = window; @@ -511,7 +555,7 @@ bool FancyZonesData::SetAppLastZones(HWND window, const std::wstring& deviceId, return true; } -void FancyZonesData::SetActiveZoneSet(const std::wstring& deviceId, const FancyZonesDataTypes::ZoneSetData& data) +void FancyZonesData::SetActiveZoneSet(const FancyZonesDataTypes::DeviceIdData& deviceId, const FancyZonesDataTypes::ZoneSetData& data) { std::scoped_lock lock{ dataLock }; @@ -576,14 +620,67 @@ void FancyZonesData::SaveZoneSettings() const { _TRACER_; std::scoped_lock lock{ dataLock }; - JSONHelpers::SaveZoneSettings(zonesSettingsFileName, deviceInfoMap, customZoneSetsMap, quickKeysMap); + + bool dirtyFlag = false; + JSONHelpers::TDeviceInfoMap updatedDeviceInfoMap; + if (m_virtualDesktopCheckCallback) + { + for (const auto& [id, data] : deviceInfoMap) + { + auto updatedId = id; + if (!m_virtualDesktopCheckCallback(id.virtualDesktopId)) + { + updatedId.virtualDesktopId = GUID_NULL; + dirtyFlag = true; + } + + updatedDeviceInfoMap.insert({ updatedId, data }); + } + } + + if (dirtyFlag) + { + JSONHelpers::SaveZoneSettings(zonesSettingsFileName, updatedDeviceInfoMap, customZoneSetsMap, quickKeysMap); + } + else + { + JSONHelpers::SaveZoneSettings(zonesSettingsFileName, deviceInfoMap, customZoneSetsMap, quickKeysMap); + } } void FancyZonesData::SaveAppZoneHistory() const { _TRACER_; std::scoped_lock lock{ dataLock }; - JSONHelpers::SaveAppZoneHistory(appZoneHistoryFileName, appZoneHistoryMap); + + bool dirtyFlag = false; + std::unordered_map> updatedHistory; + if (m_virtualDesktopCheckCallback) + { + for (const auto& [path, dataVector] : appZoneHistoryMap) + { + auto updatedVector = dataVector; + for (auto& data : updatedVector) + { + if (!m_virtualDesktopCheckCallback(data.deviceId.virtualDesktopId)) + { + data.deviceId.virtualDesktopId = GUID_NULL; + dirtyFlag = true; + } + } + + updatedHistory.insert(std::make_pair(path, updatedVector)); + } + } + + if (dirtyFlag) + { + JSONHelpers::SaveAppZoneHistory(appZoneHistoryFileName, updatedHistory); + } + else + { + JSONHelpers::SaveAppZoneHistory(appZoneHistoryFileName, appZoneHistoryMap); + } } void FancyZonesData::SaveFancyZonesEditorParameters(bool spanZonesAcrossMonitors, const std::wstring& virtualDesktopId, const HMONITOR& targetMonitor, const std::vector>& allMonitors) const @@ -650,14 +747,14 @@ void FancyZonesData::SaveFancyZonesEditorParameters(bool spanZonesAcrossMonitors json::to_file(editorParametersFileName, JSONHelpers::EditorArgs::ToJson(argsJson)); } -void FancyZonesData::RemoveDesktopAppZoneHistory(const std::wstring& desktopId) +void FancyZonesData::RemoveDesktopAppZoneHistory(GUID desktopId) { for (auto it = std::begin(appZoneHistoryMap); it != std::end(appZoneHistoryMap);) { auto& perDesktopData = it->second; for (auto desktopIt = std::begin(perDesktopData); desktopIt != std::end(perDesktopData);) { - if (ExtractVirtualDesktopId(desktopIt->deviceId) == desktopId) + if (desktopIt->deviceId.virtualDesktopId == desktopId) { desktopIt = perDesktopData.erase(desktopIt); } diff --git a/src/modules/fancyzones/FancyZonesLib/FancyZonesData.h b/src/modules/fancyzones/FancyZonesLib/FancyZonesData.h index 7497fb5083..49d3d28ee6 100644 --- a/src/modules/fancyzones/FancyZonesLib/FancyZonesData.h +++ b/src/modules/fancyzones/FancyZonesLib/FancyZonesData.h @@ -44,14 +44,13 @@ class FancyZonesData public: FancyZonesData(); - std::optional FindDeviceInfo(const std::wstring& zoneWindowId) const; + void SetVirtualDesktopCheckCallback(std::function callback); + std::optional FindDeviceInfo(const FancyZonesDataTypes::DeviceIdData& zoneWindowId) const; std::optional FindCustomZoneSet(const std::wstring& guid) const; const JSONHelpers::TDeviceInfoMap& GetDeviceInfoMap() const; - const JSONHelpers::TCustomZoneSetsMap& GetCustomZoneSetsMap() const; - const std::unordered_map>& GetAppZoneHistoryMap() const; inline const JSONHelpers::TLayoutQuickKeysMap& GetLayoutQuickKeys() const @@ -70,18 +69,18 @@ public: return settingsFileName; } - bool AddDevice(const std::wstring& deviceId); - void CloneDeviceInfo(const std::wstring& source, const std::wstring& destination); - void UpdatePrimaryDesktopData(const std::wstring& desktopId); - void RemoveDeletedDesktops(const std::vector& activeDesktops); + bool AddDevice(const FancyZonesDataTypes::DeviceIdData& deviceId); + void CloneDeviceInfo(const FancyZonesDataTypes::DeviceIdData& source, const FancyZonesDataTypes::DeviceIdData& destination); + void SyncVirtualDesktops(GUID desktopId); + void RemoveDeletedDesktops(const std::vector& activeDesktops); - bool IsAnotherWindowOfApplicationInstanceZoned(HWND window, const std::wstring_view& deviceId) const; - void UpdateProcessIdToHandleMap(HWND window, const std::wstring_view& deviceId); - ZoneIndexSet GetAppLastZoneIndexSet(HWND window, const std::wstring_view& deviceId, const std::wstring_view& zoneSetId) const; - bool RemoveAppLastZone(HWND window, const std::wstring_view& deviceId, const std::wstring_view& zoneSetId); - bool SetAppLastZones(HWND window, const std::wstring& deviceId, const std::wstring& zoneSetId, const ZoneIndexSet& zoneIndexSet); + bool IsAnotherWindowOfApplicationInstanceZoned(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId) const; + void UpdateProcessIdToHandleMap(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId); + ZoneIndexSet GetAppLastZoneIndexSet(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring_view& zoneSetId) const; + bool RemoveAppLastZone(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring_view& zoneSetId); + bool SetAppLastZones(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring& zoneSetId, const ZoneIndexSet& zoneIndexSet); - void SetActiveZoneSet(const std::wstring& deviceId, const FancyZonesDataTypes::ZoneSetData& zoneSet); + void SetActiveZoneSet(const FancyZonesDataTypes::DeviceIdData& deviceId, const FancyZonesDataTypes::ZoneSetData& zoneSet); json::JsonObject GetPersistFancyZonesJSON(); @@ -100,7 +99,7 @@ private: friend class FancyZonesUnitTests::WorkAreaCreationUnitTests; friend class FancyZonesUnitTests::ZoneSetCalculateZonesUnitTests; - inline void SetDeviceInfo(const std::wstring& deviceId, FancyZonesDataTypes::DeviceInfoData data) + inline void SetDeviceInfo(const FancyZonesDataTypes::DeviceIdData& deviceId, FancyZonesDataTypes::DeviceInfoData data) { deviceInfoMap[deviceId] = data; } @@ -130,7 +129,7 @@ private: appZoneHistoryFileName = result + L"\\" + std::wstring(L"app-zone-history.json"); } #endif - void RemoveDesktopAppZoneHistory(const std::wstring& desktopId); + void RemoveDesktopAppZoneHistory(GUID desktopId); // Maps app path to app's zone history data std::unordered_map> appZoneHistoryMap{}; @@ -146,6 +145,8 @@ private: std::wstring appZoneHistoryFileName; std::wstring editorParametersFileName; + std::function m_virtualDesktopCheckCallback; + mutable std::recursive_mutex dataLock; }; diff --git a/src/modules/fancyzones/FancyZonesLib/FancyZonesDataTypes.cpp b/src/modules/fancyzones/FancyZonesLib/FancyZonesDataTypes.cpp index 7c017d3319..de784ed296 100644 --- a/src/modules/fancyzones/FancyZonesLib/FancyZonesDataTypes.cpp +++ b/src/modules/fancyzones/FancyZonesLib/FancyZonesDataTypes.cpp @@ -126,4 +126,186 @@ 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 ZoneWindowUtils::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::stoi(std::wstring(&c)); + } + + for (const auto& c : parts[1]) + { + 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 ZoneWindowUtils::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::stoi(std::wstring(&c)); + } + for (const auto& c : parts[2]) + { + 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; + if (!SUCCEEDED(StringFromCLSID(virtualDesktopId, &virtualDesktopIdStr))) + { + 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; + } + + return result; + } + + bool DeviceIdData::isEqualWithNullVirtualDesktopId(const DeviceIdData& other) const + { + return deviceName.compare(other.deviceName) == 0 && width == other.width && height == other.height && (virtualDesktopId == other.virtualDesktopId || virtualDesktopId == GUID_NULL || other.virtualDesktopId == GUID_NULL) && monitorId.compare(other.monitorId) == 0; + } } diff --git a/src/modules/fancyzones/FancyZonesLib/FancyZonesDataTypes.h b/src/modules/fancyzones/FancyZonesLib/FancyZonesDataTypes.h index 6d3c2990d5..7d3de1b6e4 100644 --- a/src/modules/fancyzones/FancyZonesLib/FancyZonesDataTypes.h +++ b/src/modules/fancyzones/FancyZonesLib/FancyZonesDataTypes.h @@ -113,24 +113,30 @@ namespace FancyZonesDataTypes ZoneSetLayoutType type; }; + 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; + bool isEqualWithNullVirtualDesktopId(const DeviceIdData& other) const; + }; + struct AppZoneHistoryData { std::unordered_map processIdToHandleMap; // Maps process id(DWORD) of application to zoned window handle(HWND) std::wstring zoneSetUuid; - std::wstring deviceId; + DeviceIdData deviceId; ZoneIndexSet zoneIndexSet; }; - struct DeviceIdData - { - std::wstring deviceName; - int width; - int height; - GUID virtualDesktopId; - std::wstring monitorId; - }; - struct DeviceInfoData { ZoneSetData activeZoneSet; @@ -139,4 +145,31 @@ namespace FancyZonesDataTypes int zoneCount; int sensitivityRadius; }; + + 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.monitorId.compare(rhs.monitorId) == 0; + } + + inline bool operator!=(const DeviceIdData& lhs, const DeviceIdData& rhs) + { + return !(lhs == rhs); + } + + 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; + } +} + +namespace std +{ + template<> + struct hash + { + size_t operator()(const FancyZonesDataTypes::DeviceIdData& Value) const + { + return 0; + } + }; } diff --git a/src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj b/src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj index a3c999e781..0387a20044 100644 --- a/src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj +++ b/src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj @@ -43,6 +43,7 @@ + diff --git a/src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj.filters b/src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj.filters index b50f8148d4..2a1b8750e5 100644 --- a/src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj.filters +++ b/src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj.filters @@ -90,6 +90,9 @@ Header Files + + Header Files + diff --git a/src/modules/fancyzones/FancyZonesLib/GuidUtils.h b/src/modules/fancyzones/FancyZonesLib/GuidUtils.h new file mode 100644 index 0000000000..213ffdcbb3 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesLib/GuidUtils.h @@ -0,0 +1,40 @@ +#pragma once + +#include "gdiplus.h" + +namespace std +{ + template<> + struct hash + { + size_t operator()(const GUID& Value) const + { + RPC_STATUS status = RPC_S_OK; + return ::UuidHash(&const_cast(Value), &status); + } + }; +} + +inline bool operator<(const GUID& guid1, const GUID& guid2) +{ + if (guid1.Data1 != guid2.Data1) + { + return guid1.Data1 < guid2.Data1; + } + if (guid1.Data2 != guid2.Data2) + { + return guid1.Data2 < guid2.Data2; + } + if (guid1.Data3 != guid2.Data3) + { + return guid1.Data3 < guid2.Data3; + } + for (int i = 0; i < 8; i++) + { + if (guid1.Data4[i] != guid2.Data4[i]) + { + return guid1.Data4[i] < guid2.Data4[i]; + } + } + return false; +} diff --git a/src/modules/fancyzones/FancyZonesLib/JsonHelpers.cpp b/src/modules/fancyzones/FancyZonesLib/JsonHelpers.cpp index d51e0da5a1..f39d398ba6 100644 --- a/src/modules/fancyzones/FancyZonesLib/JsonHelpers.cpp +++ b/src/modules/fancyzones/FancyZonesLib/JsonHelpers.cpp @@ -109,10 +109,17 @@ namespace data.zoneIndexSet = { static_cast(json.GetNamedNumber(NonLocalizable::ZoneIndexStr)) }; } - data.deviceId = json.GetNamedString(NonLocalizable::DeviceIdStr); + std::wstring deviceIdStr = json.GetNamedString(NonLocalizable::DeviceIdStr).c_str(); + auto deviceId = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(deviceIdStr); + if (!deviceId.has_value()) + { + return std::nullopt; + } + + data.deviceId = *deviceId; data.zoneSetUuid = json.GetNamedString(NonLocalizable::ZoneSetUuidStr); - if (!FancyZonesUtils::IsValidGuid(data.zoneSetUuid) || !FancyZonesUtils::IsValidDeviceId(data.deviceId)) + if (!FancyZonesUtils::IsValidGuid(data.zoneSetUuid)) { return std::nullopt; } @@ -377,7 +384,7 @@ namespace JSONHelpers } desktopData.SetNamedValue(NonLocalizable::ZoneIndexSetStr, jsonIndexSet); - desktopData.SetNamedValue(NonLocalizable::DeviceIdStr, json::value(data.deviceId)); + desktopData.SetNamedValue(NonLocalizable::DeviceIdStr, json::value(data.deviceId.toString())); desktopData.SetNamedValue(NonLocalizable::ZoneSetUuidStr, json::value(data.zoneSetUuid)); appHistoryArray.Append(desktopData); @@ -432,7 +439,7 @@ namespace JSONHelpers { json::JsonObject result{}; - result.SetNamedValue(NonLocalizable::DeviceIdStr, json::value(device.deviceId)); + 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)); @@ -448,12 +455,15 @@ namespace JSONHelpers { DeviceInfoJSON result; - result.deviceId = device.GetNamedString(NonLocalizable::DeviceIdStr); - if (!FancyZonesUtils::IsValidDeviceId(result.deviceId)) + std::wstring deviceIdStr = device.GetNamedString(NonLocalizable::DeviceIdStr).c_str(); + auto deviceId = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(deviceIdStr); + if (!deviceId.has_value()) { return std::nullopt; } + result.deviceId = *deviceId; + if (auto zoneSet = JSONHelpers::ZoneSetDataJSON::FromJson(device.GetNamedObject(NonLocalizable::ActiveZoneSetStr)); zoneSet.has_value()) { result.data.activeZoneSet = std::move(zoneSet.value()); diff --git a/src/modules/fancyzones/FancyZonesLib/JsonHelpers.h b/src/modules/fancyzones/FancyZonesLib/JsonHelpers.h index 6432590ad2..77937aa45e 100644 --- a/src/modules/fancyzones/FancyZonesLib/JsonHelpers.h +++ b/src/modules/fancyzones/FancyZonesLib/JsonHelpers.h @@ -48,7 +48,7 @@ namespace JSONHelpers struct DeviceInfoJSON { - std::wstring deviceId; + FancyZonesDataTypes::DeviceIdData deviceId; FancyZonesDataTypes::DeviceInfoData data; static json::JsonObject ToJson(const DeviceInfoJSON& device); @@ -65,7 +65,7 @@ namespace JSONHelpers }; 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; diff --git a/src/modules/fancyzones/FancyZonesLib/MonitorWorkAreaHandler.cpp b/src/modules/fancyzones/FancyZonesLib/MonitorWorkAreaHandler.cpp index d386b15eec..900d2664ea 100644 --- a/src/modules/fancyzones/FancyZonesLib/MonitorWorkAreaHandler.cpp +++ b/src/modules/fancyzones/FancyZonesLib/MonitorWorkAreaHandler.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "MonitorWorkAreaHandler.h" #include "VirtualDesktop.h" +#include "util.h" winrt::com_ptr MonitorWorkAreaHandler::GetWorkArea(const GUID& desktopId, HMONITOR monitor) { diff --git a/src/modules/fancyzones/FancyZonesLib/MonitorWorkAreaHandler.h b/src/modules/fancyzones/FancyZonesLib/MonitorWorkAreaHandler.h index dccb226a43..a0e586c1b7 100644 --- a/src/modules/fancyzones/FancyZonesLib/MonitorWorkAreaHandler.h +++ b/src/modules/fancyzones/FancyZonesLib/MonitorWorkAreaHandler.h @@ -1,22 +1,11 @@ #pragma once +#include "GuidUtils.h" + interface IWorkArea; struct ZoneColors; enum struct OverlappingZonesAlgorithm; -namespace std -{ - template<> - struct hash - { - size_t operator()(const GUID& Value) const - { - RPC_STATUS status = RPC_S_OK; - return ::UuidHash(&const_cast(Value), &status); - } - }; -} - class MonitorWorkAreaHandler { public: diff --git a/src/modules/fancyzones/FancyZonesLib/VirtualDesktop.cpp b/src/modules/fancyzones/FancyZonesLib/VirtualDesktop.cpp index cbce8c78e8..462feee63f 100644 --- a/src/modules/fancyzones/FancyZonesLib/VirtualDesktop.cpp +++ b/src/modules/fancyzones/FancyZonesLib/VirtualDesktop.cpp @@ -1,6 +1,8 @@ #include "pch.h" #include "VirtualDesktop.h" +#include + // Non-Localizable strings namespace NonLocalizable { @@ -17,6 +19,7 @@ IServiceProvider* GetServiceProvider() IServiceProvider* provider{ nullptr }; if (FAILED(CoCreateInstance(CLSID_ImmersiveShell, nullptr, CLSCTX_LOCAL_SERVER, __uuidof(provider), (PVOID*)&provider))) { + Logger::error("Failed to get ServiceProvider for VirtualDesktopManager"); return nullptr; } return provider; @@ -28,6 +31,7 @@ IVirtualDesktopManager* GetVirtualDesktopManager() IServiceProvider* serviceProvider = GetServiceProvider(); if (serviceProvider == nullptr || FAILED(serviceProvider->QueryService(__uuidof(manager), &manager))) { + Logger::error("Failed to get VirtualDesktopManager"); return nullptr; } return manager; @@ -77,14 +81,6 @@ std::optional GetDesktopIdFromCurrentSession() return std::nullopt; } -bool GetZoneWindowDesktopId(IWorkArea* zoneWindow, GUID* desktopId) -{ - // Format: __ - std::wstring uniqueId = zoneWindow->UniqueId(); - std::wstring virtualDesktopId = uniqueId.substr(uniqueId.rfind('_') + 1); - return SUCCEEDED(CLSIDFromString(virtualDesktopId.c_str(), desktopId)); -} - HKEY OpenVirtualDesktopsRegKey() { HKEY hKey{ nullptr }; @@ -124,18 +120,7 @@ void VirtualDesktop::UnInit() } } -std::optional VirtualDesktop::GetWindowDesktopId(HWND topLevelWindow) const -{ - GUID desktopId{}; - if (m_vdManager && SUCCEEDED(m_vdManager->GetWindowDesktopId(topLevelWindow, &desktopId))) - { - return desktopId; - } - - return std::nullopt; -} - -std::optional VirtualDesktop::GetCurrentVirtualDesktopId() const +std::optional VirtualDesktop::GetCurrentVirtualDesktopIdFromRegistry() const { // On newer Windows builds, the current virtual desktop is persisted to // a totally different reg key. Look there first. @@ -160,19 +145,17 @@ std::optional VirtualDesktop::GetCurrentVirtualDesktopId() const // switch occurred in current session. else { - auto ids = GetVirtualDesktopIds(); + auto ids = GetVirtualDesktopIdsFromRegistry(); if (ids.has_value() && ids->size() > 0) { return ids->at(0); } } - desktopId = GetDesktopIdByTopLevelWindows(); - - return desktopId; + return std::nullopt; } -std::optional> VirtualDesktop::GetVirtualDesktopIds(HKEY hKey) const +std::optional> VirtualDesktop::GetVirtualDesktopIdsFromRegistry(HKEY hKey) const { if (!hKey) { @@ -205,9 +188,9 @@ std::optional> VirtualDesktop::GetVirtualDesktopIds(HKEY hKey) return temp; } -std::optional> VirtualDesktop::GetVirtualDesktopIds() const +std::optional> VirtualDesktop::GetVirtualDesktopIdsFromRegistry() const { - return GetVirtualDesktopIds(GetVirtualDesktopsRegKey()); + return GetVirtualDesktopIdsFromRegistry(GetVirtualDesktopsRegKey()); } bool VirtualDesktop::IsWindowOnCurrentDesktop(HWND window) const @@ -232,25 +215,50 @@ std::optional VirtualDesktop::GetDesktopId(HWND window) const return std::nullopt; } -std::optional VirtualDesktop::GetDesktopIdByTopLevelWindows() const +std::vector> VirtualDesktop::GetWindowsRelatedToDesktops() const { using result_t = std::vector; - result_t result; + result_t windows; auto callback = [](HWND window, LPARAM data) -> BOOL { result_t& result = *reinterpret_cast(data); result.push_back(window); return TRUE; }; - EnumWindows(callback, reinterpret_cast(&result)); + EnumWindows(callback, reinterpret_cast(&windows)); - for (const auto window : result) + std::vector> result; + for (auto window : windows) + { + auto desktop = GetDesktopId(window); + if (desktop.has_value()) + { + result.push_back({ window, *desktop }); + } + } + + return result; +} + +std::optional VirtualDesktop::GetDesktopIdByTopLevelWindows() const +{ + using result_t = std::vector; + result_t windows; + + auto callback = [](HWND window, LPARAM data) -> BOOL { + result_t& result = *reinterpret_cast(data); + result.push_back(window); + return TRUE; + }; + EnumWindows(callback, reinterpret_cast(&windows)); + + for (const auto window : windows) { std::optional id = GetDesktopId(window); if (id.has_value()) { // Otherwise keep checking other windows - return id; + return *id; } } diff --git a/src/modules/fancyzones/FancyZonesLib/VirtualDesktop.h b/src/modules/fancyzones/FancyZonesLib/VirtualDesktop.h index d634cc95a2..5abb354020 100644 --- a/src/modules/fancyzones/FancyZonesLib/VirtualDesktop.h +++ b/src/modules/fancyzones/FancyZonesLib/VirtualDesktop.h @@ -9,15 +9,36 @@ public: VirtualDesktop(const std::function& vdInitCallback, const std::function& vdUpdatedCallback); ~VirtualDesktop() = default; + inline bool IsVirtualDesktopIdSavedInRegistry(GUID id) const + { + auto ids = GetVirtualDesktopIdsFromRegistry(); + if (!ids.has_value()) + { + return false; + } + + for (const auto& regId : *ids) + { + if (regId == id) + { + return true; + } + } + + return false; + } + void Init(); void UnInit(); - std::optional GetWindowDesktopId(HWND topLevelWindow) const; - std::optional GetCurrentVirtualDesktopId() const; - std::optional> GetVirtualDesktopIds() const; + std::optional GetCurrentVirtualDesktopIdFromRegistry() const; + std::optional> GetVirtualDesktopIdsFromRegistry() const; bool IsWindowOnCurrentDesktop(HWND window) const; std::optional GetDesktopId(HWND window) const; + std::optional GetDesktopIdByTopLevelWindows() const; + + std::vector> GetWindowsRelatedToDesktops() const; private: std::function m_vdInitCallback; @@ -28,7 +49,6 @@ private: OnThreadExecutor m_virtualDesktopTrackerThread; wil::unique_handle m_terminateVirtualDesktopTrackerEvent; - std::optional> GetVirtualDesktopIds(HKEY hKey) const; - std::optional GetDesktopIdByTopLevelWindows() const; + std::optional> GetVirtualDesktopIdsFromRegistry(HKEY hKey) const; void HandleVirtualDesktopUpdates(); }; diff --git a/src/modules/fancyzones/FancyZonesLib/WorkArea.cpp b/src/modules/fancyzones/FancyZonesLib/WorkArea.cpp index e53e5380eb..4098192933 100644 --- a/src/modules/fancyzones/FancyZonesLib/WorkArea.cpp +++ b/src/modules/fancyzones/FancyZonesLib/WorkArea.cpp @@ -109,7 +109,7 @@ public: WorkArea(HINSTANCE hinstance); ~WorkArea(); - bool Init(HINSTANCE hinstance, HMONITOR monitor, const std::wstring& uniqueId, const std::wstring& parentUniqueId, const ZoneColors& zoneColors, OverlappingZonesAlgorithm overlappingAlgorithm); + bool Init(HINSTANCE hinstance, HMONITOR monitor, const FancyZonesDataTypes::DeviceIdData& uniqueId, const FancyZonesDataTypes::DeviceIdData& parentUniqueId, const ZoneColors& zoneColors, OverlappingZonesAlgorithm overlappingAlgorithm); IFACEMETHODIMP MoveSizeEnter(HWND window) noexcept; IFACEMETHODIMP MoveSizeUpdate(POINT const& ptScreen, bool dragEnabled, bool selectManyZones) noexcept; @@ -124,7 +124,7 @@ public: MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle) noexcept; IFACEMETHODIMP_(bool) ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode) noexcept; - IFACEMETHODIMP_(std::wstring) + IFACEMETHODIMP_(FancyZonesDataTypes::DeviceIdData) UniqueId() const noexcept { return { m_uniqueId }; } IFACEMETHODIMP_(void) SaveWindowProcessToZoneIndex(HWND window) noexcept; @@ -151,7 +151,7 @@ protected: static LRESULT CALLBACK s_WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) noexcept; private: - void InitializeZoneSets(const std::wstring& parentUniqueId) noexcept; + void InitializeZoneSets(const FancyZonesDataTypes::DeviceIdData& parentUniqueId) noexcept; void CalculateZoneSet(OverlappingZonesAlgorithm overlappingAlgorithm) noexcept; void UpdateActiveZoneSet(_In_opt_ IZoneSet* zoneSet) noexcept; LRESULT WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept; @@ -159,7 +159,7 @@ private: void SetAsTopmostWindow() noexcept; HMONITOR m_monitor{}; - std::wstring m_uniqueId; // Parsed deviceId + resolution + virtualDesktopId + FancyZonesDataTypes::DeviceIdData m_uniqueId; HWND m_window{}; // Hidden tool window used to represent current monitor desktop work area. HWND m_windowMoveSize{}; winrt::com_ptr m_activeZoneSet; @@ -189,7 +189,7 @@ WorkArea::~WorkArea() windowPool.FreeZoneWindow(m_window); } -bool WorkArea::Init(HINSTANCE hinstance, HMONITOR monitor, const std::wstring& uniqueId, const std::wstring& parentUniqueId, const ZoneColors& zoneColors, OverlappingZonesAlgorithm overlappingAlgorithm) +bool WorkArea::Init(HINSTANCE hinstance, HMONITOR monitor, const FancyZonesDataTypes::DeviceIdData& uniqueId, const FancyZonesDataTypes::DeviceIdData& parentUniqueId, const ZoneColors& zoneColors, OverlappingZonesAlgorithm overlappingAlgorithm) { m_zoneColors = zoneColors; m_overlappingAlgorithm = overlappingAlgorithm; @@ -467,11 +467,17 @@ WorkArea::SetOverlappingZonesAlgorithm(OverlappingZonesAlgorithm overlappingAlgo #pragma region private -void WorkArea::InitializeZoneSets(const std::wstring& parentUniqueId) noexcept +void WorkArea::InitializeZoneSets(const FancyZonesDataTypes::DeviceIdData& parentUniqueId) noexcept { + wil::unique_cotaskmem_string virtualDesktopId; + if (SUCCEEDED(StringFromCLSID(m_uniqueId.virtualDesktopId, &virtualDesktopId))) + { + Logger::debug(L"Initialize zone sets on the virtual desktop {}", virtualDesktopId.get()); + } + bool deviceAdded = FancyZonesDataInstance().AddDevice(m_uniqueId); // If the device has been added, check if it should inherit the parent's layout - if (deviceAdded && !parentUniqueId.empty()) + if (deviceAdded && parentUniqueId.virtualDesktopId != GUID_NULL) { FancyZonesDataInstance().CloneDeviceInfo(parentUniqueId, m_uniqueId); } @@ -618,7 +624,7 @@ LRESULT CALLBACK WorkArea::s_WndProc(HWND window, UINT message, WPARAM wparam, L DefWindowProc(window, message, wparam, lparam); } -winrt::com_ptr MakeWorkArea(HINSTANCE hinstance, HMONITOR monitor, const std::wstring& uniqueId, const std::wstring& parentUniqueId, const ZoneColors& zoneColors, OverlappingZonesAlgorithm overlappingAlgorithm) noexcept +winrt::com_ptr MakeWorkArea(HINSTANCE hinstance, HMONITOR monitor, const FancyZonesDataTypes::DeviceIdData& uniqueId, const FancyZonesDataTypes::DeviceIdData& parentUniqueId, const ZoneColors& zoneColors, OverlappingZonesAlgorithm overlappingAlgorithm) noexcept { auto self = winrt::make_self(hinstance); if (self->Init(hinstance, monitor, uniqueId, parentUniqueId, zoneColors, overlappingAlgorithm)) diff --git a/src/modules/fancyzones/FancyZonesLib/WorkArea.h b/src/modules/fancyzones/FancyZonesLib/WorkArea.h index 078056255f..85b42744b2 100644 --- a/src/modules/fancyzones/FancyZonesLib/WorkArea.h +++ b/src/modules/fancyzones/FancyZonesLib/WorkArea.h @@ -2,6 +2,7 @@ #include "FancyZones.h" #include "FancyZonesLib/ZoneSet.h" #include "FancyZonesLib/ZoneColors.h" +#include "FancyZonesLib/FancyZonesDataTypes.h" /** * Class representing single work area, which is defined by monitor and virtual desktop. @@ -97,7 +98,7 @@ interface __declspec(uuid("{7F017528-8110-4FB3-BE41-F472969C2560}")) IWorkArea : /** * @returns Unique work area identifier. Format: __ */ - IFACEMETHOD_(std::wstring, UniqueId)() const = 0; + IFACEMETHOD_(FancyZonesDataTypes::DeviceIdData, UniqueId)() const = 0; /** * @returns Active zone layout for this work area. */ @@ -130,4 +131,4 @@ interface __declspec(uuid("{7F017528-8110-4FB3-BE41-F472969C2560}")) IWorkArea : IFACEMETHOD_(void, SetOverlappingZonesAlgorithm)(OverlappingZonesAlgorithm overlappingAlgorithm) = 0; }; -winrt::com_ptr MakeWorkArea(HINSTANCE hinstance, HMONITOR monitor, const std::wstring& uniqueId, const std::wstring& parentUniqueId, const ZoneColors& zoneColors, OverlappingZonesAlgorithm overlappingAlgorithm) noexcept; +winrt::com_ptr MakeWorkArea(HINSTANCE hinstance, HMONITOR monitor, const FancyZonesDataTypes::DeviceIdData& uniqueId, const FancyZonesDataTypes::DeviceIdData& parentUniqueId, const ZoneColors& zoneColors, OverlappingZonesAlgorithm overlappingAlgorithm) noexcept; diff --git a/src/modules/fancyzones/FancyZonesLib/util.cpp b/src/modules/fancyzones/FancyZonesLib/util.cpp index 6773923dbe..d8b0c05861 100644 --- a/src/modules/fancyzones/FancyZonesLib/util.cpp +++ b/src/modules/fancyzones/FancyZonesLib/util.cpp @@ -84,94 +84,6 @@ namespace FancyZonesUtils } } - std::optional 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 ZoneWindowUtils::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::stoi(std::wstring(&c)); - } - - for (const auto& c : parts[1]) - { - 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; - } - typedef BOOL(WINAPI* GetDpiForMonitorInternalFunc)(HMONITOR, UINT, UINT*, UINT*); std::wstring GetDisplayDeviceId(const std::wstring& device, std::unordered_map& displayDeviceIdxMap) @@ -617,78 +529,6 @@ namespace FancyZonesUtils return std::nullopt; } - bool 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 ZoneWindowUtils::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::stoi(std::wstring(&c)); - } - for (const auto& c : parts[2]) - { - std::stoi(std::wstring(&c)); - } - } - catch (const std::exception&) - { - return false; - } - - if (!IsValidGuid(parts[3]) || parts[0].empty()) - { - return false; - } - - return true; - } - std::wstring GenerateUniqueId(HMONITOR monitor, const std::wstring& deviceId, const std::wstring& virtualDesktopId) { MONITORINFOEXW mi; diff --git a/src/modules/fancyzones/FancyZonesLib/util.h b/src/modules/fancyzones/FancyZonesLib/util.h index b529dd8590..3413234ba9 100644 --- a/src/modules/fancyzones/FancyZonesLib/util.h +++ b/src/modules/fancyzones/FancyZonesLib/util.h @@ -207,10 +207,7 @@ namespace FancyZonesUtils std::wstring GenerateUniqueId(HMONITOR monitor, const std::wstring& devideId, const std::wstring& virtualDesktopId); std::wstring GenerateUniqueIdAllMonitorsArea(const std::wstring& virtualDesktopId); - std::wstring TrimDeviceId(const std::wstring& deviceId); - std::optional ParseDeviceId(const std::wstring& deviceId); - bool IsValidDeviceId(const std::wstring& str); RECT PrepareRectForCycling(RECT windowRect, RECT zoneWindowRect, DWORD vkCode) noexcept; size_t ChooseNextZoneByPosition(DWORD vkCode, RECT windowRect, const std::vector& zoneRects) noexcept; diff --git a/src/modules/fancyzones/FancyZonesTests/UnitTests/JsonHelpers.Tests.cpp b/src/modules/fancyzones/FancyZonesTests/UnitTests/JsonHelpers.Tests.cpp index 5f58070dce..153905e91e 100644 --- a/src/modules/fancyzones/FancyZonesTests/UnitTests/JsonHelpers.Tests.cpp +++ b/src/modules/fancyzones/FancyZonesTests/UnitTests/JsonHelpers.Tests.cpp @@ -88,61 +88,61 @@ namespace FancyZonesUnitTests TEST_METHOD (DeviceId) { const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; - Assert::IsTrue(IsValidDeviceId(deviceId)); + Assert::IsTrue(FancyZonesDataTypes::DeviceIdData::IsValidDeviceId(deviceId)); } TEST_METHOD (DeviceIdWithoutHashInName) { const auto deviceId = L"LOCALDISPLAY_5120_1440_{00000000-0000-0000-0000-000000000000}"; - Assert::IsTrue(IsValidDeviceId(deviceId)); + Assert::IsTrue(FancyZonesDataTypes::DeviceIdData::IsValidDeviceId(deviceId)); } TEST_METHOD (DeviceIdWithoutHashInNameButWithUnderscores) { const auto deviceId = L"LOCAL_DISPLAY_5120_1440_{00000000-0000-0000-0000-000000000000}"; - Assert::IsFalse(IsValidDeviceId(deviceId)); + Assert::IsFalse(FancyZonesDataTypes::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(IsValidDeviceId(deviceId)); + Assert::IsTrue(FancyZonesDataTypes::DeviceIdData::IsValidDeviceId(deviceId)); } TEST_METHOD (DeviceIdInvalidFormat) { const auto deviceId = L"_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; - Assert::IsFalse(IsValidDeviceId(deviceId)); + Assert::IsFalse(FancyZonesDataTypes::DeviceIdData::IsValidDeviceId(deviceId)); } TEST_METHOD (DeviceIdInvalidFormat2) { const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_19201200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; - Assert::IsFalse(IsValidDeviceId(deviceId)); + Assert::IsFalse(FancyZonesDataTypes::DeviceIdData::IsValidDeviceId(deviceId)); } TEST_METHOD (DeviceIdInvalidDecimals) { const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_aaaa_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; - Assert::IsFalse(IsValidDeviceId(deviceId)); + Assert::IsFalse(FancyZonesDataTypes::DeviceIdData::IsValidDeviceId(deviceId)); } TEST_METHOD (DeviceIdInvalidDecimals2) { const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_19a0_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; - Assert::IsFalse(IsValidDeviceId(deviceId)); + Assert::IsFalse(FancyZonesDataTypes::DeviceIdData::IsValidDeviceId(deviceId)); } TEST_METHOD (DeviceIdInvalidDecimals3) { const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_1900_120000000000000_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; - Assert::IsFalse(IsValidDeviceId(deviceId)); + Assert::IsFalse(FancyZonesDataTypes::DeviceIdData::IsValidDeviceId(deviceId)); } TEST_METHOD (DeviceIdInvalidGuid) { const auto deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-4B5D-8851-4791D66B1539}"; - Assert::IsFalse(IsValidDeviceId(deviceId)); + Assert::IsFalse(FancyZonesDataTypes::DeviceIdData::IsValidDeviceId(deviceId)); } }; TEST_CLASS (ZoneSetLayoutTypeUnitTest) @@ -779,7 +779,7 @@ namespace FancyZonesUnitTests .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\", \"zoneset-uuid\": \"zoneset-uuid\"}]}"); + 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); compareJsonObjects(expected, actual); @@ -788,7 +788,8 @@ namespace FancyZonesUnitTests TEST_METHOD (FromJson) { AppZoneHistoryData data{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}", .zoneIndexSet = { 54321 } + .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}]}"); @@ -799,7 +800,7 @@ namespace FancyZonesUnitTests 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::AreEqual(expected.data[0].deviceId.c_str(), actual->data[0].deviceId.c_str()); + Assert::IsTrue(expected.data[0].deviceId == actual->data[0].deviceId); Assert::AreEqual(expected.data[0].zoneSetUuid.c_str(), actual->data[0].zoneSetUuid.c_str()); } @@ -855,7 +856,7 @@ namespace FancyZonesUnitTests 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\", \"zoneset-uuid\": \"zoneset-uuid1\"}, {\"zone-index-set\": [12345], \"device-id\": \"device-id2\", \"zoneset-uuid\": \"zoneset-uuid2\"}]}"); + 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(); @@ -865,10 +866,11 @@ namespace FancyZonesUnitTests TEST_METHOD (FromJsonMultipleDesktopAppHistory) { AppZoneHistoryData data1{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}", .zoneIndexSet = { 54321 } + .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 = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{8a0b9205-6128-45a2-934a-b97f5b271235}", .zoneIndexSet = { 12345 } + .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 } @@ -884,7 +886,7 @@ namespace FancyZonesUnitTests for (size_t i = 0; i < expected.data.size(); ++i) { Assert::IsTrue(expected.data[i].zoneIndexSet == actual->data[i].zoneIndexSet); - Assert::AreEqual(expected.data[i].deviceId.c_str(), actual->data[i].deviceId.c_str()); + Assert::IsTrue(expected.data[i].deviceId == actual->data[i].deviceId); Assert::AreEqual(expected.data[i].zoneSetUuid.c_str(), actual->data[i].zoneSetUuid.c_str()); } } @@ -893,10 +895,16 @@ namespace FancyZonesUnitTests TEST_CLASS (DeviceInfoUnitTests) { private: - const std::wstring m_defaultDeviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; + 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 } }; 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) { @@ -916,7 +924,7 @@ namespace FancyZonesUnitTests auto actual = DeviceInfoJSON::FromJson(json); Assert::IsTrue(actual.has_value()); - Assert::AreEqual(expected.deviceId.c_str(), actual->deviceId.c_str(), L"device id"); + Assert::IsTrue(expected.deviceId == actual->deviceId); Assert::AreEqual(expected.data.zoneCount, actual->data.zoneCount, L"zone count"); Assert::AreEqual((int)expected.data.activeZoneSet.type, (int)actual->data.activeZoneSet.type, L"zone set type"); Assert::AreEqual(expected.data.activeZoneSet.uuid.c_str(), actual->data.activeZoneSet.uuid.c_str(), L"zone set uuid"); @@ -1016,11 +1024,13 @@ namespace FancyZonesUnitTests { private: const std::wstring_view m_moduleName = L"FancyZonesUnitTests"; - const std::wstring m_defaultDeviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; + 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 json::JsonValue m_defaultCustomDeviceValue = json::JsonValue::Parse(m_defaultCustomDeviceStr); const json::JsonObject m_defaultCustomDeviceObj = json::JsonObject::Parse(m_defaultCustomDeviceStr); + const FancyZonesDataTypes::DeviceIdData m_defaultDeviceId = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(m_defaultDeviceIdStr).value(); + GUID m_defaultVDId; HINSTANCE m_hInst{}; @@ -1177,7 +1187,7 @@ namespace FancyZonesUnitTests TEST_METHOD (AppZoneHistoryParseSingle) { const std::wstring expectedAppPath = L"appPath"; - const std::wstring expectedDeviceId = m_defaultDeviceId; + const auto expectedDeviceId = m_defaultDeviceId; const std::wstring expectedZoneSetId = L"{33A2B101-06E0-437B-A61E-CDBECF502906}"; const size_t expectedIndex = 54321; @@ -1200,7 +1210,7 @@ namespace FancyZonesUnitTests const auto entryData = entry->second; Assert::AreEqual(expected.data.size(), entryData.size()); Assert::AreEqual(expectedZoneSetId.c_str(), entryData[0].zoneSetUuid.c_str()); - Assert::AreEqual(expectedDeviceId.c_str(), entryData[0].deviceId.c_str()); + Assert::IsTrue(expectedDeviceId == entryData[0].deviceId); Assert::IsTrue(std::vector{ expectedIndex } == entryData[0].zoneIndexSet); } @@ -1209,16 +1219,20 @@ namespace FancyZonesUnitTests json::JsonObject json; json::JsonArray zoneHistoryArray; AppZoneHistoryData data1{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502900}", .deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1530}", .zoneIndexSet = { 1 } + .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 = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1531}", .zoneIndexSet = { 2 } + .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 = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1532}", .zoneIndexSet = { 3 } + .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 = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1533}", .zoneIndexSet = { 4 } + .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 } })); @@ -1238,7 +1252,7 @@ namespace FancyZonesUnitTests const auto& actual = appZoneHistoryMap.at(expected->appPath); Assert::AreEqual(expected->data.size(), actual.size()); - Assert::AreEqual(expected->data[0].deviceId.c_str(), actual[0].deviceId.c_str()); + 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); @@ -1253,19 +1267,23 @@ namespace FancyZonesUnitTests const auto appPath = L"app-path"; AppZoneHistoryData data1{ - .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502900}", .deviceId = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1530}", .zoneIndexSet = { 1 } + .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 = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1531}", .zoneIndexSet = { 2 } + .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 = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1532}", .zoneIndexSet = { 3 } + .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 = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1533}", .zoneIndexSet = { 4 } + .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())); @@ -1276,7 +1294,7 @@ namespace FancyZonesUnitTests const auto& actual = appZoneHistoryMap.at(appPath); Assert::AreEqual((size_t)1, actual.size()); - Assert::AreEqual(expected.deviceId.c_str(), actual[0].deviceId.c_str()); + 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); } @@ -1610,7 +1628,7 @@ namespace FancyZonesUnitTests { FancyZonesData data; data.SetSettingsModulePath(m_moduleName); - const std::wstring uniqueId = m_defaultDeviceId; + const auto uniqueId = m_defaultDeviceId; json::JsonArray devices; devices.Append(m_defaultCustomDeviceValue); @@ -1635,7 +1653,7 @@ namespace FancyZonesUnitTests FancyZonesData data; data.SetSettingsModulePath(m_moduleName); const std::wstring expected = L"{39B25DD2-130D-4B5D-8851-4791D66B1539}"; - const std::wstring uniqueId = m_defaultDeviceId; + const auto uniqueId = m_defaultDeviceId; json::JsonArray devices; devices.Append(m_defaultCustomDeviceValue); @@ -1661,7 +1679,8 @@ namespace FancyZonesUnitTests data.SetSettingsModulePath(m_moduleName); const std::wstring expected = L"{33A2B101-06E0-437B-A61E-CDBECF502906}"; - const std::wstring uniqueId = L"id-not-contained-by-device-info-map_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; + auto uniqueId = m_defaultDeviceId; + uniqueId.deviceName = L"id-not-contained-by-device-info-map"; json::JsonArray devices; devices.Append(m_defaultCustomDeviceValue); @@ -1706,7 +1725,8 @@ namespace FancyZonesUnitTests .zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = L"device-id", .zoneIndexSet = { 54321 } }; AppZoneHistoryJSON appZoneHistory{ L"app-path", std::vector{ data } }; - DeviceInfoJSON deviceInfo{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 } }; + + DeviceInfoJSON deviceInfo { FancyZonesDataTypes::DeviceIdData{ L"device-id", 0, 0, m_defaultVDId }, DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 } }; LayoutQuickKeyJSON quickKeys{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", 1 }; json::JsonArray zoneSetsArray, appZonesArray, deviceInfoArray, quickKeysArray; zoneSetsArray.Append(CustomZoneSetJSON::ToJson(zoneSets)); @@ -1836,7 +1856,7 @@ namespace FancyZonesUnitTests TEST_METHOD (AppLastZoneIndex) { - const std::wstring deviceId = L"device-id"; + const FancyZonesDataTypes::DeviceIdData deviceId{ L"device-id" }; const std::wstring zoneSetId = L"zoneset-uuid"; const auto window = Mocks::WindowCreate(m_hInst); FancyZonesData data; @@ -1852,7 +1872,7 @@ namespace FancyZonesUnitTests TEST_METHOD (AppLastZoneIndexZero) { const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceId = L"device-id"; + const FancyZonesDataTypes::DeviceIdData deviceId{ L"device-id" }; const auto window = Mocks::WindowCreate(m_hInst); FancyZonesData data; data.SetSettingsModulePath(m_moduleName); @@ -1865,7 +1885,7 @@ namespace FancyZonesUnitTests TEST_METHOD (AppLastZoneIndexNegative) { const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceId = L"device-id"; + const FancyZonesDataTypes::DeviceIdData deviceId{ L"device-id" }; const auto window = Mocks::WindowCreate(m_hInst); FancyZonesData data; data.SetSettingsModulePath(m_moduleName); @@ -1878,7 +1898,7 @@ namespace FancyZonesUnitTests TEST_METHOD (AppLastZoneIndexOverflow) { const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceId = L"device-id"; + const FancyZonesDataTypes::DeviceIdData deviceId{ L"device-id" }; const auto window = Mocks::WindowCreate(m_hInst); FancyZonesData data; data.SetSettingsModulePath(m_moduleName); @@ -1891,7 +1911,7 @@ namespace FancyZonesUnitTests TEST_METHOD (AppLastZoneIndexOverride) { const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceId = L"device-id"; + const FancyZonesDataTypes::DeviceIdData deviceId{ L"device-id" }; const auto window = Mocks::WindowCreate(m_hInst); FancyZonesData data; data.SetSettingsModulePath(m_moduleName); @@ -1906,7 +1926,7 @@ namespace FancyZonesUnitTests TEST_METHOD (AppLastZoneInvalidWindow) { const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceId = L"device-id"; + const FancyZonesDataTypes::DeviceIdData deviceId{ L"device-id" }; const auto window = Mocks::Window(); FancyZonesData data; data.SetSettingsModulePath(m_moduleName); @@ -1920,19 +1940,20 @@ namespace FancyZonesUnitTests TEST_METHOD (AppLastZoneNullWindow) { const std::wstring zoneSetId = L"zoneset-uuid"; + const FancyZonesDataTypes::DeviceIdData deviceId{ L"device-id" }; const auto window = nullptr; FancyZonesData data; data.SetSettingsModulePath(m_moduleName); const int expectedZoneIndex = 1; - Assert::IsFalse(data.SetAppLastZones(window, L"device-id", zoneSetId, { expectedZoneIndex })); + Assert::IsFalse(data.SetAppLastZones(window, deviceId, zoneSetId, { expectedZoneIndex })); } TEST_METHOD (AppLastdeviceIdTest) { const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceId1 = L"device-id-1"; - const std::wstring deviceId2 = L"device-id-2"; + const FancyZonesDataTypes::DeviceIdData deviceId1{ L"device-id-1" }; + const FancyZonesDataTypes::DeviceIdData deviceId2{ L"device-id-2" }; const auto window = Mocks::WindowCreate(m_hInst); FancyZonesData data; data.SetSettingsModulePath(m_moduleName); @@ -1947,7 +1968,7 @@ namespace FancyZonesUnitTests { const std::wstring zoneSetId1 = L"zoneset-uuid-1"; const std::wstring zoneSetId2 = L"zoneset-uuid-2"; - const std::wstring deviceId = L"device-id"; + const FancyZonesDataTypes::DeviceIdData deviceId{ L"device-id" }; const auto window = Mocks::WindowCreate(m_hInst); FancyZonesData data; data.SetSettingsModulePath(m_moduleName); @@ -1961,7 +1982,7 @@ namespace FancyZonesUnitTests TEST_METHOD (AppLastZoneRemoveWindow) { const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceId = L"device-id"; + const FancyZonesDataTypes::DeviceIdData deviceId{ L"device-id" }; const auto window = Mocks::WindowCreate(m_hInst); FancyZonesData data; data.SetSettingsModulePath(m_moduleName); @@ -1974,7 +1995,7 @@ namespace FancyZonesUnitTests TEST_METHOD (AppLastZoneRemoveUnknownWindow) { const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceId = L"device-id"; + const FancyZonesDataTypes::DeviceIdData deviceId{ L"device-id" }; const auto window = Mocks::WindowCreate(m_hInst); FancyZonesData data; data.SetSettingsModulePath(m_moduleName); @@ -1987,7 +2008,7 @@ namespace FancyZonesUnitTests { const std::wstring zoneSetIdToInsert = L"zoneset-uuid-to-insert"; const std::wstring zoneSetIdToRemove = L"zoneset-uuid-to-remove"; - const std::wstring deviceId = L"device-id"; + const FancyZonesDataTypes::DeviceIdData deviceId{ L"device-id" }; const auto window = Mocks::WindowCreate(m_hInst); FancyZonesData data; data.SetSettingsModulePath(m_moduleName); @@ -2000,8 +2021,8 @@ namespace FancyZonesUnitTests TEST_METHOD (AppLastZoneRemoveUnknownWindowId) { const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceIdToInsert = L"device-id-insert"; - const std::wstring deviceIdToRemove = L"device-id-remove"; + const FancyZonesDataTypes::DeviceIdData deviceIdToInsert{ L"device-id-insert" }; + const FancyZonesDataTypes::DeviceIdData deviceIdToRemove{ L"device-id-remove" }; const auto window = Mocks::WindowCreate(m_hInst); FancyZonesData data; data.SetSettingsModulePath(m_moduleName); @@ -2014,7 +2035,7 @@ namespace FancyZonesUnitTests TEST_METHOD (AppLastZoneRemoveNullWindow) { const std::wstring zoneSetId = L"zoneset-uuid"; - const std::wstring deviceId = L"device-id"; + const FancyZonesDataTypes::DeviceIdData deviceId{ L"device-id" }; const auto window = Mocks::WindowCreate(m_hInst); FancyZonesData data; data.SetSettingsModulePath(m_moduleName); diff --git a/src/modules/fancyzones/FancyZonesTests/UnitTests/Util.Spec.cpp b/src/modules/fancyzones/FancyZonesTests/UnitTests/Util.Spec.cpp index 6347c390b0..ba49aeaa0e 100644 --- a/src/modules/fancyzones/FancyZonesTests/UnitTests/Util.Spec.cpp +++ b/src/modules/fancyzones/FancyZonesTests/UnitTests/Util.Spec.cpp @@ -71,7 +71,7 @@ namespace FancyZonesUnitTests CLSIDFromString(expectedGuidStr, &guid); const FancyZonesDataTypes::DeviceIdData expected{ L"AOC0001#5&37ac4db&0&UID160002", 1536, 960, guid }; - const auto actual = ParseDeviceId(input); + const auto actual = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(input); Assert::IsTrue(actual.has_value()); Assert::AreEqual(expected.deviceName, actual->deviceName); @@ -93,7 +93,7 @@ namespace FancyZonesUnitTests CLSIDFromString(expectedGuidStr, &guid); const FancyZonesDataTypes::DeviceIdData expected{ L"AOC0001#5&37ac4db&0&UID160002", 1536, 960, guid, L"monitorId" }; - const auto actual = ParseDeviceId(input); + const auto actual = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(input); Assert::IsTrue(actual.has_value()); Assert::AreEqual(expected.deviceName, actual->deviceName); @@ -116,7 +116,7 @@ namespace FancyZonesUnitTests CLSIDFromString(expectedGuidStr, &guid); const FancyZonesDataTypes::DeviceIdData expected{ L"AOC00015&37ac4db&0&UID160002", 1536, 960, guid }; - const auto actual = ParseDeviceId(input); + const auto actual = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(input); Assert::IsTrue(actual.has_value()); Assert::AreEqual(expected.deviceName, actual->deviceName); @@ -133,7 +133,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 = ParseDeviceId(input); + const auto actual = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(input); Assert::IsFalse(actual.has_value()); } @@ -141,7 +141,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 = ParseDeviceId(input); + const auto actual = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(input); Assert::IsFalse(actual.has_value()); } @@ -149,7 +149,7 @@ namespace FancyZonesUnitTests { // no guid const std::wstring input = L"AOC00015&37ac4db&0&UID160002_1536960_"; - const auto actual = ParseDeviceId(input); + const auto actual = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(input); Assert::IsFalse(actual.has_value()); } @@ -157,7 +157,7 @@ namespace FancyZonesUnitTests { // invalid guid const std::wstring input = L"AOC00015&37ac4db&0&UID160002_1536960_{asdf}"; - const auto actual = ParseDeviceId(input); + const auto actual = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(input); Assert::IsFalse(actual.has_value()); } @@ -165,7 +165,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 = ParseDeviceId(input); + const auto actual = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(input); Assert::IsFalse(actual.has_value()); } @@ -173,7 +173,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 = ParseDeviceId(input); + const auto actual = FancyZonesDataTypes::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 d2cd2897b0..5b83733d09 100644 --- a/src/modules/fancyzones/FancyZonesTests/UnitTests/WorkArea.Spec.cpp +++ b/src/modules/fancyzones/FancyZonesTests/UnitTests/WorkArea.Spec.cpp @@ -23,8 +23,8 @@ namespace FancyZonesUnitTests TEST_CLASS (WorkAreaCreationUnitTests) { - std::wstringstream m_parentUniqueId; - std::wstringstream m_uniqueId; + FancyZonesDataTypes::DeviceIdData m_parentUniqueId; + FancyZonesDataTypes::DeviceIdData m_uniqueId; HINSTANCE m_hInst{}; HMONITOR m_monitor{}; @@ -40,7 +40,7 @@ namespace FancyZonesUnitTests const std::wstring expectedWorkArea = std::to_wstring(m_monitorInfo.rcMonitor.right) + L"_" + std::to_wstring(m_monitorInfo.rcMonitor.bottom); Assert::IsNotNull(workArea.get()); - Assert::AreEqual(m_uniqueId.str().c_str(), workArea->UniqueId().c_str()); + Assert::IsTrue(m_uniqueId == workArea->UniqueId()); } TEST_METHOD_INITIALIZE(Init) @@ -51,9 +51,16 @@ namespace FancyZonesUnitTests m_monitorInfo.cbSize = sizeof(m_monitorInfo); Assert::AreNotEqual(0, GetMonitorInfoW(m_monitor, &m_monitorInfo)); - m_parentUniqueId << L"DELA026#5&10a58c63&0&UID16777488_" << m_monitorInfo.rcMonitor.right << "_" << m_monitorInfo.rcMonitor.bottom << "_{61FA9FC0-26A6-4B37-A834-491C148DFC57}"; - m_uniqueId << L"DELA026#5&10a58c63&0&UID16777488_" << m_monitorInfo.rcMonitor.right << "_" << m_monitorInfo.rcMonitor.bottom << "_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; - + 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); + m_fancyZonesData.SetSettingsModulePath(L"FancyZonesUnitTests"); m_fancyZonesData.clear_data(); @@ -71,7 +78,7 @@ namespace FancyZonesUnitTests TEST_METHOD (CreateWorkArea) { - auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); testWorkArea(workArea); auto* activeZoneSet{ workArea->ActiveZoneSet() }; @@ -82,7 +89,7 @@ namespace FancyZonesUnitTests TEST_METHOD (CreateWorkAreaNoHinst) { - auto workArea = MakeWorkArea({}, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea({}, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); testWorkArea(workArea); auto* activeZoneSet{ workArea->ActiveZoneSet() }; @@ -93,7 +100,7 @@ namespace FancyZonesUnitTests TEST_METHOD (CreateWorkAreaNoHinstFlashZones) { - auto workArea = MakeWorkArea({}, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea({}, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); testWorkArea(workArea); auto* activeZoneSet{ workArea->ActiveZoneSet() }; @@ -104,21 +111,32 @@ namespace FancyZonesUnitTests TEST_METHOD (CreateWorkAreaNoMonitor) { - auto workArea = MakeWorkArea(m_hInst, {}, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, {}, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); testWorkArea(workArea); } TEST_METHOD (CreateWorkAreaNoDeviceId) { // Generate unique id without device id - std::wstring uniqueId = FancyZonesUtils::GenerateUniqueId(m_monitor, {}, m_virtualDesktopId); - auto workArea = MakeWorkArea(m_hInst, m_monitor, uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); + 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, {}, m_zoneColors, m_overlappingAlgorithm); const std::wstring expectedWorkArea = std::to_wstring(m_monitorInfo.rcMonitor.right) + L"_" + std::to_wstring(m_monitorInfo.rcMonitor.bottom); - const std::wstring expectedUniqueId = L"FallbackDevice_" + std::to_wstring(m_monitorInfo.rcMonitor.right) + L"_" + std::to_wstring(m_monitorInfo.rcMonitor.bottom) + L"_" + m_virtualDesktopId; + const FancyZonesDataTypes::DeviceIdData expectedUniqueId{ L"FallbackDevice", m_monitorInfo.rcMonitor.right - m_monitorInfo.rcMonitor.left, m_monitorInfo.rcMonitor.bottom - m_monitorInfo.rcMonitor.top, m_virtualDesktopGuid }; Assert::IsNotNull(workArea.get()); - Assert::AreEqual(expectedUniqueId.c_str(), workArea->UniqueId().c_str()); + Assert::IsTrue(expectedUniqueId == workArea->UniqueId()); auto* activeZoneSet{ workArea->ActiveZoneSet() }; Assert::IsNotNull(activeZoneSet); @@ -129,12 +147,22 @@ namespace FancyZonesUnitTests TEST_METHOD (CreateWorkAreaNoDesktopId) { // Generate unique id without virtual desktop id - std::wstring uniqueId = FancyZonesUtils::GenerateUniqueId(m_monitor, m_deviceId, {}); + 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, {}, m_zoneColors, m_overlappingAlgorithm); const std::wstring expectedWorkArea = std::to_wstring(m_monitorInfo.rcMonitor.right) + L"_" + std::to_wstring(m_monitorInfo.rcMonitor.bottom); Assert::IsNotNull(workArea.get()); - Assert::IsTrue(workArea->UniqueId().empty()); auto* activeZoneSet{ workArea->ActiveZoneSet() }; Assert::IsNotNull(activeZoneSet); @@ -152,17 +180,17 @@ namespace FancyZonesUnitTests const auto customSetGuid = Helpers::CreateGuidString(); const auto parentZoneSet = ZoneSetData{ customSetGuid, type }; const auto parentDeviceInfo = DeviceInfoData{ parentZoneSet, true, spacing, zoneCount }; - m_fancyZonesData.SetDeviceInfo(m_parentUniqueId.str(), parentDeviceInfo); + m_fancyZonesData.SetDeviceInfo(m_parentUniqueId, parentDeviceInfo); - auto parentWorkArea = MakeWorkArea(m_hInst, m_monitor, m_parentUniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto parentWorkArea = MakeWorkArea(m_hInst, m_monitor, m_parentUniqueId, {}, m_zoneColors, m_overlappingAlgorithm); // newWorkArea = false - workArea won't be cloned from parent - auto actualWorkArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto actualWorkArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); Assert::IsNotNull(actualWorkArea->ActiveZoneSet()); - Assert::IsTrue(m_fancyZonesData.GetDeviceInfoMap().contains(m_uniqueId.str())); - auto currentDeviceInfo = m_fancyZonesData.GetDeviceInfoMap().at(m_uniqueId.str()); + Assert::IsTrue(m_fancyZonesData.GetDeviceInfoMap().contains(m_uniqueId)); + auto currentDeviceInfo = m_fancyZonesData.GetDeviceInfoMap().at(m_uniqueId); // default values Assert::AreEqual(true, currentDeviceInfo.showSpacing); Assert::AreEqual(3, currentDeviceInfo.zoneCount); @@ -173,7 +201,7 @@ namespace FancyZonesUnitTests TEST_CLASS (WorkAreaUnitTests) { - std::wstringstream m_uniqueId; + FancyZonesDataTypes::DeviceIdData m_uniqueId; HINSTANCE m_hInst{}; HMONITOR m_monitor{}; @@ -191,8 +219,11 @@ namespace FancyZonesUnitTests m_monitorInfo.cbSize = sizeof(m_monitorInfo); Assert::AreNotEqual(0, GetMonitorInfoW(m_monitor, &m_monitorInfo)); - m_uniqueId << L"DELA026#5&10a58c63&0&UID16777488_" << m_monitorInfo.rcMonitor.right << "_" << m_monitorInfo.rcMonitor.bottom << "_{39B25DD2-130D-4B5D-8851-4791D66B1539}"; - + 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); + m_fancyZonesData.SetSettingsModulePath(L"FancyZonesUnitTests"); m_fancyZonesData.clear_data(); @@ -207,7 +238,7 @@ namespace FancyZonesUnitTests public: TEST_METHOD (MoveSizeEnter) { - auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); const auto expected = S_OK; const auto actual = workArea->MoveSizeEnter(Mocks::Window()); @@ -217,7 +248,7 @@ namespace FancyZonesUnitTests TEST_METHOD (MoveSizeEnterTwice) { - auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); const auto expected = S_OK; @@ -229,7 +260,7 @@ namespace FancyZonesUnitTests TEST_METHOD (MoveSizeUpdate) { - auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); const auto expected = S_OK; const auto actual = workArea->MoveSizeUpdate(POINT{ 0, 0 }, true, false); @@ -239,7 +270,7 @@ namespace FancyZonesUnitTests TEST_METHOD (MoveSizeUpdatePointNegativeCoordinates) { - auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); const auto expected = S_OK; const auto actual = workArea->MoveSizeUpdate(POINT{ -10, -10 }, true, false); @@ -249,7 +280,7 @@ namespace FancyZonesUnitTests TEST_METHOD (MoveSizeUpdatePointBigCoordinates) { - auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); const auto expected = S_OK; const auto actual = workArea->MoveSizeUpdate(POINT{ m_monitorInfo.rcMonitor.right + 1, m_monitorInfo.rcMonitor.bottom + 1 }, true, false); @@ -259,7 +290,7 @@ namespace FancyZonesUnitTests TEST_METHOD (MoveSizeEnd) { - auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); const auto window = Mocks::Window(); workArea->MoveSizeEnter(window); @@ -276,7 +307,7 @@ namespace FancyZonesUnitTests TEST_METHOD (MoveSizeEndWindowNotAdded) { - auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); const auto window = Mocks::Window(); workArea->MoveSizeEnter(window); @@ -292,7 +323,7 @@ namespace FancyZonesUnitTests TEST_METHOD (MoveSizeEndDifferentWindows) { - auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); const auto window = Mocks::Window(); workArea->MoveSizeEnter(window); @@ -305,7 +336,7 @@ namespace FancyZonesUnitTests TEST_METHOD (MoveSizeEndWindowNotSet) { - auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); const auto expected = E_INVALIDARG; const auto actual = workArea->MoveSizeEnd(Mocks::Window(), POINT{ 0, 0 }); @@ -315,7 +346,7 @@ namespace FancyZonesUnitTests TEST_METHOD (MoveSizeEndInvalidPoint) { - auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); const auto window = Mocks::Window(); workArea->MoveSizeEnter(window); @@ -332,7 +363,7 @@ namespace FancyZonesUnitTests TEST_METHOD (MoveWindowIntoZoneByIndex) { - auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); Assert::IsNotNull(workArea->ActiveZoneSet()); workArea->MoveWindowIntoZoneByIndex(Mocks::Window(), 0); @@ -342,7 +373,7 @@ namespace FancyZonesUnitTests TEST_METHOD (MoveWindowIntoZoneByDirectionAndIndex) { - auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); Assert::IsNotNull(workArea->ActiveZoneSet()); const auto window = Mocks::WindowCreate(m_hInst); @@ -357,7 +388,7 @@ namespace FancyZonesUnitTests TEST_METHOD (MoveWindowIntoZoneByDirectionManyTimes) { - auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); Assert::IsNotNull(workArea->ActiveZoneSet()); const auto window = Mocks::WindowCreate(m_hInst); @@ -374,7 +405,7 @@ namespace FancyZonesUnitTests TEST_METHOD (SaveWindowProcessToZoneIndexNullptrWindow) { - auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); Assert::IsNotNull(workArea->ActiveZoneSet()); workArea->SaveWindowProcessToZoneIndex(nullptr); @@ -385,7 +416,7 @@ namespace FancyZonesUnitTests TEST_METHOD (SaveWindowProcessToZoneIndexNoWindowAdded) { - auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); Assert::IsNotNull(workArea->ActiveZoneSet()); auto window = Mocks::WindowCreate(m_hInst); @@ -400,7 +431,7 @@ namespace FancyZonesUnitTests TEST_METHOD (SaveWindowProcessToZoneIndexNoWindowAddedWithFilledAppZoneHistory) { - auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); Assert::IsNotNull(workArea->ActiveZoneSet()); const auto window = Mocks::WindowCreate(m_hInst); @@ -428,7 +459,7 @@ namespace FancyZonesUnitTests TEST_METHOD (SaveWindowProcessToZoneIndexWindowAdded) { - auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); Assert::IsNotNull(workArea->ActiveZoneSet()); auto window = Mocks::WindowCreate(m_hInst); @@ -458,7 +489,7 @@ namespace FancyZonesUnitTests TEST_METHOD (WhenWindowIsNotResizablePlacingItIntoTheZoneShouldNotResizeIt) { - auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId.str(), {}, m_zoneColors, m_overlappingAlgorithm); + auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm); Assert::IsNotNull(workArea->ActiveZoneSet()); auto window = Mocks::WindowCreate(m_hInst); diff --git a/src/modules/fancyzones/FancyZonesTests/UnitTests/ZoneSet.Spec.cpp b/src/modules/fancyzones/FancyZonesTests/UnitTests/ZoneSet.Spec.cpp index e2e4adb279..82cdefab19 100644 --- a/src/modules/fancyzones/FancyZonesTests/UnitTests/ZoneSet.Spec.cpp +++ b/src/modules/fancyzones/FancyZonesTests/UnitTests/ZoneSet.Spec.cpp @@ -1046,8 +1046,7 @@ namespace FancyZonesUnitTests TEST_METHOD (CustomZoneFromValidCanvasLayoutInfo) { //prepare device data - const std::wstring zoneUuid = L"default_device_id"; - FancyZonesDataInstance().SetDeviceInfo(zoneUuid, DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 }); + FancyZonesDataInstance().SetDeviceInfo(FancyZonesDataTypes::DeviceIdData{ L"default_device_id" }, DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 }); //prepare expected data wil::unique_cotaskmem_string uuid; @@ -1072,8 +1071,7 @@ namespace FancyZonesUnitTests TEST_METHOD (CustomZoneFromValidGridFullLayoutInfo) { //prepare device data - const std::wstring zoneUuid = L"default_device_id"; - FancyZonesDataInstance().SetDeviceInfo(zoneUuid, DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 }); + FancyZonesDataInstance().SetDeviceInfo(FancyZonesDataTypes::DeviceIdData{ L"default_device_id" }, DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 }); //prepare expected data wil::unique_cotaskmem_string uuid; diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs index 2f1b99adbb..b556407387 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs @@ -33,6 +33,9 @@ namespace FancyZonesEditor.Utils // Non-localizable string: Multi-monitor id private const string MultiMonitorId = "FancyZones#MultiMonitorDevice"; + // Non-localizable string: default virtual desktop id + private const string DefaultVirtualDesktopGuid = "{00000000-0000-0000-0000-000000000000}"; + private readonly IFileSystem _fileSystem = new FileSystem(); private readonly JsonSerializerOptions _options = new JsonSerializerOptions @@ -725,7 +728,13 @@ namespace FancyZonesEditor.Utils bool unused = true; foreach (Monitor monitor in monitors) { - if (monitor.Device.Id == device.DeviceId) + string deviceIdSaved = monitor.Device.Id.Substring(0, monitor.Device.Id.LastIndexOf("_")); + string deviceIdReadFromSettings = device.DeviceId.Substring(0, device.DeviceId.LastIndexOf("_")); + + string virtualDesktopIdSaved = monitor.Device.Id.Substring(monitor.Device.Id.LastIndexOf("_") + 1); + string virtualDesktopIdReadFromSettings = device.DeviceId.Substring(device.DeviceId.LastIndexOf("_") + 1); + + if (deviceIdSaved == deviceIdReadFromSettings && (virtualDesktopIdSaved == virtualDesktopIdReadFromSettings || virtualDesktopIdReadFromSettings == DefaultVirtualDesktopGuid)) { var settings = new LayoutSettings {