[FancyZones] Align zone numbers between Editor and FancyZonesLib (#7387)

* Align zone numbers between Editor and FancyZonesLib
Use zoneId on win+arrow

* Update tests

* Fix crash

* ZoneId starts from 0

* Define ZonesMap type

IFACEMETHOD_ macro is having trouble processing
std::map template when expanding, so return type needs
to be predefined

* Address PR comment

* Address more PR comments

* Handle .at
This commit is contained in:
stefansjfw
2020-10-26 09:07:11 +01:00
committed by GitHub
parent 8ef91a528f
commit e6a5b589ff
9 changed files with 150 additions and 134 deletions

View File

@@ -404,15 +404,15 @@ namespace FancyZonesEditor
_gridModel.ColumnPercents.Add(((_multiplier * (col + 1)) / cols) - ((_multiplier * col) / cols)); _gridModel.ColumnPercents.Add(((_multiplier * (col + 1)) / cols) - ((_multiplier * col) / cols));
} }
int index = ZoneCount - 1; int index = 0;
for (int col = cols - 1; col >= 0; col--) for (int row = 0; row < rows; row++)
{ {
for (int row = rows - 1; row >= 0; row--) for (int col = 0; col < cols; col++)
{ {
_gridModel.CellChildMap[row, col] = index--; _gridModel.CellChildMap[row, col] = index++;
if (index < 0) if (index == ZoneCount)
{ {
index = 0; index--;
} }
} }
} }

View File

@@ -1183,10 +1183,9 @@ bool FancyZones::OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept
auto zoneSet = workArea->ActiveZoneSet(); auto zoneSet = workArea->ActiveZoneSet();
if (zoneSet) if (zoneSet)
{ {
auto zones = zoneSet->GetZones(); const auto zones = zoneSet->GetZones();
for (size_t i = 0; i < zones.size(); i++) for (const auto& [zoneId, zone] : zones)
{ {
const auto& zone = zones[i];
RECT zoneRect = zone->GetZoneRect(); RECT zoneRect = zone->GetZoneRect();
zoneRect.left += monitorRect.left; zoneRect.left += monitorRect.left;
@@ -1195,7 +1194,7 @@ bool FancyZones::OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept
zoneRect.bottom += monitorRect.top; zoneRect.bottom += monitorRect.top;
zoneRects.emplace_back(zoneRect); zoneRects.emplace_back(zoneRect);
zoneRectsInfo.emplace_back(i, workArea); zoneRectsInfo.emplace_back(zoneId, workArea);
} }
} }
} }
@@ -1228,10 +1227,9 @@ bool FancyZones::OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept
auto zoneSet = workArea->ActiveZoneSet(); auto zoneSet = workArea->ActiveZoneSet();
if (zoneSet) if (zoneSet)
{ {
auto zones = zoneSet->GetZones(); const auto zones = zoneSet->GetZones();
for (size_t i = 0; i < zones.size(); i++) for (const auto& [zoneId, zone] : zones)
{ {
const auto& zone = zones[i];
RECT zoneRect = zone->GetZoneRect(); RECT zoneRect = zone->GetZoneRect();
zoneRect.left += currentMonitorRect.left; zoneRect.left += currentMonitorRect.left;
@@ -1240,7 +1238,7 @@ bool FancyZones::OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept
zoneRect.bottom += currentMonitorRect.top; zoneRect.bottom += currentMonitorRect.top;
zoneRects.emplace_back(zoneRect); zoneRects.emplace_back(zoneRect);
zoneRectsInfo.emplace_back(i, workArea); zoneRectsInfo.emplace_back(zoneId, workArea);
} }
} }
} }

View File

@@ -135,7 +135,7 @@ RECT Zone::ComputeActualZoneRect(HWND window, HWND zoneWindow) const noexcept
winrt::com_ptr<IZone> MakeZone(const RECT& zoneRect, const size_t zoneId) noexcept winrt::com_ptr<IZone> MakeZone(const RECT& zoneRect, const size_t zoneId) noexcept
{ {
if (ValidateZoneRect(zoneRect) && zoneId > 0) if (ValidateZoneRect(zoneRect) && zoneId >= 0)
{ {
return winrt::make_self<Zone>(zoneRect, zoneId); return winrt::make_self<Zone>(zoneRect, zoneId);
} }

View File

@@ -10,6 +10,8 @@
#include <common/dpi_aware.h> #include <common/dpi_aware.h>
#include <limits>
#include <map>
#include <utility> #include <utility>
using namespace FancyZonesUtils; using namespace FancyZonesUtils;
@@ -113,7 +115,7 @@ public:
{ {
} }
ZoneSet(ZoneSetConfig const& config, std::vector<winrt::com_ptr<IZone>> zones) : ZoneSet(ZoneSetConfig const& config, ZonesMap zones) :
m_config(config), m_config(config),
m_zones(zones) m_zones(zones)
{ {
@@ -128,8 +130,8 @@ public:
ZonesFromPoint(POINT pt) const noexcept; ZonesFromPoint(POINT pt) const noexcept;
IFACEMETHODIMP_(std::vector<size_t>) IFACEMETHODIMP_(std::vector<size_t>)
GetZoneIndexSetFromWindow(HWND window) const noexcept; GetZoneIndexSetFromWindow(HWND window) const noexcept;
IFACEMETHODIMP_(std::vector<winrt::com_ptr<IZone>>) IFACEMETHODIMP_(ZonesMap)
GetZones() const noexcept { return m_zones; } GetZones()const noexcept override { return m_zones; }
IFACEMETHODIMP_(void) IFACEMETHODIMP_(void)
MoveWindowIntoZoneByIndex(HWND window, HWND workAreaWindow, size_t index) noexcept; MoveWindowIntoZoneByIndex(HWND window, HWND workAreaWindow, size_t index) noexcept;
IFACEMETHODIMP_(void) IFACEMETHODIMP_(void)
@@ -157,7 +159,7 @@ private:
bool CalculateCustomLayout(Rect workArea, int spacing) noexcept; bool CalculateCustomLayout(Rect workArea, int spacing) noexcept;
bool CalculateGridZones(Rect workArea, FancyZonesDataTypes::GridLayoutInfo gridLayoutInfo, int spacing); bool CalculateGridZones(Rect workArea, FancyZonesDataTypes::GridLayoutInfo gridLayoutInfo, int spacing);
std::vector<winrt::com_ptr<IZone>> m_zones; ZonesMap m_zones;
std::map<HWND, std::vector<size_t>> m_windowIndexSet; std::map<HWND, std::vector<size_t>> m_windowIndexSet;
// Needed for ExtendWindowByDirectionAndPosition // Needed for ExtendWindowByDirectionAndPosition
@@ -170,7 +172,12 @@ private:
IFACEMETHODIMP ZoneSet::AddZone(winrt::com_ptr<IZone> zone) noexcept IFACEMETHODIMP ZoneSet::AddZone(winrt::com_ptr<IZone> zone) noexcept
{ {
m_zones.emplace_back(zone); auto zoneId = zone->Id();
if (m_zones.contains(zoneId))
{
return S_FALSE;
}
m_zones[zoneId] = zone;
return S_OK; return S_OK;
} }
@@ -180,19 +187,19 @@ ZoneSet::ZonesFromPoint(POINT pt) const noexcept
{ {
std::vector<size_t> capturedZones; std::vector<size_t> capturedZones;
std::vector<size_t> strictlyCapturedZones; std::vector<size_t> strictlyCapturedZones;
for (size_t i = 0; i < m_zones.size(); i++) for (const auto& [zoneId, zone] : m_zones)
{ {
const RECT& zoneRect = m_zones[i]->GetZoneRect(); const RECT& zoneRect = zone->GetZoneRect();
if (zoneRect.left - m_config.SensitivityRadius <= pt.x && pt.x <= zoneRect.right + m_config.SensitivityRadius && if (zoneRect.left - m_config.SensitivityRadius <= pt.x && pt.x <= zoneRect.right + m_config.SensitivityRadius &&
zoneRect.top - m_config.SensitivityRadius <= pt.y && pt.y <= zoneRect.bottom + m_config.SensitivityRadius) zoneRect.top - m_config.SensitivityRadius <= pt.y && pt.y <= zoneRect.bottom + m_config.SensitivityRadius)
{ {
capturedZones.emplace_back(i); capturedZones.emplace_back(zoneId);
} }
if (zoneRect.left <= pt.x && pt.x < zoneRect.right && if (zoneRect.left <= pt.x && pt.x < zoneRect.right &&
zoneRect.top <= pt.y && pt.y < zoneRect.bottom) zoneRect.top <= pt.y && pt.y < zoneRect.bottom)
{ {
strictlyCapturedZones.emplace_back(i); strictlyCapturedZones.emplace_back(zoneId);
} }
} }
@@ -210,8 +217,18 @@ ZoneSet::ZonesFromPoint(POINT pt) const noexcept
{ {
for (size_t j = i + 1; j < capturedZones.size(); ++j) for (size_t j = i + 1; j < capturedZones.size(); ++j)
{ {
const auto& rectI = m_zones[capturedZones[i]]->GetZoneRect(); RECT rectI;
const auto& rectJ = m_zones[capturedZones[j]]->GetZoneRect(); RECT rectJ;
try
{
rectI = m_zones.at(capturedZones[i])->GetZoneRect();
rectJ = m_zones.at(capturedZones[j])->GetZoneRect();
}
catch (std::out_of_range)
{
return {};
}
if (max(rectI.top, rectJ.top) + m_config.SensitivityRadius < min(rectI.bottom, rectJ.bottom) && if (max(rectI.top, rectJ.top) + m_config.SensitivityRadius < min(rectI.bottom, rectJ.bottom) &&
max(rectI.left, rectJ.left) + m_config.SensitivityRadius < min(rectI.right, rectJ.right)) max(rectI.left, rectJ.left) + m_config.SensitivityRadius < min(rectI.right, rectJ.right))
{ {
@@ -230,8 +247,17 @@ ZoneSet::ZonesFromPoint(POINT pt) const noexcept
size_t smallestIdx = 0; size_t smallestIdx = 0;
for (size_t i = 1; i < capturedZones.size(); ++i) for (size_t i = 1; i < capturedZones.size(); ++i)
{ {
const auto& rectS = m_zones[capturedZones[smallestIdx]]->GetZoneRect(); RECT rectS;
const auto& rectI = m_zones[capturedZones[i]]->GetZoneRect(); RECT rectI;
try
{
rectS = m_zones.at(capturedZones[smallestIdx])->GetZoneRect();
rectI = m_zones.at(capturedZones[i])->GetZoneRect();
}
catch (std::out_of_range)
{
return {};
}
int smallestSize = (rectS.bottom - rectS.top) * (rectS.right - rectS.left); int smallestSize = (rectS.bottom - rectS.top) * (rectS.right - rectS.left);
int iSize = (rectI.bottom - rectI.top) * (rectI.right - rectI.left); int iSize = (rectI.bottom - rectI.top) * (rectI.right - rectI.left);
@@ -267,7 +293,7 @@ ZoneSet::MoveWindowIntoZoneByIndex(HWND window, HWND workAreaWindow, size_t inde
} }
IFACEMETHODIMP_(void) IFACEMETHODIMP_(void)
ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const std::vector<size_t>& indexSet) noexcept ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const std::vector<size_t>& zoneIds) noexcept
{ {
if (m_zones.empty()) if (m_zones.empty())
{ {
@@ -287,11 +313,12 @@ ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const st
m_windowIndexSet[window] = {}; m_windowIndexSet[window] = {};
for (size_t index : indexSet) for (size_t id : zoneIds)
{ {
if (index < m_zones.size()) if (m_zones.contains(id))
{ {
RECT newSize = m_zones.at(index)->ComputeActualZoneRect(window, workAreaWindow); const auto& zone = m_zones.at(id);
const RECT newSize = zone->ComputeActualZoneRect(window, workAreaWindow);
if (!sizeEmpty) if (!sizeEmpty)
{ {
size.left = min(size.left, newSize.left); size.left = min(size.left, newSize.left);
@@ -305,12 +332,12 @@ ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const st
sizeEmpty = false; sizeEmpty = false;
} }
m_windowIndexSet[window].push_back(index); m_windowIndexSet[window].push_back(id);
} }
if (index < std::numeric_limits<size_t>::digits) if (id < std::numeric_limits<size_t>::digits)
{ {
bitmask |= 1ull << index; bitmask |= 1ull << id;
} }
} }
@@ -336,14 +363,14 @@ ZoneSet::MoveWindowIntoZoneByDirectionAndIndex(HWND window, HWND workAreaWindow,
// The window was not assigned to any zone here // The window was not assigned to any zone here
if (indexSet.size() == 0) if (indexSet.size() == 0)
{ {
MoveWindowIntoZoneByIndexSet(window, workAreaWindow, { vkCode == VK_LEFT ? numZones - 1 : 0 }); MoveWindowIntoZoneByIndex(window, workAreaWindow, vkCode == VK_LEFT ? numZones - 1 : 0);
return true; return true;
} }
size_t oldIndex = indexSet[0]; size_t oldId = indexSet[0];
// We reached the edge // We reached the edge
if ((vkCode == VK_LEFT && oldIndex == 0) || (vkCode == VK_RIGHT && oldIndex == numZones - 1)) if ((vkCode == VK_LEFT && oldId == 0) || (vkCode == VK_RIGHT && oldId == numZones - 1))
{ {
if (!cycle) if (!cycle)
{ {
@@ -352,7 +379,7 @@ ZoneSet::MoveWindowIntoZoneByDirectionAndIndex(HWND window, HWND workAreaWindow,
} }
else else
{ {
MoveWindowIntoZoneByIndexSet(window, workAreaWindow, { vkCode == VK_LEFT ? numZones - 1 : 0 }); MoveWindowIntoZoneByIndex(window, workAreaWindow, vkCode == VK_LEFT ? numZones - 1 : 0);
return true; return true;
} }
} }
@@ -360,11 +387,11 @@ ZoneSet::MoveWindowIntoZoneByDirectionAndIndex(HWND window, HWND workAreaWindow,
// We didn't reach the edge // We didn't reach the edge
if (vkCode == VK_LEFT) if (vkCode == VK_LEFT)
{ {
MoveWindowIntoZoneByIndexSet(window, workAreaWindow, { oldIndex - 1 }); MoveWindowIntoZoneByIndex(window, workAreaWindow, oldId - 1);
} }
else else
{ {
MoveWindowIntoZoneByIndexSet(window, workAreaWindow, { oldIndex + 1 }); MoveWindowIntoZoneByIndex(window, workAreaWindow, oldId + 1);
} }
return true; return true;
} }
@@ -378,20 +405,20 @@ ZoneSet::MoveWindowIntoZoneByDirectionAndPosition(HWND window, HWND workAreaWind
} }
std::vector<bool> usedZoneIndices(m_zones.size(), false); std::vector<bool> usedZoneIndices(m_zones.size(), false);
for (size_t idx : GetZoneIndexSetFromWindow(window)) for (size_t id : GetZoneIndexSetFromWindow(window))
{ {
usedZoneIndices[idx] = true; usedZoneIndices[id] = true;
} }
std::vector<RECT> zoneRects; std::vector<RECT> zoneRects;
std::vector<size_t> freeZoneIndices; std::vector<size_t> freeZoneIndices;
for (size_t i = 0; i < m_zones.size(); i++) for (const auto& [zoneId, zone] : m_zones)
{ {
if (!usedZoneIndices[i]) if (!usedZoneIndices[zoneId])
{ {
zoneRects.emplace_back(m_zones[i]->GetZoneRect()); zoneRects.emplace_back(m_zones[zoneId]->GetZoneRect());
freeZoneIndices.emplace_back(i); freeZoneIndices.emplace_back(zoneId);
} }
} }
@@ -415,7 +442,7 @@ ZoneSet::MoveWindowIntoZoneByDirectionAndPosition(HWND window, HWND workAreaWind
// Try again from the position off the screen in the opposite direction to vkCode // Try again from the position off the screen in the opposite direction to vkCode
// Consider all zones as available // Consider all zones as available
zoneRects.resize(m_zones.size()); zoneRects.resize(m_zones.size());
std::transform(m_zones.begin(), m_zones.end(), zoneRects.begin(), [](auto zone) { return zone->GetZoneRect(); }); std::transform(m_zones.begin(), m_zones.end(), zoneRects.begin(), [](auto zone) { return zone.second->GetZoneRect(); });
windowRect = FancyZonesUtils::PrepareRectForCycling(windowRect, windowZoneRect, vkCode); windowRect = FancyZonesUtils::PrepareRectForCycling(windowRect, windowZoneRect, vkCode);
result = FancyZonesUtils::ChooseNextZoneByPosition(vkCode, windowRect, zoneRects); result = FancyZonesUtils::ChooseNextZoneByPosition(vkCode, windowRect, zoneRects);
@@ -588,7 +615,7 @@ bool ZoneSet::CalculateFocusLayout(Rect workArea, int zoneCount) noexcept
for (int i = 0; i < zoneCount; i++) for (int i = 0; i < zoneCount; i++)
{ {
auto zone = MakeZone(focusZoneRect, m_zones.size() + 1); auto zone = MakeZone(focusZoneRect, m_zones.size());
if (zone) if (zone)
{ {
AddZone(zone); AddZone(zone);
@@ -645,7 +672,7 @@ bool ZoneSet::CalculateColumnsAndRowsLayout(Rect workArea, FancyZonesDataTypes::
} }
auto zone = MakeZone(RECT{ left, top, right, bottom }, m_zones.size() + 1); auto zone = MakeZone(RECT{ left, top, right, bottom }, m_zones.size());
if (zone) if (zone)
{ {
AddZone(zone); AddZone(zone);
@@ -713,9 +740,9 @@ bool ZoneSet::CalculateGridLayout(Rect workArea, FancyZonesDataTypes::ZoneSetLay
} }
int index = 0; int index = 0;
for (int col = columns - 1; col >= 0; col--) for (int row = 0; row < rows; row++)
{ {
for (int row = rows - 1; row >= 0; row--) for (int col = 0; col < columns; col++)
{ {
gridLayoutInfo.cellChildMap()[row][col] = index++; gridLayoutInfo.cellChildMap()[row][col] = index++;
if (index == zoneCount) if (index == zoneCount)
@@ -765,7 +792,7 @@ bool ZoneSet::CalculateCustomLayout(Rect workArea, int spacing) noexcept
DPIAware::Convert(m_config.Monitor, x, y); DPIAware::Convert(m_config.Monitor, x, y);
DPIAware::Convert(m_config.Monitor, width, height); DPIAware::Convert(m_config.Monitor, width, height);
auto zone = MakeZone(RECT{ x, y, x + width, y + height }, m_zones.size() + 1); auto zone = MakeZone(RECT{ x, y, x + width, y + height }, m_zones.size());
if (zone) if (zone)
{ {
AddZone(zone); AddZone(zone);
@@ -848,7 +875,7 @@ bool ZoneSet::CalculateGridZones(Rect workArea, FancyZonesDataTypes::GridLayoutI
long right = columnInfo[maxCol].End; long right = columnInfo[maxCol].End;
long bottom = rowInfo[maxRow].End; long bottom = rowInfo[maxRow].End;
auto zone = MakeZone(RECT{ left, top, right, bottom }, m_zones.size() + 1); auto zone = MakeZone(RECT{ left, top, right, bottom }, i);
if (zone) if (zone)
{ {
AddZone(zone); AddZone(zone);
@@ -873,30 +900,32 @@ std::vector<size_t> ZoneSet::GetCombinedZoneRange(const std::vector<size_t>& ini
RECT boundingRect; RECT boundingRect;
bool boundingRectEmpty = true; bool boundingRectEmpty = true;
auto zones = GetZones();
for (size_t zoneId : combinedZones) for (size_t zoneId : combinedZones)
{ {
const RECT& rect = zones[zoneId]->GetZoneRect(); if (m_zones.contains(zoneId))
if (boundingRectEmpty)
{ {
boundingRect = rect; const RECT rect = m_zones.at(zoneId)->GetZoneRect();
boundingRectEmpty = false; if (boundingRectEmpty)
} {
else boundingRect = rect;
{ boundingRectEmpty = false;
boundingRect.left = min(boundingRect.left, rect.left); }
boundingRect.top = min(boundingRect.top, rect.top); else
boundingRect.right = max(boundingRect.right, rect.right); {
boundingRect.bottom = max(boundingRect.bottom, rect.bottom); boundingRect.left = min(boundingRect.left, rect.left);
boundingRect.top = min(boundingRect.top, rect.top);
boundingRect.right = max(boundingRect.right, rect.right);
boundingRect.bottom = max(boundingRect.bottom, rect.bottom);
}
} }
} }
if (!boundingRectEmpty) if (!boundingRectEmpty)
{ {
for (size_t zoneId = 0; zoneId < zones.size(); zoneId++) for (const auto& [zoneId, zone] : m_zones)
{ {
RECT rect = zones[zoneId]->GetZoneRect(); const RECT rect = zone->GetZoneRect();
if (boundingRect.left <= rect.left && rect.right <= boundingRect.right && if (boundingRect.left <= rect.left && rect.right <= boundingRect.right &&
boundingRect.top <= rect.top && rect.bottom <= boundingRect.bottom) boundingRect.top <= rect.top && rect.bottom <= boundingRect.bottom)
{ {

View File

@@ -6,13 +6,15 @@ namespace FancyZonesDataTypes
{ {
enum class ZoneSetLayoutType; enum class ZoneSetLayoutType;
} }
/** /**
* Class representing single zone layout. ZoneSet is responsible for actual calculation of rectangle coordinates * Class representing single zone layout. ZoneSet is responsible for actual calculation of rectangle coordinates
* (whether is grid or canvas layout) and moving windows through them. * (whether is grid or canvas layout) and moving windows through them.
*/ */
interface __declspec(uuid("{E4839EB7-669D-49CF-84A9-71A2DFD851A3}")) IZoneSet : public IUnknown interface __declspec(uuid("{E4839EB7-669D-49CF-84A9-71A2DFD851A3}")) IZoneSet : public IUnknown
{ {
// Mapping zone id to zone
using ZonesMap = std::map<size_t, winrt::com_ptr<IZone>>;
/** /**
* @returns Unique identifier of zone layout. * @returns Unique identifier of zone layout.
*/ */
@@ -45,7 +47,7 @@ interface __declspec(uuid("{E4839EB7-669D-49CF-84A9-71A2DFD851A3}")) IZoneSet :
/** /**
* @returns Array of zone objects (defining coordinates of the zone) inside this zone layout. * @returns Array of zone objects (defining coordinates of the zone) inside this zone layout.
*/ */
IFACEMETHOD_(std::vector<winrt::com_ptr<IZone>>, GetZones)() const = 0; IFACEMETHOD_(ZonesMap, GetZones) () const = 0;
/** /**
* Assign window to the zone based on zone index inside zone layout. * Assign window to the zone based on zone index inside zone layout.
* *

View File

@@ -69,7 +69,7 @@ namespace ZoneWindowUtils
COLORREF hostZoneBorderColor, COLORREF hostZoneBorderColor,
COLORREF hostZoneHighlightColor, COLORREF hostZoneHighlightColor,
int hostZoneHighlightOpacity, int hostZoneHighlightOpacity,
std::vector<winrt::com_ptr<IZone>> zones, IZoneSet::ZonesMap zones,
std::vector<size_t> highlightZone, std::vector<size_t> highlightZone,
bool flashMode) bool flashMode)
{ {
@@ -621,7 +621,7 @@ void ZoneWindow::OnPaint(HDC hdc) noexcept
COLORREF hostZoneBorderColor{}; COLORREF hostZoneBorderColor{};
COLORREF hostZoneHighlightColor{}; COLORREF hostZoneHighlightColor{};
int hostZoneHighlightOpacity{}; int hostZoneHighlightOpacity{};
std::vector<winrt::com_ptr<IZone>> zones{}; IZoneSet::ZonesMap zones;
std::vector<size_t> highlightZone = m_highlightZone; std::vector<size_t> highlightZone = m_highlightZone;
bool flashMode = m_flashMode; bool flashMode = m_flashMode;

View File

@@ -1,7 +1,10 @@
#include "pch.h" #include "pch.h"
#include "ZoneWindowDrawing.h" #include "ZoneWindowDrawing.h"
#include <algorithm>
#include <map>
#include <string> #include <string>
#include <vector>
namespace NonLocalizable namespace NonLocalizable
{ {
@@ -79,7 +82,7 @@ namespace
g.DrawString(text.c_str(), -1, &font, gdiRect, &stringFormat, &solidBrush); g.DrawString(text.c_str(), -1, &font, gdiRect, &stringFormat, &solidBrush);
} }
void DrawZone(wil::unique_hdc& hdc, ZoneWindowDrawing::ColorSetting const& colorSetting, winrt::com_ptr<IZone> zone, const std::vector<winrt::com_ptr<IZone>>& zones, bool flashMode) noexcept void DrawZone(wil::unique_hdc& hdc, ZoneWindowDrawing::ColorSetting const& colorSetting, winrt::com_ptr<IZone> zone, bool flashMode)noexcept
{ {
RECT zoneRect = zone->GetZoneRect(); RECT zoneRect = zone->GetZoneRect();
@@ -95,7 +98,7 @@ namespace
if (!flashMode) if (!flashMode)
{ {
DrawIndex(hdc, zoneRect, zone->Id()); DrawIndex(hdc, zoneRect, zone->Id() + 1);
} }
} }
} }
@@ -112,7 +115,7 @@ namespace ZoneWindowDrawing
COLORREF zoneBorderColor, COLORREF zoneBorderColor,
COLORREF highlightColor, COLORREF highlightColor,
int zoneOpacity, int zoneOpacity,
const std::vector<winrt::com_ptr<IZone>>& zones, const IZoneSet::ZonesMap& zones,
const std::vector<size_t>& highlightZones, const std::vector<size_t>& highlightZones,
bool flashMode) noexcept bool flashMode) noexcept
{ {
@@ -121,52 +124,41 @@ namespace ZoneWindowDrawing
ColorSetting colorHighlight{ OpacitySettingToAlpha(zoneOpacity), 0, 255, 0, -2 }; ColorSetting colorHighlight{ OpacitySettingToAlpha(zoneOpacity), 0, 255, 0, -2 };
ColorSetting const colorFlash{ OpacitySettingToAlpha(zoneOpacity), RGB(81, 92, 107), 200, RGB(104, 118, 138), -2 }; ColorSetting const colorFlash{ OpacitySettingToAlpha(zoneOpacity), RGB(81, 92, 107), 200, RGB(104, 118, 138), -2 };
std::vector<bool> isHighlighted(zones.size(), false);
for (size_t x : highlightZones)
{
isHighlighted[x] = true;
}
// First draw the inactive zones // First draw the inactive zones
for (auto iter = zones.begin(); iter != zones.end(); iter++) for (auto iter = zones.begin(); iter != zones.end(); iter++)
{ {
int zoneId = static_cast<int>(iter - zones.begin()); winrt::com_ptr<IZone> zone = iter->second;
winrt::com_ptr<IZone> zone = iter->try_as<IZone>(); size_t zoneId = zone->Id();
if (!zone) if (!zone)
{ {
continue; continue;
} }
if (!isHighlighted[zoneId]) auto zoneIt = std::find(highlightZones.begin(), highlightZones.end(), zoneId);
if (zoneIt == highlightZones.end())
{ {
if (flashMode) if (flashMode)
{ {
DrawZone(hdc, colorFlash, zone, zones, flashMode); DrawZone(hdc, colorFlash, zone, flashMode);
} }
else else
{ {
colorViewer.fill = zoneColor; colorViewer.fill = zoneColor;
colorViewer.border = zoneBorderColor; colorViewer.border = zoneBorderColor;
DrawZone(hdc, colorViewer, zone, zones, flashMode); DrawZone(hdc, colorViewer, zone, flashMode);
} }
} }
} }
// Draw the active zones on top of the inactive zones // Draw the active zones on top of the inactive zones
for (auto iter = zones.begin(); iter != zones.end(); iter++) for (const auto& zoneId : highlightZones)
{ {
int zoneId = static_cast<int>(iter - zones.begin()); colorHighlight.fill = highlightColor;
winrt::com_ptr<IZone> zone = iter->try_as<IZone>(); colorHighlight.border = zoneBorderColor;
if (!zone)
{
continue;
}
if (isHighlighted[zoneId]) if (zones.contains(zoneId))
{ {
colorHighlight.fill = highlightColor; DrawZone(hdc, colorHighlight, zones.at(zoneId), flashMode);
colorHighlight.border = zoneBorderColor;
DrawZone(hdc, colorHighlight, zone, zones, flashMode);
} }
} }
} }

View File

@@ -1,11 +1,13 @@
#pragma once #pragma once
#include <map>
#include <vector> #include <vector>
#include <wil\resource.h> #include <wil\resource.h>
#include <winrt/base.h> #include <winrt/base.h>
#include "util.h" #include "util.h"
#include "Zone.h" #include "Zone.h"
#include "ZoneSet.h"
namespace ZoneWindowDrawing namespace ZoneWindowDrawing
{ {
@@ -24,7 +26,7 @@ namespace ZoneWindowDrawing
COLORREF zoneBorderColor, COLORREF zoneBorderColor,
COLORREF highlightColor, COLORREF highlightColor,
int zoneOpacity, int zoneOpacity,
const std::vector<winrt::com_ptr<IZone>>& zones, const IZoneSet::ZonesMap& zones,
const std::vector<size_t>& highlightZones, const std::vector<size_t>& highlightZones,
bool flashMode) noexcept; bool flashMode) noexcept;
} }

View File

@@ -85,28 +85,28 @@ namespace FancyZonesUnitTests
TEST_METHOD (AddOne) TEST_METHOD (AddOne)
{ {
constexpr size_t zoneId = 1; constexpr size_t zoneId = 0;
winrt::com_ptr<IZone> zone = MakeZone({ 0, 0, 100, 100 }, zoneId); winrt::com_ptr<IZone> zone = MakeZone({ 0, 0, 100, 100 }, zoneId);
Assert::IsNotNull(zone.get()); Assert::IsNotNull(zone.get());
m_set->AddZone(zone); m_set->AddZone(zone);
auto zones = m_set->GetZones(); auto zones = m_set->GetZones();
Assert::AreEqual((size_t)1, zones.size()); Assert::AreEqual((size_t)1, zones.size());
compareZones(zone, zones[0]); compareZones(zone, zones[zoneId]);
Assert::AreEqual(zoneId, zones[0]->Id()); Assert::AreEqual(zoneId, zones[zoneId]->Id());
} }
TEST_METHOD (AddManyEqual) TEST_METHOD (AddManyEqual)
{ {
for (size_t i = 0; i < 1024; i++) for (size_t i = 0; i < 1024; i++)
{ {
size_t zoneId = i + 1; size_t zoneId = i;
winrt::com_ptr<IZone> zone = MakeZone({ 0, 0, 100, 100 }, zoneId); winrt::com_ptr<IZone> zone = MakeZone({ 0, 0, 100, 100 }, zoneId);
Assert::IsNotNull(zone.get()); Assert::IsNotNull(zone.get());
m_set->AddZone(zone); m_set->AddZone(zone);
auto zones = m_set->GetZones(); auto zones = m_set->GetZones();
Assert::AreEqual(i + 1, zones.size()); Assert::AreEqual(i + 1, zones.size());
compareZones(zone, zones[i]); compareZones(zone, zones[zoneId]);
Assert::AreEqual(zoneId, zones[i]->Id()); Assert::AreEqual(zoneId, zones[zoneId]->Id());
} }
} }
@@ -114,7 +114,7 @@ namespace FancyZonesUnitTests
{ {
for (size_t i = 0; i < 1024; i++) for (size_t i = 0; i < 1024; i++)
{ {
size_t zoneId = i + 1; size_t zoneId = i;
int left = rand() % 10; int left = rand() % 10;
int top = rand() % 10; int top = rand() % 10;
int right = left + 1 + rand() % 100; int right = left + 1 + rand() % 100;
@@ -124,8 +124,8 @@ namespace FancyZonesUnitTests
m_set->AddZone(zone); m_set->AddZone(zone);
auto zones = m_set->GetZones(); auto zones = m_set->GetZones();
Assert::AreEqual(i + 1, zones.size()); Assert::AreEqual(i + 1, zones.size());
compareZones(zone, zones[i]); compareZones(zone, zones[zoneId]);
Assert::AreEqual(zoneId, zones[i]->Id()); Assert::AreEqual(zoneId, zones[zoneId]->Id());
} }
} }
@@ -135,13 +135,6 @@ namespace FancyZonesUnitTests
Assert::IsNotNull(zone.get()); Assert::IsNotNull(zone.get());
} }
TEST_METHOD (MakeZoneWithInvalidId)
{
constexpr size_t invalidZoneId = 0;
winrt::com_ptr<IZone> zone = MakeZone({ 0, 0, 0, 0 }, invalidZoneId);
Assert::IsNull(zone.get());
}
TEST_METHOD (MakeZoneFromInvalidRectWidth) TEST_METHOD (MakeZoneFromInvalidRectWidth)
{ {
winrt::com_ptr<IZone> zone = MakeZone({ 100, 100, 99, 101 }, 1); winrt::com_ptr<IZone> zone = MakeZone({ 100, 100, 99, 101 }, 1);
@@ -361,9 +354,9 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveWindowIntoZoneByIndexSeveralTimesSameWindow) TEST_METHOD (MoveWindowIntoZoneByIndexSeveralTimesSameWindow)
{ {
// Add a couple of zones. // Add a couple of zones.
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 1); winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 0);
winrt::com_ptr<IZone> zone2 = MakeZone({ 1, 1, 101, 101 }, 2); winrt::com_ptr<IZone> zone2 = MakeZone({ 1, 1, 101, 101 }, 1);
winrt::com_ptr<IZone> zone3 = MakeZone({ 2, 2, 102, 102 }, 3); winrt::com_ptr<IZone> zone3 = MakeZone({ 2, 2, 102, 102 }, 2);
m_set->AddZone(zone1); m_set->AddZone(zone1);
m_set->AddZone(zone2); m_set->AddZone(zone2);
m_set->AddZone(zone3); m_set->AddZone(zone3);
@@ -382,9 +375,9 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveWindowIntoZoneByIndexSeveralTimesSameIndex) TEST_METHOD (MoveWindowIntoZoneByIndexSeveralTimesSameIndex)
{ {
// Add a couple of zones. // Add a couple of zones.
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 1); winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 0);
winrt::com_ptr<IZone> zone2 = MakeZone({ 1, 1, 101, 101 }, 2); winrt::com_ptr<IZone> zone2 = MakeZone({ 1, 1, 101, 101 }, 1);
winrt::com_ptr<IZone> zone3 = MakeZone({ 2, 2, 102, 102 }, 3); winrt::com_ptr<IZone> zone3 = MakeZone({ 2, 2, 102, 102 }, 2);
m_set->AddZone(zone1); m_set->AddZone(zone1);
m_set->AddZone(zone2); m_set->AddZone(zone2);
m_set->AddZone(zone3); m_set->AddZone(zone3);
@@ -414,7 +407,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveWindowIntoZoneByPointInnerPoint) TEST_METHOD (MoveWindowIntoZoneByPointInnerPoint)
{ {
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 1); winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 0);
m_set->AddZone(zone1); m_set->AddZone(zone1);
auto window = Mocks::Window(); auto window = Mocks::Window();
@@ -425,8 +418,8 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveWindowIntoZoneByPointInnerPointOverlappingZones) TEST_METHOD (MoveWindowIntoZoneByPointInnerPointOverlappingZones)
{ {
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 1); winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 0);
winrt::com_ptr<IZone> zone2 = MakeZone({ 10, 10, 90, 90 }, 2); winrt::com_ptr<IZone> zone2 = MakeZone({ 10, 10, 90, 90 }, 1);
m_set->AddZone(zone1); m_set->AddZone(zone1);
m_set->AddZone(zone2); m_set->AddZone(zone2);
@@ -441,8 +434,8 @@ namespace FancyZonesUnitTests
const auto window = Mocks::Window(); const auto window = Mocks::Window();
const auto zoneWindow = Mocks::Window(); const auto zoneWindow = Mocks::Window();
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 1); winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 0);
winrt::com_ptr<IZone> zone2 = MakeZone({ 10, 10, 90, 90 }, 2); winrt::com_ptr<IZone> zone2 = MakeZone({ 10, 10, 90, 90 }, 1);
m_set->AddZone(zone1); m_set->AddZone(zone1);
m_set->AddZone(zone2); m_set->AddZone(zone2);
@@ -459,8 +452,8 @@ namespace FancyZonesUnitTests
const auto window = Mocks::Window(); const auto window = Mocks::Window();
const auto zoneWindow = Mocks::Window(); const auto zoneWindow = Mocks::Window();
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 1); winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 0);
winrt::com_ptr<IZone> zone2 = MakeZone({ 10, 10, 90, 90 }, 2); winrt::com_ptr<IZone> zone2 = MakeZone({ 10, 10, 90, 90 }, 1);
m_set->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 1); m_set->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 1);
@@ -477,9 +470,9 @@ namespace FancyZonesUnitTests
const auto window = Mocks::Window(); const auto window = Mocks::Window();
const auto zoneWindow = Mocks::Window(); const auto zoneWindow = Mocks::Window();
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 1); winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 0);
winrt::com_ptr<IZone> zone2 = MakeZone({ 10, 10, 90, 90 }, 2); winrt::com_ptr<IZone> zone2 = MakeZone({ 10, 10, 90, 90 }, 1);
winrt::com_ptr<IZone> zone3 = MakeZone({ 20, 20, 80, 80 }, 3); winrt::com_ptr<IZone> zone3 = MakeZone({ 20, 20, 80, 80 }, 2);
m_set->AddZone(zone1); m_set->AddZone(zone1);
m_set->AddZone(zone2); m_set->AddZone(zone2);
@@ -507,9 +500,9 @@ namespace FancyZonesUnitTests
m_set = MakeZoneSet(config); m_set = MakeZoneSet(config);
// Add a couple of zones. // Add a couple of zones.
m_zone1 = MakeZone({ 0, 0, 100, 100 }, 1); m_zone1 = MakeZone({ 0, 0, 100, 100 }, 0);
m_zone2 = MakeZone({ 0, 0, 100, 100 }, 2); m_zone2 = MakeZone({ 0, 0, 100, 100 }, 1);
m_zone3 = MakeZone({ 0, 0, 100, 100 }, 3); m_zone3 = MakeZone({ 0, 0, 100, 100 }, 2);
m_set->AddZone(m_zone1); m_set->AddZone(m_zone1);
m_set->AddZone(m_zone2); m_set->AddZone(m_zone2);
m_set->AddZone(m_zone3); m_set->AddZone(m_zone3);
@@ -776,7 +769,7 @@ namespace FancyZonesUnitTests
{ {
Assert::IsTrue(set->IsZoneEmpty(zoneId)); Assert::IsTrue(set->IsZoneEmpty(zoneId));
const auto& zoneRect = zone->GetZoneRect(); const auto& zoneRect = zone.second->GetZoneRect();
Assert::IsTrue(zoneRect.left >= 0, L"left border is less than zero"); Assert::IsTrue(zoneRect.left >= 0, L"left border is less than zero");
Assert::IsTrue(zoneRect.top >= 0, L"top border is less than zero"); Assert::IsTrue(zoneRect.top >= 0, L"top border is less than zero");