From 4aadaf9bf12889f36f5ea8cd90a526cf66c678df Mon Sep 17 00:00:00 2001 From: Seraphima Zykova Date: Fri, 25 Mar 2022 19:09:59 +0300 Subject: [PATCH] [FancyZones] Fix canvas layout with scaling reset issue (#17186) * canvas scaling * predef layout check * return false on custom layout error * clean up * update unit tests * spelling * floating point convert * fix build --- .github/actions/spell-check/expect.txt | 1 + src/common/Display/dpi_aware.cpp | 14 +- src/common/Display/dpi_aware.h | 6 +- .../FancyZonesLib/FancyZonesLib.vcxproj | 2 + .../FancyZonesLib.vcxproj.filters | 6 + .../FancyZonesLib/LayoutConfigurator.cpp | 433 ++++++++++++++++++ .../FancyZonesLib/LayoutConfigurator.h | 23 + .../fancyzones/FancyZonesLib/WindowUtils.cpp | 20 +- .../fancyzones/FancyZonesLib/ZoneSet.cpp | 430 +---------------- .../fancyzones/FancyZonesLib/ZoneSet.h | 11 +- .../fancyzones/FancyZonesLib/ZonesOverlay.cpp | 2 +- .../fancyzones/FancyZonesLib/ZonesOverlay.h | 2 +- .../UnitTests/WorkArea.Spec.cpp | 13 +- .../UnitTests/ZoneSet.Spec.cpp | 371 +++++---------- .../EditKeyboardWindow.cpp | 20 +- .../EditShortcutsWindow.cpp | 20 +- 16 files changed, 651 insertions(+), 723 deletions(-) create mode 100644 src/modules/fancyzones/FancyZonesLib/LayoutConfigurator.cpp create mode 100644 src/modules/fancyzones/FancyZonesLib/LayoutConfigurator.h diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index 20e1e5dcad..81c52fcf13 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -294,6 +294,7 @@ comsupp Concat concrt configs +Configurator CONFLICTINGMODIFIERKEY CONFLICTINGMODIFIERSHORTCUT CONOUT diff --git a/src/common/Display/dpi_aware.cpp b/src/common/Display/dpi_aware.cpp index 169583316d..2ed0228ae3 100644 --- a/src/common/Display/dpi_aware.cpp +++ b/src/common/Display/dpi_aware.cpp @@ -44,7 +44,7 @@ namespace DPIAware return GetScreenDPIForMonitor(targetMonitor, dpi); } - void Convert(HMONITOR monitor_handle, int& width, int& height) + void Convert(HMONITOR monitor_handle, float& width, float& height) { if (monitor_handle == NULL) { @@ -55,12 +55,12 @@ namespace DPIAware UINT dpi_x, dpi_y; if (GetDpiForMonitor(monitor_handle, MDT_EFFECTIVE_DPI, &dpi_x, &dpi_y) == S_OK) { - width = width * static_cast(dpi_x) / DEFAULT_DPI; - height = height * static_cast(dpi_y) / DEFAULT_DPI; + width = width * dpi_x / DEFAULT_DPI; + height = height * dpi_y / DEFAULT_DPI; } } - void ConvertByCursorPosition(int& width, int& height) + void ConvertByCursorPosition(float& width, float& height) { HMONITOR targetMonitor = nullptr; POINT currentCursorPos{ 0 }; @@ -73,7 +73,7 @@ namespace DPIAware Convert(targetMonitor, width, height); } - void InverseConvert(HMONITOR monitor_handle, int& width, int& height) + void InverseConvert(HMONITOR monitor_handle, float& width, float& height) { if (monitor_handle == NULL) { @@ -84,8 +84,8 @@ namespace DPIAware UINT dpi_x, dpi_y; if (GetDpiForMonitor(monitor_handle, MDT_EFFECTIVE_DPI, &dpi_x, &dpi_y) == S_OK) { - width = width * DEFAULT_DPI / static_cast(dpi_x); - height = height * DEFAULT_DPI / static_cast(dpi_y); + width = width * DEFAULT_DPI / dpi_x; + height = height * DEFAULT_DPI / dpi_y; } } diff --git a/src/common/Display/dpi_aware.h b/src/common/Display/dpi_aware.h index 4853621fef..f93e8f87ad 100644 --- a/src/common/Display/dpi_aware.h +++ b/src/common/Display/dpi_aware.h @@ -11,9 +11,9 @@ namespace DPIAware HRESULT GetScreenDPIForWindow(HWND hwnd, UINT& dpi); HRESULT GetScreenDPIForPoint(POINT p, UINT& dpi); HRESULT GetScreenDPIForCursor(UINT& dpi); - void Convert(HMONITOR monitor_handle, int& width, int& height); - void ConvertByCursorPosition(int& width, int& height); - void InverseConvert(HMONITOR monitor_handle, int& width, int& height); + void Convert(HMONITOR monitor_handle, float& width, float& height); + void ConvertByCursorPosition(float& width, float& height); + void InverseConvert(HMONITOR monitor_handle, float& width, float& height); void EnableDPIAwarenessForThisProcess(); enum AwarenessLevel diff --git a/src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj b/src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj index e59f5e7529..903bd5538f 100644 --- a/src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj +++ b/src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj @@ -58,6 +58,7 @@ + @@ -109,6 +110,7 @@ ../pch.h ../pch.h + diff --git a/src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj.filters b/src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj.filters index 218536344a..f20dfc7e33 100644 --- a/src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj.filters +++ b/src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj.filters @@ -126,6 +126,9 @@ Header Files + + Header Files + @@ -209,6 +212,9 @@ Source Files + + Source Files + diff --git a/src/modules/fancyzones/FancyZonesLib/LayoutConfigurator.cpp b/src/modules/fancyzones/FancyZonesLib/LayoutConfigurator.cpp new file mode 100644 index 0000000000..ce5472e9d0 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesLib/LayoutConfigurator.cpp @@ -0,0 +1,433 @@ +#include "pch.h" +#include "LayoutConfigurator.h" + +#include +#include + +#include + +namespace +{ + constexpr int C_MULTIPLIER = 10000; + + // PriorityGrid layout is unique for zoneCount <= 11. For zoneCount > 11 PriorityGrid is same as Grid + FancyZonesDataTypes::GridLayoutInfo predefinedPriorityGridLayouts[11] = { + /* 1 */ + FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ + .rows = 1, + .columns = 1, + .rowsPercents = { 10000 }, + .columnsPercents = { 10000 }, + .cellChildMap = { { 0 } } }), + /* 2 */ + FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ + .rows = 1, + .columns = 2, + .rowsPercents = { 10000 }, + .columnsPercents = { 6667, 3333 }, + .cellChildMap = { { 0, 1 } } }), + /* 3 */ + FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ + .rows = 1, + .columns = 3, + .rowsPercents = { 10000 }, + .columnsPercents = { 2500, 5000, 2500 }, + .cellChildMap = { { 0, 1, 2 } } }), + /* 4 */ + FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ + .rows = 2, + .columns = 3, + .rowsPercents = { 5000, 5000 }, + .columnsPercents = { 2500, 5000, 2500 }, + .cellChildMap = { { 0, 1, 2 }, { 0, 1, 3 } } }), + /* 5 */ + FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ + .rows = 2, + .columns = 3, + .rowsPercents = { 5000, 5000 }, + .columnsPercents = { 2500, 5000, 2500 }, + .cellChildMap = { { 0, 1, 2 }, { 3, 1, 4 } } }), + /* 6 */ + FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ + .rows = 3, + .columns = 3, + .rowsPercents = { 3333, 3334, 3333 }, + .columnsPercents = { 2500, 5000, 2500 }, + .cellChildMap = { { 0, 1, 2 }, { 0, 1, 3 }, { 4, 1, 5 } } }), + /* 7 */ + FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ + .rows = 3, + .columns = 3, + .rowsPercents = { 3333, 3334, 3333 }, + .columnsPercents = { 2500, 5000, 2500 }, + .cellChildMap = { { 0, 1, 2 }, { 3, 1, 4 }, { 5, 1, 6 } } }), + /* 8 */ + FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ + .rows = 3, + .columns = 4, + .rowsPercents = { 3333, 3334, 3333 }, + .columnsPercents = { 2500, 2500, 2500, 2500 }, + .cellChildMap = { { 0, 1, 2, 3 }, { 4, 1, 2, 5 }, { 6, 1, 2, 7 } } }), + /* 9 */ + FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ + .rows = 3, + .columns = 4, + .rowsPercents = { 3333, 3334, 3333 }, + .columnsPercents = { 2500, 2500, 2500, 2500 }, + .cellChildMap = { { 0, 1, 2, 3 }, { 4, 1, 2, 5 }, { 6, 1, 7, 8 } } }), + /* 10 */ + FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ + .rows = 3, + .columns = 4, + .rowsPercents = { 3333, 3334, 3333 }, + .columnsPercents = { 2500, 2500, 2500, 2500 }, + .cellChildMap = { { 0, 1, 2, 3 }, { 4, 1, 5, 6 }, { 7, 1, 8, 9 } } }), + /* 11 */ + FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ + .rows = 3, + .columns = 4, + .rowsPercents = { 3333, 3334, 3333 }, + .columnsPercents = { 2500, 2500, 2500, 2500 }, + .cellChildMap = { { 0, 1, 2, 3 }, { 4, 1, 5, 6 }, { 7, 8, 9, 10 } } }), + }; +} + +bool AddZone(winrt::com_ptr zone, ZonesMap& zones) noexcept +{ + auto zoneId = zone->Id(); + if (zones.contains(zoneId)) + { + return false; + } + + zones[zoneId] = zone; + return true; +} + +ZonesMap CalculateGridZones(FancyZonesUtils::Rect workArea, FancyZonesDataTypes::GridLayoutInfo gridLayoutInfo, int spacing) +{ + ZonesMap zones; + + long totalWidth = workArea.width(); + long totalHeight = workArea.height(); + struct Info + { + long Extent; + long Start; + long End; + }; + std::vector rowInfo(gridLayoutInfo.rows()); + std::vector columnInfo(gridLayoutInfo.columns()); + + // Note: The expressions below are carefully written to + // make the sum of all zones' sizes exactly total{Width|Height} + int totalPercents = 0; + for (int row = 0; row < gridLayoutInfo.rows(); row++) + { + rowInfo[row].Start = totalPercents * totalHeight / C_MULTIPLIER; + totalPercents += gridLayoutInfo.rowsPercents()[row]; + rowInfo[row].End = totalPercents * totalHeight / C_MULTIPLIER; + rowInfo[row].Extent = rowInfo[row].End - rowInfo[row].Start; + } + + totalPercents = 0; + for (int col = 0; col < gridLayoutInfo.columns(); col++) + { + columnInfo[col].Start = totalPercents * totalWidth / C_MULTIPLIER; + totalPercents += gridLayoutInfo.columnsPercents()[col]; + columnInfo[col].End = totalPercents * totalWidth / C_MULTIPLIER; + columnInfo[col].Extent = columnInfo[col].End - columnInfo[col].Start; + } + + for (int row = 0; row < gridLayoutInfo.rows(); row++) + { + for (int col = 0; col < gridLayoutInfo.columns(); col++) + { + int i = gridLayoutInfo.cellChildMap()[row][col]; + if (((row == 0) || (gridLayoutInfo.cellChildMap()[row - 1][col] != i)) && + ((col == 0) || (gridLayoutInfo.cellChildMap()[row][col - 1] != i))) + { + long left = columnInfo[col].Start; + long top = rowInfo[row].Start; + + int maxRow = row; + while (((maxRow + 1) < gridLayoutInfo.rows()) && (gridLayoutInfo.cellChildMap()[maxRow + 1][col] == i)) + { + maxRow++; + } + int maxCol = col; + while (((maxCol + 1) < gridLayoutInfo.columns()) && (gridLayoutInfo.cellChildMap()[row][maxCol + 1] == i)) + { + maxCol++; + } + + long right = columnInfo[maxCol].End; + long bottom = rowInfo[maxRow].End; + + top += row == 0 ? spacing : spacing / 2; + bottom -= maxRow == gridLayoutInfo.rows() - 1 ? spacing : spacing / 2; + left += col == 0 ? spacing : spacing / 2; + right -= maxCol == gridLayoutInfo.columns() - 1 ? spacing : spacing / 2; + + auto zone = MakeZone(RECT{ left, top, right, bottom }, i); + if (zone) + { + if (!AddZone(zone, zones)) + { + Logger::error(L"Failed to create grid layout. Invalid zone id"); + return {}; + } + } + else + { + // All zones within zone set should be valid in order to use its functionality. + Logger::error(L"Failed to create grid layout. Invalid zone"); + return {}; + } + } + } + } + + return zones; +} + +ZonesMap LayoutConfigurator::Focus(FancyZonesUtils::Rect workArea, int zoneCount) noexcept +{ + ZonesMap zones; + + long left{ 100 }; + long top{ 100 }; + long right{ left + long(workArea.width() * 0.4) }; + long bottom{ top + long(workArea.height() * 0.4) }; + + RECT focusZoneRect{ left, top, right, bottom }; + + long focusRectXIncrement = (zoneCount <= 1) ? 0 : 50; + long focusRectYIncrement = (zoneCount <= 1) ? 0 : 50; + + for (int i = 0; i < zoneCount; i++) + { + auto zone = MakeZone(focusZoneRect, zones.size()); + if (zone) + { + if (!AddZone(zone, zones)) + { + Logger::error(L"Failed to create Focus layout. Invalid zone id"); + return {}; + } + } + else + { + // All zones within zone set should be valid in order to use its functionality. + Logger::error(L"Failed to create Focus layout. Invalid zone"); + return {}; + } + + focusZoneRect.left += focusRectXIncrement; + focusZoneRect.right += focusRectXIncrement; + focusZoneRect.bottom += focusRectYIncrement; + focusZoneRect.top += focusRectYIncrement; + } + + return zones; +} + +ZonesMap LayoutConfigurator::Rows(FancyZonesUtils::Rect workArea, int zoneCount, int spacing) noexcept +{ + ZonesMap zones; + + long totalWidth = workArea.width() - (spacing * 2); + long totalHeight = workArea.height() - (spacing * (zoneCount + 1)); + + long top = spacing; + long left = spacing; + long bottom; + long right; + + // Note: The expressions below are NOT equal to total{Width|Height} / zoneCount and are done + // like this to make the sum of all zones' sizes exactly total{Width|Height}. + for (int zoneIndex = 0; zoneIndex < zoneCount; ++zoneIndex) + { + right = totalWidth + spacing; + bottom = top + (zoneIndex + 1) * totalHeight / zoneCount - zoneIndex * totalHeight / zoneCount; + + auto zone = MakeZone(RECT{ left, top, right, bottom }, zones.size()); + if (zone) + { + if (!AddZone(zone, zones)) + { + Logger::error(L"Failed to create Rows layout. Invalid zone id"); + return {}; + } + } + else + { + // All zones within zone set should be valid in order to use its functionality. + Logger::error(L"Failed to create Rows layout. Invalid zone"); + return {}; + } + + top = bottom + spacing; + } + + return zones; +} + +ZonesMap LayoutConfigurator::Columns(FancyZonesUtils::Rect workArea, int zoneCount, int spacing) noexcept +{ + ZonesMap zones; + + long totalWidth = workArea.width() - (spacing * (zoneCount + 1)); + long totalHeight = workArea.height() - (spacing * 2); + + long top = spacing; + long left = spacing; + long bottom; + long right; + + // Note: The expressions below are NOT equal to total{Width|Height} / zoneCount and are done + // like this to make the sum of all zones' sizes exactly total{Width|Height}. + for (int zoneIndex = 0; zoneIndex < zoneCount; ++zoneIndex) + { + right = left + (zoneIndex + 1) * totalWidth / zoneCount - zoneIndex * totalWidth / zoneCount; + bottom = totalHeight + spacing; + + auto zone = MakeZone(RECT{ left, top, right, bottom }, zones.size()); + if (zone) + { + if (!AddZone(zone, zones)) + { + Logger::error(L"Failed to create Columns layout. Invalid zone id"); + return {}; + } + } + else + { + // All zones within zone set should be valid in order to use its functionality. + Logger::error(L"Failed to create Columns layout. Invalid zone"); + return {}; + } + + left = right + spacing; + } + + return zones; +} + +ZonesMap LayoutConfigurator::Grid(FancyZonesUtils::Rect workArea, int zoneCount, int spacing) noexcept +{ + int rows = 1, columns = 1; + while (zoneCount / rows >= rows) + { + rows++; + } + rows--; + columns = zoneCount / rows; + if (zoneCount % rows == 0) + { + // even grid + } + else + { + columns++; + } + + FancyZonesDataTypes::GridLayoutInfo gridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Minimal{ .rows = rows, .columns = columns }); + + // Note: The expressions below are NOT equal to C_MULTIPLIER / {rows|columns} and are done + // like this to make the sum of all percents exactly C_MULTIPLIER + for (int row = 0; row < rows; row++) + { + gridLayoutInfo.rowsPercents()[row] = C_MULTIPLIER * (row + 1) / rows - C_MULTIPLIER * row / rows; + } + for (int col = 0; col < columns; col++) + { + gridLayoutInfo.columnsPercents()[col] = C_MULTIPLIER * (col + 1) / columns - C_MULTIPLIER * col / columns; + } + + for (int i = 0; i < rows; ++i) + { + gridLayoutInfo.cellChildMap()[i] = std::vector(columns); + } + + int index = 0; + for (int row = 0; row < rows; row++) + { + for (int col = 0; col < columns; col++) + { + gridLayoutInfo.cellChildMap()[row][col] = index++; + if (index == zoneCount) + { + index--; + } + } + } + + return CalculateGridZones(workArea, gridLayoutInfo, spacing); +} + +ZonesMap LayoutConfigurator::PriorityGrid(FancyZonesUtils::Rect workArea, int zoneCount, int spacing) noexcept +{ + if (zoneCount <= 0) + { + return {}; + } + + constexpr int predefinedLayoutsCount = sizeof(predefinedPriorityGridLayouts) / sizeof(FancyZonesDataTypes::GridLayoutInfo); + if (zoneCount < predefinedLayoutsCount) + { + return CalculateGridZones(workArea, predefinedPriorityGridLayouts[zoneCount - 1], spacing); + } + + return Grid(workArea, zoneCount, spacing); +} + +ZonesMap LayoutConfigurator::Custom(FancyZonesUtils::Rect workArea, HMONITOR monitor, const FancyZonesDataTypes::CustomLayoutData& zoneSet, int spacing) noexcept +{ + if (zoneSet.type == FancyZonesDataTypes::CustomLayoutType::Canvas && std::holds_alternative(zoneSet.info)) + { + ZonesMap zones; + const auto& zoneSetInfo = std::get(zoneSet.info); + + float width = static_cast(workArea.width()); + float height = static_cast(workArea.height()); + + DPIAware::InverseConvert(monitor, width, height); + + for (const auto& zone : zoneSetInfo.zones) + { + float x = static_cast(zone.x) * width / zoneSetInfo.lastWorkAreaWidth; + float y = static_cast(zone.y) * height / zoneSetInfo.lastWorkAreaHeight; + float zoneWidth = static_cast(zone.width) * width / zoneSetInfo.lastWorkAreaWidth; + float zoneHeight = static_cast(zone.height) * height / zoneSetInfo.lastWorkAreaHeight; + + DPIAware::Convert(monitor, x, y); + DPIAware::Convert(monitor, zoneWidth, zoneHeight); + + auto zone = MakeZone(RECT{ static_cast(x), static_cast(y), static_cast(x + zoneWidth), static_cast(y + zoneHeight) }, zones.size()); + if (zone) + { + if (!AddZone(zone, zones)) + { + Logger::error(L"Failed to create Custom layout. Invalid zone id"); + return {}; + } + } + else + { + // All zones within zone set should be valid in order to use its functionality. + Logger::error(L"Failed to create Custom layout. Invalid zone"); + return {}; + } + } + + return zones; + } + else if (zoneSet.type == FancyZonesDataTypes::CustomLayoutType::Grid && std::holds_alternative(zoneSet.info)) + { + const auto& info = std::get(zoneSet.info); + return CalculateGridZones(workArea, info, spacing); + } + + return {}; +} diff --git a/src/modules/fancyzones/FancyZonesLib/LayoutConfigurator.h b/src/modules/fancyzones/FancyZonesLib/LayoutConfigurator.h new file mode 100644 index 0000000000..9abc0243e3 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesLib/LayoutConfigurator.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +// Mapping zone id to zone +using ZonesMap = std::map>; + +namespace FancyZonesDataTypes +{ + struct CustomLayoutData; +} + +class LayoutConfigurator +{ +public: + static ZonesMap Focus(FancyZonesUtils::Rect workArea, int zoneCount) noexcept; + static ZonesMap Rows(FancyZonesUtils::Rect workArea, int zoneCount, int spacing) noexcept; + static ZonesMap Columns(FancyZonesUtils::Rect workArea, int zoneCount, int spacing) noexcept; + static ZonesMap Grid(FancyZonesUtils::Rect workArea, int zoneCount, int spacing) noexcept; + static ZonesMap PriorityGrid(FancyZonesUtils::Rect workArea, int zoneCount, int spacing) noexcept; + static ZonesMap Custom(FancyZonesUtils::Rect workArea, HMONITOR monitor, const FancyZonesDataTypes::CustomLayoutData& data, int spacing) noexcept; +}; diff --git a/src/modules/fancyzones/FancyZonesLib/WindowUtils.cpp b/src/modules/fancyzones/FancyZonesLib/WindowUtils.cpp index 3671017930..b15c2998ca 100644 --- a/src/modules/fancyzones/FancyZonesLib/WindowUtils.cpp +++ b/src/modules/fancyzones/FancyZonesLib/WindowUtils.cpp @@ -373,16 +373,16 @@ void FancyZonesWindowUtils::SaveWindowSizeAndOrigin(HWND window) noexcept RECT rect; if (GetWindowRect(window, &rect)) { - int width = rect.right - rect.left; - int height = rect.bottom - rect.top; - int originX = rect.left; - int originY = rect.top; + float width = static_cast(rect.right - rect.left); + float height = static_cast(rect.bottom - rect.top); + float originX = static_cast(rect.left); + float originY = static_cast(rect.top); DPIAware::InverseConvert(MonitorFromWindow(window, MONITOR_DEFAULTTONULL), width, height); DPIAware::InverseConvert(MonitorFromWindow(window, MONITOR_DEFAULTTONULL), originX, originY); - std::array windowSizeData = { width, height }; - std::array windowOriginData = { originX, originY }; + std::array windowSizeData = { static_cast(width), static_cast(height) }; + std::array windowOriginData = { static_cast(originX), static_cast(originY) }; HANDLE rawData; memcpy(&rawData, windowSizeData.data(), sizeof rawData); SetPropW(window, ZonedWindowProperties::PropertyRestoreSizeID, rawData); @@ -399,8 +399,10 @@ void FancyZonesWindowUtils::RestoreWindowSize(HWND window) noexcept std::array windowSize; memcpy(windowSize.data(), &windowSizeData, sizeof windowSize); + float windowWidth = static_cast(windowSize[0]), windowHeight = static_cast(windowSize[1]); + // {width, height} - DPIAware::Convert(MonitorFromWindow(window, MONITOR_DEFAULTTONULL), windowSize[0], windowSize[1]); + DPIAware::Convert(MonitorFromWindow(window, MONITOR_DEFAULTTONULL), windowWidth, windowHeight); RECT rect; if (GetWindowRect(window, &rect)) @@ -428,8 +430,10 @@ void FancyZonesWindowUtils::RestoreWindowOrigin(HWND window) noexcept std::array windowOrigin; memcpy(windowOrigin.data(), &windowOriginData, sizeof windowOrigin); + float windowWidth = static_cast(windowOrigin[0]), windowHeight = static_cast(windowOrigin[1]); + // {width, height} - DPIAware::Convert(MonitorFromWindow(window, MONITOR_DEFAULTTONULL), windowOrigin[0], windowOrigin[1]); + DPIAware::Convert(MonitorFromWindow(window, MONITOR_DEFAULTTONULL), windowWidth, windowHeight); RECT rect; if (GetWindowRect(window, &rect)) diff --git a/src/modules/fancyzones/FancyZonesLib/ZoneSet.cpp b/src/modules/fancyzones/FancyZonesLib/ZoneSet.cpp index 41f65325ab..2fa56bce21 100644 --- a/src/modules/fancyzones/FancyZonesLib/ZoneSet.cpp +++ b/src/modules/fancyzones/FancyZonesLib/ZoneSet.cpp @@ -3,108 +3,17 @@ #include "ZoneSet.h" #include -#include "FancyZonesDataTypes.h" -#include "FancyZonesWindowProperties.h" -#include "Settings.h" -#include "Zone.h" -#include +#include #include #include -#include #include -#include -#include -#include - using namespace FancyZonesUtils; namespace { - constexpr int C_MULTIPLIER = 10000; constexpr int OVERLAPPING_CENTERS_SENSITIVITY = 75; - - // PriorityGrid layout is unique for zoneCount <= 11. For zoneCount > 11 PriorityGrid is same as Grid - FancyZonesDataTypes::GridLayoutInfo predefinedPriorityGridLayouts[11] = { - /* 1 */ - FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ - .rows = 1, - .columns = 1, - .rowsPercents = { 10000 }, - .columnsPercents = { 10000 }, - .cellChildMap = { { 0 } } }), - /* 2 */ - FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ - .rows = 1, - .columns = 2, - .rowsPercents = { 10000 }, - .columnsPercents = { 6667, 3333 }, - .cellChildMap = { { 0, 1 } } }), - /* 3 */ - FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ - .rows = 1, - .columns = 3, - .rowsPercents = { 10000 }, - .columnsPercents = { 2500, 5000, 2500 }, - .cellChildMap = { { 0, 1, 2 } } }), - /* 4 */ - FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ - .rows = 2, - .columns = 3, - .rowsPercents = { 5000, 5000 }, - .columnsPercents = { 2500, 5000, 2500 }, - .cellChildMap = { { 0, 1, 2 }, { 0, 1, 3 } } }), - /* 5 */ - FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ - .rows = 2, - .columns = 3, - .rowsPercents = { 5000, 5000 }, - .columnsPercents = { 2500, 5000, 2500 }, - .cellChildMap = { { 0, 1, 2 }, { 3, 1, 4 } } }), - /* 6 */ - FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ - .rows = 3, - .columns = 3, - .rowsPercents = { 3333, 3334, 3333 }, - .columnsPercents = { 2500, 5000, 2500 }, - .cellChildMap = { { 0, 1, 2 }, { 0, 1, 3 }, { 4, 1, 5 } } }), - /* 7 */ - FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ - .rows = 3, - .columns = 3, - .rowsPercents = { 3333, 3334, 3333 }, - .columnsPercents = { 2500, 5000, 2500 }, - .cellChildMap = { { 0, 1, 2 }, { 3, 1, 4 }, { 5, 1, 6 } } }), - /* 8 */ - FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ - .rows = 3, - .columns = 4, - .rowsPercents = { 3333, 3334, 3333 }, - .columnsPercents = { 2500, 2500, 2500, 2500 }, - .cellChildMap = { { 0, 1, 2, 3 }, { 4, 1, 2, 5 }, { 6, 1, 2, 7 } } }), - /* 9 */ - FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ - .rows = 3, - .columns = 4, - .rowsPercents = { 3333, 3334, 3333 }, - .columnsPercents = { 2500, 2500, 2500, 2500 }, - .cellChildMap = { { 0, 1, 2, 3 }, { 4, 1, 2, 5 }, { 6, 1, 7, 8 } } }), - /* 10 */ - FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ - .rows = 3, - .columns = 4, - .rowsPercents = { 3333, 3334, 3333 }, - .columnsPercents = { 2500, 2500, 2500, 2500 }, - .cellChildMap = { { 0, 1, 2, 3 }, { 4, 1, 5, 6 }, { 7, 1, 8, 9 } } }), - /* 11 */ - FancyZonesDataTypes::GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{ - .rows = 3, - .columns = 4, - .rowsPercents = { 3333, 3334, 3333 }, - .columnsPercents = { 2500, 2500, 2500, 2500 }, - .cellChildMap = { { 0, 1, 2, 3 }, { 4, 1, 5, 6 }, { 7, 8, 9, 10 } } }), - }; } struct ZoneSet : winrt::implements @@ -125,7 +34,6 @@ public: Id() const noexcept { return m_config.Id; } IFACEMETHODIMP_(FancyZonesDataTypes::ZoneSetLayoutType) LayoutType() const noexcept { return m_config.LayoutType; } - IFACEMETHODIMP AddZone(winrt::com_ptr zone) noexcept; IFACEMETHODIMP_(ZoneIndexSet) ZonesFromPoint(POINT pt) const noexcept; IFACEMETHODIMP_(ZoneIndexSet) GetZoneIndexSetFromWindow(HWND window) const noexcept; IFACEMETHODIMP_(ZonesMap) GetZones()const noexcept override { return m_zones; } @@ -151,12 +59,6 @@ public: IFACEMETHODIMP_(ZoneIndexSet) GetCombinedZoneRange(const ZoneIndexSet& initialZones, const ZoneIndexSet& finalZones) const noexcept; private: - bool CalculateFocusLayout(Rect workArea, int zoneCount) noexcept; - bool CalculateColumnsAndRowsLayout(Rect workArea, FancyZonesDataTypes::ZoneSetLayoutType type, int zoneCount, int spacing) noexcept; - bool CalculateGridLayout(Rect workArea, FancyZonesDataTypes::ZoneSetLayoutType type, int zoneCount, int spacing) noexcept; - bool CalculateUniquePriorityGridLayout(Rect workArea, int zoneCount, int spacing) noexcept; - bool CalculateCustomLayout(Rect workArea, int spacing) noexcept; - bool CalculateGridZones(Rect workArea, FancyZonesDataTypes::GridLayoutInfo gridLayoutInfo, int spacing); HWND GetNextTab(ZoneIndexSet indexSet, HWND current, bool reverse) noexcept; void InsertTabIntoZone(HWND window, std::optional tabSortKeyWithinZone, const ZoneIndexSet& indexSet); ZoneIndexSet ZoneSelectSubregion(const ZoneIndexSet& capturedZones, POINT pt) const; @@ -178,18 +80,6 @@ private: ZoneSetConfig m_config; }; -IFACEMETHODIMP ZoneSet::AddZone(winrt::com_ptr zone) noexcept -{ - auto zoneId = zone->Id(); - if (m_zones.contains(zoneId)) - { - return S_FALSE; - } - m_zones[zoneId] = zone; - - return S_OK; -} - IFACEMETHODIMP_(ZoneIndexSet) ZoneSet::ZonesFromPoint(POINT pt) const noexcept { @@ -691,26 +581,40 @@ ZoneSet::CalculateZones(RECT workAreaRect, int zoneCount, int spacing) noexcept return false; } - bool success = true; switch (m_config.LayoutType) { case FancyZonesDataTypes::ZoneSetLayoutType::Focus: - success = CalculateFocusLayout(workArea, zoneCount); + m_zones = LayoutConfigurator::Focus(workArea, zoneCount); break; case FancyZonesDataTypes::ZoneSetLayoutType::Columns: + m_zones = LayoutConfigurator::Columns(workArea, zoneCount, spacing); + break; case FancyZonesDataTypes::ZoneSetLayoutType::Rows: - success = CalculateColumnsAndRowsLayout(workArea, m_config.LayoutType, zoneCount, spacing); + m_zones = LayoutConfigurator::Rows(workArea, zoneCount, spacing); break; case FancyZonesDataTypes::ZoneSetLayoutType::Grid: + m_zones = LayoutConfigurator::Grid(workArea, zoneCount, spacing); + break; case FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid: - success = CalculateGridLayout(workArea, m_config.LayoutType, zoneCount, spacing); + m_zones = LayoutConfigurator::PriorityGrid(workArea, zoneCount, spacing); break; case FancyZonesDataTypes::ZoneSetLayoutType::Custom: - success = CalculateCustomLayout(workArea, spacing); - break; + { + const auto zoneSetSearchResult = CustomLayouts::instance().GetCustomLayoutData(m_config.Id); + if (zoneSetSearchResult.has_value()) + { + m_zones = LayoutConfigurator::Custom(workArea, m_config.Monitor, zoneSetSearchResult.value(), spacing); + } + else + { + Logger::error(L"Custom layout not found"); + return false; + } + } + break; } - return success; + return m_zones.size() == zoneCount; } bool ZoneSet::IsZoneEmpty(ZoneIndex zoneIndex) const noexcept @@ -726,296 +630,6 @@ bool ZoneSet::IsZoneEmpty(ZoneIndex zoneIndex) const noexcept return true; } -bool ZoneSet::CalculateFocusLayout(Rect workArea, int zoneCount) noexcept -{ - long left{ 100 }; - long top{ 100 }; - long right{ left + long(workArea.width() * 0.4) }; - long bottom{ top + long(workArea.height() * 0.4) }; - - RECT focusZoneRect{ left, top, right, bottom }; - - long focusRectXIncrement = (zoneCount <= 1) ? 0 : 50; - long focusRectYIncrement = (zoneCount <= 1) ? 0 : 50; - - for (int i = 0; i < zoneCount; i++) - { - auto zone = MakeZone(focusZoneRect, m_zones.size()); - if (zone) - { - AddZone(zone); - } - else - { - // All zones within zone set should be valid in order to use its functionality. - m_zones.clear(); - return false; - } - focusZoneRect.left += focusRectXIncrement; - focusZoneRect.right += focusRectXIncrement; - focusZoneRect.bottom += focusRectYIncrement; - focusZoneRect.top += focusRectYIncrement; - } - - return true; -} - -bool ZoneSet::CalculateColumnsAndRowsLayout(Rect workArea, FancyZonesDataTypes::ZoneSetLayoutType type, int zoneCount, int spacing) noexcept -{ - long totalWidth; - long totalHeight; - - if (type == FancyZonesDataTypes::ZoneSetLayoutType::Columns) - { - totalWidth = workArea.width() - (spacing * (zoneCount + 1)); - totalHeight = workArea.height() - (spacing * 2); - } - else - { //Rows - totalWidth = workArea.width() - (spacing * 2); - totalHeight = workArea.height() - (spacing * (zoneCount + 1)); - } - - long top = spacing; - long left = spacing; - long bottom; - long right; - - // Note: The expressions below are NOT equal to total{Width|Height} / zoneCount and are done - // like this to make the sum of all zones' sizes exactly total{Width|Height}. - for (int zoneIndex = 0; zoneIndex < zoneCount; ++zoneIndex) - { - if (type == FancyZonesDataTypes::ZoneSetLayoutType::Columns) - { - right = left + (zoneIndex + 1) * totalWidth / zoneCount - zoneIndex * totalWidth / zoneCount; - bottom = totalHeight + spacing; - } - else - { //Rows - right = totalWidth + spacing; - bottom = top + (zoneIndex + 1) * totalHeight / zoneCount - zoneIndex * totalHeight / zoneCount; - } - - - auto zone = MakeZone(RECT{ left, top, right, bottom }, m_zones.size()); - if (zone) - { - AddZone(zone); - } - else - { - // All zones within zone set should be valid in order to use its functionality. - m_zones.clear(); - return false; - } - - if (type == FancyZonesDataTypes::ZoneSetLayoutType::Columns) - { - left = right + spacing; - } - else - { //Rows - top = bottom + spacing; - } - } - - return true; -} - -bool ZoneSet::CalculateGridLayout(Rect workArea, FancyZonesDataTypes::ZoneSetLayoutType type, int zoneCount, int spacing) noexcept -{ - const auto count = sizeof(predefinedPriorityGridLayouts) / sizeof(FancyZonesDataTypes::GridLayoutInfo); - if (type == FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid && zoneCount < count) - { - return CalculateUniquePriorityGridLayout(workArea, zoneCount, spacing); - } - - int rows = 1, columns = 1; - while (zoneCount / rows >= rows) - { - rows++; - } - rows--; - columns = zoneCount / rows; - if (zoneCount % rows == 0) - { - // even grid - } - else - { - columns++; - } - - FancyZonesDataTypes::GridLayoutInfo gridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Minimal{ .rows = rows, .columns = columns }); - - // Note: The expressions below are NOT equal to C_MULTIPLIER / {rows|columns} and are done - // like this to make the sum of all percents exactly C_MULTIPLIER - for (int row = 0; row < rows; row++) - { - gridLayoutInfo.rowsPercents()[row] = C_MULTIPLIER * (row + 1) / rows - C_MULTIPLIER * row / rows; - } - for (int col = 0; col < columns; col++) - { - gridLayoutInfo.columnsPercents()[col] = C_MULTIPLIER * (col + 1) / columns - C_MULTIPLIER * col / columns; - } - - for (int i = 0; i < rows; ++i) - { - gridLayoutInfo.cellChildMap()[i] = std::vector(columns); - } - - int index = 0; - for (int row = 0; row < rows; row++) - { - for (int col = 0; col < columns; col++) - { - gridLayoutInfo.cellChildMap()[row][col] = index++; - if (index == zoneCount) - { - index--; - } - } - } - return CalculateGridZones(workArea, gridLayoutInfo, spacing); -} - -bool ZoneSet::CalculateUniquePriorityGridLayout(Rect workArea, int zoneCount, int spacing) noexcept -{ - if (zoneCount <= 0 || zoneCount >= sizeof(predefinedPriorityGridLayouts)) - { - return false; - } - - return CalculateGridZones(workArea, predefinedPriorityGridLayouts[zoneCount - 1], spacing); -} - -bool ZoneSet::CalculateCustomLayout(Rect workArea, int spacing) noexcept -{ - const auto zoneSetSearchResult = CustomLayouts::instance().GetCustomLayoutData(m_config.Id); - if (!zoneSetSearchResult.has_value()) - { - return false; - } - - const auto& zoneSet = *zoneSetSearchResult; - if (zoneSet.type == FancyZonesDataTypes::CustomLayoutType::Canvas && std::holds_alternative(zoneSet.info)) - { - const auto& zoneSetInfo = std::get(zoneSet.info); - for (const auto& zone : zoneSetInfo.zones) - { - int x = zone.x; - int y = zone.y; - int width = zone.width; - int height = zone.height; - - DPIAware::Convert(m_config.Monitor, x, y); - DPIAware::Convert(m_config.Monitor, width, height); - - auto zone = MakeZone(RECT{ x, y, x + width, y + height }, m_zones.size()); - if (zone) - { - AddZone(zone); - } - else - { - // All zones within zone set should be valid in order to use its functionality. - m_zones.clear(); - return false; - } - } - - return true; - } - else if (zoneSet.type == FancyZonesDataTypes::CustomLayoutType::Grid && std::holds_alternative(zoneSet.info)) - { - const auto& info = std::get(zoneSet.info); - return CalculateGridZones(workArea, info, spacing); - } - - return false; -} - -bool ZoneSet::CalculateGridZones(Rect workArea, FancyZonesDataTypes::GridLayoutInfo gridLayoutInfo, int spacing) -{ - long totalWidth = workArea.width(); - long totalHeight = workArea.height(); - struct Info - { - long Extent; - long Start; - long End; - }; - std::vector rowInfo(gridLayoutInfo.rows()); - std::vector columnInfo(gridLayoutInfo.columns()); - - // Note: The expressions below are carefully written to - // make the sum of all zones' sizes exactly total{Width|Height} - int totalPercents = 0; - for (int row = 0; row < gridLayoutInfo.rows(); row++) - { - rowInfo[row].Start = totalPercents * totalHeight / C_MULTIPLIER; - totalPercents += gridLayoutInfo.rowsPercents()[row]; - rowInfo[row].End = totalPercents * totalHeight / C_MULTIPLIER; - rowInfo[row].Extent = rowInfo[row].End - rowInfo[row].Start; - } - - totalPercents = 0; - for (int col = 0; col < gridLayoutInfo.columns(); col++) - { - columnInfo[col].Start = totalPercents * totalWidth / C_MULTIPLIER; - totalPercents += gridLayoutInfo.columnsPercents()[col]; - columnInfo[col].End = totalPercents * totalWidth / C_MULTIPLIER; - columnInfo[col].Extent = columnInfo[col].End - columnInfo[col].Start; - } - - for (int row = 0; row < gridLayoutInfo.rows(); row++) - { - for (int col = 0; col < gridLayoutInfo.columns(); col++) - { - int i = gridLayoutInfo.cellChildMap()[row][col]; - if (((row == 0) || (gridLayoutInfo.cellChildMap()[row - 1][col] != i)) && - ((col == 0) || (gridLayoutInfo.cellChildMap()[row][col - 1] != i))) - { - long left = columnInfo[col].Start; - long top = rowInfo[row].Start; - - int maxRow = row; - while (((maxRow + 1) < gridLayoutInfo.rows()) && (gridLayoutInfo.cellChildMap()[maxRow + 1][col] == i)) - { - maxRow++; - } - int maxCol = col; - while (((maxCol + 1) < gridLayoutInfo.columns()) && (gridLayoutInfo.cellChildMap()[row][maxCol + 1] == i)) - { - maxCol++; - } - - long right = columnInfo[maxCol].End; - long bottom = rowInfo[maxRow].End; - - top += row == 0 ? spacing : spacing / 2; - bottom -= maxRow == gridLayoutInfo.rows() - 1 ? spacing : spacing / 2; - left += col == 0 ? spacing : spacing / 2; - right -= maxCol == gridLayoutInfo.columns() - 1 ? spacing : spacing / 2; - - auto zone = MakeZone(RECT{ left, top, right, bottom }, i); - if (zone) - { - AddZone(zone); - } - else - { - // All zones within zone set should be valid in order to use its functionality. - m_zones.clear(); - return false; - } - } - } - } - - return true; -} - ZoneIndexSet ZoneSet::GetCombinedZoneRange(const ZoneIndexSet& initialZones, const ZoneIndexSet& finalZones) const noexcept { ZoneIndexSet combinedZones, result; diff --git a/src/modules/fancyzones/FancyZonesLib/ZoneSet.h b/src/modules/fancyzones/FancyZonesLib/ZoneSet.h index de1bbfc635..794b3f78f6 100644 --- a/src/modules/fancyzones/FancyZonesLib/ZoneSet.h +++ b/src/modules/fancyzones/FancyZonesLib/ZoneSet.h @@ -1,6 +1,6 @@ #pragma once -#include "Zone.h" +#include #include "Settings.h" namespace FancyZonesDataTypes @@ -13,9 +13,6 @@ namespace FancyZonesDataTypes */ interface __declspec(uuid("{E4839EB7-669D-49CF-84A9-71A2DFD851A3}")) IZoneSet : public IUnknown { - // Mapping zone id to zone - using ZonesMap = std::map>; - /** * @returns Unique identifier of zone layout. */ @@ -24,12 +21,6 @@ interface __declspec(uuid("{E4839EB7-669D-49CF-84A9-71A2DFD851A3}")) IZoneSet : * @returns Type of the zone layout. Layout type can be focus, columns, rows, grid, priority grid or custom. */ IFACEMETHOD_(FancyZonesDataTypes::ZoneSetLayoutType, LayoutType)() const = 0; - /** - * Add zone to the zone layout. - * - * @param zone Zone object (defining coordinates of the zone). - */ - IFACEMETHOD(AddZone)(winrt::com_ptr zone) = 0; /** * Get zones from cursor coordinates. * diff --git a/src/modules/fancyzones/FancyZonesLib/ZonesOverlay.cpp b/src/modules/fancyzones/FancyZonesLib/ZonesOverlay.cpp index 8f11c553ab..812a1e4c44 100644 --- a/src/modules/fancyzones/FancyZonesLib/ZonesOverlay.cpp +++ b/src/modules/fancyzones/FancyZonesLib/ZonesOverlay.cpp @@ -277,7 +277,7 @@ void ZonesOverlay::Flash() m_cv.notify_all(); } -void ZonesOverlay::DrawActiveZoneSet(const IZoneSet::ZonesMap& zones, +void ZonesOverlay::DrawActiveZoneSet(const ZonesMap& zones, const ZoneIndexSet& highlightZones, const Colors::ZoneColors& colors, const bool showZoneText) diff --git a/src/modules/fancyzones/FancyZonesLib/ZonesOverlay.h b/src/modules/fancyzones/FancyZonesLib/ZonesOverlay.h index adc51ecc87..6589cdb52f 100644 --- a/src/modules/fancyzones/FancyZonesLib/ZonesOverlay.h +++ b/src/modules/fancyzones/FancyZonesLib/ZonesOverlay.h @@ -66,7 +66,7 @@ public: void Hide(); void Show(); void Flash(); - void DrawActiveZoneSet(const IZoneSet::ZonesMap& zones, + void DrawActiveZoneSet(const ZonesMap& zones, const ZoneIndexSet& highlightZones, const Colors::ZoneColors& colors, const bool showZoneText); diff --git a/src/modules/fancyzones/FancyZonesTests/UnitTests/WorkArea.Spec.cpp b/src/modules/fancyzones/FancyZonesTests/UnitTests/WorkArea.Spec.cpp index 0aecf6d23b..ba18404725 100644 --- a/src/modules/fancyzones/FancyZonesTests/UnitTests/WorkArea.Spec.cpp +++ b/src/modules/fancyzones/FancyZonesTests/UnitTests/WorkArea.Spec.cpp @@ -407,8 +407,7 @@ namespace FancyZonesUnitTests Assert::IsNotNull(workArea->ZoneSet()); auto window = Mocks::WindowCreate(m_hInst); - auto zone = MakeZone(RECT{ 0, 0, 100, 100 }, 1); - workArea->ZoneSet()->AddZone(zone); + workArea->ZoneSet()->CalculateZones(RECT{ 0, 0, 1920, 1080 }, 1, 0); workArea->SaveWindowProcessToZoneIndex(window); @@ -434,8 +433,7 @@ namespace FancyZonesUnitTests Assert::IsTrue(std::vector{ 0 } == appHistoryArray1[0].zoneIndexSet); // add zone without window - const auto zone = MakeZone(RECT{ 0, 0, 100, 100 }, 1); - workArea->ZoneSet()->AddZone(zone); + workArea->ZoneSet()->CalculateZones(RECT{ 0, 0, 1920, 1080 }, 1, 0); workArea->SaveWindowProcessToZoneIndex(window); Assert::AreEqual((size_t)1, AppZoneHistory::instance().GetFullAppZoneHistory().size()); @@ -454,8 +452,7 @@ namespace FancyZonesUnitTests const auto deviceId = workArea->UniqueId(); const auto zoneSetId = workArea->ZoneSet()->Id(); - auto zone = MakeZone(RECT{ 0, 0, 100, 100 }, 1); - workArea->ZoneSet()->AddZone(zone); + workArea->ZoneSet()->CalculateZones(RECT{ 0, 0, 1920, 1080 }, 1, 0); workArea->MoveWindowIntoZoneByIndex(window, 0); //fill app zone history map @@ -487,9 +484,7 @@ namespace FancyZonesUnitTests SetWindowPos(window, nullptr, 150, 150, originalWidth, originalHeight, SWP_SHOWWINDOW); SetWindowLong(window, GWL_STYLE, GetWindowLong(window, GWL_STYLE) & ~WS_SIZEBOX); - auto zone = MakeZone(RECT{ 50, 50, 300, 300 }, 1); - workArea->ZoneSet()->AddZone(zone); - + workArea->ZoneSet()->CalculateZones(RECT{ 0, 0, 1920, 1080 }, 1, 0); workArea->MoveWindowIntoZoneByDirectionAndIndex(window, VK_LEFT, true); RECT inZoneRect; diff --git a/src/modules/fancyzones/FancyZonesTests/UnitTests/ZoneSet.Spec.cpp b/src/modules/fancyzones/FancyZonesTests/UnitTests/ZoneSet.Spec.cpp index cf22fe65f9..6aa3cc0598 100644 --- a/src/modules/fancyzones/FancyZonesTests/UnitTests/ZoneSet.Spec.cpp +++ b/src/modules/fancyzones/FancyZonesTests/UnitTests/ZoneSet.Spec.cpp @@ -1,4 +1,5 @@ #include "pch.h" +#include #include #include "FancyZonesLib\FancyZonesDataTypes.h" #include "FancyZonesLib\ZoneIndexSetBitmask.h" @@ -19,18 +20,23 @@ namespace FancyZonesUnitTests TEST_CLASS (ZoneSetUnitTests) { GUID m_id; - const ZoneSetLayoutType m_layoutType = ZoneSetLayoutType::Custom; + const ZoneSetLayoutType m_layoutType = ZoneSetLayoutType::Grid; winrt::com_ptr m_set; TEST_METHOD_INITIALIZE(Init) - { - auto hres = CoCreateGuid(&m_id); - Assert::AreEqual(S_OK, hres); + { + auto hres = CoCreateGuid(&m_id); + Assert::AreEqual(S_OK, hres); - ZoneSetConfig m_config = ZoneSetConfig(m_id, m_layoutType, Mocks::Monitor(), DefaultValues::SensitivityRadius, OverlappingZonesAlgorithm::Smallest); - m_set = MakeZoneSet(m_config); - } + ZoneSetConfig m_config = ZoneSetConfig(m_id, m_layoutType, Mocks::Monitor(), DefaultValues::SensitivityRadius, OverlappingZonesAlgorithm::Smallest); + m_set = MakeZoneSet(m_config); + } + + TEST_METHOD_CLEANUP(CleanUp) + { + std::filesystem::remove_all(CustomLayouts::CustomLayoutsFileName()); + } void compareZones(const winrt::com_ptr& expected, const winrt::com_ptr& actual) { @@ -41,6 +47,40 @@ namespace FancyZonesUnitTests Assert::AreEqual(expected->GetZoneRect().bottom, actual->GetZoneRect().bottom); } + void saveCustomLayout(const std::vector& zones) + { + json::JsonObject root{}; + json::JsonArray layoutsArray{}; + + json::JsonObject canvasLayoutJson{}; + canvasLayoutJson.SetNamedValue(NonLocalizable::CustomLayoutsIds::UuidID, json::value(FancyZonesUtils::GuidToString(m_id).value())); + canvasLayoutJson.SetNamedValue(NonLocalizable::CustomLayoutsIds::NameID, json::value(L"Custom canvas layout")); + canvasLayoutJson.SetNamedValue(NonLocalizable::CustomLayoutsIds::TypeID, json::value(NonLocalizable::CustomLayoutsIds::CanvasID)); + + json::JsonObject info{}; + info.SetNamedValue(NonLocalizable::CustomLayoutsIds::RefWidthID, json::value(1920)); + info.SetNamedValue(NonLocalizable::CustomLayoutsIds::RefHeightID, json::value(1080)); + + json::JsonArray zonesArray{}; + for (const auto& zoneRect : zones) + { + json::JsonObject zone{}; + zone.SetNamedValue(NonLocalizable::CustomLayoutsIds::XID, json::value(zoneRect.left)); + zone.SetNamedValue(NonLocalizable::CustomLayoutsIds::YID, json::value(zoneRect.top)); + zone.SetNamedValue(NonLocalizable::CustomLayoutsIds::WidthID, json::value(zoneRect.right - zoneRect.left)); + zone.SetNamedValue(NonLocalizable::CustomLayoutsIds::HeightID, json::value(zoneRect.bottom - zoneRect.top)); + zonesArray.Append(zone); + } + + info.SetNamedValue(NonLocalizable::CustomLayoutsIds::ZonesID, zonesArray); + canvasLayoutJson.SetNamedValue(NonLocalizable::CustomLayoutsIds::InfoID, info); + layoutsArray.Append(canvasLayoutJson); + root.SetNamedValue(NonLocalizable::CustomLayoutsIds::CustomLayoutsArrayID, layoutsArray); + json::to_file(CustomLayouts::CustomLayoutsFileName(), root); + + CustomLayouts::instance().LoadData(); + } + public: TEST_METHOD (TestCreateZoneSet) { @@ -84,52 +124,6 @@ namespace FancyZonesUnitTests Assert::AreEqual((size_t)0, zones.size()); } - TEST_METHOD (AddOne) - { - constexpr ZoneIndex zoneId = 0; - winrt::com_ptr zone = MakeZone({ 0, 0, 100, 100 }, zoneId); - Assert::IsNotNull(zone.get()); - m_set->AddZone(zone); - auto zones = m_set->GetZones(); - Assert::AreEqual((size_t)1, zones.size()); - compareZones(zone, zones[zoneId]); - Assert::AreEqual(zoneId, zones[zoneId]->Id()); - } - - TEST_METHOD (AddManyEqual) - { - for (size_t i = 0; i < 1024; i++) - { - ZoneIndex zoneId = i; - winrt::com_ptr zone = MakeZone({ 0, 0, 100, 100 }, zoneId); - Assert::IsNotNull(zone.get()); - m_set->AddZone(zone); - auto zones = m_set->GetZones(); - Assert::AreEqual(i + 1, zones.size()); - compareZones(zone, zones[zoneId]); - Assert::AreEqual(zoneId, zones[zoneId]->Id()); - } - } - - TEST_METHOD (AddManyDifferent) - { - for (size_t i = 0; i < 1024; i++) - { - ZoneIndex zoneId = i; - int left = rand() % 10; - int top = rand() % 10; - int right = left + 1 + rand() % 100; - int bottom = top + 1 + rand() % 100; - winrt::com_ptr zone = MakeZone({ left, top, right, bottom }, zoneId); - Assert::IsNotNull(zone.get()); - m_set->AddZone(zone); - auto zones = m_set->GetZones(); - Assert::AreEqual(i + 1, zones.size()); - compareZones(zone, zones[zoneId]); - Assert::AreEqual(zoneId, zones[zoneId]->Id()); - } - } - TEST_METHOD (MakeZoneFromZeroRect) { winrt::com_ptr zone = MakeZone({ 0, 0, 0, 0 }, 1); @@ -163,143 +157,71 @@ namespace FancyZonesUnitTests TEST_METHOD (ZoneFromPointInner) { - const int left = 0, top = 0, right = 100, bottom = 100; - winrt::com_ptr expected = MakeZone({ left, top, right, bottom }, 1); - m_set->AddZone(expected); - - for (int i = left + 1; i < right; i++) - { - for (int j = top + 1; j < bottom; j++) - { - auto actual = m_set->ZonesFromPoint(POINT{ i, j }); - Assert::IsTrue(actual.size() == 1); - compareZones(expected, m_set->GetZones()[actual[0]]); - } - } + m_set->CalculateZones(RECT{ 0, 0, 1920, 1080 }, 1, 0); + + auto actual = m_set->ZonesFromPoint(POINT{ 1, 1 }); + Assert::IsTrue(actual.size() == 1); } TEST_METHOD (ZoneFromPointBorder) { - const int left = 0, top = 0, right = 100, bottom = 100; - winrt::com_ptr expected = MakeZone({ left, top, right, bottom }, 1); - m_set->AddZone(expected); + m_set->CalculateZones(RECT{ 0, 0, 1920, 1080 }, 1, 0); - for (int i = left; i < right; i++) - { - auto actual = m_set->ZonesFromPoint(POINT{ i, top }); - Assert::IsTrue(actual.size() == 1); - compareZones(expected, m_set->GetZones()[actual[0]]); - } - - for (int i = top; i < bottom; i++) - { - auto actual = m_set->ZonesFromPoint(POINT{ left, i }); - Assert::IsTrue(actual.size() == 1); - compareZones(expected, m_set->GetZones()[actual[0]]); - } - - //bottom and right borders considered to be outside - for (int i = left; i < right; i++) - { - auto actual = m_set->ZonesFromPoint(POINT{ i, bottom }); - Assert::IsTrue(actual.size() == 0); - } - - for (int i = top; i < bottom; i++) - { - auto actual = m_set->ZonesFromPoint(POINT{ right, i }); - Assert::IsTrue(actual.size() == 0); - } + Assert::IsTrue(m_set->ZonesFromPoint(POINT{ 0, 0 }).size() == 1); + Assert::IsTrue(m_set->ZonesFromPoint(POINT{ 1920, 1080 }).size() == 0); } TEST_METHOD (ZoneFromPointOuter) { - const int left = 0, top = 0, right = 100, bottom = 100; - winrt::com_ptr zone = MakeZone({ left, top, right, bottom }, 1); - m_set->AddZone(zone); + m_set->CalculateZones(RECT{ 0, 0, 1920, 1080 }, 1, 0); - auto actual = m_set->ZonesFromPoint(POINT{ 200, 200 }); + auto actual = m_set->ZonesFromPoint(POINT{ 1921, 1080 }); Assert::IsTrue(actual.size() == 0); } TEST_METHOD (ZoneFromPointOverlapping) { - winrt::com_ptr zone1 = MakeZone({ 0, 0, 100, 100 }, 1); - m_set->AddZone(zone1); - winrt::com_ptr zone2 = MakeZone({ 10, 10, 90, 90 }, 2); - m_set->AddZone(zone2); - winrt::com_ptr zone3 = MakeZone({ 10, 10, 150, 150 }, 3); - m_set->AddZone(zone3); - winrt::com_ptr zone4 = MakeZone({ 10, 10, 50, 50 }, 4); - m_set->AddZone(zone4); + // prepare layout with overlapping zones + saveCustomLayout({ RECT{ 0, 0, 100, 100 }, RECT{ 10, 10, 90, 90 }, RECT{ 10, 10, 150, 150 }, RECT{ 10, 10, 50, 50 } }); + + ZoneSetConfig config = ZoneSetConfig(m_id, FancyZonesDataTypes::ZoneSetLayoutType::Custom, Mocks::Monitor(), DefaultValues::SensitivityRadius, OverlappingZonesAlgorithm::Smallest); + auto set = MakeZoneSet(config); + set->CalculateZones(RECT{0,0,1920,1080}, 4, 0); // zone4 is expected because it's the smallest one, and it's considered to be inside // since Multizones support + auto zones = set->ZonesFromPoint(POINT{ 50, 50 }); + Assert::IsTrue(zones.size() == 1); - auto actual = m_set->ZonesFromPoint(POINT{ 50, 50 }); - Assert::IsTrue(actual.size() == 1); - compareZones(zone4, m_set->GetZones()[actual[0]]); + auto expected = MakeZone({ 10, 10, 50, 50 }, 3); + auto actual = set->GetZones()[zones[0]]; + compareZones(expected, actual); } - TEST_METHOD (ZoneFromPointMultizoneHorizontal) + TEST_METHOD (ZoneFromPointMultizone) { - winrt::com_ptr zone1 = MakeZone({ 0, 0, 100, 100 }, 1); - m_set->AddZone(zone1); - winrt::com_ptr zone2 = MakeZone({ 100, 0, 200, 100 }, 2); - m_set->AddZone(zone2); - winrt::com_ptr zone3 = MakeZone({ 0, 100, 100, 200 }, 3); - m_set->AddZone(zone3); - winrt::com_ptr zone4 = MakeZone({ 100, 100, 200, 200 }, 4); - m_set->AddZone(zone4); + // prepare layout with overlapping zones + saveCustomLayout({ RECT{ 0, 0, 100, 100 }, RECT{ 100, 0, 200, 100 }, RECT{ 0, 100, 100, 200 }, RECT{ 100, 100, 200, 200 } }); - auto actual = m_set->ZonesFromPoint(POINT{ 50, 100 }); + ZoneSetConfig config = ZoneSetConfig(m_id, FancyZonesDataTypes::ZoneSetLayoutType::Custom, Mocks::Monitor(), DefaultValues::SensitivityRadius, OverlappingZonesAlgorithm::Smallest); + auto set = MakeZoneSet(config); + set->CalculateZones(RECT{ 0, 0, 1920, 1080 }, 4, 0); + + auto actual = set->ZonesFromPoint(POINT{ 50, 100 }); Assert::IsTrue(actual.size() == 2); - compareZones(zone1, m_set->GetZones()[actual[0]]); - compareZones(zone3, m_set->GetZones()[actual[1]]); - } - TEST_METHOD (ZoneFromPointMultizoneVertical) - { - winrt::com_ptr zone1 = MakeZone({ 0, 0, 100, 100 }, 1); - m_set->AddZone(zone1); - winrt::com_ptr zone2 = MakeZone({ 100, 0, 200, 100 }, 2); - m_set->AddZone(zone2); - winrt::com_ptr zone3 = MakeZone({ 0, 100, 100, 200 }, 3); - m_set->AddZone(zone3); - winrt::com_ptr zone4 = MakeZone({ 100, 100, 200, 200 }, 4); - m_set->AddZone(zone4); + auto zone1 = MakeZone({ 0, 0, 100, 100 }, 0); + compareZones(zone1, set->GetZones()[actual[0]]); - auto actual = m_set->ZonesFromPoint(POINT{ 100, 50 }); - Assert::IsTrue(actual.size() == 2); - compareZones(zone1, m_set->GetZones()[actual[0]]); - compareZones(zone2, m_set->GetZones()[actual[1]]); - } - - TEST_METHOD (ZoneFromPointMultizoneQuad) - { - winrt::com_ptr zone1 = MakeZone({ 0, 0, 100, 100 }, 1); - m_set->AddZone(zone1); - winrt::com_ptr zone2 = MakeZone({ 100, 0, 200, 100 }, 2); - m_set->AddZone(zone2); - winrt::com_ptr zone3 = MakeZone({ 0, 100, 100, 200 }, 3); - m_set->AddZone(zone3); - winrt::com_ptr zone4 = MakeZone({ 100, 100, 200, 200 }, 4); - m_set->AddZone(zone4); - - auto actual = m_set->ZonesFromPoint(POINT{ 100, 100 }); - Assert::IsTrue(actual.size() == 4); - compareZones(zone1, m_set->GetZones()[actual[0]]); - compareZones(zone2, m_set->GetZones()[actual[1]]); - compareZones(zone3, m_set->GetZones()[actual[2]]); - compareZones(zone4, m_set->GetZones()[actual[3]]); + auto zone3 = MakeZone({ 0, 100, 100, 200 }, 2); + compareZones(zone3, set->GetZones()[actual[1]]); } TEST_METHOD (ZoneIndexFromWindowUnknown) { - winrt::com_ptr zone = MakeZone({ 0, 0, 100, 100 }, 1); HWND window = Mocks::Window(); HWND workArea = Mocks::Window(); - m_set->AddZone(zone); + m_set->CalculateZones(RECT{0,0,1920, 1080}, 1, 0); m_set->MoveWindowIntoZoneByIndexSet(window, workArea, { 0 }); auto actual = m_set->GetZoneIndexSetFromWindow(Mocks::Window()); @@ -308,10 +230,9 @@ namespace FancyZonesUnitTests TEST_METHOD (ZoneIndexFromWindowNull) { - winrt::com_ptr zone = MakeZone({ 0, 0, 100, 100 }, 1); HWND window = Mocks::Window(); HWND workArea = Mocks::Window(); - m_set->AddZone(zone); + m_set->CalculateZones(RECT{ 0, 0, 1920, 1080 }, 1, 0); m_set->MoveWindowIntoZoneByIndexSet(window, workArea, { 0 }); auto actual = m_set->GetZoneIndexSetFromWindow(nullptr); @@ -320,16 +241,16 @@ namespace FancyZonesUnitTests TEST_METHOD (MoveWindowIntoZoneByIndex) { - winrt::com_ptr zone1 = MakeZone({ 0, 0, 100, 100 }, 1); - winrt::com_ptr zone2 = MakeZone({ 0, 0, 100, 100 }, 2); - winrt::com_ptr zone3 = MakeZone({ 0, 0, 100, 100 }, 3); - m_set->AddZone(zone1); - m_set->AddZone(zone2); - m_set->AddZone(zone3); + // prepare layout with overlapping zones + saveCustomLayout({ RECT{ 0, 0, 100, 100 }, RECT{ 0, 0, 100, 100 }, RECT{ 0, 0, 100, 100 } }); + + ZoneSetConfig config = ZoneSetConfig(m_id, FancyZonesDataTypes::ZoneSetLayoutType::Custom, Mocks::Monitor(), DefaultValues::SensitivityRadius, OverlappingZonesAlgorithm::Smallest); + auto set = MakeZoneSet(config); + set->CalculateZones(RECT{ 0, 0, 1920, 1080 }, 3, 0); HWND window = Mocks::Window(); - m_set->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 1); - Assert::IsTrue(std::vector{ 1 } == m_set->GetZoneIndexSetFromWindow(window)); + set->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 1); + Assert::IsTrue(std::vector{ 1 } == set->GetZoneIndexSetFromWindow(window)); } TEST_METHOD (MoveWindowIntoZoneByIndexWithNoZones) @@ -340,12 +261,7 @@ namespace FancyZonesUnitTests TEST_METHOD (MoveWindowIntoZoneByIndexWithInvalidIndex) { - winrt::com_ptr zone1 = MakeZone({ 0, 0, 100, 100 }, 1); - winrt::com_ptr zone2 = MakeZone({ 0, 0, 100, 100 }, 2); - winrt::com_ptr zone3 = MakeZone({ 0, 0, 100, 100 }, 3); - m_set->AddZone(zone1); - m_set->AddZone(zone2); - m_set->AddZone(zone3); + m_set->CalculateZones(RECT{ 0, 0, 1920, 1080 }, 1, 0); HWND window = Mocks::Window(); m_set->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 100); @@ -354,13 +270,7 @@ namespace FancyZonesUnitTests TEST_METHOD (MoveWindowIntoZoneByIndexSeveralTimesSameWindow) { - // Add a couple of zones. - winrt::com_ptr zone1 = MakeZone({ 0, 0, 100, 100 }, 0); - winrt::com_ptr zone2 = MakeZone({ 1, 1, 101, 101 }, 1); - winrt::com_ptr zone3 = MakeZone({ 2, 2, 102, 102 }, 2); - m_set->AddZone(zone1); - m_set->AddZone(zone2); - m_set->AddZone(zone3); + m_set->CalculateZones(RECT{ 0, 0, 1920, 1080 }, 3, 0); HWND window = Mocks::Window(); m_set->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 0); @@ -375,17 +285,13 @@ namespace FancyZonesUnitTests TEST_METHOD (MoveWindowIntoZoneByIndexSeveralTimesSameIndex) { - // Add a couple of zones. - winrt::com_ptr zone1 = MakeZone({ 0, 0, 100, 100 }, 0); - winrt::com_ptr zone2 = MakeZone({ 1, 1, 101, 101 }, 1); - winrt::com_ptr zone3 = MakeZone({ 2, 2, 102, 102 }, 2); - m_set->AddZone(zone1); - m_set->AddZone(zone2); - m_set->AddZone(zone3); + m_set->CalculateZones(RECT{ 0, 0, 1920, 1080 }, 3, 0); HWND window = Mocks::Window(); m_set->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 0); + Assert::IsTrue(std::vector{ 0 } == m_set->GetZoneIndexSetFromWindow(window)); m_set->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 0); + Assert::IsTrue(std::vector{ 0 } == m_set->GetZoneIndexSetFromWindow(window)); m_set->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 0); Assert::IsTrue(std::vector{ 0 } == m_set->GetZoneIndexSetFromWindow(window)); } @@ -397,19 +303,17 @@ namespace FancyZonesUnitTests TEST_METHOD (MoveWindowIntoZoneByPointOuterPoint) { - winrt::com_ptr zone1 = MakeZone({ 0, 0, 100, 100 }, 1); - m_set->AddZone(zone1); + m_set->CalculateZones(RECT{ 0, 0, 1920, 1080 }, 1, 0); auto window = Mocks::Window(); - m_set->MoveWindowIntoZoneByPoint(window, Mocks::Window(), POINT{ 200, 200 }); + m_set->MoveWindowIntoZoneByPoint(window, Mocks::Window(), POINT{ 1921, 1081 }); Assert::IsTrue(std::vector{} == m_set->GetZoneIndexSetFromWindow(window)); } TEST_METHOD (MoveWindowIntoZoneByPointInnerPoint) { - winrt::com_ptr zone1 = MakeZone({ 0, 0, 100, 100 }, 0); - m_set->AddZone(zone1); + m_set->CalculateZones(RECT{ 0, 0, 1920, 1080 }, 1, 0); auto window = Mocks::Window(); m_set->MoveWindowIntoZoneByPoint(window, Mocks::Window(), POINT{ 50, 50 }); @@ -419,71 +323,33 @@ namespace FancyZonesUnitTests TEST_METHOD (MoveWindowIntoZoneByPointInnerPointOverlappingZones) { - winrt::com_ptr zone1 = MakeZone({ 0, 0, 100, 100 }, 0); - winrt::com_ptr zone2 = MakeZone({ 10, 10, 90, 90 }, 1); - m_set->AddZone(zone1); - m_set->AddZone(zone2); + saveCustomLayout({ RECT{ 0, 0, 100, 100 }, RECT{ 10, 10, 90, 90 } }); + + ZoneSetConfig config = ZoneSetConfig(m_id, FancyZonesDataTypes::ZoneSetLayoutType::Custom, Mocks::Monitor(), DefaultValues::SensitivityRadius, OverlappingZonesAlgorithm::Smallest); + auto set = MakeZoneSet(config); + set->CalculateZones(RECT{ 0, 0, 1920, 1080 }, 3, 0); auto window = Mocks::Window(); - m_set->MoveWindowIntoZoneByPoint(window, Mocks::Window(), POINT{ 50, 50 }); + set->MoveWindowIntoZoneByPoint(window, Mocks::Window(), POINT{ 50, 50 }); - Assert::IsTrue(std::vector{ 1 } == m_set->GetZoneIndexSetFromWindow(window)); + Assert::IsTrue(std::vector{ 1 } == set->GetZoneIndexSetFromWindow(window)); } TEST_METHOD (MoveWindowIntoZoneByPointDropAddWindow) { + saveCustomLayout({ RECT{ 0, 0, 100, 100 }, RECT{ 10, 10, 90, 90 } }); + + ZoneSetConfig config = ZoneSetConfig(m_id, FancyZonesDataTypes::ZoneSetLayoutType::Custom, Mocks::Monitor(), DefaultValues::SensitivityRadius, OverlappingZonesAlgorithm::Smallest); + auto set = MakeZoneSet(config); + set->CalculateZones(RECT{ 0, 0, 1920, 1080 }, 3, 0); + const auto window = Mocks::Window(); const auto workArea = Mocks::Window(); - winrt::com_ptr zone1 = MakeZone({ 0, 0, 100, 100 }, 0); - winrt::com_ptr zone2 = MakeZone({ 10, 10, 90, 90 }, 1); + set->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 0); + set->MoveWindowIntoZoneByPoint(window, Mocks::Window(), POINT{ 50, 50 }); - m_set->AddZone(zone1); - m_set->AddZone(zone2); - - m_set->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 0); - - m_set->MoveWindowIntoZoneByPoint(window, Mocks::Window(), POINT{ 50, 50 }); - - Assert::IsTrue(std::vector{ 1 } == m_set->GetZoneIndexSetFromWindow(window)); - } - - TEST_METHOD (MoveWindowIntoZoneByPointDropAddWindowToSameZone) - { - const auto window = Mocks::Window(); - const auto workArea = Mocks::Window(); - - winrt::com_ptr zone1 = MakeZone({ 0, 0, 100, 100 }, 0); - winrt::com_ptr zone2 = MakeZone({ 10, 10, 90, 90 }, 1); - - m_set->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 1); - - m_set->AddZone(zone1); - m_set->AddZone(zone2); - - m_set->MoveWindowIntoZoneByPoint(window, Mocks::Window(), POINT{ 50, 50 }); - - Assert::IsTrue(std::vector{ 1 } == m_set->GetZoneIndexSetFromWindow(window)); - } - - TEST_METHOD (MoveWindowIntoZoneByPointSeveralZonesWithSameWindow) - { - const auto window = Mocks::Window(); - const auto workArea = Mocks::Window(); - - winrt::com_ptr zone1 = MakeZone({ 0, 0, 100, 100 }, 0); - winrt::com_ptr zone2 = MakeZone({ 10, 10, 90, 90 }, 1); - winrt::com_ptr zone3 = MakeZone({ 20, 20, 80, 80 }, 2); - - m_set->AddZone(zone1); - m_set->AddZone(zone2); - m_set->AddZone(zone3); - - m_set->MoveWindowIntoZoneByIndexSet(window, Mocks::Window(), { 0, 1, 2 }); - - m_set->MoveWindowIntoZoneByPoint(window, Mocks::Window(), POINT{ 50, 50 }); - - Assert::IsTrue(std::vector{ 2 } == m_set->GetZoneIndexSetFromWindow(window)); + Assert::IsTrue(std::vector{ 1 } == set->GetZoneIndexSetFromWindow(window)); } }; @@ -497,16 +363,9 @@ namespace FancyZonesUnitTests TEST_METHOD_INITIALIZE(Initialize) { - ZoneSetConfig config({}, ZoneSetLayoutType::Custom, Mocks::Monitor(), DefaultValues::SensitivityRadius); + ZoneSetConfig config({}, ZoneSetLayoutType::Grid, Mocks::Monitor(), DefaultValues::SensitivityRadius); m_set = MakeZoneSet(config); - - // Add a couple of zones. - m_zone1 = MakeZone({ 0, 0, 100, 100 }, 0); - m_zone2 = MakeZone({ 0, 0, 100, 100 }, 1); - m_zone3 = MakeZone({ 0, 0, 100, 100 }, 2); - m_set->AddZone(m_zone1); - m_set->AddZone(m_zone2); - m_set->AddZone(m_zone3); + m_set->CalculateZones(RECT{ 0, 0, 1920, 1080 }, 3, 10); } TEST_METHOD (EmptyZonesLeft) diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditKeyboardWindow.cpp b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditKeyboardWindow.cpp index 069e0ac89b..d2fa577f4c 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditKeyboardWindow.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditKeyboardWindow.cpp @@ -144,8 +144,8 @@ inline void CreateEditKeyboardWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMan RECT desktopRect = UIHelpers::GetForegroundWindowDesktopRect(); // Calculate DPI dependent window size - int windowWidth = EditorConstants::DefaultEditKeyboardWindowWidth; - int windowHeight = EditorConstants::DefaultEditKeyboardWindowHeight; + float windowWidth = EditorConstants::DefaultEditKeyboardWindowWidth; + float windowHeight = EditorConstants::DefaultEditKeyboardWindowHeight; DPIAware::ConvertByCursorPosition(windowWidth, windowHeight); DPIAware::GetScreenDPIForCursor(g_currentDPI); @@ -155,10 +155,10 @@ inline void CreateEditKeyboardWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMan szWindowClass, GET_RESOURCE_STRING(IDS_EDITKEYBOARD_WINDOWNAME).c_str(), WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MAXIMIZEBOX, - ((desktopRect.right + desktopRect.left) / 2) - (windowWidth / 2), - ((desktopRect.bottom + desktopRect.top) / 2) - (windowHeight / 2), - windowWidth, - windowHeight, + ((desktopRect.right + desktopRect.left) / 2) - ((int)windowWidth / 2), + ((desktopRect.bottom + desktopRect.top) / 2) - ((int)windowHeight / 2), + static_cast(windowWidth), + static_cast(windowHeight), NULL, NULL, hInst, @@ -415,11 +415,11 @@ LRESULT CALLBACK EditKeyboardWindowProc(HWND hWnd, UINT messageCode, WPARAM wPar case WM_GETMINMAXINFO: { LPMINMAXINFO mmi = (LPMINMAXINFO)lParam; - int minWidth = EditorConstants::MinimumEditKeyboardWindowWidth; - int minHeight = EditorConstants::MinimumEditKeyboardWindowHeight; + float minWidth = EditorConstants::MinimumEditKeyboardWindowWidth; + float minHeight = EditorConstants::MinimumEditKeyboardWindowHeight; DPIAware::Convert(MonitorFromWindow(hWnd, MONITOR_DEFAULTTONULL), minWidth, minHeight); - mmi->ptMinTrackSize.x = minWidth; - mmi->ptMinTrackSize.y = minHeight; + mmi->ptMinTrackSize.x = static_cast(minWidth); + mmi->ptMinTrackSize.y = static_cast(minHeight); } break; case WM_GETDPISCALEDSIZE: diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditShortcutsWindow.cpp b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditShortcutsWindow.cpp index 716b398177..dd7d19171a 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditShortcutsWindow.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditShortcutsWindow.cpp @@ -96,8 +96,8 @@ inline void CreateEditShortcutsWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMa RECT desktopRect = UIHelpers::GetForegroundWindowDesktopRect(); // Calculate DPI dependent window size - int windowWidth = EditorConstants::DefaultEditShortcutsWindowWidth; - int windowHeight = EditorConstants::DefaultEditShortcutsWindowHeight; + float windowWidth = EditorConstants::DefaultEditShortcutsWindowWidth; + float windowHeight = EditorConstants::DefaultEditShortcutsWindowHeight; DPIAware::ConvertByCursorPosition(windowWidth, windowHeight); DPIAware::GetScreenDPIForCursor(g_currentDPI); @@ -106,10 +106,10 @@ inline void CreateEditShortcutsWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMa szWindowClass, GET_RESOURCE_STRING(IDS_EDITSHORTCUTS_WINDOWNAME).c_str(), WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MAXIMIZEBOX, - ((desktopRect.right + desktopRect.left) / 2) - (windowWidth / 2), - ((desktopRect.bottom + desktopRect.top) / 2) - (windowHeight / 2), - windowWidth, - windowHeight, + ((desktopRect.right + desktopRect.left) / 2) - ((int)windowWidth / 2), + ((desktopRect.bottom + desktopRect.top) / 2) - ((int)windowHeight / 2), + static_cast(windowWidth), + static_cast(windowHeight), NULL, NULL, hInst, @@ -387,11 +387,11 @@ LRESULT CALLBACK EditShortcutsWindowProc(HWND hWnd, UINT messageCode, WPARAM wPa case WM_GETMINMAXINFO: { LPMINMAXINFO mmi = (LPMINMAXINFO)lParam; - int minWidth = EditorConstants::MinimumEditShortcutsWindowWidth; - int minHeight = EditorConstants::MinimumEditShortcutsWindowHeight; + float minWidth = EditorConstants::MinimumEditShortcutsWindowWidth; + float minHeight = EditorConstants::MinimumEditShortcutsWindowHeight; DPIAware::Convert(MonitorFromWindow(hWnd, MONITOR_DEFAULTTONULL), minWidth, minHeight); - mmi->ptMinTrackSize.x = minWidth; - mmi->ptMinTrackSize.y = minHeight; + mmi->ptMinTrackSize.x = static_cast(minWidth); + mmi->ptMinTrackSize.y = static_cast(minHeight); } break; case WM_GETDPISCALEDSIZE: