[FancyZones] Avoid unnecessary calculations when selecting a zone (#11815)

This commit is contained in:
Seraphima Zykova 2021-06-22 11:34:27 +03:00 committed by GitHub
parent 4c3fbad9ee
commit 7e79654ee0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 30 deletions

View file

@ -33,6 +33,7 @@ public:
}
IFACEMETHODIMP_(RECT) GetZoneRect() const noexcept { return m_zoneRect; }
IFACEMETHODIMP_(long) GetZoneArea() const noexcept { return max(m_zoneRect.bottom - m_zoneRect.top, 0) * max(m_zoneRect.right - m_zoneRect.left, 0); }
IFACEMETHODIMP_(size_t) Id() const noexcept { return m_id; }
IFACEMETHODIMP_(RECT) ComputeActualZoneRect(HWND window, HWND zoneWindow) const noexcept;

View file

@ -14,6 +14,10 @@ interface __declspec(uuid("{8228E934-B6EF-402A-9892-15A1441BF8B0}")) IZone : pub
* @returns Zone coordinates (top-left and bottom-right corner) represented as RECT structure.
*/
IFACEMETHOD_(RECT, GetZoneRect)() const = 0;
/**
* @returns Zone area calculated from zone rect
*/
IFACEMETHOD_(long, GetZoneArea)() const = 0;
/**
* @returns Zone identifier.
*/

View file

@ -161,6 +161,7 @@ private:
bool CalculateCustomLayout(Rect workArea, int spacing) noexcept;
bool CalculateGridZones(Rect workArea, FancyZonesDataTypes::GridLayoutInfo gridLayoutInfo, int spacing);
std::vector<size_t> ZoneSelectSubregion(const std::vector<size_t>& capturedZones, POINT pt) const;
std::vector<size_t> ZoneSelectClosestCenter(const std::vector<size_t>& capturedZones, POINT pt) const;
// `compare` should return true if the first argument is a better choice than the second argument.
template<class CompareF>
@ -251,33 +252,6 @@ ZoneSet::ZonesFromPoint(POINT pt) const noexcept
if (overlap)
{
auto zoneArea = [](auto zone) {
RECT rect = zone->GetZoneRect();
return max(rect.bottom - rect.top, 0) * max(rect.right - rect.left, 0);
};
auto getCenter = [](auto zone) {
RECT rect = zone->GetZoneRect();
return POINT{ (rect.right + rect.left) / 2, (rect.top + rect.bottom) / 2 };
};
auto pointDifference = [](POINT pt1, POINT pt2) {
return (pt1.x - pt2.x) * (pt1.x - pt2.x) + (pt1.y - pt2.y) * (pt1.y - pt2.y);
};
auto distanceFromCenter = [&](auto zone) {
POINT center = getCenter(zone);
return pointDifference(center, pt);
};
auto closerToCenter = [&](auto zone1, auto zone2) {
if (pointDifference(getCenter(zone1), getCenter(zone2)) > OVERLAPPING_CENTERS_SENSITIVITY)
{
return distanceFromCenter(zone1) < distanceFromCenter(zone2);
}
else
{
return zoneArea(zone1) < zoneArea(zone2);
};
};
try
{
using Algorithm = Settings::OverlappingZonesAlgorithm;
@ -285,13 +259,13 @@ ZoneSet::ZonesFromPoint(POINT pt) const noexcept
switch (m_config.SelectionAlgorithm)
{
case Algorithm::Smallest:
return ZoneSelectPriority(capturedZones, [&](auto zone1, auto zone2) { return zoneArea(zone1) < zoneArea(zone2); });
return ZoneSelectPriority(capturedZones, [&](auto zone1, auto zone2) { return zone1->GetZoneArea() < zone2->GetZoneArea(); });
case Algorithm::Largest:
return ZoneSelectPriority(capturedZones, [&](auto zone1, auto zone2) { return zoneArea(zone1) > zoneArea(zone2); });
return ZoneSelectPriority(capturedZones, [&](auto zone1, auto zone2) { return zone1->GetZoneArea() > zone2->GetZoneArea(); });
case Algorithm::Positional:
return ZoneSelectSubregion(capturedZones, pt);
case Algorithm::ClosestCenter:
return ZoneSelectPriority(capturedZones, closerToCenter);
return ZoneSelectClosestCenter(capturedZones, pt);
}
}
catch (std::out_of_range)
@ -1018,6 +992,32 @@ std::vector<size_t> ZoneSet::ZoneSelectSubregion(const std::vector<size_t>& capt
return { capturedZones[zoneIndex] };
}
std::vector<size_t> ZoneSet::ZoneSelectClosestCenter(const std::vector<size_t>& capturedZones, POINT pt) const
{
auto getCenter = [](auto zone) {
RECT rect = zone->GetZoneRect();
return POINT{ (rect.right + rect.left) / 2, (rect.top + rect.bottom) / 2 };
};
auto pointDifference = [](POINT pt1, POINT pt2) {
return (pt1.x - pt2.x) * (pt1.x - pt2.x) + (pt1.y - pt2.y) * (pt1.y - pt2.y);
};
auto distanceFromCenter = [&](auto zone) {
POINT center = getCenter(zone);
return pointDifference(center, pt);
};
auto closerToCenter = [&](auto zone1, auto zone2) {
if (pointDifference(getCenter(zone1), getCenter(zone2)) > OVERLAPPING_CENTERS_SENSITIVITY)
{
return distanceFromCenter(zone1) < distanceFromCenter(zone2);
}
else
{
return zone1->GetZoneArea() < zone2->GetZoneArea();
};
};
return ZoneSelectPriority(capturedZones, closerToCenter);
}
template<class CompareF>
std::vector<size_t> ZoneSet::ZoneSelectPriority(const std::vector<size_t>& capturedZones, CompareF compare) const
{