Files
PowerToys/src/modules/fancyzones/FancyZonesTests/UnitTests/WindowKeyboardSnap.Spec.cpp

1452 lines
73 KiB
C++
Raw Normal View History

#include "pch.h"
#include <FancyZonesLib/WindowKeyboardSnap.h>
#include <FancyZonesLib/FancyZonesData/AppliedLayouts.h>
#include <FancyZonesLib/FancyZonesData/AppZoneHistory.h>
#include <FancyZonesLib/Settings.h>
#include <FancyZonesLib/WorkArea.h>
#include <FancyZonesLib/util.h>
#include <common/utils/json.h>
#include <filesystem>
#include "Util.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace FancyZonesUnitTests
{
TEST_CLASS (WindowKeyboardSnap_ByIndex_UnitTests)
{
const std::wstring m_virtualDesktopIdStr = L"{A998CA86-F08D-4BCA-AED8-77F5C8FC9925}";
const std::wstring m_layoutIdStr = L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}";
constexpr GUID layoutId()
{
return FancyZonesUtils::GuidFromString(m_layoutIdStr).value();
}
const HMONITOR m_monitor = Mocks::Monitor();
const FancyZonesDataTypes::WorkAreaId m_workAreaId = {
.monitorId = {
.monitor = m_monitor,
.deviceId = {
.id = L"device-id-1",
.instanceId = L"5&10a58c63&0&UID16777488",
.number = 1,
},
.serialNumber = L"serial-number-1" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(m_virtualDesktopIdStr).value() };
std::unordered_map<HMONITOR, std::unique_ptr<WorkArea>> m_workAreaMap;
HINSTANCE m_hInst{};
json::JsonObject WorkAreaLayoutObject(const FancyZonesDataTypes::WorkAreaId& workAreaId)
{
json::JsonObject layout{};
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::UuidID, json::value(m_layoutIdStr));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::TypeID, json::value(FancyZonesDataTypes::TypeToString(FancyZonesDataTypes::ZoneSetLayoutType::Grid)));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ShowSpacingID, json::value(false));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SpacingID, json::value(0));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ZoneCountID, json::value(4));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SensitivityRadiusID, json::value(20));
json::JsonObject workAreaIdObj{};
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorID, json::value(workAreaId.monitorId.deviceId.id));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorInstanceID, json::value(workAreaId.monitorId.deviceId.instanceId));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorSerialNumberID, json::value(workAreaId.monitorId.serialNumber));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorNumberID, json::value(workAreaId.monitorId.deviceId.number));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::VirtualDesktopID, json::value(m_virtualDesktopIdStr));
json::JsonObject obj{};
obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::DeviceID, workAreaIdObj);
obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutID, layout);
return obj;
}
void PrepareGridLayout()
{
json::JsonObject root{};
json::JsonArray layoutsArray{};
layoutsArray.Append(WorkAreaLayoutObject(m_workAreaId));
root.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutsArrayID, layoutsArray);
json::to_file(AppliedLayouts::AppliedLayoutsFileName(), root);
AppliedLayouts::instance().LoadData();
}
TEST_METHOD_INITIALIZE (Init)
{
AppZoneHistory::instance().LoadData();
PrepareGridLayout();
FancyZonesSettings::instance().SetSettings({ .overrideSnapHotkeys = true, .moveWindowsBasedOnPosition = false });
auto workArea = WorkArea::Create(m_hInst, m_workAreaId, {}, FancyZonesUtils::Rect{ RECT(0, 0, 1920, 1080) });
m_workAreaMap.insert({ m_monitor, std::move(workArea) });
}
TEST_METHOD_CLEANUP(CleanUp)
{
std::filesystem::remove(AppliedLayouts::AppliedLayoutsFileName());
std::filesystem::remove(AppZoneHistory::AppZoneHistoryFileName());
}
TEST_METHOD (Snap_Left)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
Assert::IsTrue(windowKeyboardSnap.Snap(window, m_monitor, VK_LEFT, m_workAreaMap, { m_monitor }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 3 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 3 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
TEST_METHOD (Snap_Right)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
Assert::IsTrue(windowKeyboardSnap.Snap(window, m_monitor, VK_RIGHT, m_workAreaMap, { m_monitor }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 0 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
TEST_METHOD (MoveToNextZone)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitor)->Snap(window, { 1 }, true);
Assert::IsTrue(windowKeyboardSnap.Snap(window, m_monitor, VK_RIGHT, m_workAreaMap, { m_monitor }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 2 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 2 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
TEST_METHOD (MoveToPrevZone)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitor)->Snap(window, { 1 }, true);
Assert::IsTrue(windowKeyboardSnap.Snap(window, m_monitor, VK_LEFT, m_workAreaMap, { m_monitor }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 0 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
TEST_METHOD (MoveNext_Cycle)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitor)->Snap(window, { 3 }, true);
auto settings = FancyZonesSettings::settings();
settings.moveWindowAcrossMonitors = true;
FancyZonesSettings::instance().SetSettings(settings);
Assert::IsTrue(windowKeyboardSnap.Snap(window, m_monitor, VK_RIGHT, m_workAreaMap, { m_monitor }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 0 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
TEST_METHOD (MovePrev_Cycle)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitor)->Snap(window, { 0 }, true);
auto settings = FancyZonesSettings::settings();
settings.moveWindowAcrossMonitors = true;
FancyZonesSettings::instance().SetSettings(settings);
Assert::IsTrue(windowKeyboardSnap.Snap(window, m_monitor, VK_LEFT, m_workAreaMap, { m_monitor }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 3 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 3 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
TEST_METHOD (MoveNext_NoCycle)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitor)->Snap(window, { 3 }, true);
auto settings = FancyZonesSettings::settings();
settings.moveWindowAcrossMonitors = false;
FancyZonesSettings::instance().SetSettings(settings);
Assert::IsFalse(windowKeyboardSnap.Snap(window, m_monitor, VK_RIGHT, m_workAreaMap, { m_monitor }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 3 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 3 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
TEST_METHOD (MovePrev_NoCycle)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitor)->Snap(window, { 0 }, true);
auto settings = FancyZonesSettings::settings();
settings.moveWindowAcrossMonitors = false;
FancyZonesSettings::instance().SetSettings(settings);
Assert::IsFalse(windowKeyboardSnap.Snap(window, m_monitor, VK_LEFT, m_workAreaMap, { m_monitor }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 0 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
};
TEST_CLASS (WindowKeyboardSnap_MoveAcrossMonitors_ByIndex_UnitTests)
{
const std::wstring m_virtualDesktopIdStr = L"{A998CA86-F08D-4BCA-AED8-77F5C8FC9925}";
const std::vector<HMONITOR> m_monitors = { Mocks::Monitor(), Mocks::Monitor() };
const std::vector<FancyZonesDataTypes::WorkAreaId> m_workAreaIds = {
FancyZonesDataTypes::WorkAreaId{
.monitorId = {
.monitor = m_monitors[0],
.deviceId = {
.id = L"device-id-1",
.instanceId = L"5&10a58c63&0&UID16777488",
.number = 1,
},
.serialNumber = L"serial-number-1" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(m_virtualDesktopIdStr).value() },
FancyZonesDataTypes::WorkAreaId{
.monitorId = {
.monitor = m_monitors[1],
.deviceId = {
.id = L"device-id-2",
.instanceId = L"5&10a58c63&0&UID16777489",
.number = 2,
},
.serialNumber = L"serial-number-2" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(m_virtualDesktopIdStr).value() }
};
std::unordered_map<HMONITOR, std::unique_ptr<WorkArea>> m_workAreaMap;
HINSTANCE m_hInst{};
json::JsonObject WorkAreaLayoutObject(const FancyZonesDataTypes::WorkAreaId& workAreaId)
{
json::JsonObject layout{};
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::UuidID, json::value(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}"));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::TypeID, json::value(FancyZonesDataTypes::TypeToString(FancyZonesDataTypes::ZoneSetLayoutType::Grid)));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ShowSpacingID, json::value(false));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SpacingID, json::value(0));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ZoneCountID, json::value(4));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SensitivityRadiusID, json::value(20));
json::JsonObject workAreaIdObj{};
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorID, json::value(workAreaId.monitorId.deviceId.id));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorInstanceID, json::value(workAreaId.monitorId.deviceId.instanceId));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorSerialNumberID, json::value(workAreaId.monitorId.serialNumber));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorNumberID, json::value(workAreaId.monitorId.deviceId.number));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::VirtualDesktopID, json::value(m_virtualDesktopIdStr));
json::JsonObject obj{};
obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::DeviceID, workAreaIdObj);
obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutID, layout);
return obj;
}
void PrepareGridLayout()
{
json::JsonObject root{};
json::JsonArray layoutsArray{};
for (const auto& workAreaId : m_workAreaIds)
{
layoutsArray.Append(WorkAreaLayoutObject(workAreaId));
}
root.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutsArrayID, layoutsArray);
json::to_file(AppliedLayouts::AppliedLayoutsFileName(), root);
AppliedLayouts::instance().LoadData();
}
TEST_METHOD_INITIALIZE(Init)
{
AppZoneHistory::instance().LoadData();
PrepareGridLayout();
auto settings = FancyZonesSettings::settings();
settings.moveWindowAcrossMonitors = true;
FancyZonesSettings::instance().SetSettings(settings);
auto workArea1 = WorkArea::Create(m_hInst, m_workAreaIds[0], {}, FancyZonesUtils::Rect{ RECT(0, 0, 1920, 1080) });
m_workAreaMap.insert({ m_monitors[0], std::move(workArea1) });
auto workArea2 = WorkArea::Create(m_hInst, m_workAreaIds[1], {}, FancyZonesUtils::Rect{ RECT(1920, 0, 3840, 1080) });
m_workAreaMap.insert({ m_monitors[1], std::move(workArea2) });
}
TEST_METHOD_CLEANUP(CleanUp)
{
std::filesystem::remove(AppliedLayouts::AppliedLayoutsFileName());
std::filesystem::remove(AppZoneHistory::AppZoneHistoryFileName());
}
TEST_METHOD (Snap_Left)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
Assert::IsTrue(windowKeyboardSnap.Snap(window, m_monitors[0], VK_LEFT, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
const auto& layoutWindows = m_workAreaMap.at(m_monitors[0])->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 3 } == layoutWindows.GetZoneIndexSetFromWindow(window));
}
TEST_METHOD (Snap_Right)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
Assert::IsTrue(windowKeyboardSnap.Snap(window, m_monitors[0], VK_RIGHT, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
const auto& layoutWindows = m_workAreaMap.at(m_monitors[0])->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0 } == layoutWindows.GetZoneIndexSetFromWindow(window));
}
TEST_METHOD (Snap_Left_NextWorkArea)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap[m_monitors[1]]->Snap(window, { 0 });
Assert::IsTrue(windowKeyboardSnap.Snap(window, m_monitors[1], VK_LEFT, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
const auto& layoutWindowsPrevWorkArea = m_workAreaMap.at(m_monitors[1])->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{} == layoutWindowsPrevWorkArea.GetZoneIndexSetFromWindow(window));
const auto& layoutWindowsActualWorkArea = m_workAreaMap.at(m_monitors[0])->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 3 } == layoutWindowsActualWorkArea.GetZoneIndexSetFromWindow(window));
}
TEST_METHOD (Snap_Right_NextWorkArea)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitors[0])->Snap(window, { 3 });
Assert::IsTrue(windowKeyboardSnap.Snap(window, m_monitors[0], VK_RIGHT, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
const auto& layoutWindowsPrevWorkArea = m_workAreaMap.at(m_monitors[0])->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{} == layoutWindowsPrevWorkArea.GetZoneIndexSetFromWindow(window));
const auto& layoutWindowsActualWorkArea = m_workAreaMap.at(m_monitors[1])->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0 } == layoutWindowsActualWorkArea.GetZoneIndexSetFromWindow(window));
}
TEST_METHOD (Snap_Left_NextWorkArea_Cycle)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap[m_monitors[0]]->Snap(window, { 0 });
Assert::IsTrue(windowKeyboardSnap.Snap(window, m_monitors[0], VK_LEFT, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
const auto& layoutWindowsPrevWorkArea = m_workAreaMap.at(m_monitors[0])->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{} == layoutWindowsPrevWorkArea.GetZoneIndexSetFromWindow(window));
const auto& layoutWindowsActualWorkArea = m_workAreaMap.at(m_monitors[1])->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 3 } == layoutWindowsActualWorkArea.GetZoneIndexSetFromWindow(window));
}
TEST_METHOD (Snap_Right_NextWorkArea_Cycle)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitors[1])->Snap(window, { 3 });
Assert::IsTrue(windowKeyboardSnap.Snap(window, m_monitors[1], VK_RIGHT, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
const auto& layoutWindowsPrevWorkArea = m_workAreaMap.at(m_monitors[1])->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{} == layoutWindowsPrevWorkArea.GetZoneIndexSetFromWindow(window));
const auto& layoutWindowsActualWorkArea = m_workAreaMap.at(m_monitors[0])->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0 } == layoutWindowsActualWorkArea.GetZoneIndexSetFromWindow(window));
}
TEST_METHOD (Snap_Left_NoCycle)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap[m_monitors[0]]->Snap(window, { 0 });
auto settings = FancyZonesSettings::settings();
settings.moveWindowAcrossMonitors = false;
FancyZonesSettings::instance().SetSettings(settings);
Assert::IsFalse(windowKeyboardSnap.Snap(window, m_monitors[0], VK_LEFT, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
const auto& layoutWindowsPrevWorkArea = m_workAreaMap.at(m_monitors[0])->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0 } == layoutWindowsPrevWorkArea.GetZoneIndexSetFromWindow(window));
const auto& layoutWindowsActualWorkArea = m_workAreaMap.at(m_monitors[1])->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{} == layoutWindowsActualWorkArea.GetZoneIndexSetFromWindow(window));
}
TEST_METHOD (Snap_Right_NoCycle)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitors[1])->Snap(window, { 3 });
auto settings = FancyZonesSettings::settings();
settings.moveWindowAcrossMonitors = false;
FancyZonesSettings::instance().SetSettings(settings);
Assert::IsFalse(windowKeyboardSnap.Snap(window, m_monitors[1], VK_RIGHT, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
const auto& layoutWindowsPrevWorkArea = m_workAreaMap.at(m_monitors[1])->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 3 } == layoutWindowsPrevWorkArea.GetZoneIndexSetFromWindow(window));
const auto& layoutWindowsActualWorkArea = m_workAreaMap.at(m_monitors[0])->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{} == layoutWindowsActualWorkArea.GetZoneIndexSetFromWindow(window));
}
};
TEST_CLASS (WindowKeyboardSnap_ByPosition_UnitTests)
{
const std::wstring m_virtualDesktopIdStr = L"{A998CA86-F08D-4BCA-AED8-77F5C8FC9925}";
const std::wstring m_layoutIdStr = L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}";
constexpr GUID layoutId()
{
return FancyZonesUtils::GuidFromString(m_layoutIdStr).value();
}
const HMONITOR m_monitor = Mocks::Monitor();
const RECT m_rect = RECT{ 0, 0, 1920, 1080 };
const FancyZonesDataTypes::WorkAreaId m_workAreaId = {
.monitorId = {
.monitor = m_monitor,
.deviceId = {
.id = L"device-id-1",
.instanceId = L"5&10a58c63&0&UID16777488",
.number = 1,
},
.serialNumber = L"serial-number-1" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(m_virtualDesktopIdStr).value()
};
std::unordered_map<HMONITOR, std::unique_ptr<WorkArea>> m_workAreaMap;
HINSTANCE m_hInst{};
json::JsonObject WorkAreaLayoutObject(const FancyZonesDataTypes::WorkAreaId& workAreaId)
{
json::JsonObject layout{};
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::UuidID, json::value(m_layoutIdStr));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::TypeID, json::value(FancyZonesDataTypes::TypeToString(FancyZonesDataTypes::ZoneSetLayoutType::Grid)));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ShowSpacingID, json::value(false));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SpacingID, json::value(0));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ZoneCountID, json::value(4));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SensitivityRadiusID, json::value(20));
json::JsonObject workAreaIdObj{};
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorID, json::value(workAreaId.monitorId.deviceId.id));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorInstanceID, json::value(workAreaId.monitorId.deviceId.instanceId));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorSerialNumberID, json::value(workAreaId.monitorId.serialNumber));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorNumberID, json::value(workAreaId.monitorId.deviceId.number));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::VirtualDesktopID, json::value(m_virtualDesktopIdStr));
json::JsonObject obj{};
obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::DeviceID, workAreaIdObj);
obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutID, layout);
return obj;
}
void PrepareGridLayout()
{
json::JsonObject root{};
json::JsonArray layoutsArray{};
layoutsArray.Append(WorkAreaLayoutObject(m_workAreaId));
root.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutsArrayID, layoutsArray);
json::to_file(AppliedLayouts::AppliedLayoutsFileName(), root);
AppliedLayouts::instance().LoadData();
}
// using zone rects instead of the actual window rect
// otherwise we'll need to wait after snapping, for the window to be resized
RECT GetZoneRect(const WorkArea* workArea, ZoneIndex index)
{
auto rect = workArea->GetLayout()->Zones().at(index).GetZoneRect();
auto workAreaRect = workArea->GetWorkAreaRect();
return rect;
}
TEST_METHOD_INITIALIZE(Init)
{
AppZoneHistory::instance().LoadData();
PrepareGridLayout();
auto workArea = WorkArea::Create(m_hInst, m_workAreaId, {}, FancyZonesUtils::Rect{ m_rect });
m_workAreaMap.insert({ m_monitor, std::move(workArea) });
}
TEST_METHOD_CLEANUP(CleanUp)
{
std::filesystem::remove(AppliedLayouts::AppliedLayoutsFileName());
std::filesystem::remove(AppZoneHistory::AppZoneHistoryFileName());
}
TEST_METHOD (Snap_Left)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
RECT windowRect;
Assert::IsTrue(GetWindowRect(window, &windowRect));
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitor, VK_LEFT, m_workAreaMap, { { m_monitor, m_rect } }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::AreEqual((size_t)1, layoutWindows.GetZoneIndexSetFromWindow(window).size());
Assert::AreEqual((size_t)1, AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()).size());
}
TEST_METHOD (Snap_Right)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
RECT windowRect;
Assert::IsTrue(GetWindowRect(window, &windowRect));
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitor, VK_RIGHT, m_workAreaMap, { { m_monitor, m_rect } }));
Assert::AreEqual((size_t)1, AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()).size());
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::AreEqual((size_t)1, layoutWindows.GetZoneIndexSetFromWindow(window).size());
}
TEST_METHOD (Snap_Up)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
RECT windowRect;
Assert::IsTrue(GetWindowRect(window, &windowRect));
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitor, VK_UP, m_workAreaMap, { { m_monitor, m_rect } }));
Assert::AreEqual((size_t)1, AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()).size());
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::AreEqual((size_t)1, layoutWindows.GetZoneIndexSetFromWindow(window).size());
}
TEST_METHOD (Snap_Down)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
RECT windowRect;
Assert::IsTrue(GetWindowRect(window, &windowRect));
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitor, VK_DOWN, m_workAreaMap, { { m_monitor, m_rect } }));
Assert::AreEqual((size_t)1, AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()).size());
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::AreEqual((size_t)1, layoutWindows.GetZoneIndexSetFromWindow(window).size());
}
TEST_METHOD (Move_Left)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitor)->Snap(window, { 1 }, true);
RECT windowRect = GetZoneRect(m_workAreaMap[m_monitor].get(), 1);
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitor, VK_LEFT, m_workAreaMap, { { m_monitor, m_rect } }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 0 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
TEST_METHOD (Move_Right)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitor)->Snap(window, { 0 }, true);
RECT windowRect = GetZoneRect(m_workAreaMap[m_monitor].get(), 0);
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitor, VK_RIGHT, m_workAreaMap, { { m_monitor, m_rect } }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 1 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 1 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
TEST_METHOD (Move_Up)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitor)->Snap(window, { 2 }, true);
RECT windowRect = GetZoneRect(m_workAreaMap[m_monitor].get(), 2);
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitor, VK_UP, m_workAreaMap, { { m_monitor, m_rect } }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 0 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
TEST_METHOD (Move_Down)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitor)->Snap(window, { 0 }, true);
RECT windowRect = GetZoneRect(m_workAreaMap[m_monitor].get(), 0);
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitor, VK_DOWN, m_workAreaMap, { { m_monitor, m_rect } }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 2 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 2 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
TEST_METHOD (MoveLeft_Cycle)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitor)->Snap(window, { 0 }, true);
RECT windowRect = GetZoneRect(m_workAreaMap[m_monitor].get(), 0);
auto settings = FancyZonesSettings::settings();
settings.moveWindowAcrossMonitors = true;
FancyZonesSettings::instance().SetSettings(settings);
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitor, VK_LEFT, m_workAreaMap, { { m_monitor, m_rect } }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 1 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 1 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
TEST_METHOD (MoveRight_Cycle)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitor)->Snap(window, { 1 }, true);
RECT windowRect = GetZoneRect(m_workAreaMap[m_monitor].get(), 1);
auto settings = FancyZonesSettings::settings();
settings.moveWindowAcrossMonitors = true;
FancyZonesSettings::instance().SetSettings(settings);
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitor, VK_RIGHT, m_workAreaMap, { { m_monitor, m_rect } }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 0 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
TEST_METHOD (MoveUp_Cycle)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitor)->Snap(window, { 0 }, true);
RECT windowRect = GetZoneRect(m_workAreaMap[m_monitor].get(), 0);
auto settings = FancyZonesSettings::settings();
settings.moveWindowAcrossMonitors = true;
FancyZonesSettings::instance().SetSettings(settings);
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitor, VK_UP, m_workAreaMap, { { m_monitor, m_rect } }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 2 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 2 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
TEST_METHOD (MoveDown_Cycle)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitor)->Snap(window, { 2 }, true);
RECT windowRect = GetZoneRect(m_workAreaMap[m_monitor].get(), 2);
auto settings = FancyZonesSettings::settings();
settings.moveWindowAcrossMonitors = true;
FancyZonesSettings::instance().SetSettings(settings);
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitor, VK_DOWN, m_workAreaMap, { { m_monitor, m_rect } }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 0 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
};
TEST_CLASS (WindowKeyboardSnap_MoveAcrossMonitors_ByPosition_UnitTests)
{
const std::wstring m_virtualDesktopIdStr = L"{A998CA86-F08D-4BCA-AED8-77F5C8FC9925}";
const std::vector<std::pair<HMONITOR, RECT>> m_monitors = {
{ Mocks::Monitor(), RECT{ 0, 0, 1920, 1080 } }, // left
{ Mocks::Monitor(), RECT{ 1920, 0, 3840, 1080 } }, // right
{ Mocks::Monitor(), RECT{ 0, -1080, 1920, 0 } } // top
};
const std::vector<FancyZonesDataTypes::WorkAreaId> m_workAreaIds = {
FancyZonesDataTypes::WorkAreaId{
.monitorId = {
.monitor = m_monitors[0].first,
.deviceId = {
.id = L"device-id-left",
.instanceId = L"5&10a58c63&0&UID16777488",
.number = 1,
},
.serialNumber = L"serial-number-left" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(m_virtualDesktopIdStr).value() },
FancyZonesDataTypes::WorkAreaId{
.monitorId = {
.monitor = m_monitors[1].first,
.deviceId = {
.id = L"device-id-right",
.instanceId = L"5&10a58c63&0&UID16777489",
.number = 2,
},
.serialNumber = L"serial-number-right" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(m_virtualDesktopIdStr).value() },
FancyZonesDataTypes::WorkAreaId{
.monitorId = {
.monitor = m_monitors[2].first,
.deviceId = {
.id = L"device-id-top",
.instanceId = L"5&10a58c63&0&UID16777487",
.number = 3,
},
.serialNumber = L"serial-number-top" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(m_virtualDesktopIdStr).value() }
};
std::unordered_map<HMONITOR, std::unique_ptr<WorkArea>> m_workAreaMap;
HINSTANCE m_hInst{};
json::JsonObject WorkAreaLayoutObject(const FancyZonesDataTypes::WorkAreaId& workAreaId)
{
json::JsonObject layout{};
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::UuidID, json::value(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}"));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::TypeID, json::value(FancyZonesDataTypes::TypeToString(FancyZonesDataTypes::ZoneSetLayoutType::Grid)));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ShowSpacingID, json::value(false));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SpacingID, json::value(0));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ZoneCountID, json::value(4));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SensitivityRadiusID, json::value(20));
json::JsonObject workAreaIdObj{};
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorID, json::value(workAreaId.monitorId.deviceId.id));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorInstanceID, json::value(workAreaId.monitorId.deviceId.instanceId));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorSerialNumberID, json::value(workAreaId.monitorId.serialNumber));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorNumberID, json::value(workAreaId.monitorId.deviceId.number));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::VirtualDesktopID, json::value(m_virtualDesktopIdStr));
json::JsonObject obj{};
obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::DeviceID, workAreaIdObj);
obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutID, layout);
return obj;
}
void PrepareGridLayout()
{
json::JsonObject root{};
json::JsonArray layoutsArray{};
for (const auto& workAreaId : m_workAreaIds)
{
layoutsArray.Append(WorkAreaLayoutObject(workAreaId));
}
root.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutsArrayID, layoutsArray);
json::to_file(AppliedLayouts::AppliedLayoutsFileName(), root);
AppliedLayouts::instance().LoadData();
}
RECT GetAdjustedZoneRect(const WorkArea* workArea, ZoneIndex index)
{
auto rect = workArea->GetLayout()->Zones().at(index).GetZoneRect();
auto workAreaRect = workArea->GetWorkAreaRect();
rect.left += workAreaRect.left();
rect.right += workAreaRect.left();
rect.top += workAreaRect.top();
rect.bottom += workAreaRect.top();
return rect;
}
TEST_METHOD_INITIALIZE(Init)
{
AppZoneHistory::instance().LoadData();
PrepareGridLayout();
auto settings = FancyZonesSettings::settings();
settings.moveWindowAcrossMonitors = true;
FancyZonesSettings::instance().SetSettings(settings);
auto workArea1 = WorkArea::Create(m_hInst, m_workAreaIds[0], {}, FancyZonesUtils::Rect{ m_monitors[0].second });
m_workAreaMap.insert({ m_monitors[0].first, std::move(workArea1) });
auto workArea2 = WorkArea::Create(m_hInst, m_workAreaIds[1], {}, FancyZonesUtils::Rect{ m_monitors[1].second });
m_workAreaMap.insert({ m_monitors[1].first, std::move(workArea2) });
auto workArea3 = WorkArea::Create(m_hInst, m_workAreaIds[2], {}, FancyZonesUtils::Rect{ m_monitors[2].second });
m_workAreaMap.insert({ m_monitors[2].first, std::move(workArea3) });
}
TEST_METHOD_CLEANUP(CleanUp)
{
std::filesystem::remove(AppliedLayouts::AppliedLayoutsFileName());
std::filesystem::remove(AppZoneHistory::AppZoneHistoryFileName());
}
TEST_METHOD (Snap_Left)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
RECT windowRect;
Assert::IsTrue(GetWindowRect(window, &windowRect));
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitors[0].first, VK_LEFT, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
}
TEST_METHOD (Snap_Right)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
RECT windowRect;
Assert::IsTrue(GetWindowRect(window, &windowRect));
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitors[0].first, VK_RIGHT, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
}
TEST_METHOD (Snap_Up)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
RECT windowRect;
Assert::IsTrue(GetWindowRect(window, &windowRect));
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitors[0].first, VK_UP, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
}
TEST_METHOD (Snap_Down)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
RECT windowRect;
Assert::IsTrue(GetWindowRect(window, &windowRect));
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitors[0].first, VK_DOWN, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
const auto& layoutWindows = m_workAreaMap.at(m_monitors[0].first)->GetLayoutWindows();
Assert::AreEqual((size_t)1, layoutWindows.GetZoneIndexSetFromWindow(window).size());
}
TEST_METHOD (Snap_Left_NextWorkArea)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
const ZoneIndex initialZoneIndex = 0;
m_workAreaMap[m_monitors[1].first]->Snap(window, { initialZoneIndex });
RECT windowRect = GetAdjustedZoneRect(m_workAreaMap[m_monitors[1].first].get(), initialZoneIndex); // use zone rect instead of the actual position
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitors[1].first, VK_LEFT, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
const auto& layoutWindowsPrevWorkArea = m_workAreaMap.at(m_monitors[1].first)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{} == layoutWindowsPrevWorkArea.GetZoneIndexSetFromWindow(window));
const auto& layoutWindowsActualWorkArea = m_workAreaMap.at(m_monitors[0].first)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 1 } == layoutWindowsActualWorkArea.GetZoneIndexSetFromWindow(window));
}
TEST_METHOD (Snap_Right_NextWorkArea)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
const ZoneIndex initialZoneIndex = 3;
m_workAreaMap[m_monitors[0].first]->Snap(window, { initialZoneIndex });
RECT windowRect = GetAdjustedZoneRect(m_workAreaMap[m_monitors[0].first].get(), initialZoneIndex); // use zone rect instead of the actual position
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitors[0].first, VK_RIGHT, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
const auto& layoutWindowsPrevWorkArea = m_workAreaMap.at(m_monitors[0].first)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{} == layoutWindowsPrevWorkArea.GetZoneIndexSetFromWindow(window));
const auto& layoutWindowsActualWorkArea = m_workAreaMap.at(m_monitors[1].first)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 2 } == layoutWindowsActualWorkArea.GetZoneIndexSetFromWindow(window));
}
TEST_METHOD (Snap_Up_NextWorkArea)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
const ZoneIndex initialZoneIndex = 0;
m_workAreaMap[m_monitors[0].first]->Snap(window, { initialZoneIndex });
RECT windowRect = GetAdjustedZoneRect(m_workAreaMap[m_monitors[0].first].get(), initialZoneIndex); // use zone rect instead of the actual position
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitors[0].first, VK_UP, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
const auto& layoutWindowsPrevWorkArea = m_workAreaMap.at(m_monitors[0].first)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{} == layoutWindowsPrevWorkArea.GetZoneIndexSetFromWindow(window));
const auto& layoutWindowsActualWorkArea = m_workAreaMap.at(m_monitors[2].first)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 2 } == layoutWindowsActualWorkArea.GetZoneIndexSetFromWindow(window));
}
TEST_METHOD (Snap_Down_NextWorkArea)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
const ZoneIndex initialZoneIndex = 2;
m_workAreaMap[m_monitors[2].first]->Snap(window, { initialZoneIndex });
RECT windowRect = GetAdjustedZoneRect(m_workAreaMap[m_monitors[2].first].get(), initialZoneIndex); // use zone rect instead of the actual position
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitors[2].first, VK_DOWN, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
const auto& layoutWindowsPrevWorkArea = m_workAreaMap.at(m_monitors[2].first)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{} == layoutWindowsPrevWorkArea.GetZoneIndexSetFromWindow(window));
const auto& layoutWindowsActualWorkArea = m_workAreaMap.at(m_monitors[0].first)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0 } == layoutWindowsActualWorkArea.GetZoneIndexSetFromWindow(window));
}
TEST_METHOD (Snap_Left_NextWorkArea_Cycle)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
const ZoneIndex initialZoneIndex = 0;
m_workAreaMap[m_monitors[0].first]->Snap(window, { initialZoneIndex });
RECT windowRect = GetAdjustedZoneRect(m_workAreaMap[m_monitors[0].first].get(), initialZoneIndex); // use zone rect instead of the actual position
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitors[0].first, VK_LEFT, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
const auto& layoutWindowsPrevWorkArea = m_workAreaMap.at(m_monitors[0].first)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{} == layoutWindowsPrevWorkArea.GetZoneIndexSetFromWindow(window));
const auto& layoutWindowsActualWorkArea = m_workAreaMap.at(m_monitors[1].first)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 1 } == layoutWindowsActualWorkArea.GetZoneIndexSetFromWindow(window));
}
TEST_METHOD (Snap_Right_NextWorkArea_Cycle)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
const ZoneIndex initialZoneIndex = 3;
m_workAreaMap[m_monitors[1].first]->Snap(window, { initialZoneIndex });
RECT windowRect = GetAdjustedZoneRect(m_workAreaMap[m_monitors[1].first].get(), initialZoneIndex); // use zone rect instead of the actual position
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitors[1].first, VK_RIGHT, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
const auto& layoutWindowsPrevWorkArea = m_workAreaMap.at(m_monitors[1].first)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{} == layoutWindowsPrevWorkArea.GetZoneIndexSetFromWindow(window));
const auto& layoutWindowsActualWorkArea = m_workAreaMap.at(m_monitors[0].first)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 2 } == layoutWindowsActualWorkArea.GetZoneIndexSetFromWindow(window));
}
TEST_METHOD (Snap_Up_NextWorkArea_Cycle)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
const ZoneIndex initialZoneIndex = 0;
m_workAreaMap[m_monitors[2].first]->Snap(window, { initialZoneIndex });
RECT windowRect = GetAdjustedZoneRect(m_workAreaMap[m_monitors[2].first].get(), initialZoneIndex); // use zone rect instead of the actual position
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitors[2].first, VK_UP, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
const auto& layoutWindowsPrevWorkArea = m_workAreaMap.at(m_monitors[2].first)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{} == layoutWindowsPrevWorkArea.GetZoneIndexSetFromWindow(window));
const auto& layoutWindowsActualWorkArea = m_workAreaMap.at(m_monitors[0].first)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 2 } == layoutWindowsActualWorkArea.GetZoneIndexSetFromWindow(window));
}
TEST_METHOD (Snap_Down_NextWorkArea_Cycle)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
const ZoneIndex initialZoneIndex = 2;
m_workAreaMap[m_monitors[0].first]->Snap(window, { initialZoneIndex });
RECT windowRect = GetAdjustedZoneRect(m_workAreaMap[m_monitors[0].first].get(), initialZoneIndex); // use zone rect instead of the actual position
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitors[0].first, VK_DOWN, m_workAreaMap, m_monitors));
const auto& actualAppZoneHistory = AppZoneHistory::instance().GetFullAppZoneHistory();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
const auto& layoutWindowsPrevWorkArea = m_workAreaMap.at(m_monitors[0].first)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{} == layoutWindowsPrevWorkArea.GetZoneIndexSetFromWindow(window));
const auto& layoutWindowsActualWorkArea = m_workAreaMap.at(m_monitors[2].first)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0 } == layoutWindowsActualWorkArea.GetZoneIndexSetFromWindow(window));
}
};
TEST_CLASS (WindowKeyboardSnap_Extend_UnitTests)
{
const std::wstring m_virtualDesktopIdStr = L"{A998CA86-F08D-4BCA-AED8-77F5C8FC9925}";
const std::wstring m_layoutIdStr = L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}";
constexpr GUID layoutId()
{
return FancyZonesUtils::GuidFromString(m_layoutIdStr).value();
}
const HMONITOR m_monitor = Mocks::Monitor();
const FancyZonesDataTypes::WorkAreaId m_workAreaId = {
.monitorId = {
.monitor = m_monitor,
.deviceId = {
.id = L"device-id-1",
.instanceId = L"5&10a58c63&0&UID16777488",
.number = 1,
},
.serialNumber = L"serial-number-1" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(m_virtualDesktopIdStr).value()
};
std::unordered_map<HMONITOR, std::unique_ptr<WorkArea>> m_workAreaMap = {};
HINSTANCE m_hInst{};
json::JsonObject WorkAreaLayoutObject(const FancyZonesDataTypes::WorkAreaId& workAreaId)
{
json::JsonObject layout{};
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::UuidID, json::value(m_layoutIdStr));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::TypeID, json::value(FancyZonesDataTypes::TypeToString(FancyZonesDataTypes::ZoneSetLayoutType::Grid)));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ShowSpacingID, json::value(false));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SpacingID, json::value(0));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ZoneCountID, json::value(4));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SensitivityRadiusID, json::value(20));
json::JsonObject workAreaIdObj{};
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorID, json::value(workAreaId.monitorId.deviceId.id));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorInstanceID, json::value(workAreaId.monitorId.deviceId.instanceId));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorSerialNumberID, json::value(workAreaId.monitorId.serialNumber));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorNumberID, json::value(workAreaId.monitorId.deviceId.number));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::VirtualDesktopID, json::value(m_virtualDesktopIdStr));
json::JsonObject obj{};
obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::DeviceID, workAreaIdObj);
obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutID, layout);
return obj;
}
void PrepareGridLayout()
{
json::JsonObject root{};
json::JsonArray layoutsArray{};
layoutsArray.Append(WorkAreaLayoutObject(m_workAreaId));
root.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutsArrayID, layoutsArray);
json::to_file(AppliedLayouts::AppliedLayoutsFileName(), root);
AppliedLayouts::instance().LoadData();
}
RECT GetAdjustedZoneRect(const WorkArea* workArea, ZoneIndex index)
{
auto rect = workArea->GetLayout()->Zones().at(index).GetZoneRect();
auto workAreaRect = workArea->GetWorkAreaRect();
rect.left += workAreaRect.left();
rect.right += workAreaRect.left();
rect.top += workAreaRect.top();
rect.bottom += workAreaRect.top();
return rect;
}
TEST_METHOD_INITIALIZE(Init)
{
AppZoneHistory::instance().LoadData();
PrepareGridLayout();
auto workArea = WorkArea::Create(m_hInst, m_workAreaId, {}, FancyZonesUtils::Rect{ RECT(0, 0, 1920, 1080) });
m_workAreaMap.insert({ m_monitor, std::move(workArea) });
}
TEST_METHOD_CLEANUP(CleanUp)
{
std::filesystem::remove(AppliedLayouts::AppliedLayoutsFileName());
std::filesystem::remove(AppZoneHistory::AppZoneHistoryFileName());
}
TEST_METHOD(ExtendNonSnappedWindow)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
RECT windowRect = {10,10,150,150};
Assert::IsTrue(SetWindowPos(window, nullptr, windowRect.left, windowRect.top, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, 0));
Assert::IsTrue(windowKeyboardSnap.Extend(window, windowRect, m_monitor, VK_RIGHT, m_workAreaMap));
const auto& layoutWindows = m_workAreaMap[m_monitor]->GetLayoutWindows();
Assert::AreEqual((size_t)1, layoutWindows.GetZoneIndexSetFromWindow(window).size());
Assert::AreEqual((size_t)1, AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaMap[m_monitor]->UniqueId(), m_workAreaMap[m_monitor]->GetLayoutId()).size());
}
TEST_METHOD (ExtendSnappedWindow)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
const auto& workArea = m_workAreaMap[m_monitor];
workArea->Snap(window, { 0 });
RECT windowRect = GetAdjustedZoneRect(workArea.get(), 0);
Assert::IsTrue(windowKeyboardSnap.Extend(window, windowRect, m_monitor, VK_RIGHT, m_workAreaMap));
const auto& layoutWindows = workArea->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0, 1 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 0, 1 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, workArea->UniqueId(), workArea->GetLayoutId()));
}
TEST_METHOD (ExtendLeft)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
const auto& workArea = m_workAreaMap[m_monitor];
workArea->Snap(window, { 1 });
RECT windowRect = GetAdjustedZoneRect(workArea.get(), 1);
Assert::IsTrue(windowKeyboardSnap.Extend(window, windowRect, m_monitor, VK_LEFT, m_workAreaMap));
const auto& layoutWindows = workArea->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0, 1 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 0, 1 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, workArea->UniqueId(), workArea->GetLayoutId()));
}
TEST_METHOD (ExtendRight)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
const auto& workArea = m_workAreaMap[m_monitor];
workArea->Snap(window, { 0 });
RECT windowRect = GetAdjustedZoneRect(workArea.get(), 0);
Assert::IsTrue(windowKeyboardSnap.Extend(window, windowRect, m_monitor, VK_RIGHT, m_workAreaMap));
const auto& layoutWindows = workArea->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0, 1 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 0, 1 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, workArea->UniqueId(), workArea->GetLayoutId()));
}
TEST_METHOD (ExtendUp)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
const auto& workArea = m_workAreaMap[m_monitor];
workArea->Snap(window, { 2 });
RECT windowRect = GetAdjustedZoneRect(workArea.get(), 2);
Assert::IsTrue(windowKeyboardSnap.Extend(window, windowRect, m_monitor, VK_UP, m_workAreaMap));
const auto& layoutWindows = workArea->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0, 2 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 0, 2 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, workArea->UniqueId(), workArea->GetLayoutId()));
}
TEST_METHOD (ExtendDown)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
const auto& workArea = m_workAreaMap[m_monitor];
workArea->Snap(window, { 0 });
RECT windowRect = GetAdjustedZoneRect(workArea.get(), 0);
Assert::IsTrue(windowKeyboardSnap.Extend(window, windowRect, m_monitor, VK_DOWN, m_workAreaMap));
const auto& layoutWindows = workArea->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0, 2 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 0, 2 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, workArea->UniqueId(), workArea->GetLayoutId()));
}
TEST_METHOD (ExtendAndRevert)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
const auto& workArea = m_workAreaMap[m_monitor];
workArea->Snap(window, { 0 });
RECT windowRect = GetAdjustedZoneRect(workArea.get(), 0);
Assert::IsTrue(windowKeyboardSnap.Extend(window, windowRect, m_monitor, VK_RIGHT, m_workAreaMap));
Assert::IsTrue(windowKeyboardSnap.Extend(window, windowRect, m_monitor, VK_DOWN, m_workAreaMap));
Assert::IsTrue(windowKeyboardSnap.Extend(window, windowRect, m_monitor, VK_LEFT, m_workAreaMap));
Assert::IsTrue(windowKeyboardSnap.Extend(window, windowRect, m_monitor, VK_UP, m_workAreaMap));
const auto& layoutWindows = workArea->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 0 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, workArea->UniqueId(), workArea->GetLayoutId()));
}
};
TEST_CLASS(WindowKeyboardSnap_MultiMonitorMode_UnitTests)
{
const std::wstring m_virtualDesktopIdStr = L"{A998CA86-F08D-4BCA-AED8-77F5C8FC9925}";
const std::wstring m_layoutIdStr = L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}";
constexpr GUID layoutId()
{
return FancyZonesUtils::GuidFromString(m_layoutIdStr).value();
}
HINSTANCE m_hInst{};
const RECT m_rect = RECT{ 0, 0, 1920, 1080 };
const HMONITOR m_monitor = nullptr;
const FancyZonesDataTypes::WorkAreaId m_workAreaId = {
.monitorId = {
.monitor = m_monitor,
.deviceId = {
.id = L"FancyZones",
.instanceId = L"MultiMonitorDevice",
.number = 0,
},
.serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(m_virtualDesktopIdStr).value()
};
std::unordered_map<HMONITOR, std::unique_ptr<WorkArea>> m_workAreaMap = {};
json::JsonObject WorkAreaLayoutObject(const FancyZonesDataTypes::WorkAreaId& workAreaId)
{
json::JsonObject layout{};
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::UuidID, json::value(m_layoutIdStr));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::TypeID, json::value(FancyZonesDataTypes::TypeToString(FancyZonesDataTypes::ZoneSetLayoutType::Grid)));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ShowSpacingID, json::value(false));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SpacingID, json::value(0));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ZoneCountID, json::value(4));
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SensitivityRadiusID, json::value(20));
json::JsonObject workAreaIdObj{};
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorID, json::value(workAreaId.monitorId.deviceId.id));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorInstanceID, json::value(workAreaId.monitorId.deviceId.instanceId));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorSerialNumberID, json::value(workAreaId.monitorId.serialNumber));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorNumberID, json::value(workAreaId.monitorId.deviceId.number));
workAreaIdObj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::VirtualDesktopID, json::value(m_virtualDesktopIdStr));
json::JsonObject obj{};
obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::DeviceID, workAreaIdObj);
obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutID, layout);
return obj;
}
void PrepareGridLayout()
{
json::JsonObject root{};
json::JsonArray layoutsArray{};
layoutsArray.Append(WorkAreaLayoutObject(m_workAreaId));
root.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutsArrayID, layoutsArray);
json::to_file(AppliedLayouts::AppliedLayoutsFileName(), root);
AppliedLayouts::instance().LoadData();
}
// use zone rects instead of the actual window rect
// otherwise we'll need to wait after snapping, for the window to be resized
// important when snapping/extending by position
RECT GetZoneRect(const WorkArea* workArea, ZoneIndex index)
{
auto rect = workArea->GetLayout()->Zones().at(index).GetZoneRect();
auto workAreaRect = workArea->GetWorkAreaRect();
return rect;
}
TEST_METHOD_INITIALIZE(Init)
{
AppZoneHistory::instance().LoadData();
PrepareGridLayout();
auto workArea = WorkArea::Create(m_hInst, m_workAreaId, {}, FancyZonesUtils::Rect{ RECT(0, 0, 1920, 1080) });
m_workAreaMap.insert({ m_monitor, std::move(workArea) });
}
TEST_METHOD_CLEANUP(CleanUp)
{
std::filesystem::remove(AppliedLayouts::AppliedLayoutsFileName());
std::filesystem::remove(AppZoneHistory::AppZoneHistoryFileName());
}
TEST_METHOD(Snap_ByIndex)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
Assert::IsTrue(windowKeyboardSnap.Snap(window, m_monitor, VK_LEFT, m_workAreaMap, { m_monitor }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 3 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 3 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
TEST_METHOD(Move_ByIndex)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitor)->Snap(window, { 1 }, true);
Assert::IsTrue(windowKeyboardSnap.Snap(window, m_monitor, VK_RIGHT, m_workAreaMap, { m_monitor }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 2 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 2 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
TEST_METHOD (Move_ByIndex_Cycle)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitor)->Snap(window, { 3 }, true);
auto settings = FancyZonesSettings::settings();
settings.moveWindowAcrossMonitors = true;
FancyZonesSettings::instance().SetSettings(settings);
Assert::IsTrue(windowKeyboardSnap.Snap(window, m_monitor, VK_RIGHT, m_workAreaMap, { m_monitor }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 0 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
TEST_METHOD (Snap_ByPosition)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
RECT windowRect;
Assert::IsTrue(GetWindowRect(window, &windowRect));
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitor, VK_LEFT, m_workAreaMap, { { m_monitor, m_rect } }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::AreEqual((size_t)1, layoutWindows.GetZoneIndexSetFromWindow(window).size());
Assert::AreEqual((size_t)1, AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()).size());
}
TEST_METHOD (Move_ByPosition)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitor)->Snap(window, { 0 }, true);
RECT windowRect = GetZoneRect(m_workAreaMap[m_monitor].get(), 0);
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitor, VK_RIGHT, m_workAreaMap, { { m_monitor, m_rect } }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 1 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 1 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
TEST_METHOD (Move_ByPosition_Cycle)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
m_workAreaMap.at(m_monitor)->Snap(window, { 0 }, true);
RECT windowRect = GetZoneRect(m_workAreaMap[m_monitor].get(), 0);
auto settings = FancyZonesSettings::settings();
settings.moveWindowAcrossMonitors = true;
FancyZonesSettings::instance().SetSettings(settings);
Assert::IsTrue(windowKeyboardSnap.Snap(window, windowRect, m_monitor, VK_UP, m_workAreaMap, { { m_monitor, m_rect } }));
const auto& layoutWindows = m_workAreaMap.at(m_monitor)->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 2 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 2 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_workAreaId, layoutId()));
}
TEST_METHOD (Extend)
{
WindowKeyboardSnap windowKeyboardSnap;
const auto window = Mocks::WindowCreate(m_hInst);
const auto& workArea = m_workAreaMap[m_monitor];
workArea->Snap(window, { 0 });
RECT windowRect = GetZoneRect(m_workAreaMap[m_monitor].get(), 0);
Assert::IsTrue(windowKeyboardSnap.Extend(window, windowRect, m_monitor, VK_DOWN, m_workAreaMap));
const auto& layoutWindows = workArea->GetLayoutWindows();
Assert::IsTrue(ZoneIndexSet{ 0, 2 } == layoutWindows.GetZoneIndexSetFromWindow(window));
Assert::IsTrue(ZoneIndexSet{ 0, 2 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, workArea->UniqueId(), workArea->GetLayoutId()));
}
};
}