[FancyZones] Added persistence to app zone history (#3132)

* Persist app zone history in a separate file

* Almost ready to be functionally tested

* Now all unit tests pass

* Bug fixes, it seems to work

* Various fixups

* Improved performance of FancyZones::UpdateWindowsPositions()
This commit is contained in:
Ivan Stošić
2020-05-26 16:01:12 +02:00
committed by GitHub
parent bc9add783c
commit 6f22c7ad19
17 changed files with 349 additions and 881 deletions

View File

@@ -2,6 +2,7 @@
#include "util.h"
#include "lib/ZoneSet.h"
#include "Settings.h"
#include <common/dpi_aware.h>
@@ -123,8 +124,8 @@ public:
IFACEMETHODIMP AddZone(winrt::com_ptr<IZone> zone) noexcept;
IFACEMETHODIMP_(std::vector<int>)
ZonesFromPoint(POINT pt) noexcept;
IFACEMETHODIMP_(int)
GetZoneIndexFromWindow(HWND window) noexcept;
IFACEMETHODIMP_(std::vector<int>)
GetZoneIndexSetFromWindow(HWND window) noexcept;
IFACEMETHODIMP_(std::vector<winrt::com_ptr<IZone>>)
GetZones() noexcept { return m_zones; }
IFACEMETHODIMP_(void)
@@ -137,6 +138,8 @@ public:
MoveWindowIntoZoneByPoint(HWND window, HWND zoneWindow, POINT ptClient) noexcept;
IFACEMETHODIMP_(bool)
CalculateZones(MONITORINFO monitorInfo, int zoneCount, int spacing) noexcept;
IFACEMETHODIMP_(bool)
IsZoneEmpty(int zoneIndex) noexcept;
private:
bool CalculateFocusLayout(Rect workArea, int zoneCount) noexcept;
@@ -144,12 +147,11 @@ private:
bool CalculateGridLayout(Rect workArea, JSONHelpers::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, JSONHelpers::GridLayoutInfo gridLayoutInfo, int spacing);
winrt::com_ptr<IZone> ZoneFromWindow(HWND window) noexcept;
void StampWindow(HWND window, size_t bitmask) noexcept;
std::vector<winrt::com_ptr<IZone>> m_zones;
std::map<HWND, std::vector<int>> m_windowIndexSet;
ZoneSetConfig m_config;
};
@@ -238,45 +240,23 @@ ZoneSet::ZonesFromPoint(POINT pt) noexcept
return capturedZones;
}
IFACEMETHODIMP_(int)
ZoneSet::GetZoneIndexFromWindow(HWND window) noexcept
std::vector<int> ZoneSet::GetZoneIndexSetFromWindow(HWND window) noexcept
{
int zoneIndex = 0;
for (auto iter = m_zones.begin(); iter != m_zones.end(); iter++, zoneIndex++)
auto it = m_windowIndexSet.find(window);
if (it == m_windowIndexSet.end())
{
if (winrt::com_ptr<IZone> zone = iter->try_as<IZone>())
{
if (zone->ContainsWindow(window))
{
return zoneIndex;
}
}
return {};
}
else
{
return it->second;
}
return -1;
}
IFACEMETHODIMP_(void)
ZoneSet::MoveWindowIntoZoneByIndex(HWND window, HWND windowZone, int index, bool stampZone) noexcept
{
if (m_zones.empty())
{
return;
}
if (index >= int(m_zones.size()))
{
return;
}
while (auto zoneDrop = ZoneFromWindow(window))
{
zoneDrop->RemoveWindowFromZone(window, !IsZoomed(window));
}
if (auto zone = m_zones.at(index))
{
zone->AddWindowToZone(window, windowZone, stampZone);
}
MoveWindowIntoZoneByIndexSet(window, windowZone, { index }, stampZone);
}
IFACEMETHODIMP_(void)
@@ -287,19 +267,12 @@ ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND windowZone, const std::v
return;
}
while (auto zoneDrop = ZoneFromWindow(window))
{
zoneDrop->RemoveWindowFromZone(window, !IsZoomed(window));
}
if (indexSet.size() == 1)
{
MoveWindowIntoZoneByIndex(window, windowZone, indexSet[0], stampZone);
return;
}
RECT size;
bool sizeEmpty = true;
size_t bitmask = 0;
auto& storedIndexSet = m_windowIndexSet[window];
storedIndexSet = {};
for (int index : indexSet)
{
@@ -318,12 +291,23 @@ ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND windowZone, const std::v
size = newSize;
sizeEmpty = false;
}
storedIndexSet.push_back(index);
}
if (index < std::numeric_limits<size_t>::digits)
{
bitmask |= 1ull << index;
}
}
if (!sizeEmpty)
{
SizeWindowToRect(window, size);
if (stampZone)
{
StampWindow(window, bitmask);
}
}
}
@@ -335,64 +319,48 @@ ZoneSet::MoveWindowIntoZoneByDirection(HWND window, HWND windowZone, DWORD vkCod
return false;
}
winrt::com_ptr<IZone> oldZone = nullptr;
winrt::com_ptr<IZone> newZone = nullptr;
auto indexSet = GetZoneIndexSetFromWindow(window);
int numZones = static_cast<int>(m_zones.size());
auto iter = std::find(m_zones.begin(), m_zones.end(), ZoneFromWindow(window));
if (iter == m_zones.end())
// The window was not assigned to any zone here
if (indexSet.size() == 0)
{
iter = (vkCode == VK_RIGHT) ? m_zones.begin() : m_zones.end() - 1;
}
else if (oldZone = iter->as<IZone>())
{
if (vkCode == VK_LEFT)
{
if (iter == m_zones.begin())
{
if (!cycle)
{
oldZone->RemoveWindowFromZone(window, false);
return false;
}
iter = m_zones.end();
}
iter--;
}
else if (vkCode == VK_RIGHT)
{
iter++;
if (iter == m_zones.end())
{
if (!cycle)
{
oldZone->RemoveWindowFromZone(window, false);
return false;
}
iter = m_zones.begin();
}
}
}
if (newZone = iter->as<IZone>())
{
if (oldZone)
{
oldZone->RemoveWindowFromZone(window, false);
}
newZone->AddWindowToZone(window, windowZone, true);
MoveWindowIntoZoneByIndexSet(window, windowZone, { vkCode == VK_LEFT ? numZones - 1 : 0 }, true);
return true;
}
return false;
int oldIndex = indexSet[0];
// We reached the edge
if ((vkCode == VK_LEFT && oldIndex == 0) || (vkCode == VK_RIGHT && oldIndex == numZones - 1))
{
if (!cycle)
{
MoveWindowIntoZoneByIndexSet(window, windowZone, {}, true);
return false;
}
else
{
MoveWindowIntoZoneByIndexSet(window, windowZone, { vkCode == VK_LEFT ? numZones - 1 : 0 }, true);
return true;
}
}
// We didn't reach the edge
if (vkCode == VK_LEFT)
{
MoveWindowIntoZoneByIndexSet(window, windowZone, { oldIndex - 1 }, true);
}
else
{
MoveWindowIntoZoneByIndexSet(window, windowZone, { oldIndex + 1 }, true);
}
return true;
}
IFACEMETHODIMP_(void)
ZoneSet::MoveWindowIntoZoneByPoint(HWND window, HWND zoneWindow, POINT ptClient) noexcept
{
while (auto zoneDrop = ZoneFromWindow(window))
{
zoneDrop->RemoveWindowFromZone(window, !IsZoomed(window));
}
auto zones = ZonesFromPoint(ptClient);
MoveWindowIntoZoneByIndexSet(window, zoneWindow, zones, true);
}
@@ -435,6 +403,19 @@ ZoneSet::CalculateZones(MONITORINFO monitorInfo, int zoneCount, int spacing) noe
return success;
}
bool ZoneSet::IsZoneEmpty(int zoneIndex) noexcept
{
for (auto& [window, zones] : m_windowIndexSet)
{
if (find(begin(zones), end(zones), zoneIndex) != end(zones))
{
return false;
}
}
return true;
}
bool ZoneSet::CalculateFocusLayout(Rect workArea, int zoneCount) noexcept
{
bool success = true;
@@ -713,19 +694,9 @@ bool ZoneSet::CalculateGridZones(Rect workArea, JSONHelpers::GridLayoutInfo grid
return success;
}
winrt::com_ptr<IZone> ZoneSet::ZoneFromWindow(HWND window) noexcept
void ZoneSet::StampWindow(HWND window, size_t bitmask) noexcept
{
for (auto iter = m_zones.begin(); iter != m_zones.end(); iter++)
{
if (winrt::com_ptr<IZone> zone = iter->try_as<IZone>())
{
if (zone->ContainsWindow(window))
{
return zone;
}
}
}
return nullptr;
SetProp(window, MULTI_ZONE_STAMP, reinterpret_cast<HANDLE>(bitmask));
}
winrt::com_ptr<IZoneSet> MakeZoneSet(ZoneSetConfig const& config) noexcept