diff --git a/src/modules/fancyzones/lib/FancyZones.cpp b/src/modules/fancyzones/lib/FancyZones.cpp index 15eda418d5..ce05da6464 100644 --- a/src/modules/fancyzones/lib/FancyZones.cpp +++ b/src/modules/fancyzones/lib/FancyZones.cpp @@ -681,7 +681,7 @@ void FancyZones::AddZoneWindow(HMONITOR monitor, PCWSTR deviceId) noexcept //const bool flash = m_settings->GetSettings()->zoneSetChange_flashZones && newWorkArea; const bool flash = false; - auto zoneWindow = MakeZoneWindow(this, m_hinstance, monitor, uniqueId, flash); + auto zoneWindow = MakeZoneWindow(this, m_hinstance, monitor, uniqueId, flash, newWorkArea); if (zoneWindow) { m_zoneWindowMap[monitor] = std::move(zoneWindow); diff --git a/src/modules/fancyzones/lib/JsonHelpers.h b/src/modules/fancyzones/lib/JsonHelpers.h index 9917209bb1..3b5ecd27f0 100644 --- a/src/modules/fancyzones/lib/JsonHelpers.h +++ b/src/modules/fancyzones/lib/JsonHelpers.h @@ -212,6 +212,11 @@ namespace JSONHelpers customZoneSetsMap.clear(); activeDeviceId.clear(); } + + inline void SetDeviceInfo(const std::wstring& deviceId, DeviceInfoData data) + { + deviceInfoMap[deviceId] = data; + } #endif inline void SetActiveDeviceId(const std::wstring& deviceId) diff --git a/src/modules/fancyzones/lib/ZoneWindow.cpp b/src/modules/fancyzones/lib/ZoneWindow.cpp index 3e75c8d5a1..81cd60ac22 100644 --- a/src/modules/fancyzones/lib/ZoneWindow.cpp +++ b/src/modules/fancyzones/lib/ZoneWindow.cpp @@ -205,7 +205,7 @@ public: ZoneWindow(HINSTANCE hinstance); ~ZoneWindow(); - bool Init(IZoneWindowHost* host, HINSTANCE hinstance, HMONITOR monitor, const std::wstring& uniqueId, bool flashZones); + bool Init(IZoneWindowHost* host, HINSTANCE hinstance, HMONITOR monitor, const std::wstring& uniqueId, bool flashZones, bool newWorkArea); IFACEMETHODIMP MoveSizeEnter(HWND window, bool dragEnabled) noexcept; IFACEMETHODIMP MoveSizeUpdate(POINT const& ptScreen, bool dragEnabled) noexcept; @@ -240,7 +240,7 @@ protected: private: void LoadSettings() noexcept; - void InitializeZoneSets(MONITORINFO const& mi) noexcept; + void InitializeZoneSets(bool newWorkArea) noexcept; void CalculateZoneSet() noexcept; void UpdateActiveZoneSet(_In_opt_ IZoneSet* zoneSet) noexcept; LRESULT WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept; @@ -297,7 +297,7 @@ ZoneWindow::~ZoneWindow() Gdiplus::GdiplusShutdown(gdiplusToken); } -bool ZoneWindow::Init(IZoneWindowHost* host, HINSTANCE hinstance, HMONITOR monitor, const std::wstring& uniqueId, bool flashZones) +bool ZoneWindow::Init(IZoneWindowHost* host, HINSTANCE hinstance, HMONITOR monitor, const std::wstring& uniqueId, bool flashZones, bool newWorkArea) { m_host.copy_from(host); @@ -316,7 +316,7 @@ bool ZoneWindow::Init(IZoneWindowHost* host, HINSTANCE hinstance, HMONITOR monit m_uniqueId = uniqueId; LoadSettings(); - InitializeZoneSets(mi); + InitializeZoneSets(newWorkArea); m_window = wil::unique_hwnd{ CreateWindowExW(WS_EX_TOOLWINDOW, L"SuperFancyZones_ZoneWindow", L"", WS_POPUP, workAreaRect.left(), workAreaRect.top(), workAreaRect.width(), workAreaRect.height(), nullptr, nullptr, hinstance, this) @@ -543,10 +543,10 @@ void ZoneWindow::LoadSettings() noexcept JSONHelpers::FancyZonesDataInstance().AddDevice(m_uniqueId); } -void ZoneWindow::InitializeZoneSets(MONITORINFO const& mi) noexcept +void ZoneWindow::InitializeZoneSets(bool newWorkArea) noexcept { auto parent = m_host->GetParentZoneWindow(m_monitor); - if (parent) + if (newWorkArea && parent) { // Update device info with device info from parent virtual desktop (if empty). JSONHelpers::FancyZonesDataInstance().CloneDeviceInfo(parent->UniqueId(), m_uniqueId); @@ -787,10 +787,10 @@ LRESULT CALLBACK ZoneWindow::s_WndProc(HWND window, UINT message, WPARAM wparam, DefWindowProc(window, message, wparam, lparam); } -winrt::com_ptr MakeZoneWindow(IZoneWindowHost* host, HINSTANCE hinstance, HMONITOR monitor, const std::wstring& uniqueId, bool flashZones) noexcept +winrt::com_ptr MakeZoneWindow(IZoneWindowHost* host, HINSTANCE hinstance, HMONITOR monitor, const std::wstring& uniqueId, bool flashZones, bool newWorkArea) noexcept { auto self = winrt::make_self(hinstance); - if (self->Init(host, hinstance, monitor, uniqueId, flashZones)) + if (self->Init(host, hinstance, monitor, uniqueId, flashZones, newWorkArea)) { return self; } diff --git a/src/modules/fancyzones/lib/ZoneWindow.h b/src/modules/fancyzones/lib/ZoneWindow.h index 0961163752..e66c6f0b49 100644 --- a/src/modules/fancyzones/lib/ZoneWindow.h +++ b/src/modules/fancyzones/lib/ZoneWindow.h @@ -105,4 +105,4 @@ interface __declspec(uuid("{7F017528-8110-4FB3-BE41-F472969C2560}")) IZoneWindow }; winrt::com_ptr MakeZoneWindow(IZoneWindowHost* host, HINSTANCE hinstance, HMONITOR monitor, - const std::wstring& uniqueId, bool flashZones) noexcept; + const std::wstring& uniqueId, bool flashZones, bool newWorkArea) noexcept; diff --git a/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp b/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp index 9be58b22ec..3460894f32 100644 --- a/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp +++ b/src/modules/fancyzones/tests/UnitTests/ZoneWindow.Spec.cpp @@ -55,6 +55,7 @@ namespace FancyZonesUnitTests { const std::wstring m_deviceId = L"\\\\?\\DISPLAY#DELA026#5&10a58c63&0&UID16777488#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}"; const std::wstring m_virtualDesktopId = L"MyVirtualDesktopId"; + std::wstringstream m_parentUniqueId; std::wstringstream m_uniqueId; HINSTANCE m_hInst{}; @@ -75,6 +76,7 @@ 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}"; Assert::IsFalse(ZoneWindowUtils::GetActiveZoneSetTmpPath().empty()); @@ -113,7 +115,7 @@ namespace FancyZonesUnitTests m_fancyZonesData.ParseDeviceInfoFromTmpFile(activeZoneSetTempPath); - return MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false); + return MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, false); } void testZoneWindow(winrt::com_ptr zoneWindow) @@ -129,14 +131,14 @@ namespace FancyZonesUnitTests public: TEST_METHOD(CreateZoneWindow) { - m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false); + m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, false); testZoneWindow(m_zoneWindow); Assert::IsNull(m_zoneWindow->ActiveZoneSet()); } TEST_METHOD(CreateZoneWindowNoHinst) { - m_zoneWindow = MakeZoneWindow(m_hostPtr, {}, m_monitor, m_uniqueId.str(), false); + m_zoneWindow = MakeZoneWindow(m_hostPtr, {}, m_monitor, m_uniqueId.str(), false, false); testZoneWindow(m_zoneWindow); Assert::IsNull(m_zoneWindow->ActiveZoneSet()); @@ -144,7 +146,7 @@ namespace FancyZonesUnitTests TEST_METHOD(CreateZoneWindowNoHinstFlashZones) { - m_zoneWindow = MakeZoneWindow(m_hostPtr, {}, m_monitor, m_uniqueId.str(), true); + m_zoneWindow = MakeZoneWindow(m_hostPtr, {}, m_monitor, m_uniqueId.str(), true, false); testZoneWindow(m_zoneWindow); Assert::IsNull(m_zoneWindow->ActiveZoneSet()); @@ -152,7 +154,7 @@ namespace FancyZonesUnitTests TEST_METHOD(CreateZoneWindowNoMonitor) { - m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, {}, m_uniqueId.str(), false); + m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, {}, m_uniqueId.str(), false, false); Assert::IsNull(m_zoneWindow.get()); Assert::IsNotNull(m_hostPtr); @@ -160,7 +162,7 @@ namespace FancyZonesUnitTests TEST_METHOD(CreateZoneWindowNoMonitorFlashZones) { - m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, {}, m_uniqueId.str(), true); + m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, {}, m_uniqueId.str(), true, false); Assert::IsNull(m_zoneWindow.get()); Assert::IsNotNull(m_hostPtr); @@ -170,7 +172,7 @@ namespace FancyZonesUnitTests { // Generate unique id without device id std::wstring uniqueId = ZoneWindowUtils::GenerateUniqueId(m_monitor, nullptr, m_virtualDesktopId.c_str()); - m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, uniqueId, false); + m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, uniqueId, false, false); 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; @@ -186,7 +188,7 @@ namespace FancyZonesUnitTests { // Generate unique id without virtual desktop id std::wstring uniqueId = ZoneWindowUtils::GenerateUniqueId(m_monitor, m_deviceId.c_str(), nullptr); - m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, uniqueId, false); + m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, uniqueId, false, false); const std::wstring expectedWorkArea = std::to_wstring(m_monitorInfo.rcMonitor.right) + L"_" + std::to_wstring(m_monitorInfo.rcMonitor.bottom); Assert::IsNotNull(m_zoneWindow.get()); @@ -213,7 +215,7 @@ namespace FancyZonesUnitTests m_fancyZonesData.ParseDeviceInfoFromTmpFile(activeZoneSetTempPath); //temp file read on initialization - auto actual = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false); + auto actual = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, false); testZoneWindow(actual); @@ -237,7 +239,7 @@ namespace FancyZonesUnitTests m_fancyZonesData.ParseDeviceInfoFromTmpFile(activeZoneSetTempPath); //temp file read on initialization - auto actual = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false); + auto actual = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, false); testZoneWindow(actual); @@ -273,7 +275,7 @@ namespace FancyZonesUnitTests m_fancyZonesData.ParseCustomZoneSetFromTmpFile(appliedZoneSetTempPath); //temp file read on initialization - auto actual = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false); + auto actual = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, false); testZoneWindow(actual); @@ -320,7 +322,7 @@ namespace FancyZonesUnitTests m_fancyZonesData.ParseCustomZoneSetFromTmpFile(appliedZoneSetTempPath); //temp file read on initialization - auto actual = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false); + auto actual = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, false); testZoneWindow(actual); @@ -367,7 +369,7 @@ namespace FancyZonesUnitTests m_fancyZonesData.ParseCustomZoneSetFromTmpFile(appliedZoneSetTempPath); //temp file read on initialization - auto actual = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false); + auto actual = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, false); testZoneWindow(actual); @@ -376,9 +378,68 @@ namespace FancyZonesUnitTests Assert::AreEqual((size_t)1, actualZoneSet.size()); } + TEST_METHOD (CreateZoneWindowClonedFromParent) + { + using namespace JSONHelpers; + + const ZoneSetLayoutType type = ZoneSetLayoutType::PriorityGrid; + const int spacing = 10; + const int zoneCount = 5; + 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); + + auto parentZoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_parentUniqueId.str(), false, false); + m_zoneWindowHost.m_zoneWindow = parentZoneWindow.get(); + + // newWorkArea = true - zoneWindow will be cloned from parent + auto actualZoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, true); + + Assert::IsNotNull(actualZoneWindow->ActiveZoneSet()); + const auto actualZoneSet = actualZoneWindow->ActiveZoneSet()->GetZones(); + Assert::AreEqual((size_t)zoneCount, actualZoneSet.size()); + + Assert::IsTrue(m_fancyZonesData.GetDeviceInfoMap().contains(m_uniqueId.str())); + auto currentDeviceInfo = m_fancyZonesData.GetDeviceInfoMap().at(m_uniqueId.str()); + Assert::AreEqual(zoneCount, currentDeviceInfo.zoneCount); + Assert::AreEqual(spacing, currentDeviceInfo.spacing); + Assert::AreEqual(static_cast(type), static_cast(currentDeviceInfo.activeZoneSet.type)); + } + + TEST_METHOD (CreateZoneWindowNotClonedFromParent) + { + using namespace JSONHelpers; + + const ZoneSetLayoutType type = ZoneSetLayoutType::PriorityGrid; + const int spacing = 10; + const int zoneCount = 5; + 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); + + auto parentZoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_parentUniqueId.str(), false, false); + m_zoneWindowHost.m_zoneWindow = parentZoneWindow.get(); + + // newWorkArea = false - zoneWindow won't be cloned from parent + auto actualZoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, false); + + Assert::IsNull(actualZoneWindow->ActiveZoneSet()); + + Assert::IsTrue(m_fancyZonesData.GetDeviceInfoMap().contains(m_uniqueId.str())); + auto currentDeviceInfo = m_fancyZonesData.GetDeviceInfoMap().at(m_uniqueId.str()); + // default values + Assert::AreEqual(false, currentDeviceInfo.showSpacing); + Assert::AreEqual(0, currentDeviceInfo.zoneCount); + Assert::AreEqual(0, currentDeviceInfo.spacing); + Assert::AreEqual(std::wstring{ L"null" }, currentDeviceInfo.activeZoneSet.uuid); + Assert::AreEqual(static_cast(ZoneSetLayoutType::Blank), static_cast(currentDeviceInfo.activeZoneSet.type)); + } + TEST_METHOD(MoveSizeEnter) { - m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false); + m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, false); const auto expected = S_OK; const auto actual = m_zoneWindow->MoveSizeEnter(Mocks::Window(), true); @@ -389,7 +450,7 @@ namespace FancyZonesUnitTests TEST_METHOD(MoveSizeEnterTwice) { - m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false); + m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, false); const auto expected = E_INVALIDARG; @@ -402,7 +463,7 @@ namespace FancyZonesUnitTests TEST_METHOD(MoveSizeUpdate) { - m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false); + m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, false); const auto expected = S_OK; const auto actual = m_zoneWindow->MoveSizeUpdate(POINT{ 0, 0 }, true); @@ -413,7 +474,7 @@ namespace FancyZonesUnitTests TEST_METHOD(MoveSizeUpdatePointNegativeCoordinates) { - m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false); + m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, false); const auto expected = S_OK; const auto actual = m_zoneWindow->MoveSizeUpdate(POINT{ -10, -10 }, true); @@ -424,7 +485,7 @@ namespace FancyZonesUnitTests TEST_METHOD(MoveSizeUpdatePointBigCoordinates) { - m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false); + m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, false); const auto expected = S_OK; const auto actual = m_zoneWindow->MoveSizeUpdate(POINT{ m_monitorInfo.rcMonitor.right + 1, m_monitorInfo.rcMonitor.bottom + 1 }, true); @@ -468,7 +529,7 @@ namespace FancyZonesUnitTests TEST_METHOD(MoveSizeEndDifferentWindows) { - m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false); + m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, false); const auto window = Mocks::Window(); m_zoneWindow->MoveSizeEnter(window, true); @@ -481,7 +542,7 @@ namespace FancyZonesUnitTests TEST_METHOD(MoveSizeEndWindowNotSet) { - m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false); + m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, false); const auto expected = E_INVALIDARG; const auto actual = m_zoneWindow->MoveSizeEnd(Mocks::Window(), POINT{ 0, 0 }); @@ -508,7 +569,7 @@ namespace FancyZonesUnitTests TEST_METHOD(MoveWindowIntoZoneByIndexNoActiveZoneSet) { - m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false); + m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, false); Assert::IsNull(m_zoneWindow->ActiveZoneSet()); m_zoneWindow->MoveWindowIntoZoneByIndex(Mocks::Window(), 0); @@ -526,7 +587,7 @@ namespace FancyZonesUnitTests TEST_METHOD(MoveWindowIntoZoneByDirectionNoActiveZoneSet) { - m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false); + m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, false); Assert::IsNull(m_zoneWindow->ActiveZoneSet()); m_zoneWindow->MoveWindowIntoZoneByIndex(Mocks::Window(), 0); @@ -564,7 +625,7 @@ namespace FancyZonesUnitTests TEST_METHOD(SaveWindowProcessToZoneIndexNoActiveZoneSet) { - m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false); + m_zoneWindow = MakeZoneWindow(m_hostPtr, m_hInst, m_monitor, m_uniqueId.str(), false, false); Assert::IsNull(m_zoneWindow->ActiveZoneSet()); m_zoneWindow->SaveWindowProcessToZoneIndex(Mocks::Window());