[FancyZones] Avoid unnecessary calculations when selecting a zone (#11815)
This commit is contained in:
parent
4c3fbad9ee
commit
7e79654ee0
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue