[FancyZones] Split zones-settings: app zone history (#15690)

This commit is contained in:
Seraphima Zykova
2022-01-24 14:54:17 +03:00
committed by GitHub
parent 7833ace553
commit 453bb613af
15 changed files with 582 additions and 525 deletions

View File

@@ -12,6 +12,7 @@
#include <common/SettingsAPI/FileWatcher.h>
#include <FancyZonesLib/FancyZonesData.h>
#include <FancyZonesLib/FancyZonesData/AppZoneHistory.h>
#include <FancyZonesLib/FancyZonesData/CustomLayouts.h>
#include <FancyZonesLib/FancyZonesData/LayoutHotkeys.h>
#include <FancyZonesLib/FancyZonesWindowProperties.h>
@@ -74,6 +75,7 @@ public:
FancyZonesDataInstance().ReplaceZoneSettingsFileFromOlderVersions();
LayoutHotkeys::instance().LoadData();
CustomLayouts::instance().LoadData();
AppZoneHistory::instance().LoadData();
}
// IFancyZones
@@ -275,6 +277,7 @@ FancyZones::Run() noexcept
});
FancyZonesDataInstance().SetVirtualDesktopCheckCallback(std::bind(&VirtualDesktop::IsVirtualDesktopIdSavedInRegistry, &m_virtualDesktop, std::placeholders::_1));
AppZoneHistory::instance().SetVirtualDesktopCheckCallback(std::bind(&VirtualDesktop::IsVirtualDesktopIdSavedInRegistry, &m_virtualDesktop, std::placeholders::_1));
}
// IFancyZones
@@ -334,14 +337,14 @@ void FancyZones::MoveWindowIntoZone(HWND window, winrt::com_ptr<IWorkArea> workA
{
_TRACER_;
auto& fancyZonesData = FancyZonesDataInstance();
if (!fancyZonesData.IsAnotherWindowOfApplicationInstanceZoned(window, workArea->UniqueId()))
if (!AppZoneHistory::instance().IsAnotherWindowOfApplicationInstanceZoned(window, workArea->UniqueId()))
{
if (workArea)
{
Trace::FancyZones::SnapNewWindowIntoZone(workArea->ZoneSet());
}
m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, zoneIndexSet, workArea);
fancyZonesData.UpdateProcessIdToHandleMap(window, workArea->UniqueId());
AppZoneHistory::instance().UpdateProcessIdToHandleMap(window, workArea->UniqueId());
}
}

View File

@@ -22,6 +22,7 @@
#include <common/utils/process_path.h>
#include <common/logger/logger.h>
#include <FancyZonesLib/FancyZonesData/AppZoneHistory.h>
#include <FancyZonesLib/FancyZonesData/CustomLayouts.h>
#include <FancyZonesLib/FancyZonesData/LayoutHotkeys.h>
#include <FancyZonesLib/ModuleConstants.h>
@@ -167,9 +168,7 @@ void FancyZonesData::ReplaceZoneSettingsFileFromOlderVersions()
{
json::JsonObject fancyZonesDataJSON = GetPersistFancyZonesJSON();
//appZoneHistoryMap = JSONHelpers::ParseAppZoneHistory(fancyZonesDataJSON);
//deviceInfoMap = JSONHelpers::ParseDeviceInfos(fancyZonesDataJSON);
//customZoneSetsMap = JSONHelpers::ParseCustomZoneSets(fancyZonesDataJSON);
auto customLayouts = JSONHelpers::ParseCustomZoneSets(fancyZonesDataJSON);
if (customLayouts)
@@ -204,12 +203,6 @@ const JSONHelpers::TDeviceInfoMap& FancyZonesData::GetDeviceInfoMap() const
return deviceInfoMap;
}
const std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>>& FancyZonesData::GetAppZoneHistoryMap() const
{
std::scoped_lock lock{ dataLock };
return appZoneHistoryMap;
}
std::optional<FancyZonesDataTypes::DeviceInfoData> FancyZonesData::FindDeviceInfo(const FancyZonesDataTypes::DeviceIdData& id) const
{
std::scoped_lock lock{ dataLock };
@@ -353,7 +346,8 @@ void FancyZonesData::SyncVirtualDesktops(GUID currentVirtualDesktopId)
Logger::info(L"Update Virtual Desktop id to {}", virtualDesktopIdStr.get());
}
SaveAppZoneHistoryAndZoneSettings();
SaveZoneSettings();
AppZoneHistory::instance().SaveData();
}
}
@@ -378,7 +372,7 @@ void FancyZonesData::RemoveDeletedDesktops(const std::vector<GUID>& activeDeskto
Logger::info(L"Remove Virtual Desktop id {}", virtualDesktopIdStr.get());
}
RemoveDesktopAppZoneHistory(desktopId);
AppZoneHistory::instance().RemoveDesktopAppZoneHistory(desktopId);
it = deviceInfoMap.erase(it);
dirtyFlag = true;
continue;
@@ -389,204 +383,11 @@ void FancyZonesData::RemoveDeletedDesktops(const std::vector<GUID>& activeDeskto
if (dirtyFlag)
{
SaveAppZoneHistoryAndZoneSettings();
SaveZoneSettings();
AppZoneHistory::instance().SaveData();
}
}
bool FancyZonesData::IsAnotherWindowOfApplicationInstanceZoned(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId) const
{
std::scoped_lock lock{ dataLock };
auto processPath = get_process_path(window);
if (!processPath.empty())
{
auto history = appZoneHistoryMap.find(processPath);
if (history != std::end(appZoneHistoryMap))
{
auto& perDesktopData = history->second;
for (auto& data : perDesktopData)
{
if (data.deviceId.isEqualWithNullVirtualDesktopId(deviceId))
{
DWORD processId = 0;
GetWindowThreadProcessId(window, &processId);
auto processIdIt = data.processIdToHandleMap.find(processId);
if (processIdIt == std::end(data.processIdToHandleMap))
{
return false;
}
else if (processIdIt->second != window && IsWindow(processIdIt->second))
{
return true;
}
}
}
}
}
return false;
}
void FancyZonesData::UpdateProcessIdToHandleMap(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId)
{
std::scoped_lock lock{ dataLock };
auto processPath = get_process_path(window);
if (!processPath.empty())
{
auto history = appZoneHistoryMap.find(processPath);
if (history != std::end(appZoneHistoryMap))
{
auto& perDesktopData = history->second;
for (auto& data : perDesktopData)
{
if (data.deviceId.isEqualWithNullVirtualDesktopId(deviceId))
{
DWORD processId = 0;
GetWindowThreadProcessId(window, &processId);
data.processIdToHandleMap[processId] = window;
break;
}
}
}
}
}
ZoneIndexSet FancyZonesData::GetAppLastZoneIndexSet(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring_view& zoneSetId) const
{
std::scoped_lock lock{ dataLock };
auto processPath = get_process_path(window);
if (!processPath.empty())
{
auto history = appZoneHistoryMap.find(processPath);
if (history != std::end(appZoneHistoryMap))
{
const auto& perDesktopData = history->second;
for (const auto& data : perDesktopData)
{
if (data.zoneSetUuid == zoneSetId && data.deviceId.isEqualWithNullVirtualDesktopId(deviceId))
{
return data.zoneIndexSet;
}
}
}
}
return {};
}
bool FancyZonesData::RemoveAppLastZone(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring_view& zoneSetId)
{
_TRACER_;
std::scoped_lock lock{ dataLock };
auto processPath = get_process_path(window);
if (!processPath.empty())
{
auto history = appZoneHistoryMap.find(processPath);
if (history != std::end(appZoneHistoryMap))
{
auto& perDesktopData = history->second;
for (auto data = std::begin(perDesktopData); data != std::end(perDesktopData);)
{
if (data->deviceId.isEqualWithNullVirtualDesktopId(deviceId) && data->zoneSetUuid == zoneSetId)
{
if (!IsAnotherWindowOfApplicationInstanceZoned(window, deviceId))
{
DWORD processId = 0;
GetWindowThreadProcessId(window, &processId);
data->processIdToHandleMap.erase(processId);
}
// if there is another instance of same application placed in the same zone don't erase history
ZoneIndex windowZoneStamp = reinterpret_cast<ZoneIndex>(::GetProp(window, ZonedWindowProperties::PropertyMultipleZoneID));
for (auto placedWindow : data->processIdToHandleMap)
{
ZoneIndex placedWindowZoneStamp = reinterpret_cast<ZoneIndex>(::GetProp(placedWindow.second, ZonedWindowProperties::PropertyMultipleZoneID));
if (IsWindow(placedWindow.second) && (windowZoneStamp == placedWindowZoneStamp))
{
return false;
}
}
data = perDesktopData.erase(data);
if (perDesktopData.empty())
{
appZoneHistoryMap.erase(processPath);
}
SaveAppZoneHistory();
return true;
}
else
{
++data;
}
}
}
}
return false;
}
bool FancyZonesData::SetAppLastZones(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring& zoneSetId, const ZoneIndexSet& zoneIndexSet)
{
_TRACER_;
std::scoped_lock lock{ dataLock };
if (IsAnotherWindowOfApplicationInstanceZoned(window, deviceId))
{
return false;
}
auto processPath = get_process_path(window);
if (processPath.empty())
{
return false;
}
DWORD processId = 0;
GetWindowThreadProcessId(window, &processId);
auto history = appZoneHistoryMap.find(processPath);
if (history != std::end(appZoneHistoryMap))
{
auto& perDesktopData = history->second;
for (auto& data : perDesktopData)
{
if (data.deviceId.isEqualWithNullVirtualDesktopId(deviceId))
{
// application already has history on this work area, update it with new window position
data.processIdToHandleMap[processId] = window;
data.zoneSetUuid = zoneSetId;
data.zoneIndexSet = zoneIndexSet;
SaveAppZoneHistory();
return true;
}
}
}
std::unordered_map<DWORD, HWND> processIdToHandleMap{};
processIdToHandleMap[processId] = window;
FancyZonesDataTypes::AppZoneHistoryData data{ .processIdToHandleMap = processIdToHandleMap,
.zoneSetUuid = zoneSetId,
.deviceId = deviceId,
.zoneIndexSet = zoneIndexSet };
if (appZoneHistoryMap.contains(processPath))
{
// application already has history but on other desktop, add with new desktop info
appZoneHistoryMap[processPath].push_back(data);
}
else
{
// new application, create entry in app zone history map
appZoneHistoryMap[processPath] = std::vector<FancyZonesDataTypes::AppZoneHistoryData>{ data };
}
SaveAppZoneHistory();
return true;
}
void FancyZonesData::SetActiveZoneSet(const FancyZonesDataTypes::DeviceIdData& deviceId, const FancyZonesDataTypes::ZoneSetData& data)
{
std::scoped_lock lock{ dataLock };
@@ -635,23 +436,17 @@ void FancyZonesData::LoadFancyZonesData()
{
if (!std::filesystem::exists(zonesSettingsFileName))
{
SaveAppZoneHistoryAndZoneSettings();
SaveZoneSettings();
AppZoneHistory::instance().SaveData();
}
else
{
json::JsonObject fancyZonesDataJSON = GetPersistFancyZonesJSON();
appZoneHistoryMap = JSONHelpers::ParseAppZoneHistory(fancyZonesDataJSON);
deviceInfoMap = JSONHelpers::ParseDeviceInfos(fancyZonesDataJSON);
}
}
void FancyZonesData::SaveAppZoneHistoryAndZoneSettings() const
{
SaveZoneSettings();
SaveAppZoneHistory();
}
void FancyZonesData::SaveZoneSettings() const
{
_TRACER_;
@@ -684,41 +479,6 @@ void FancyZonesData::SaveZoneSettings() const
}
}
void FancyZonesData::SaveAppZoneHistory() const
{
_TRACER_;
std::scoped_lock lock{ dataLock };
bool dirtyFlag = false;
std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>> updatedHistory;
if (m_virtualDesktopCheckCallback)
{
for (const auto& [path, dataVector] : appZoneHistoryMap)
{
auto updatedVector = dataVector;
for (auto& data : updatedVector)
{
if (!m_virtualDesktopCheckCallback(data.deviceId.virtualDesktopId))
{
data.deviceId.virtualDesktopId = GUID_NULL;
dirtyFlag = true;
}
}
updatedHistory.insert(std::make_pair(path, updatedVector));
}
}
if (dirtyFlag)
{
JSONHelpers::SaveAppZoneHistory(appZoneHistoryFileName, updatedHistory);
}
else
{
JSONHelpers::SaveAppZoneHistory(appZoneHistoryFileName, appZoneHistoryMap);
}
}
void FancyZonesData::SaveFancyZonesEditorParameters(bool spanZonesAcrossMonitors, const std::wstring& virtualDesktopId, const HMONITOR& targetMonitor, const std::vector<std::pair<HMONITOR, MONITORINFOEX>>& allMonitors) const
{
JSONHelpers::EditorArgs argsJson; /* json arguments */
@@ -782,31 +542,3 @@ void FancyZonesData::SaveFancyZonesEditorParameters(bool spanZonesAcrossMonitors
json::to_file(editorParametersFileName, JSONHelpers::EditorArgs::ToJson(argsJson));
}
void FancyZonesData::RemoveDesktopAppZoneHistory(GUID desktopId)
{
for (auto it = std::begin(appZoneHistoryMap); it != std::end(appZoneHistoryMap);)
{
auto& perDesktopData = it->second;
for (auto desktopIt = std::begin(perDesktopData); desktopIt != std::end(perDesktopData);)
{
if (desktopIt->deviceId.virtualDesktopId == desktopId)
{
desktopIt = perDesktopData.erase(desktopIt);
}
else
{
++desktopIt;
}
}
if (perDesktopData.empty())
{
it = appZoneHistoryMap.erase(it);
}
else
{
++it;
}
}
}

View File

@@ -48,7 +48,6 @@ public:
std::optional<FancyZonesDataTypes::DeviceInfoData> FindDeviceInfo(const FancyZonesDataTypes::DeviceIdData& id) const;
const JSONHelpers::TDeviceInfoMap& GetDeviceInfoMap() const;
const std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>>& GetAppZoneHistoryMap() const;
inline const std::wstring& GetZonesSettingsFileName() const
{
@@ -65,20 +64,12 @@ public:
void SyncVirtualDesktops(GUID desktopId);
void RemoveDeletedDesktops(const std::vector<GUID>& activeDesktops);
bool IsAnotherWindowOfApplicationInstanceZoned(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId) const;
void UpdateProcessIdToHandleMap(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId);
ZoneIndexSet GetAppLastZoneIndexSet(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring_view& zoneSetId) const;
bool RemoveAppLastZone(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring_view& zoneSetId);
bool SetAppLastZones(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring& zoneSetId, const ZoneIndexSet& zoneIndexSet);
void SetActiveZoneSet(const FancyZonesDataTypes::DeviceIdData& deviceId, const FancyZonesDataTypes::ZoneSetData& zoneSet);
json::JsonObject GetPersistFancyZonesJSON();
void LoadFancyZonesData();
void SaveAppZoneHistoryAndZoneSettings() const;
void SaveZoneSettings() const;
void SaveAppZoneHistory() const;
void SaveFancyZonesEditorParameters(bool spanZonesAcrossMonitors, const std::wstring& virtualDesktopId, const HMONITOR& targetMonitor, const std::vector<std::pair<HMONITOR, MONITORINFOEX>>& allMonitors) const;
@@ -123,8 +114,6 @@ private:
return result + L"\\" + std::wstring(L"zones-settings.json");
}
#endif
void RemoveDesktopAppZoneHistory(GUID desktopId);
// Maps app path to app's zone history data
std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>> appZoneHistoryMap{};
// Maps device unique ID to device data

View File

@@ -0,0 +1,327 @@
#include "../pch.h"
#include "AppZoneHistory.h"
#include <common/logger/call_tracer.h>
#include <common/logger/logger.h>
#include <common/utils/process_path.h>
#include <FancyZonesLib/FancyZonesWindowProperties.h>
#include <FancyZonesLib/JsonHelpers.h>
AppZoneHistory::AppZoneHistory()
{
}
AppZoneHistory& AppZoneHistory::instance()
{
static AppZoneHistory self;
return self;
}
void AppZoneHistory::SetVirtualDesktopCheckCallback(std::function<bool(GUID)> callback)
{
m_virtualDesktopCheckCallback = callback;
}
void AppZoneHistory::LoadData()
{
auto file = AppZoneHistoryFileName();
auto data = json::from_file(file);
try
{
if (data)
{
m_history = JSONHelpers::ParseAppZoneHistory(data.value());
}
else
{
m_history.clear();
Logger::error(L"app-zone-history.json file is missing or malformed");
}
}
catch (const winrt::hresult_error& e)
{
Logger::error(L"Parsing app-zone-history error: {}", e.message());
}
}
void AppZoneHistory::SaveData()
{
_TRACER_;
bool dirtyFlag = false;
std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>> updatedHistory;
if (m_virtualDesktopCheckCallback)
{
for (const auto& [path, dataVector] : m_history)
{
auto updatedVector = dataVector;
for (auto& data : updatedVector)
{
if (!m_virtualDesktopCheckCallback(data.deviceId.virtualDesktopId))
{
data.deviceId.virtualDesktopId = GUID_NULL;
dirtyFlag = true;
}
}
updatedHistory.insert(std::make_pair(path, updatedVector));
}
}
if (dirtyFlag)
{
JSONHelpers::SaveAppZoneHistory(AppZoneHistoryFileName(), updatedHistory);
}
else
{
JSONHelpers::SaveAppZoneHistory(AppZoneHistoryFileName(), m_history);
}
}
bool AppZoneHistory::SetAppLastZones(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring& zoneSetId, const ZoneIndexSet& zoneIndexSet)
{
_TRACER_;
if (IsAnotherWindowOfApplicationInstanceZoned(window, deviceId))
{
return false;
}
auto processPath = get_process_path(window);
if (processPath.empty())
{
return false;
}
DWORD processId = 0;
GetWindowThreadProcessId(window, &processId);
auto history = m_history.find(processPath);
if (history != std::end(m_history))
{
auto& perDesktopData = history->second;
for (auto& data : perDesktopData)
{
if (data.deviceId.isEqualWithNullVirtualDesktopId(deviceId))
{
// application already has history on this work area, update it with new window position
data.processIdToHandleMap[processId] = window;
data.zoneSetUuid = zoneSetId;
data.zoneIndexSet = zoneIndexSet;
SaveData();
return true;
}
}
}
std::unordered_map<DWORD, HWND> processIdToHandleMap{};
processIdToHandleMap[processId] = window;
FancyZonesDataTypes::AppZoneHistoryData data{ .processIdToHandleMap = processIdToHandleMap,
.zoneSetUuid = zoneSetId,
.deviceId = deviceId,
.zoneIndexSet = zoneIndexSet };
if (m_history.contains(processPath))
{
// application already has history but on other desktop, add with new desktop info
m_history[processPath].push_back(data);
}
else
{
// new application, create entry in app zone history map
m_history[processPath] = std::vector<FancyZonesDataTypes::AppZoneHistoryData>{ data };
}
SaveData();
return true;
}
bool AppZoneHistory::RemoveAppLastZone(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring_view& zoneSetId)
{
_TRACER_;
auto processPath = get_process_path(window);
if (!processPath.empty())
{
auto history = m_history.find(processPath);
if (history != std::end(m_history))
{
auto& perDesktopData = history->second;
for (auto data = std::begin(perDesktopData); data != std::end(perDesktopData);)
{
if (data->deviceId.isEqualWithNullVirtualDesktopId(deviceId) && data->zoneSetUuid == zoneSetId)
{
if (!IsAnotherWindowOfApplicationInstanceZoned(window, deviceId))
{
DWORD processId = 0;
GetWindowThreadProcessId(window, &processId);
data->processIdToHandleMap.erase(processId);
}
// if there is another instance of same application placed in the same zone don't erase history
ZoneIndex windowZoneStamp = reinterpret_cast<ZoneIndex>(::GetProp(window, ZonedWindowProperties::PropertyMultipleZoneID));
for (auto placedWindow : data->processIdToHandleMap)
{
ZoneIndex placedWindowZoneStamp = reinterpret_cast<ZoneIndex>(::GetProp(placedWindow.second, ZonedWindowProperties::PropertyMultipleZoneID));
if (IsWindow(placedWindow.second) && (windowZoneStamp == placedWindowZoneStamp))
{
return false;
}
}
data = perDesktopData.erase(data);
if (perDesktopData.empty())
{
m_history.erase(processPath);
}
SaveData();
return true;
}
else
{
++data;
}
}
}
}
return false;
}
void AppZoneHistory::RemoveApp(const std::wstring& appPath)
{
m_history.erase(appPath);
}
const AppZoneHistory::TAppZoneHistoryMap& AppZoneHistory::GetFullAppZoneHistory() const noexcept
{
return m_history;
}
std::optional<FancyZonesDataTypes::AppZoneHistoryData> AppZoneHistory::GetZoneHistory(const std::wstring& appPath, const FancyZonesDataTypes::DeviceIdData& deviceId) const noexcept
{
auto iter = m_history.find(appPath);
if (iter != m_history.end())
{
auto historyVector = iter->second;
for (const auto& history : historyVector)
{
if (history.deviceId.isEqualWithNullVirtualDesktopId(deviceId))
{
return history;
}
}
}
return std::nullopt;
}
bool AppZoneHistory::IsAnotherWindowOfApplicationInstanceZoned(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId) const noexcept
{
auto processPath = get_process_path(window);
if (!processPath.empty())
{
auto history = m_history.find(processPath);
if (history != std::end(m_history))
{
auto& perDesktopData = history->second;
for (auto& data : perDesktopData)
{
if (data.deviceId.isEqualWithNullVirtualDesktopId(deviceId))
{
DWORD processId = 0;
GetWindowThreadProcessId(window, &processId);
auto processIdIt = data.processIdToHandleMap.find(processId);
if (processIdIt == std::end(data.processIdToHandleMap))
{
return false;
}
else if (processIdIt->second != window && IsWindow(processIdIt->second))
{
return true;
}
}
}
}
}
return false;
}
void AppZoneHistory::UpdateProcessIdToHandleMap(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId)
{
auto processPath = get_process_path(window);
if (!processPath.empty())
{
auto history = m_history.find(processPath);
if (history != std::end(m_history))
{
auto& perDesktopData = history->second;
for (auto& data : perDesktopData)
{
if (data.deviceId.isEqualWithNullVirtualDesktopId(deviceId))
{
DWORD processId = 0;
GetWindowThreadProcessId(window, &processId);
data.processIdToHandleMap[processId] = window;
break;
}
}
}
}
}
ZoneIndexSet AppZoneHistory::GetAppLastZoneIndexSet(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring_view& zoneSetId) const
{
auto processPath = get_process_path(window);
if (!processPath.empty())
{
auto history = m_history.find(processPath);
if (history != std::end(m_history))
{
const auto& perDesktopData = history->second;
for (const auto& data : perDesktopData)
{
if (data.zoneSetUuid == zoneSetId && data.deviceId.isEqualWithNullVirtualDesktopId(deviceId))
{
return data.zoneIndexSet;
}
}
}
}
return {};
}
void AppZoneHistory::RemoveDesktopAppZoneHistory(GUID desktopId)
{
for (auto it = std::begin(m_history); it != std::end(m_history);)
{
auto& perDesktopData = it->second;
for (auto desktopIt = std::begin(perDesktopData); desktopIt != std::end(perDesktopData);)
{
if (desktopIt->deviceId.virtualDesktopId == desktopId)
{
desktopIt = perDesktopData.erase(desktopIt);
}
else
{
++desktopIt;
}
}
if (perDesktopData.empty())
{
it = m_history.erase(it);
}
else
{
++it;
}
}
}

View File

@@ -0,0 +1,49 @@
#pragma once
#include <FancyZonesLib/FancyZonesDataTypes.h>
#include <FancyZonesLib/ModuleConstants.h>
#include <common/SettingsAPI/settings_helpers.h>
class AppZoneHistory
{
public:
using TAppZoneHistoryMap = std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>>;
static AppZoneHistory& instance();
inline static std::wstring AppZoneHistoryFileName()
{
std::wstring saveFolderPath = PTSettingsHelper::get_module_save_folder_location(NonLocalizable::ModuleKey);
#if defined(UNIT_TESTS)
return saveFolderPath + L"\\test-app-zone-history.json";
#endif
return saveFolderPath + L"\\app-zone-history.json";
}
void SetVirtualDesktopCheckCallback(std::function<bool(GUID)> callback);
void LoadData();
void SaveData();
bool SetAppLastZones(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring& zoneSetId, const ZoneIndexSet& zoneIndexSet);
bool RemoveAppLastZone(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring_view& zoneSetId);
void RemoveApp(const std::wstring& appPath);
const TAppZoneHistoryMap& GetFullAppZoneHistory() const noexcept;
std::optional<FancyZonesDataTypes::AppZoneHistoryData> GetZoneHistory(const std::wstring& appPath, const FancyZonesDataTypes::DeviceIdData& deviceId) const noexcept;
bool IsAnotherWindowOfApplicationInstanceZoned(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId) const noexcept;
void UpdateProcessIdToHandleMap(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId);
ZoneIndexSet GetAppLastZoneIndexSet(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring_view& zoneSetId) const;
void RemoveDesktopAppZoneHistory(GUID desktopId);
private:
AppZoneHistory();
~AppZoneHistory() = default;
TAppZoneHistoryMap m_history;
std::function<bool(GUID)> m_virtualDesktopCheckCallback;
};

View File

@@ -38,6 +38,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="FancyZonesData\CustomLayouts.h" />
<ClInclude Include="FancyZonesData\AppZoneHistory.h" />
<ClInclude Include="FancyZones.h" />
<ClInclude Include="FancyZonesDataTypes.h" />
<ClInclude Include="FancyZonesData\LayoutTemplates.h" />
@@ -68,6 +69,10 @@
<ClInclude Include="ZonesOverlay.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="FancyZonesData\AppZoneHistory.cpp">
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../pch.h</PrecompiledHeaderFile>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../pch.h</PrecompiledHeaderFile>
</ClCompile>
<ClCompile Include="FancyZonesData\CustomLayouts.cpp">
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../pch.h</PrecompiledHeaderFile>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../pch.h</PrecompiledHeaderFile>

View File

@@ -90,6 +90,9 @@
<ClInclude Include="GuidUtils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FancyZonesData\AppZoneHistory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FancyZonesData\CustomLayouts.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -167,6 +170,9 @@
<ClCompile Include="FancyZonesData\LayoutHotkeys.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FancyZonesData\AppZoneHistory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

View File

@@ -7,7 +7,7 @@
#include <common/utils/elevation.h>
#include <common/utils/resources.h>
#include "FancyZonesData.h"
#include "FancyZonesData/AppZoneHistory.h"
#include "Settings.h"
#include "WorkArea.h"
#include "util.h"
@@ -261,7 +261,7 @@ void WindowMoveHandler::MoveSizeEnd(HWND window, POINT const& ptScreen, const st
wil::unique_cotaskmem_string guidString;
if (SUCCEEDED_LOG(StringFromCLSID(zoneSet->Id(), &guidString)))
{
FancyZonesDataInstance().RemoveAppLastZone(window, workAreaPtr->UniqueId(), guidString.get());
AppZoneHistory::instance().RemoveAppLastZone(window, workAreaPtr->UniqueId(), guidString.get());
}
}
}

View File

@@ -5,6 +5,7 @@
#include <common/logger/logger.h>
#include "FancyZonesData.h"
#include "FancyZonesData/AppZoneHistory.h"
#include "FancyZonesDataTypes.h"
#include "ZonesOverlay.h"
#include "trace.h"
@@ -379,7 +380,7 @@ WorkArea::SaveWindowProcessToZoneIndex(HWND window) noexcept
OLECHAR* guidString;
if (StringFromCLSID(m_zoneSet->Id(), &guidString) == S_OK)
{
FancyZonesDataInstance().SetAppLastZones(window, m_uniqueId, guidString, zoneIndexSet);
AppZoneHistory::instance().SetAppLastZones(window, m_uniqueId, guidString, zoneIndexSet);
}
CoTaskMemFree(guidString);
@@ -395,7 +396,7 @@ WorkArea::GetWindowZoneIndexes(HWND window) const noexcept
wil::unique_cotaskmem_string zoneSetId;
if (SUCCEEDED(StringFromCLSID(m_zoneSet->Id(), &zoneSetId)))
{
return FancyZonesDataInstance().GetAppLastZoneIndexSet(window, m_uniqueId, zoneSetId.get());
return AppZoneHistory::instance().GetAppLastZoneIndexSet(window, m_uniqueId, zoneSetId.get());
}
}
return {};

View File

@@ -3,6 +3,7 @@
#include "FancyZonesLib/ZoneSet.h"
#include "FancyZonesLib/Settings.h"
#include "FancyZonesLib/FancyZonesData.h"
#include "FancyZonesData/AppZoneHistory.h"
#include "FancyZonesLib/FancyZonesData/CustomLayouts.h"
#include "FancyZonesLib/FancyZonesData/LayoutHotkeys.h"
#include "FancyZonesLib/FancyZonesDataTypes.h"
@@ -145,7 +146,7 @@ void Trace::FancyZones::OnKeyDown(DWORD vkCode, bool win, bool control, bool inM
void Trace::FancyZones::DataChanged() noexcept
{
const FancyZonesData& data = FancyZonesDataInstance();
int appsHistorySize = static_cast<int>(data.GetAppZoneHistoryMap().size());
int appsHistorySize = static_cast<int>(AppZoneHistory::instance().GetFullAppZoneHistory().size());
const auto& customZones = CustomLayouts::instance().GetAllLayouts();
const auto& devices = data.GetDeviceInfoMap();
auto quickKeysCount = LayoutHotkeys::instance().GetHotkeysCount();