mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-05 10:46:33 +02:00
[FancyZones] Split zones-settings: devices -> applied layouts (#15779)
This commit is contained in:
@@ -12,9 +12,11 @@
|
||||
#include <common/SettingsAPI/FileWatcher.h>
|
||||
|
||||
#include <FancyZonesLib/FancyZonesData.h>
|
||||
#include <FancyZonesLib/FancyZonesData/AppliedLayouts.h>
|
||||
#include <FancyZonesLib/FancyZonesData/AppZoneHistory.h>
|
||||
#include <FancyZonesLib/FancyZonesData/CustomLayouts.h>
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutHotkeys.h>
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutTemplates.h>
|
||||
#include <FancyZonesLib/FancyZonesWindowProperties.h>
|
||||
#include <FancyZonesLib/FancyZonesWinHookEventIDs.h>
|
||||
#include <FancyZonesLib/MonitorUtils.h>
|
||||
@@ -57,9 +59,6 @@ public:
|
||||
m_windowMoveHandler(settings, [this]() {
|
||||
PostMessageW(m_window, WM_PRIV_LOCATIONCHANGE, NULL, NULL);
|
||||
}),
|
||||
m_zonesSettingsFileWatcher(FancyZonesDataInstance().GetZonesSettingsFileName(), [this]() {
|
||||
PostMessageW(m_window, WM_PRIV_FILE_UPDATE, NULL, NULL);
|
||||
}),
|
||||
m_settingsFileWatcher(FancyZonesDataInstance().GetSettingsFileName(), [this]() {
|
||||
PostMessageW(m_window, WM_PRIV_SETTINGS_CHANGED, NULL, NULL);
|
||||
}),
|
||||
@@ -73,8 +72,10 @@ public:
|
||||
this->disableModuleCallback = std::move(disableModuleCallback);
|
||||
|
||||
FancyZonesDataInstance().ReplaceZoneSettingsFileFromOlderVersions();
|
||||
LayoutHotkeys::instance().LoadData();
|
||||
LayoutTemplates::instance().LoadData();
|
||||
CustomLayouts::instance().LoadData();
|
||||
LayoutHotkeys::instance().LoadData();
|
||||
AppliedLayouts::instance().LoadData();
|
||||
AppZoneHistory::instance().LoadData();
|
||||
}
|
||||
|
||||
@@ -199,7 +200,6 @@ private:
|
||||
MonitorWorkAreaHandler m_workAreaHandler;
|
||||
VirtualDesktop m_virtualDesktop;
|
||||
|
||||
FileWatcher m_zonesSettingsFileWatcher;
|
||||
FileWatcher m_settingsFileWatcher;
|
||||
|
||||
winrt::com_ptr<IFancyZonesSettings> m_settings{};
|
||||
@@ -276,7 +276,7 @@ FancyZones::Run() noexcept
|
||||
}
|
||||
});
|
||||
|
||||
FancyZonesDataInstance().SetVirtualDesktopCheckCallback(std::bind(&VirtualDesktop::IsVirtualDesktopIdSavedInRegistry, &m_virtualDesktop, std::placeholders::_1));
|
||||
AppliedLayouts::instance().SetVirtualDesktopCheckCallback(std::bind(&VirtualDesktop::IsVirtualDesktopIdSavedInRegistry, &m_virtualDesktop, std::placeholders::_1));
|
||||
AppZoneHistory::instance().SetVirtualDesktopCheckCallback(std::bind(&VirtualDesktop::IsVirtualDesktopIdSavedInRegistry, &m_virtualDesktop, std::placeholders::_1));
|
||||
}
|
||||
|
||||
@@ -336,7 +336,7 @@ std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet> FancyZones::GetAppZoneHistory
|
||||
void FancyZones::MoveWindowIntoZone(HWND window, winrt::com_ptr<IWorkArea> workArea, const ZoneIndexSet& zoneIndexSet) noexcept
|
||||
{
|
||||
_TRACER_;
|
||||
auto& fancyZonesData = FancyZonesDataInstance();
|
||||
|
||||
if (!AppZoneHistory::instance().IsAnotherWindowOfApplicationInstanceZoned(window, workArea->UniqueId()))
|
||||
{
|
||||
if (workArea)
|
||||
@@ -771,19 +771,23 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
|
||||
auto hwnd = reinterpret_cast<HWND>(wparam);
|
||||
WindowCreated(hwnd);
|
||||
}
|
||||
else if (message == WM_PRIV_FILE_UPDATE)
|
||||
{
|
||||
FancyZonesDataInstance().LoadFancyZonesData();
|
||||
UpdateZoneSets();
|
||||
}
|
||||
else if (message == WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE)
|
||||
{
|
||||
LayoutHotkeys::instance().LoadData();
|
||||
}
|
||||
else if (message == WM_PRIV_LAYOUT_TEMPLATES_FILE_UPDATE)
|
||||
{
|
||||
LayoutTemplates::instance().LoadData();
|
||||
}
|
||||
else if (message == WM_PRIV_CUSTOM_LAYOUTS_FILE_UPDATE)
|
||||
{
|
||||
CustomLayouts::instance().LoadData();
|
||||
}
|
||||
else if (message == WM_PRIV_APPLIED_LAYOUTS_FILE_UPDATE)
|
||||
{
|
||||
AppliedLayouts::instance().LoadData();
|
||||
UpdateZoneSets();
|
||||
}
|
||||
else if (message == WM_PRIV_QUICK_LAYOUT_KEY)
|
||||
{
|
||||
ApplyQuickLayout(static_cast<int>(lparam));
|
||||
@@ -895,7 +899,7 @@ void FancyZones::AddWorkArea(HMONITOR monitor, const std::wstring& deviceId) noe
|
||||
if (workArea)
|
||||
{
|
||||
m_workAreaHandler.AddWorkArea(m_currentDesktopId, monitor, workArea);
|
||||
FancyZonesDataInstance().SaveZoneSettings();
|
||||
AppliedLayouts::instance().SaveData();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1217,10 +1221,12 @@ void FancyZones::RegisterVirtualDesktopUpdates() noexcept
|
||||
if (guids.has_value())
|
||||
{
|
||||
m_workAreaHandler.RegisterUpdates(*guids);
|
||||
FancyZonesDataInstance().RemoveDeletedDesktops(*guids);
|
||||
AppZoneHistory::instance().RemoveDeletedVirtualDesktops(*guids);
|
||||
AppliedLayouts::instance().RemoveDeletedVirtualDesktops(*guids);
|
||||
}
|
||||
|
||||
FancyZonesDataInstance().SyncVirtualDesktops(m_currentDesktopId);
|
||||
AppZoneHistory::instance().SyncVirtualDesktops(m_currentDesktopId);
|
||||
AppliedLayouts::instance().SyncVirtualDesktops(m_currentDesktopId);
|
||||
}
|
||||
|
||||
void FancyZones::UpdateHotkey(int hotkeyId, const PowerToysSettings::HotkeyObject& hotkeyObject, bool enable) noexcept
|
||||
@@ -1269,8 +1275,8 @@ void FancyZones::OnSettingsChanged() noexcept
|
||||
void FancyZones::OnEditorExitEvent() noexcept
|
||||
{
|
||||
// Collect information about changes in zone layout after editor exited.
|
||||
FancyZonesDataInstance().LoadFancyZonesData();
|
||||
FancyZonesDataInstance().SyncVirtualDesktops(m_currentDesktopId);
|
||||
AppZoneHistory::instance().SyncVirtualDesktops(m_currentDesktopId);
|
||||
AppliedLayouts::instance().SyncVirtualDesktops(m_currentDesktopId);
|
||||
UpdateZoneSets();
|
||||
}
|
||||
|
||||
@@ -1332,8 +1338,8 @@ void FancyZones::ApplyQuickLayout(int key) noexcept
|
||||
FancyZonesDataTypes::ZoneSetData data{ .uuid = uuidStr.value(), .type = FancyZonesDataTypes::ZoneSetLayoutType::Custom };
|
||||
|
||||
auto workArea = m_workAreaHandler.GetWorkAreaFromCursor(m_currentDesktopId);
|
||||
FancyZonesDataInstance().SetActiveZoneSet(workArea->UniqueId(), data);
|
||||
FancyZonesDataInstance().SaveZoneSettings();
|
||||
AppliedLayouts::instance().ApplyLayout(workArea->UniqueId(), data);
|
||||
AppliedLayouts::instance().SaveData();
|
||||
UpdateZoneSets();
|
||||
FlashZones();
|
||||
}
|
||||
|
||||
@@ -1,149 +1,23 @@
|
||||
#include "pch.h"
|
||||
#include "FancyZonesData.h"
|
||||
#include "FancyZonesDataTypes.h"
|
||||
#include "JsonHelpers.h"
|
||||
#include "ZoneSet.h"
|
||||
#include "Settings.h"
|
||||
#include "GuidUtils.h"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include <common/Display/dpi_aware.h>
|
||||
#include <common/logger/call_tracer.h>
|
||||
#include <common/utils/json.h>
|
||||
#include <FancyZonesLib/util.h>
|
||||
#include <FancyZonesLib/FancyZonesWindowProperties.h>
|
||||
|
||||
#include <shlwapi.h>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
#include <unordered_set>
|
||||
#include <common/utils/process_path.h>
|
||||
#include <common/logger/logger.h>
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
|
||||
#include <FancyZonesLib/FancyZonesData/AppZoneHistory.h>
|
||||
#include <FancyZonesLib/FancyZonesData/CustomLayouts.h>
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutHotkeys.h>
|
||||
#include <FancyZonesLib/JsonHelpers.h>
|
||||
#include <FancyZonesLib/ModuleConstants.h>
|
||||
#include <FancyZonesLib/util.h>
|
||||
|
||||
// Non-localizable strings
|
||||
namespace NonLocalizable
|
||||
{
|
||||
const wchar_t NullStr[] = L"null";
|
||||
|
||||
const wchar_t FancyZonesSettingsFile[] = L"settings.json";
|
||||
const wchar_t FancyZonesDataFile[] = L"zones-settings.json";
|
||||
const wchar_t FancyZonesAppZoneHistoryFile[] = L"app-zone-history.json";
|
||||
const wchar_t FancyZonesEditorParametersFile[] = L"editor-parameters.json";
|
||||
const wchar_t RegistryPath[] = L"Software\\SuperFancyZones";
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
std::wstring ExtractVirtualDesktopId(const std::wstring& deviceId)
|
||||
{
|
||||
// Format: <device-id>_<resolution>_<virtual-desktop-id>
|
||||
return deviceId.substr(deviceId.rfind('_') + 1);
|
||||
}
|
||||
|
||||
const std::wstring& GetTempDirPath()
|
||||
{
|
||||
static std::wstring tmpDirPath;
|
||||
static std::once_flag flag;
|
||||
|
||||
std::call_once(flag, []() {
|
||||
wchar_t buffer[MAX_PATH];
|
||||
|
||||
auto charsWritten = GetTempPath(MAX_PATH, buffer);
|
||||
if (charsWritten > MAX_PATH || (charsWritten == 0))
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
tmpDirPath = std::wstring{ buffer };
|
||||
});
|
||||
|
||||
return tmpDirPath;
|
||||
}
|
||||
|
||||
bool DeleteRegistryKey(HKEY hKeyRoot, LPTSTR lpSubKey)
|
||||
{
|
||||
// First, see if we can delete the key without having to recurse.
|
||||
if (ERROR_SUCCESS == RegDeleteKey(hKeyRoot, lpSubKey))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
HKEY hKey;
|
||||
if (ERROR_SUCCESS != RegOpenKeyEx(hKeyRoot, lpSubKey, 0, KEY_READ, &hKey))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for an ending slash and add one if it is missing.
|
||||
LPTSTR lpEnd = lpSubKey + lstrlen(lpSubKey);
|
||||
|
||||
if (*(lpEnd - 1) != TEXT('\\'))
|
||||
{
|
||||
*lpEnd = TEXT('\\');
|
||||
lpEnd++;
|
||||
*lpEnd = TEXT('\0');
|
||||
}
|
||||
|
||||
// Enumerate the keys
|
||||
|
||||
DWORD dwSize = MAX_PATH;
|
||||
TCHAR szName[MAX_PATH];
|
||||
FILETIME ftWrite;
|
||||
auto result = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite);
|
||||
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
do
|
||||
{
|
||||
*lpEnd = TEXT('\0');
|
||||
StringCchCat(lpSubKey, MAX_PATH * 2, szName);
|
||||
|
||||
if (!DeleteRegistryKey(hKeyRoot, lpSubKey))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
dwSize = MAX_PATH;
|
||||
result = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite);
|
||||
} while (result == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
lpEnd--;
|
||||
*lpEnd = TEXT('\0');
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
||||
// Try again to delete the root key.
|
||||
if (ERROR_SUCCESS == RegDeleteKey(hKeyRoot, lpSubKey))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DeleteFancyZonesRegistryData()
|
||||
{
|
||||
wchar_t key[256];
|
||||
StringCchPrintf(key, ARRAYSIZE(key), L"%s", NonLocalizable::RegistryPath);
|
||||
|
||||
HKEY hKey;
|
||||
if (ERROR_FILE_NOT_FOUND == RegOpenKeyEx(HKEY_CURRENT_USER, key, 0, KEY_READ, &hKey))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DeleteRegistryKey(HKEY_CURRENT_USER, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FancyZonesData& FancyZonesDataInstance()
|
||||
@@ -157,8 +31,8 @@ FancyZonesData::FancyZonesData()
|
||||
std::wstring saveFolderPath = PTSettingsHelper::get_module_save_folder_location(NonLocalizable::ModuleKey);
|
||||
|
||||
settingsFileName = saveFolderPath + L"\\" + std::wstring(NonLocalizable::FancyZonesSettingsFile);
|
||||
zonesSettingsFileName = saveFolderPath + L"\\" + std::wstring(NonLocalizable::FancyZonesDataFile);
|
||||
appZoneHistoryFileName = saveFolderPath + L"\\" + std::wstring(NonLocalizable::FancyZonesAppZoneHistoryFile);
|
||||
zonesSettingsFileName = saveFolderPath + L"\\" + std::wstring(NonLocalizable::FancyZonesDataFile);
|
||||
editorParametersFileName = saveFolderPath + L"\\" + std::wstring(NonLocalizable::FancyZonesEditorParametersFile);
|
||||
}
|
||||
|
||||
@@ -166,9 +40,15 @@ void FancyZonesData::ReplaceZoneSettingsFileFromOlderVersions()
|
||||
{
|
||||
if (std::filesystem::exists(zonesSettingsFileName))
|
||||
{
|
||||
json::JsonObject fancyZonesDataJSON = GetPersistFancyZonesJSON();
|
||||
Logger::info("Replace zones-settings file");
|
||||
|
||||
//deviceInfoMap = JSONHelpers::ParseDeviceInfos(fancyZonesDataJSON);
|
||||
json::JsonObject fancyZonesDataJSON = JSONHelpers::GetPersistFancyZonesJSON(zonesSettingsFileName, appZoneHistoryFileName);
|
||||
|
||||
auto deviceInfoMap = JSONHelpers::ParseDeviceInfos(fancyZonesDataJSON);
|
||||
if (deviceInfoMap)
|
||||
{
|
||||
JSONHelpers::SaveAppliedLayouts(deviceInfoMap.value());
|
||||
}
|
||||
|
||||
auto customLayouts = JSONHelpers::ParseCustomZoneSets(fancyZonesDataJSON);
|
||||
if (customLayouts)
|
||||
@@ -187,295 +67,8 @@ void FancyZonesData::ReplaceZoneSettingsFileFromOlderVersions()
|
||||
{
|
||||
JSONHelpers::SaveLayoutHotkeys(quickKeysMap.value());
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: remove zone-settings.json after getting all info from it
|
||||
}
|
||||
|
||||
void FancyZonesData::SetVirtualDesktopCheckCallback(std::function<bool(GUID)> callback)
|
||||
{
|
||||
m_virtualDesktopCheckCallback = callback;
|
||||
}
|
||||
|
||||
const JSONHelpers::TDeviceInfoMap& FancyZonesData::GetDeviceInfoMap() const
|
||||
{
|
||||
std::scoped_lock lock{ dataLock };
|
||||
return deviceInfoMap;
|
||||
}
|
||||
|
||||
std::optional<FancyZonesDataTypes::DeviceInfoData> FancyZonesData::FindDeviceInfo(const FancyZonesDataTypes::DeviceIdData& id) const
|
||||
{
|
||||
std::scoped_lock lock{ dataLock };
|
||||
for (const auto& [deviceId, deviceInfo] : deviceInfoMap)
|
||||
{
|
||||
if (id.isEqualWithNullVirtualDesktopId(deviceId))
|
||||
{
|
||||
return deviceInfo;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool FancyZonesData::AddDevice(const FancyZonesDataTypes::DeviceIdData& deviceId)
|
||||
{
|
||||
_TRACER_;
|
||||
using namespace FancyZonesDataTypes;
|
||||
|
||||
auto deviceInfo = FindDeviceInfo(deviceId);
|
||||
|
||||
std::scoped_lock lock{ dataLock };
|
||||
|
||||
if (!deviceInfo.has_value())
|
||||
{
|
||||
wil::unique_cotaskmem_string virtualDesktopId;
|
||||
if (SUCCEEDED(StringFromCLSID(deviceId.virtualDesktopId, &virtualDesktopId)))
|
||||
{
|
||||
Logger::info(L"Create new device on virtual desktop {}", virtualDesktopId.get());
|
||||
}
|
||||
|
||||
// Creates default entry in map when WorkArea is created
|
||||
GUID guid;
|
||||
auto result{ CoCreateGuid(&guid) };
|
||||
wil::unique_cotaskmem_string guidString;
|
||||
if (result == S_OK && SUCCEEDED(StringFromCLSID(guid, &guidString)))
|
||||
{
|
||||
const ZoneSetData zoneSetData{ guidString.get(), ZoneSetLayoutType::PriorityGrid };
|
||||
DeviceInfoData defaultDeviceInfoData{ zoneSetData, DefaultValues::ShowSpacing, DefaultValues::Spacing, DefaultValues::ZoneCount, DefaultValues::SensitivityRadius };
|
||||
deviceInfoMap[deviceId] = std::move(defaultDeviceInfoData);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::error("Failed to create an ID for the new layout");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void FancyZonesData::CloneDeviceInfo(const FancyZonesDataTypes::DeviceIdData& source, const FancyZonesDataTypes::DeviceIdData& destination)
|
||||
{
|
||||
if (source == destination)
|
||||
{
|
||||
return;
|
||||
}
|
||||
std::scoped_lock lock{ dataLock };
|
||||
|
||||
// The source virtual desktop is deleted, simply ignore it.
|
||||
if (!FindDeviceInfo(source).has_value())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
deviceInfoMap[destination] = deviceInfoMap[source];
|
||||
}
|
||||
|
||||
void FancyZonesData::SyncVirtualDesktops(GUID currentVirtualDesktopId)
|
||||
{
|
||||
_TRACER_;
|
||||
// Explorer persists current virtual desktop identifier to registry on a per session basis,
|
||||
// but only after first virtual desktop switch happens. If the user hasn't switched virtual
|
||||
// desktops in this session value in registry will be empty and we will use default GUID in
|
||||
// that case (00000000-0000-0000-0000-000000000000).
|
||||
// This method will go through all our persisted data with default GUID and update it with
|
||||
// valid one.
|
||||
|
||||
std::scoped_lock lock{ dataLock };
|
||||
bool dirtyFlag = false;
|
||||
|
||||
for (auto& [path, perDesktopData] : appZoneHistoryMap)
|
||||
{
|
||||
for (auto& data : perDesktopData)
|
||||
{
|
||||
if (data.deviceId.virtualDesktopId == GUID_NULL)
|
||||
{
|
||||
data.deviceId.virtualDesktopId = currentVirtualDesktopId;
|
||||
dirtyFlag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_virtualDesktopCheckCallback && !m_virtualDesktopCheckCallback(data.deviceId.virtualDesktopId))
|
||||
{
|
||||
data.deviceId.virtualDesktopId = GUID_NULL;
|
||||
dirtyFlag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<FancyZonesDataTypes::DeviceIdData> replaceWithCurrentId{};
|
||||
std::vector<FancyZonesDataTypes::DeviceIdData> replaceWithNullId{};
|
||||
|
||||
for (const auto& [desktopId, data] : deviceInfoMap)
|
||||
{
|
||||
if (desktopId.virtualDesktopId == GUID_NULL)
|
||||
{
|
||||
replaceWithCurrentId.push_back(desktopId);
|
||||
dirtyFlag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_virtualDesktopCheckCallback && !m_virtualDesktopCheckCallback(desktopId.virtualDesktopId))
|
||||
{
|
||||
replaceWithNullId.push_back(desktopId);
|
||||
dirtyFlag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& id : replaceWithCurrentId)
|
||||
{
|
||||
auto mapEntry = deviceInfoMap.extract(id);
|
||||
mapEntry.key().virtualDesktopId = currentVirtualDesktopId;
|
||||
deviceInfoMap.insert(std::move(mapEntry));
|
||||
}
|
||||
|
||||
for (const auto& id : replaceWithNullId)
|
||||
{
|
||||
auto mapEntry = deviceInfoMap.extract(id);
|
||||
mapEntry.key().virtualDesktopId = GUID_NULL;
|
||||
deviceInfoMap.insert(std::move(mapEntry));
|
||||
}
|
||||
|
||||
if (dirtyFlag)
|
||||
{
|
||||
wil::unique_cotaskmem_string virtualDesktopIdStr;
|
||||
if (SUCCEEDED(StringFromCLSID(currentVirtualDesktopId, &virtualDesktopIdStr)))
|
||||
{
|
||||
Logger::info(L"Update Virtual Desktop id to {}", virtualDesktopIdStr.get());
|
||||
}
|
||||
|
||||
SaveZoneSettings();
|
||||
AppZoneHistory::instance().SaveData();
|
||||
}
|
||||
}
|
||||
|
||||
void FancyZonesData::RemoveDeletedDesktops(const std::vector<GUID>& activeDesktops)
|
||||
{
|
||||
std::unordered_set<GUID> active(std::begin(activeDesktops), std::end(activeDesktops));
|
||||
std::scoped_lock lock{ dataLock };
|
||||
bool dirtyFlag = false;
|
||||
|
||||
for (auto it = std::begin(deviceInfoMap); it != std::end(deviceInfoMap);)
|
||||
{
|
||||
GUID desktopId = it->first.virtualDesktopId;
|
||||
|
||||
if (desktopId != GUID_NULL)
|
||||
{
|
||||
auto foundId = active.find(desktopId);
|
||||
if (foundId == std::end(active))
|
||||
{
|
||||
wil::unique_cotaskmem_string virtualDesktopIdStr;
|
||||
if (SUCCEEDED(StringFromCLSID(desktopId, &virtualDesktopIdStr)))
|
||||
{
|
||||
Logger::info(L"Remove Virtual Desktop id {}", virtualDesktopIdStr.get());
|
||||
}
|
||||
|
||||
AppZoneHistory::instance().RemoveDesktopAppZoneHistory(desktopId);
|
||||
it = deviceInfoMap.erase(it);
|
||||
dirtyFlag = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
if (dirtyFlag)
|
||||
{
|
||||
SaveZoneSettings();
|
||||
AppZoneHistory::instance().SaveData();
|
||||
}
|
||||
}
|
||||
|
||||
void FancyZonesData::SetActiveZoneSet(const FancyZonesDataTypes::DeviceIdData& deviceId, const FancyZonesDataTypes::ZoneSetData& data)
|
||||
{
|
||||
std::scoped_lock lock{ dataLock };
|
||||
|
||||
for (auto& [deviceIdData, deviceInfo] : deviceInfoMap)
|
||||
{
|
||||
if (deviceId.isEqualWithNullVirtualDesktopId(deviceIdData))
|
||||
{
|
||||
deviceInfo.activeZoneSet = data;
|
||||
|
||||
// If the zone set is custom, we need to copy its properties to the device
|
||||
auto id = FancyZonesUtils::GuidFromString(data.uuid);
|
||||
if (id.has_value())
|
||||
{
|
||||
auto layout = CustomLayouts::instance().GetLayout(id.value());
|
||||
if (layout)
|
||||
{
|
||||
if (layout.value().type == FancyZonesDataTypes::CustomLayoutType::Grid)
|
||||
{
|
||||
auto layoutInfo = std::get<FancyZonesDataTypes::GridLayoutInfo>(layout.value().info);
|
||||
deviceInfo.sensitivityRadius = layoutInfo.sensitivityRadius();
|
||||
deviceInfo.showSpacing = layoutInfo.showSpacing();
|
||||
deviceInfo.spacing = layoutInfo.spacing();
|
||||
deviceInfo.zoneCount = layoutInfo.zoneCount();
|
||||
}
|
||||
else if (layout.value().type == FancyZonesDataTypes::CustomLayoutType::Canvas)
|
||||
{
|
||||
auto layoutInfo = std::get<FancyZonesDataTypes::CanvasLayoutInfo>(layout.value().info);
|
||||
deviceInfo.sensitivityRadius = layoutInfo.sensitivityRadius;
|
||||
deviceInfo.zoneCount = (int)layoutInfo.zones.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
json::JsonObject FancyZonesData::GetPersistFancyZonesJSON()
|
||||
{
|
||||
return JSONHelpers::GetPersistFancyZonesJSON(zonesSettingsFileName, appZoneHistoryFileName);
|
||||
}
|
||||
|
||||
void FancyZonesData::LoadFancyZonesData()
|
||||
{
|
||||
if (!std::filesystem::exists(zonesSettingsFileName))
|
||||
{
|
||||
SaveZoneSettings();
|
||||
AppZoneHistory::instance().SaveData();
|
||||
}
|
||||
else
|
||||
{
|
||||
json::JsonObject fancyZonesDataJSON = GetPersistFancyZonesJSON();
|
||||
|
||||
deviceInfoMap = JSONHelpers::ParseDeviceInfos(fancyZonesDataJSON);
|
||||
}
|
||||
}
|
||||
|
||||
void FancyZonesData::SaveZoneSettings() const
|
||||
{
|
||||
_TRACER_;
|
||||
std::scoped_lock lock{ dataLock };
|
||||
|
||||
bool dirtyFlag = false;
|
||||
JSONHelpers::TDeviceInfoMap updatedDeviceInfoMap;
|
||||
if (m_virtualDesktopCheckCallback)
|
||||
{
|
||||
for (const auto& [id, data] : deviceInfoMap)
|
||||
{
|
||||
auto updatedId = id;
|
||||
if (!m_virtualDesktopCheckCallback(id.virtualDesktopId))
|
||||
{
|
||||
updatedId.virtualDesktopId = GUID_NULL;
|
||||
dirtyFlag = true;
|
||||
}
|
||||
|
||||
updatedDeviceInfoMap.insert({ updatedId, data });
|
||||
}
|
||||
}
|
||||
|
||||
if (dirtyFlag)
|
||||
{
|
||||
JSONHelpers::SaveZoneSettings(zonesSettingsFileName, updatedDeviceInfoMap);
|
||||
}
|
||||
else
|
||||
{
|
||||
JSONHelpers::SaveZoneSettings(zonesSettingsFileName, deviceInfoMap);
|
||||
std::filesystem::remove(zonesSettingsFileName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,38 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "JsonHelpers.h"
|
||||
|
||||
#if defined(UNIT_TESTS)
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
#include <common/utils/json.h>
|
||||
#include <mutex>
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include <winnt.h>
|
||||
#include <FancyZonesLib/JsonHelpers.h>
|
||||
|
||||
namespace FancyZonesDataTypes
|
||||
{
|
||||
struct ZoneSetData;
|
||||
struct DeviceIdData;
|
||||
struct DeviceInfoData;
|
||||
struct CustomLayoutData;
|
||||
struct AppZoneHistoryData;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(UNIT_TESTS)
|
||||
namespace FancyZonesUnitTests
|
||||
{
|
||||
class FancyZonesDataUnitTests;
|
||||
class FancyZonesIFancyZonesCallbackUnitTests;
|
||||
class ZoneSetCalculateZonesUnitTests;
|
||||
class WorkAreaUnitTests;
|
||||
class WorkAreaCreationUnitTests;
|
||||
class LayoutHotkeysUnitTests;
|
||||
class LayoutTemplatesUnitTests;
|
||||
class CustomLayoutsUnitTests;
|
||||
class AppliedLayoutsUnitTests;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -43,63 +21,19 @@ public:
|
||||
|
||||
void ReplaceZoneSettingsFileFromOlderVersions();
|
||||
|
||||
void SetVirtualDesktopCheckCallback(std::function<bool(GUID)> callback);
|
||||
|
||||
std::optional<FancyZonesDataTypes::DeviceInfoData> FindDeviceInfo(const FancyZonesDataTypes::DeviceIdData& id) const;
|
||||
|
||||
const JSONHelpers::TDeviceInfoMap& GetDeviceInfoMap() const;
|
||||
|
||||
inline const std::wstring& GetZonesSettingsFileName() const
|
||||
{
|
||||
return zonesSettingsFileName;
|
||||
}
|
||||
|
||||
inline const std::wstring& GetSettingsFileName() const
|
||||
{
|
||||
return settingsFileName;
|
||||
}
|
||||
|
||||
bool AddDevice(const FancyZonesDataTypes::DeviceIdData& deviceId);
|
||||
void CloneDeviceInfo(const FancyZonesDataTypes::DeviceIdData& source, const FancyZonesDataTypes::DeviceIdData& destination);
|
||||
void SyncVirtualDesktops(GUID desktopId);
|
||||
void RemoveDeletedDesktops(const std::vector<GUID>& activeDesktops);
|
||||
|
||||
void SetActiveZoneSet(const FancyZonesDataTypes::DeviceIdData& deviceId, const FancyZonesDataTypes::ZoneSetData& zoneSet);
|
||||
|
||||
json::JsonObject GetPersistFancyZonesJSON();
|
||||
|
||||
void LoadFancyZonesData();
|
||||
void SaveZoneSettings() const;
|
||||
|
||||
void SaveFancyZonesEditorParameters(bool spanZonesAcrossMonitors, const std::wstring& virtualDesktopId, const HMONITOR& targetMonitor, const std::vector<std::pair<HMONITOR, MONITORINFOEX>>& allMonitors) const;
|
||||
|
||||
private:
|
||||
#if defined(UNIT_TESTS)
|
||||
friend class FancyZonesUnitTests::FancyZonesDataUnitTests;
|
||||
friend class FancyZonesUnitTests::FancyZonesIFancyZonesCallbackUnitTests;
|
||||
friend class FancyZonesUnitTests::WorkAreaUnitTests;
|
||||
friend class FancyZonesUnitTests::WorkAreaCreationUnitTests;
|
||||
friend class FancyZonesUnitTests::ZoneSetCalculateZonesUnitTests;
|
||||
friend class FancyZonesUnitTests::LayoutHotkeysUnitTests;
|
||||
friend class FancyZonesUnitTests::LayoutTemplatesUnitTests;
|
||||
friend class FancyZonesUnitTests::CustomLayoutsUnitTests;
|
||||
|
||||
inline void SetDeviceInfo(const FancyZonesDataTypes::DeviceIdData& deviceId, FancyZonesDataTypes::DeviceInfoData data)
|
||||
{
|
||||
deviceInfoMap[deviceId] = data;
|
||||
}
|
||||
|
||||
inline bool ParseDeviceInfos(const json::JsonObject& fancyZonesDataJSON)
|
||||
{
|
||||
deviceInfoMap = JSONHelpers::ParseDeviceInfos(fancyZonesDataJSON);
|
||||
return !deviceInfoMap.empty();
|
||||
}
|
||||
|
||||
inline void clear_data()
|
||||
{
|
||||
appZoneHistoryMap.clear();
|
||||
deviceInfoMap.clear();
|
||||
}
|
||||
friend class FancyZonesUnitTests::AppliedLayoutsUnitTests;
|
||||
|
||||
inline void SetSettingsModulePath(std::wstring_view moduleName)
|
||||
{
|
||||
@@ -114,27 +48,10 @@ private:
|
||||
return result + L"\\" + std::wstring(L"zones-settings.json");
|
||||
}
|
||||
#endif
|
||||
// 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
|
||||
JSONHelpers::TDeviceInfoMap deviceInfoMap{};
|
||||
|
||||
std::wstring settingsFileName;
|
||||
std::wstring zonesSettingsFileName;
|
||||
std::wstring appZoneHistoryFileName;
|
||||
std::wstring editorParametersFileName;
|
||||
|
||||
std::function<bool(GUID)> m_virtualDesktopCheckCallback;
|
||||
|
||||
mutable std::recursive_mutex dataLock;
|
||||
};
|
||||
|
||||
FancyZonesData& FancyZonesDataInstance();
|
||||
|
||||
namespace DefaultValues
|
||||
{
|
||||
const int ZoneCount = 3;
|
||||
const bool ShowSpacing = true;
|
||||
const int Spacing = 16;
|
||||
const int SensitivityRadius = 20;
|
||||
}
|
||||
FancyZonesData& FancyZonesDataInstance();
|
||||
@@ -5,8 +5,10 @@
|
||||
#include <common/logger/logger.h>
|
||||
#include <common/utils/process_path.h>
|
||||
|
||||
#include <FancyZonesLib/GuidUtils.h>
|
||||
#include <FancyZonesLib/FancyZonesWindowProperties.h>
|
||||
#include <FancyZonesLib/JsonHelpers.h>
|
||||
#include <FancyZonesLib/util.h>
|
||||
|
||||
AppZoneHistory::AppZoneHistory()
|
||||
{
|
||||
@@ -104,7 +106,7 @@ bool AppZoneHistory::SetAppLastZones(HWND window, const FancyZonesDataTypes::Dev
|
||||
auto& perDesktopData = history->second;
|
||||
for (auto& data : perDesktopData)
|
||||
{
|
||||
if (data.deviceId.isEqualWithNullVirtualDesktopId(deviceId))
|
||||
if (data.deviceId == deviceId)
|
||||
{
|
||||
// application already has history on this work area, update it with new window position
|
||||
data.processIdToHandleMap[processId] = window;
|
||||
@@ -151,7 +153,7 @@ bool AppZoneHistory::RemoveAppLastZone(HWND window, const FancyZonesDataTypes::D
|
||||
auto& perDesktopData = history->second;
|
||||
for (auto data = std::begin(perDesktopData); data != std::end(perDesktopData);)
|
||||
{
|
||||
if (data->deviceId.isEqualWithNullVirtualDesktopId(deviceId) && data->zoneSetUuid == zoneSetId)
|
||||
if (data->deviceId == deviceId && data->zoneSetUuid == zoneSetId)
|
||||
{
|
||||
if (!IsAnotherWindowOfApplicationInstanceZoned(window, deviceId))
|
||||
{
|
||||
@@ -209,7 +211,7 @@ std::optional<FancyZonesDataTypes::AppZoneHistoryData> AppZoneHistory::GetZoneHi
|
||||
auto historyVector = iter->second;
|
||||
for (const auto& history : historyVector)
|
||||
{
|
||||
if (history.deviceId.isEqualWithNullVirtualDesktopId(deviceId))
|
||||
if (history.deviceId == deviceId)
|
||||
{
|
||||
return history;
|
||||
}
|
||||
@@ -230,7 +232,7 @@ bool AppZoneHistory::IsAnotherWindowOfApplicationInstanceZoned(HWND window, cons
|
||||
auto& perDesktopData = history->second;
|
||||
for (auto& data : perDesktopData)
|
||||
{
|
||||
if (data.deviceId.isEqualWithNullVirtualDesktopId(deviceId))
|
||||
if (data.deviceId == deviceId)
|
||||
{
|
||||
DWORD processId = 0;
|
||||
GetWindowThreadProcessId(window, &processId);
|
||||
@@ -264,7 +266,7 @@ void AppZoneHistory::UpdateProcessIdToHandleMap(HWND window, const FancyZonesDat
|
||||
auto& perDesktopData = history->second;
|
||||
for (auto& data : perDesktopData)
|
||||
{
|
||||
if (data.deviceId.isEqualWithNullVirtualDesktopId(deviceId))
|
||||
if (data.deviceId == deviceId)
|
||||
{
|
||||
DWORD processId = 0;
|
||||
GetWindowThreadProcessId(window, &processId);
|
||||
@@ -287,7 +289,7 @@ ZoneIndexSet AppZoneHistory::GetAppLastZoneIndexSet(HWND window, const FancyZone
|
||||
const auto& perDesktopData = history->second;
|
||||
for (const auto& data : perDesktopData)
|
||||
{
|
||||
if (data.zoneSetUuid == zoneSetId && data.deviceId.isEqualWithNullVirtualDesktopId(deviceId))
|
||||
if (data.zoneSetUuid == zoneSetId && data.deviceId == deviceId)
|
||||
{
|
||||
return data.zoneIndexSet;
|
||||
}
|
||||
@@ -298,16 +300,68 @@ ZoneIndexSet AppZoneHistory::GetAppLastZoneIndexSet(HWND window, const FancyZone
|
||||
return {};
|
||||
}
|
||||
|
||||
void AppZoneHistory::RemoveDesktopAppZoneHistory(GUID desktopId)
|
||||
void AppZoneHistory::SyncVirtualDesktops(GUID currentVirtualDesktopId)
|
||||
{
|
||||
_TRACER_;
|
||||
// Explorer persists current virtual desktop identifier to registry on a per session basis,
|
||||
// but only after first virtual desktop switch happens. If the user hasn't switched virtual
|
||||
// desktops in this session value in registry will be empty and we will use default GUID in
|
||||
// that case (00000000-0000-0000-0000-000000000000).
|
||||
|
||||
bool dirtyFlag = false;
|
||||
|
||||
for (auto& [path, perDesktopData] : m_history)
|
||||
{
|
||||
for (auto& data : perDesktopData)
|
||||
{
|
||||
if (data.deviceId.virtualDesktopId == GUID_NULL)
|
||||
{
|
||||
data.deviceId.virtualDesktopId = currentVirtualDesktopId;
|
||||
dirtyFlag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_virtualDesktopCheckCallback && !m_virtualDesktopCheckCallback(data.deviceId.virtualDesktopId))
|
||||
{
|
||||
data.deviceId.virtualDesktopId = GUID_NULL;
|
||||
dirtyFlag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dirtyFlag)
|
||||
{
|
||||
wil::unique_cotaskmem_string virtualDesktopIdStr;
|
||||
if (SUCCEEDED(StringFromCLSID(currentVirtualDesktopId, &virtualDesktopIdStr)))
|
||||
{
|
||||
Logger::info(L"Update Virtual Desktop id to {}", virtualDesktopIdStr.get());
|
||||
}
|
||||
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
|
||||
void AppZoneHistory::RemoveDeletedVirtualDesktops(const std::vector<GUID>& activeDesktops)
|
||||
{
|
||||
std::unordered_set<GUID> active(std::begin(activeDesktops), std::end(activeDesktops));
|
||||
bool dirtyFlag = false;
|
||||
|
||||
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)
|
||||
if (desktopIt->deviceId.virtualDesktopId != GUID_NULL && !active.contains(desktopIt->deviceId.virtualDesktopId))
|
||||
{
|
||||
auto virtualDesktopIdStr = FancyZonesUtils::GuidToString(desktopIt->deviceId.virtualDesktopId);
|
||||
if (virtualDesktopIdStr)
|
||||
{
|
||||
Logger::info(L"Remove Virtual Desktop id {} from app-zone-history", virtualDesktopIdStr.value());
|
||||
}
|
||||
|
||||
desktopIt = perDesktopData.erase(desktopIt);
|
||||
dirtyFlag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -324,4 +378,9 @@ void AppZoneHistory::RemoveDesktopAppZoneHistory(GUID desktopId)
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirtyFlag)
|
||||
{
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@ public:
|
||||
return saveFolderPath + L"\\app-zone-history.json";
|
||||
}
|
||||
|
||||
void SetVirtualDesktopCheckCallback(std::function<bool(GUID)> callback);
|
||||
|
||||
void LoadData();
|
||||
void SaveData();
|
||||
|
||||
@@ -38,7 +36,9 @@ public:
|
||||
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);
|
||||
void SetVirtualDesktopCheckCallback(std::function<bool(GUID)> callback);
|
||||
void SyncVirtualDesktops(GUID currentVirtualDesktopId);
|
||||
void RemoveDeletedVirtualDesktops(const std::vector<GUID>& activeDesktops);
|
||||
|
||||
private:
|
||||
AppZoneHistory();
|
||||
|
||||
@@ -0,0 +1,420 @@
|
||||
#include "../pch.h"
|
||||
#include "AppliedLayouts.h"
|
||||
|
||||
#include <common/logger/call_tracer.h>
|
||||
#include <common/logger/logger.h>
|
||||
|
||||
#include <FancyZonesLib/GuidUtils.h>
|
||||
#include <FancyZonesLib/FancyZonesData/CustomLayouts.h>
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutDefaults.h>
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutTemplates.h>
|
||||
#include <FancyZonesLib/FancyZonesWinHookEventIDs.h>
|
||||
#include <FancyZonesLib/JsonHelpers.h>
|
||||
#include <FancyZonesLib/util.h>
|
||||
|
||||
namespace JsonUtils
|
||||
{
|
||||
struct LayoutJSON
|
||||
{
|
||||
static std::optional<Layout> FromJson(const json::JsonObject& json)
|
||||
{
|
||||
try
|
||||
{
|
||||
Layout data;
|
||||
auto idStr = json.GetNamedString(NonLocalizable::AppliedLayoutsIds::UuidID);
|
||||
auto id = FancyZonesUtils::GuidFromString(idStr.c_str());
|
||||
if (!id.has_value())
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
data.uuid = id.value();
|
||||
data.type = FancyZonesDataTypes::TypeFromString(std::wstring{ json.GetNamedString(NonLocalizable::AppliedLayoutsIds::TypeID) });
|
||||
data.showSpacing = json.GetNamedBoolean(NonLocalizable::AppliedLayoutsIds::ShowSpacingID);
|
||||
data.spacing = static_cast<int>(json.GetNamedNumber(NonLocalizable::AppliedLayoutsIds::SpacingID));
|
||||
data.zoneCount = static_cast<int>(json.GetNamedNumber(NonLocalizable::AppliedLayoutsIds::ZoneCountID));
|
||||
data.sensitivityRadius = static_cast<int>(json.GetNamedNumber(NonLocalizable::AppliedLayoutsIds::SensitivityRadiusID, DefaultValues::SensitivityRadius));
|
||||
|
||||
return data;
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
static json::JsonObject ToJson(const Layout& data)
|
||||
{
|
||||
json::JsonObject result{};
|
||||
result.SetNamedValue(NonLocalizable::AppliedLayoutsIds::UuidID, json::value(FancyZonesUtils::GuidToString(data.uuid).value()));
|
||||
result.SetNamedValue(NonLocalizable::AppliedLayoutsIds::TypeID, json::value(FancyZonesDataTypes::TypeToString(data.type)));
|
||||
result.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ShowSpacingID, json::value(data.showSpacing));
|
||||
result.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SpacingID, json::value(data.spacing));
|
||||
result.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ZoneCountID, json::value(data.zoneCount));
|
||||
result.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SensitivityRadiusID, json::value(data.sensitivityRadius));
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
struct AppliedLayoutsJSON
|
||||
{
|
||||
FancyZonesDataTypes::DeviceIdData deviceId;
|
||||
Layout data;
|
||||
|
||||
static std::optional<AppliedLayoutsJSON> FromJson(const json::JsonObject& json)
|
||||
{
|
||||
try
|
||||
{
|
||||
AppliedLayoutsJSON result;
|
||||
|
||||
std::wstring deviceIdStr = json.GetNamedString(NonLocalizable::AppliedLayoutsIds::DeviceIdID).c_str();
|
||||
auto deviceId = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(deviceIdStr);
|
||||
if (!deviceId.has_value())
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto layout = JsonUtils::LayoutJSON::FromJson(json.GetNamedObject(NonLocalizable::AppliedLayoutsIds::AppliedLayoutID));
|
||||
if (!layout.has_value())
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
result.deviceId = std::move(deviceId.value());
|
||||
result.data = std::move(layout.value());
|
||||
return result;
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
static json::JsonObject ToJson(const AppliedLayoutsJSON& value)
|
||||
{
|
||||
json::JsonObject result{};
|
||||
|
||||
result.SetNamedValue(NonLocalizable::AppliedLayoutsIds::DeviceIdID, json::value(value.deviceId.toString()));
|
||||
result.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutID, JsonUtils::LayoutJSON::ToJson(value.data));
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
AppliedLayouts::TAppliedLayoutsMap ParseJson(const json::JsonObject& json)
|
||||
{
|
||||
AppliedLayouts::TAppliedLayoutsMap map{};
|
||||
auto layouts = json.GetNamedArray(NonLocalizable::AppliedLayoutsIds::AppliedLayoutsArrayID);
|
||||
|
||||
for (uint32_t i = 0; i < layouts.Size(); ++i)
|
||||
{
|
||||
if (auto obj = AppliedLayoutsJSON::FromJson(layouts.GetObjectAt(i)); obj.has_value())
|
||||
{
|
||||
map[obj->deviceId] = std::move(obj->data);
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
json::JsonObject SerializeJson(const AppliedLayouts::TAppliedLayoutsMap& map)
|
||||
{
|
||||
json::JsonObject json{};
|
||||
json::JsonArray layoutArray{};
|
||||
|
||||
for (const auto& [id, data] : map)
|
||||
{
|
||||
AppliedLayoutsJSON obj{};
|
||||
obj.deviceId = id;
|
||||
obj.data = data;
|
||||
layoutArray.Append(AppliedLayoutsJSON::ToJson(obj));
|
||||
}
|
||||
|
||||
json.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutsArrayID, layoutArray);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AppliedLayouts::AppliedLayouts()
|
||||
{
|
||||
const std::wstring& fileName = AppliedLayoutsFileName();
|
||||
m_fileWatcher = std::make_unique<FileWatcher>(fileName, [&]() {
|
||||
PostMessageW(HWND_BROADCAST, WM_PRIV_APPLIED_LAYOUTS_FILE_UPDATE, NULL, NULL);
|
||||
});
|
||||
}
|
||||
|
||||
AppliedLayouts& AppliedLayouts::instance()
|
||||
{
|
||||
static AppliedLayouts self;
|
||||
return self;
|
||||
}
|
||||
|
||||
void AppliedLayouts::LoadData()
|
||||
{
|
||||
auto data = json::from_file(AppliedLayoutsFileName());
|
||||
|
||||
try
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
m_layouts = JsonUtils::ParseJson(data.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_layouts.clear();
|
||||
Logger::info(L"applied-layouts.json file is missing or malformed");
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error& e)
|
||||
{
|
||||
Logger::error(L"Parsing applied-layouts error: {}", e.message());
|
||||
}
|
||||
}
|
||||
|
||||
void AppliedLayouts::SaveData()
|
||||
{
|
||||
_TRACER_;
|
||||
|
||||
bool dirtyFlag = false;
|
||||
TAppliedLayoutsMap updatedMap;
|
||||
if (m_virtualDesktopCheckCallback)
|
||||
{
|
||||
for (const auto& [id, data] : m_layouts)
|
||||
{
|
||||
auto updatedId = id;
|
||||
if (!m_virtualDesktopCheckCallback(id.virtualDesktopId))
|
||||
{
|
||||
updatedId.virtualDesktopId = GUID_NULL;
|
||||
dirtyFlag = true;
|
||||
}
|
||||
|
||||
updatedMap.insert({ updatedId, data });
|
||||
}
|
||||
}
|
||||
|
||||
if (dirtyFlag)
|
||||
{
|
||||
json::to_file(AppliedLayoutsFileName(), JsonUtils::SerializeJson(updatedMap));
|
||||
}
|
||||
else
|
||||
{
|
||||
json::to_file(AppliedLayoutsFileName(), JsonUtils::SerializeJson(m_layouts));
|
||||
}
|
||||
}
|
||||
|
||||
void AppliedLayouts::SetVirtualDesktopCheckCallback(std::function<bool(GUID)> callback)
|
||||
{
|
||||
m_virtualDesktopCheckCallback = callback;
|
||||
}
|
||||
|
||||
void AppliedLayouts::SyncVirtualDesktops(GUID currentVirtualDesktopId)
|
||||
{
|
||||
_TRACER_;
|
||||
// Explorer persists current virtual desktop identifier to registry on a per session basis,
|
||||
// but only after first virtual desktop switch happens. If the user hasn't switched virtual
|
||||
// desktops in this session value in registry will be empty and we will use default GUID in
|
||||
// that case (00000000-0000-0000-0000-000000000000).
|
||||
|
||||
bool dirtyFlag = false;
|
||||
|
||||
std::vector<FancyZonesDataTypes::DeviceIdData> replaceWithCurrentId{};
|
||||
std::vector<FancyZonesDataTypes::DeviceIdData> replaceWithNullId{};
|
||||
|
||||
for (const auto& [id, data] : m_layouts)
|
||||
{
|
||||
if (id.virtualDesktopId == GUID_NULL)
|
||||
{
|
||||
replaceWithCurrentId.push_back(id);
|
||||
dirtyFlag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_virtualDesktopCheckCallback && !m_virtualDesktopCheckCallback(id.virtualDesktopId))
|
||||
{
|
||||
replaceWithNullId.push_back(id);
|
||||
dirtyFlag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& id : replaceWithCurrentId)
|
||||
{
|
||||
auto mapEntry = m_layouts.extract(id);
|
||||
mapEntry.key().virtualDesktopId = currentVirtualDesktopId;
|
||||
m_layouts.insert(std::move(mapEntry));
|
||||
}
|
||||
|
||||
for (const auto& id : replaceWithNullId)
|
||||
{
|
||||
auto mapEntry = m_layouts.extract(id);
|
||||
mapEntry.key().virtualDesktopId = GUID_NULL;
|
||||
m_layouts.insert(std::move(mapEntry));
|
||||
}
|
||||
|
||||
if (dirtyFlag)
|
||||
{
|
||||
wil::unique_cotaskmem_string virtualDesktopIdStr;
|
||||
if (SUCCEEDED(StringFromCLSID(currentVirtualDesktopId, &virtualDesktopIdStr)))
|
||||
{
|
||||
Logger::info(L"Update Virtual Desktop id to {}", virtualDesktopIdStr.get());
|
||||
}
|
||||
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
|
||||
void AppliedLayouts::RemoveDeletedVirtualDesktops(const std::vector<GUID>& activeDesktops)
|
||||
{
|
||||
std::unordered_set<GUID> active(std::begin(activeDesktops), std::end(activeDesktops));
|
||||
bool dirtyFlag = false;
|
||||
|
||||
for (auto it = std::begin(m_layouts); it != std::end(m_layouts);)
|
||||
{
|
||||
GUID desktopId = it->first.virtualDesktopId;
|
||||
|
||||
if (desktopId != GUID_NULL)
|
||||
{
|
||||
auto foundId = active.find(desktopId);
|
||||
if (foundId == std::end(active))
|
||||
{
|
||||
wil::unique_cotaskmem_string virtualDesktopIdStr;
|
||||
if (SUCCEEDED(StringFromCLSID(desktopId, &virtualDesktopIdStr)))
|
||||
{
|
||||
Logger::info(L"Remove Virtual Desktop id {}", virtualDesktopIdStr.get());
|
||||
}
|
||||
|
||||
it = m_layouts.erase(it);
|
||||
dirtyFlag = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
if (dirtyFlag)
|
||||
{
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<Layout> AppliedLayouts::GetDeviceLayout(const FancyZonesDataTypes::DeviceIdData& id) const noexcept
|
||||
{
|
||||
auto iter = m_layouts.find(id);
|
||||
if (iter != m_layouts.end())
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const AppliedLayouts::TAppliedLayoutsMap& AppliedLayouts::GetAppliedLayoutMap() const noexcept
|
||||
{
|
||||
return m_layouts;
|
||||
}
|
||||
|
||||
bool AppliedLayouts::IsLayoutApplied(const FancyZonesDataTypes::DeviceIdData& id) const noexcept
|
||||
{
|
||||
auto iter = m_layouts.find(id);
|
||||
return iter != m_layouts.end();
|
||||
}
|
||||
|
||||
bool AppliedLayouts::ApplyLayout(const FancyZonesDataTypes::DeviceIdData& deviceId, const FancyZonesDataTypes::ZoneSetData& layout)
|
||||
{
|
||||
auto uuid = FancyZonesUtils::GuidFromString(layout.uuid);
|
||||
if (!uuid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Layout layoutToApply {
|
||||
.uuid = uuid.value(),
|
||||
.type = layout.type,
|
||||
.showSpacing = DefaultValues::ShowSpacing,
|
||||
.spacing = DefaultValues::Spacing,
|
||||
.zoneCount = DefaultValues::ZoneCount,
|
||||
.sensitivityRadius = DefaultValues::SensitivityRadius,
|
||||
};
|
||||
|
||||
// copy layouts properties to the applied-layout
|
||||
auto customLayout = CustomLayouts::instance().GetLayout(layoutToApply.uuid);
|
||||
if (customLayout)
|
||||
{
|
||||
if (customLayout.value().type == FancyZonesDataTypes::CustomLayoutType::Grid)
|
||||
{
|
||||
auto layoutInfo = std::get<FancyZonesDataTypes::GridLayoutInfo>(customLayout.value().info);
|
||||
layoutToApply.sensitivityRadius = layoutInfo.sensitivityRadius();
|
||||
layoutToApply.showSpacing = layoutInfo.showSpacing();
|
||||
layoutToApply.spacing = layoutInfo.spacing();
|
||||
layoutToApply.zoneCount = layoutInfo.zoneCount();
|
||||
}
|
||||
else if (customLayout.value().type == FancyZonesDataTypes::CustomLayoutType::Canvas)
|
||||
{
|
||||
auto layoutInfo = std::get<FancyZonesDataTypes::CanvasLayoutInfo>(customLayout.value().info);
|
||||
layoutToApply.sensitivityRadius = layoutInfo.sensitivityRadius;
|
||||
layoutToApply.zoneCount = (int)layoutInfo.zones.size();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// check templates only if it wasn't a custom layout, since templates don't have ids yet
|
||||
auto templateLayout = LayoutTemplates::instance().GetLayout(layout.type);
|
||||
if (templateLayout)
|
||||
{
|
||||
auto layoutInfo = templateLayout.value();
|
||||
layoutToApply.sensitivityRadius = layoutInfo.sensitivityRadius;
|
||||
layoutToApply.showSpacing = layoutInfo.showSpacing;
|
||||
layoutToApply.spacing = layoutInfo.spacing;
|
||||
layoutToApply.zoneCount = layoutInfo.zoneCount;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
m_layouts[deviceId] = std::move(layoutToApply);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AppliedLayouts::ApplyDefaultLayout(const FancyZonesDataTypes::DeviceIdData& deviceId)
|
||||
{
|
||||
Logger::info(L"Set default layout on {}", deviceId.toString());
|
||||
|
||||
GUID guid;
|
||||
auto result{ CoCreateGuid(&guid) };
|
||||
if (!SUCCEEDED(result))
|
||||
{
|
||||
Logger::error("Failed to create an ID for the new layout");
|
||||
return false;
|
||||
}
|
||||
|
||||
Layout layout{
|
||||
.uuid = guid,
|
||||
.type = FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid,
|
||||
.showSpacing = DefaultValues::ShowSpacing,
|
||||
.spacing = DefaultValues::Spacing,
|
||||
.zoneCount = DefaultValues::ZoneCount,
|
||||
.sensitivityRadius = DefaultValues::SensitivityRadius
|
||||
};
|
||||
|
||||
m_layouts[deviceId] = std::move(layout);
|
||||
|
||||
SaveData();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AppliedLayouts::CloneLayout(const FancyZonesDataTypes::DeviceIdData& srcId, const FancyZonesDataTypes::DeviceIdData& dstId)
|
||||
{
|
||||
if (srcId == dstId || m_layouts.find(srcId) == m_layouts.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Logger::info(L"Clone layout from {} to {}", dstId.toString(), srcId.toString());
|
||||
m_layouts[dstId] = m_layouts[srcId];
|
||||
|
||||
SaveData();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include <FancyZonesLib/FancyZonesData/Layout.h>
|
||||
#include <FancyZonesLib/ModuleConstants.h>
|
||||
|
||||
#include <common/SettingsAPI/FileWatcher.h>
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
|
||||
namespace NonLocalizable
|
||||
{
|
||||
namespace AppliedLayoutsIds
|
||||
{
|
||||
const static wchar_t* AppliedLayoutsArrayID = L"applied-layouts";
|
||||
const static wchar_t* DeviceIdID = L"device-id";
|
||||
const static wchar_t* AppliedLayoutID = L"applied-layout";
|
||||
const static wchar_t* UuidID = L"uuid";
|
||||
const static wchar_t* TypeID = L"type";
|
||||
const static wchar_t* ShowSpacingID = L"show-spacing";
|
||||
const static wchar_t* SpacingID = L"spacing";
|
||||
const static wchar_t* ZoneCountID = L"zone-count";
|
||||
const static wchar_t* SensitivityRadiusID = L"sensitivity-radius";
|
||||
}
|
||||
}
|
||||
|
||||
class AppliedLayouts
|
||||
{
|
||||
public:
|
||||
using TAppliedLayoutsMap = std::unordered_map<FancyZonesDataTypes::DeviceIdData, Layout>;
|
||||
|
||||
static AppliedLayouts& instance();
|
||||
|
||||
inline static std::wstring AppliedLayoutsFileName()
|
||||
{
|
||||
std::wstring saveFolderPath = PTSettingsHelper::get_module_save_folder_location(NonLocalizable::ModuleKey);
|
||||
#if defined(UNIT_TESTS)
|
||||
return saveFolderPath + L"\\test-applied-layouts.json";
|
||||
#endif
|
||||
return saveFolderPath + L"\\applied-layouts.json";
|
||||
}
|
||||
|
||||
void LoadData();
|
||||
void SaveData();
|
||||
|
||||
void SetVirtualDesktopCheckCallback(std::function<bool(GUID)> callback);
|
||||
void SyncVirtualDesktops(GUID currentVirtualDesktopId);
|
||||
void RemoveDeletedVirtualDesktops(const std::vector<GUID>& activeDesktops);
|
||||
|
||||
std::optional<Layout> GetDeviceLayout(const FancyZonesDataTypes::DeviceIdData& id) const noexcept;
|
||||
const TAppliedLayoutsMap& GetAppliedLayoutMap() const noexcept;
|
||||
|
||||
bool IsLayoutApplied(const FancyZonesDataTypes::DeviceIdData& id) const noexcept;
|
||||
|
||||
bool ApplyLayout(const FancyZonesDataTypes::DeviceIdData& deviceId, const FancyZonesDataTypes::ZoneSetData& layout);
|
||||
bool ApplyDefaultLayout(const FancyZonesDataTypes::DeviceIdData& deviceId);
|
||||
bool CloneLayout(const FancyZonesDataTypes::DeviceIdData& srcId, const FancyZonesDataTypes::DeviceIdData& dstId);
|
||||
|
||||
private:
|
||||
AppliedLayouts();
|
||||
~AppliedLayouts() = default;
|
||||
|
||||
std::unique_ptr<FileWatcher> m_fileWatcher;
|
||||
TAppliedLayoutsMap m_layouts;
|
||||
std::function<bool(GUID)> m_virtualDesktopCheckCallback;
|
||||
};
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <common/logger/logger.h>
|
||||
|
||||
#include <FancyZonesLib/FancyZonesData.h> // layout defaults
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutDefaults.h>
|
||||
#include <FancyZonesLib/FancyZonesWinHookEventIDs.h>
|
||||
#include <FancyZonesLib/JsonHelpers.h>
|
||||
#include <FancyZonesLib/util.h>
|
||||
|
||||
15
src/modules/fancyzones/FancyZonesLib/FancyZonesData/Layout.h
Normal file
15
src/modules/fancyzones/FancyZonesLib/FancyZonesData/Layout.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <guiddef.h>
|
||||
|
||||
#include <FancyZonesLib/FancyZonesDataTypes.h>
|
||||
|
||||
struct Layout
|
||||
{
|
||||
GUID uuid;
|
||||
FancyZonesDataTypes::ZoneSetLayoutType type;
|
||||
bool showSpacing;
|
||||
int spacing;
|
||||
int zoneCount;
|
||||
int sensitivityRadius;
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
namespace DefaultValues
|
||||
{
|
||||
const int ZoneCount = 3;
|
||||
const bool ShowSpacing = true;
|
||||
const int Spacing = 16;
|
||||
const int SensitivityRadius = 20;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
#include "../pch.h"
|
||||
#include "LayoutTemplates.h"
|
||||
|
||||
#include <common/logger/logger.h>
|
||||
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutDefaults.h>
|
||||
#include <FancyZonesLib/FancyZonesWinHookEventIDs.h>
|
||||
|
||||
namespace JsonUtils
|
||||
{
|
||||
struct TemplateLayoutJSON
|
||||
{
|
||||
static std::optional<Layout> FromJson(const json::JsonObject& json)
|
||||
{
|
||||
try
|
||||
{
|
||||
Layout data;
|
||||
|
||||
data.uuid = GUID_NULL;
|
||||
data.type = FancyZonesDataTypes::TypeFromString(std::wstring{ json.GetNamedString(NonLocalizable::LayoutTemplatesIds::TypeID) });
|
||||
data.showSpacing = json.GetNamedBoolean(NonLocalizable::LayoutTemplatesIds::ShowSpacingID, DefaultValues::ShowSpacing);
|
||||
data.spacing = static_cast<int>(json.GetNamedNumber(NonLocalizable::LayoutTemplatesIds::SpacingID, DefaultValues::Spacing));
|
||||
data.zoneCount = static_cast<int>(json.GetNamedNumber(NonLocalizable::LayoutTemplatesIds::ZoneCountID, DefaultValues::ZoneCount));
|
||||
data.sensitivityRadius = static_cast<int>(json.GetNamedNumber(NonLocalizable::LayoutTemplatesIds::SensitivityRadiusID, DefaultValues::SensitivityRadius));
|
||||
|
||||
return data;
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<Layout> ParseJson(const json::JsonObject& json)
|
||||
{
|
||||
std::vector<Layout> vec{};
|
||||
auto layouts = json.GetNamedArray(NonLocalizable::LayoutTemplatesIds::LayoutTemplatesArrayID);
|
||||
|
||||
for (uint32_t i = 0; i < layouts.Size(); ++i)
|
||||
{
|
||||
if (auto obj = TemplateLayoutJSON::FromJson(layouts.GetObjectAt(i)); obj.has_value())
|
||||
{
|
||||
vec.emplace_back(std::move(obj.value()));
|
||||
}
|
||||
}
|
||||
|
||||
return vec;
|
||||
}
|
||||
}
|
||||
|
||||
LayoutTemplates::LayoutTemplates()
|
||||
{
|
||||
const std::wstring& fileName = LayoutTemplatesFileName();
|
||||
m_fileWatcher = std::make_unique<FileWatcher>(fileName, [&]() {
|
||||
PostMessageW(HWND_BROADCAST, WM_PRIV_LAYOUT_TEMPLATES_FILE_UPDATE, NULL, NULL);
|
||||
});
|
||||
}
|
||||
|
||||
LayoutTemplates& LayoutTemplates::instance()
|
||||
{
|
||||
static LayoutTemplates self;
|
||||
return self;
|
||||
}
|
||||
|
||||
void LayoutTemplates::LoadData()
|
||||
{
|
||||
auto data = json::from_file(LayoutTemplatesFileName());
|
||||
|
||||
try
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
m_layouts = JsonUtils::ParseJson(data.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_layouts.clear();
|
||||
Logger::info(L"layout-templates.json file is missing or malformed");
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error& e)
|
||||
{
|
||||
Logger::error(L"Parsing layout-templates error: {}", e.message());
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<Layout> LayoutTemplates::GetLayout(FancyZonesDataTypes::ZoneSetLayoutType type) const noexcept
|
||||
{
|
||||
for (const auto& layout : m_layouts)
|
||||
{
|
||||
if (layout.type == type)
|
||||
{
|
||||
return layout;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <FancyZonesLib/FancyZonesData/Layout.h>
|
||||
#include <FancyZonesLib/ModuleConstants.h>
|
||||
|
||||
#include <common/SettingsAPI/FileWatcher.h>
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
|
||||
namespace NonLocalizable
|
||||
@@ -9,12 +11,19 @@ namespace NonLocalizable
|
||||
namespace LayoutTemplatesIds
|
||||
{
|
||||
const static wchar_t* LayoutTemplatesArrayID = L"layout-templates";
|
||||
const static wchar_t* TypeID = L"type";
|
||||
const static wchar_t* ShowSpacingID = L"show-spacing";
|
||||
const static wchar_t* SpacingID = L"spacing";
|
||||
const static wchar_t* ZoneCountID = L"zone-count";
|
||||
const static wchar_t* SensitivityRadiusID = L"sensitivity-radius";
|
||||
}
|
||||
}
|
||||
|
||||
class LayoutTemplates
|
||||
{
|
||||
public:
|
||||
static LayoutTemplates& instance();
|
||||
|
||||
inline static std::wstring LayoutTemplatesFileName()
|
||||
{
|
||||
std::wstring saveFolderPath = PTSettingsHelper::get_module_save_folder_location(NonLocalizable::ModuleKey);
|
||||
@@ -23,4 +32,15 @@ public:
|
||||
#endif
|
||||
return saveFolderPath + L"\\layout-templates.json";
|
||||
}
|
||||
|
||||
void LoadData();
|
||||
|
||||
std::optional<Layout> GetLayout(FancyZonesDataTypes::ZoneSetLayoutType type) const noexcept;
|
||||
|
||||
private:
|
||||
LayoutTemplates();
|
||||
~LayoutTemplates() = default;
|
||||
|
||||
std::unique_ptr<FileWatcher> m_fileWatcher;
|
||||
std::vector<Layout> m_layouts;
|
||||
};
|
||||
@@ -305,9 +305,4 @@ namespace FancyZonesDataTypes
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool DeviceIdData::isEqualWithNullVirtualDesktopId(const DeviceIdData& other) const
|
||||
{
|
||||
return deviceName.compare(other.deviceName) == 0 && width == other.width && height == other.height && (virtualDesktopId == other.virtualDesktopId || virtualDesktopId == GUID_NULL || other.virtualDesktopId == GUID_NULL) && monitorId.compare(other.monitorId) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +125,6 @@ namespace FancyZonesDataTypes
|
||||
static bool IsValidDeviceId(const std::wstring& str);
|
||||
|
||||
std::wstring toString() const;
|
||||
bool isEqualWithNullVirtualDesktopId(const DeviceIdData& other) const;
|
||||
};
|
||||
|
||||
struct AppZoneHistoryData
|
||||
@@ -153,7 +152,7 @@ namespace FancyZonesDataTypes
|
||||
|
||||
inline bool operator==(const DeviceIdData& lhs, const DeviceIdData& rhs)
|
||||
{
|
||||
return lhs.deviceName.compare(rhs.deviceName) == 0 && lhs.width == rhs.width && lhs.height == rhs.height && lhs.virtualDesktopId == rhs.virtualDesktopId && lhs.monitorId.compare(rhs.monitorId) == 0;
|
||||
return lhs.deviceName.compare(rhs.deviceName) == 0 && lhs.width == rhs.width && lhs.height == rhs.height && (lhs.virtualDesktopId == rhs.virtualDesktopId || lhs.virtualDesktopId == GUID_NULL || rhs.virtualDesktopId == GUID_NULL) && lhs.monitorId.compare(rhs.monitorId) == 0;
|
||||
}
|
||||
|
||||
inline bool operator!=(const DeviceIdData& lhs, const DeviceIdData& rhs)
|
||||
|
||||
@@ -38,9 +38,12 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="FancyZonesData\CustomLayouts.h" />
|
||||
<ClInclude Include="FancyZonesData\AppliedLayouts.h" />
|
||||
<ClInclude Include="FancyZonesData\AppZoneHistory.h" />
|
||||
<ClInclude Include="FancyZones.h" />
|
||||
<ClInclude Include="FancyZonesDataTypes.h" />
|
||||
<ClInclude Include="FancyZonesData\Layout.h" />
|
||||
<ClInclude Include="FancyZonesData\LayoutDefaults.h" />
|
||||
<ClInclude Include="FancyZonesData\LayoutTemplates.h" />
|
||||
<ClInclude Include="FancyZonesWinHookEventIDs.h" />
|
||||
<ClInclude Include="GenericKeyHook.h" />
|
||||
@@ -79,6 +82,14 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZones.cpp" />
|
||||
<ClCompile Include="FancyZonesDataTypes.cpp" />
|
||||
<ClCompile Include="FancyZonesData\AppliedLayouts.cpp">
|
||||
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesData\LayoutTemplates.cpp">
|
||||
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesWinHookEventIDs.cpp" />
|
||||
<ClCompile Include="FancyZonesData.cpp" />
|
||||
<ClCompile Include="JsonHelpers.cpp" />
|
||||
|
||||
@@ -93,6 +93,9 @@
|
||||
<ClInclude Include="FancyZonesData\AppZoneHistory.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\AppliedLayouts.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\CustomLayouts.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -105,6 +108,12 @@
|
||||
<ClInclude Include="FancyZonesData\LayoutTemplates.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\LayoutDefaults.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\Layout.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp">
|
||||
@@ -173,6 +182,12 @@
|
||||
<ClCompile Include="FancyZonesData\AppZoneHistory.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesData\AppliedLayouts.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesData\LayoutTemplates.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
||||
@@ -11,9 +11,10 @@ UINT WM_PRIV_VD_INIT;
|
||||
UINT WM_PRIV_VD_SWITCH;
|
||||
UINT WM_PRIV_VD_UPDATE;
|
||||
UINT WM_PRIV_EDITOR;
|
||||
UINT WM_PRIV_FILE_UPDATE;
|
||||
UINT WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE;
|
||||
UINT WM_PRIV_LAYOUT_TEMPLATES_FILE_UPDATE;
|
||||
UINT WM_PRIV_CUSTOM_LAYOUTS_FILE_UPDATE;
|
||||
UINT WM_PRIV_APPLIED_LAYOUTS_FILE_UPDATE;
|
||||
UINT WM_PRIV_SNAP_HOTKEY;
|
||||
UINT WM_PRIV_QUICK_LAYOUT_KEY;
|
||||
UINT WM_PRIV_SETTINGS_CHANGED;
|
||||
@@ -32,9 +33,10 @@ void InitializeWinhookEventIds()
|
||||
WM_PRIV_VD_SWITCH = RegisterWindowMessage(L"{128c2cb0-6bdf-493e-abbe-f8705e04aa95}");
|
||||
WM_PRIV_VD_UPDATE = RegisterWindowMessage(L"{b8b72b46-f42f-4c26-9e20-29336cf2f22e}");
|
||||
WM_PRIV_EDITOR = RegisterWindowMessage(L"{87543824-7080-4e91-9d9c-0404642fc7b6}");
|
||||
WM_PRIV_FILE_UPDATE = RegisterWindowMessage(L"{632f17a9-55a7-45f1-a4db-162e39271d92}");
|
||||
WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE = RegisterWindowMessage(L"{07229b7e-4f22-4357-b136-33c289be2295}");
|
||||
WM_PRIV_LAYOUT_TEMPLATES_FILE_UPDATE = RegisterWindowMessage(L"{4686f019-5d3d-4c5c-9051-b7cbbccca77d}");
|
||||
WM_PRIV_CUSTOM_LAYOUTS_FILE_UPDATE = RegisterWindowMessage(L"{0972787e-cdab-4e16-b228-91acdc38f40f}");
|
||||
WM_PRIV_APPLIED_LAYOUTS_FILE_UPDATE = RegisterWindowMessage(L"{2ef2c8a7-e0d5-4f31-9ede-52aade2d284d}");
|
||||
WM_PRIV_SNAP_HOTKEY = RegisterWindowMessage(L"{72f4fd8e-23f1-43ab-bbbc-029363df9a84}");
|
||||
WM_PRIV_QUICK_LAYOUT_KEY = RegisterWindowMessage(L"{15baab3d-c67b-4a15-aFF0-13610e05e947}");
|
||||
WM_PRIV_SETTINGS_CHANGED = RegisterWindowMessage(L"{89ca3Daa-bf2d-4e73-9f3f-c60716364e27}");
|
||||
|
||||
@@ -9,9 +9,10 @@ extern UINT WM_PRIV_VD_INIT; // Scheduled when FancyZones is initialized
|
||||
extern UINT WM_PRIV_VD_SWITCH; // Scheduled when virtual desktop switch occurs
|
||||
extern UINT WM_PRIV_VD_UPDATE; // Scheduled on virtual desktops update (creation/deletion)
|
||||
extern UINT WM_PRIV_EDITOR; // Scheduled when the editor exits
|
||||
extern UINT WM_PRIV_FILE_UPDATE; // Scheduled when the watched zone-settings file is updated
|
||||
extern UINT WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE; // Scheduled when the watched layout-hotkeys.json file is updated
|
||||
extern UINT WM_PRIV_LAYOUT_TEMPLATES_FILE_UPDATE; // Scheduled when the watched layout-templates.json file is updated
|
||||
extern UINT WM_PRIV_CUSTOM_LAYOUTS_FILE_UPDATE; // Scheduled when the watched custom-layouts.json file is updated
|
||||
extern UINT WM_PRIV_APPLIED_LAYOUTS_FILE_UPDATE; // Scheduled when the watched applied-layouts.json file is updated
|
||||
extern UINT WM_PRIV_SNAP_HOTKEY; // Scheduled when we receive a snap hotkey key down press
|
||||
extern UINT WM_PRIV_QUICK_LAYOUT_KEY; // Scheduled when we receive a key down press to quickly apply a layout
|
||||
extern UINT WM_PRIV_SETTINGS_CHANGED; // Scheduled when the a watched settings file is updated
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "JsonHelpers.h"
|
||||
#include "FancyZonesData.h"
|
||||
#include "FancyZonesDataTypes.h"
|
||||
#include "trace.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <FancyZonesLib/FancyZonesData/AppliedLayouts.h>
|
||||
#include <FancyZonesLib/FancyZonesData/CustomLayouts.h>
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutDefaults.h>
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutHotkeys.h>
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutTemplates.h>
|
||||
|
||||
@@ -580,21 +581,6 @@ namespace JSONHelpers
|
||||
}
|
||||
}
|
||||
|
||||
void SaveZoneSettings(const std::wstring& zonesSettingsFileName, const TDeviceInfoMap& deviceInfoMap)
|
||||
{
|
||||
auto before = json::from_file(zonesSettingsFileName);
|
||||
|
||||
json::JsonObject root{};
|
||||
|
||||
root.SetNamedValue(NonLocalizable::DevicesStr, JSONHelpers::SerializeDeviceInfos(deviceInfoMap));
|
||||
|
||||
if (!before.has_value() || before.value().Stringify() != root.Stringify())
|
||||
{
|
||||
Trace::FancyZones::DataChanged();
|
||||
json::to_file(zonesSettingsFileName, root);
|
||||
}
|
||||
}
|
||||
|
||||
void SaveAppZoneHistory(const std::wstring& appZoneHistoryFileName, const TAppZoneHistoryMap& appZoneHistoryMap)
|
||||
{
|
||||
json::JsonObject root{};
|
||||
@@ -644,7 +630,7 @@ namespace JSONHelpers
|
||||
return appHistoryArray;
|
||||
}
|
||||
|
||||
TDeviceInfoMap ParseDeviceInfos(const json::JsonObject& fancyZonesDataJSON)
|
||||
std::optional<TDeviceInfoMap> ParseDeviceInfos(const json::JsonObject& fancyZonesDataJSON)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -661,22 +647,37 @@ namespace JSONHelpers
|
||||
|
||||
return std::move(deviceInfoMap);
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
catch (const winrt::hresult_error& e)
|
||||
{
|
||||
return {};
|
||||
Logger::error(L"Parsing device info error: {}", e.message());
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
json::JsonArray SerializeDeviceInfos(const TDeviceInfoMap& deviceInfoMap)
|
||||
void SaveAppliedLayouts(const TDeviceInfoMap& deviceInfoMap)
|
||||
{
|
||||
json::JsonArray DeviceInfosJSON{};
|
||||
json::JsonObject root{};
|
||||
json::JsonArray layoutsArray{};
|
||||
|
||||
for (const auto& [deviceID, deviceData] : deviceInfoMap)
|
||||
for (const auto& [deviceID, data] : deviceInfoMap)
|
||||
{
|
||||
DeviceInfosJSON.Append(DeviceInfoJSON::DeviceInfoJSON::ToJson(DeviceInfoJSON{ deviceID, deviceData }));
|
||||
json::JsonObject layout{};
|
||||
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::UuidID, json::value(data.activeZoneSet.uuid));
|
||||
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::TypeID, json::value(FancyZonesDataTypes::TypeToString(data.activeZoneSet.type)));
|
||||
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ShowSpacingID, json::value(data.showSpacing));
|
||||
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SpacingID, json::value(data.spacing));
|
||||
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ZoneCountID, json::value(data.zoneCount));
|
||||
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SensitivityRadiusID, json::value(data.sensitivityRadius));
|
||||
|
||||
json::JsonObject obj{};
|
||||
obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::DeviceIdID, json::value(deviceID.toString()));
|
||||
obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutID, layout);
|
||||
|
||||
layoutsArray.Append(obj);
|
||||
}
|
||||
|
||||
return DeviceInfosJSON;
|
||||
root.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutsArrayID, layoutsArray);
|
||||
json::to_file(AppliedLayouts::AppliedLayoutsFileName(), root);
|
||||
}
|
||||
|
||||
json::JsonArray SerializeCustomZoneSets(const TCustomZoneSetsMap& customZoneSetsMap)
|
||||
|
||||
@@ -93,14 +93,13 @@ namespace JSONHelpers
|
||||
|
||||
json::JsonObject GetPersistFancyZonesJSON(const std::wstring& zonesSettingsFileName, const std::wstring& appZoneHistoryFileName);
|
||||
|
||||
void SaveZoneSettings(const std::wstring& zonesSettingsFileName, const TDeviceInfoMap& deviceInfoMap);
|
||||
void SaveAppZoneHistory(const std::wstring& appZoneHistoryFileName, const TAppZoneHistoryMap& appZoneHistoryMap);
|
||||
|
||||
TAppZoneHistoryMap ParseAppZoneHistory(const json::JsonObject& fancyZonesDataJSON);
|
||||
json::JsonArray SerializeAppZoneHistory(const TAppZoneHistoryMap& appZoneHistoryMap);
|
||||
void SaveAppZoneHistory(const std::wstring& appZoneHistoryFileName, const TAppZoneHistoryMap& appZoneHistoryMap);
|
||||
|
||||
TDeviceInfoMap ParseDeviceInfos(const json::JsonObject& fancyZonesDataJSON);
|
||||
json::JsonArray SerializeDeviceInfos(const TDeviceInfoMap& deviceInfoMap);
|
||||
// replace zones-settings: applied layouts
|
||||
std::optional<TDeviceInfoMap> ParseDeviceInfos(const json::JsonObject& fancyZonesDataJSON);
|
||||
void SaveAppliedLayouts(const TDeviceInfoMap& deviceInfoMap);
|
||||
|
||||
// replace zones-settings: layout hotkeys
|
||||
std::optional<TLayoutQuickKeysMap> ParseQuickKeys(const json::JsonObject& fancyZonesDataJSON);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <common/logger/call_tracer.h>
|
||||
#include <common/logger/logger.h>
|
||||
|
||||
#include "FancyZonesData.h"
|
||||
#include "FancyZonesData/AppliedLayouts.h"
|
||||
#include "FancyZonesData/AppZoneHistory.h"
|
||||
#include "FancyZonesDataTypes.h"
|
||||
#include "ZonesOverlay.h"
|
||||
@@ -486,73 +486,65 @@ void WorkArea::InitializeZoneSets(const FancyZonesDataTypes::DeviceIdData& paren
|
||||
wil::unique_cotaskmem_string virtualDesktopId;
|
||||
if (SUCCEEDED(StringFromCLSID(m_uniqueId.virtualDesktopId, &virtualDesktopId)))
|
||||
{
|
||||
Logger::debug(L"Initialize zone sets on the virtual desktop {}", virtualDesktopId.get());
|
||||
Logger::debug(L"Initialize layout on the virtual desktop {}", virtualDesktopId.get());
|
||||
}
|
||||
|
||||
bool deviceAdded = FancyZonesDataInstance().AddDevice(m_uniqueId);
|
||||
// If the device has been added, check if it should inherit the parent's layout
|
||||
if (deviceAdded && parentUniqueId.virtualDesktopId != GUID_NULL)
|
||||
bool isLayoutAlreadyApplied = AppliedLayouts::instance().IsLayoutApplied(m_uniqueId);
|
||||
if (!isLayoutAlreadyApplied)
|
||||
{
|
||||
FancyZonesDataInstance().CloneDeviceInfo(parentUniqueId, m_uniqueId);
|
||||
if (parentUniqueId.virtualDesktopId != GUID_NULL)
|
||||
{
|
||||
AppliedLayouts::instance().CloneLayout(parentUniqueId, m_uniqueId);
|
||||
}
|
||||
else
|
||||
{
|
||||
AppliedLayouts::instance().ApplyDefaultLayout(m_uniqueId);
|
||||
}
|
||||
}
|
||||
|
||||
CalculateZoneSet(m_overlappingAlgorithm);
|
||||
}
|
||||
|
||||
void WorkArea::CalculateZoneSet(OverlappingZonesAlgorithm overlappingAlgorithm) noexcept
|
||||
{
|
||||
const auto& fancyZonesData = FancyZonesDataInstance();
|
||||
const auto deviceInfoData = fancyZonesData.FindDeviceInfo(m_uniqueId);
|
||||
|
||||
if (!deviceInfoData.has_value())
|
||||
const auto appliedLayout = AppliedLayouts::instance().GetDeviceLayout(m_uniqueId);
|
||||
if (!appliedLayout.has_value())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& activeZoneSet = deviceInfoData->activeZoneSet;
|
||||
auto zoneSet = MakeZoneSet(ZoneSetConfig(
|
||||
appliedLayout->uuid,
|
||||
appliedLayout->type,
|
||||
m_monitor,
|
||||
appliedLayout->sensitivityRadius,
|
||||
overlappingAlgorithm));
|
||||
|
||||
if (activeZoneSet.uuid.empty())
|
||||
RECT workArea;
|
||||
if (m_monitor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GUID zoneSetId;
|
||||
if (SUCCEEDED_LOG(CLSIDFromString(activeZoneSet.uuid.c_str(), &zoneSetId)))
|
||||
{
|
||||
int sensitivityRadius = deviceInfoData->sensitivityRadius;
|
||||
|
||||
auto zoneSet = MakeZoneSet(ZoneSetConfig(
|
||||
zoneSetId,
|
||||
activeZoneSet.type,
|
||||
m_monitor,
|
||||
sensitivityRadius,
|
||||
overlappingAlgorithm));
|
||||
|
||||
RECT workArea;
|
||||
if (m_monitor)
|
||||
MONITORINFO monitorInfo{};
|
||||
monitorInfo.cbSize = sizeof(monitorInfo);
|
||||
if (GetMonitorInfoW(m_monitor, &monitorInfo))
|
||||
{
|
||||
MONITORINFO monitorInfo{};
|
||||
monitorInfo.cbSize = sizeof(monitorInfo);
|
||||
if (GetMonitorInfoW(m_monitor, &monitorInfo))
|
||||
{
|
||||
workArea = monitorInfo.rcWork;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
workArea = monitorInfo.rcWork;
|
||||
}
|
||||
else
|
||||
{
|
||||
workArea = GetAllMonitorsCombinedRect<&MONITORINFO::rcWork>();
|
||||
return;
|
||||
}
|
||||
|
||||
bool showSpacing = deviceInfoData->showSpacing;
|
||||
int spacing = showSpacing ? deviceInfoData->spacing : 0;
|
||||
int zoneCount = deviceInfoData->zoneCount;
|
||||
|
||||
zoneSet->CalculateZones(workArea, zoneCount, spacing);
|
||||
UpdateActiveZoneSet(zoneSet.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
workArea = GetAllMonitorsCombinedRect<&MONITORINFO::rcWork>();
|
||||
}
|
||||
|
||||
bool showSpacing = appliedLayout->showSpacing;
|
||||
int spacing = showSpacing ? appliedLayout->spacing : 0;
|
||||
int zoneCount = appliedLayout->zoneCount;
|
||||
|
||||
zoneSet->CalculateZones(workArea, zoneCount, spacing);
|
||||
UpdateActiveZoneSet(zoneSet.get());
|
||||
}
|
||||
|
||||
void WorkArea::UpdateActiveZoneSet(_In_opt_ IZoneSet* zoneSet) noexcept
|
||||
@@ -568,7 +560,8 @@ void WorkArea::UpdateActiveZoneSet(_In_opt_ IZoneSet* zoneSet) noexcept
|
||||
.uuid = zoneSetId.get(),
|
||||
.type = m_zoneSet->LayoutType()
|
||||
};
|
||||
FancyZonesDataInstance().SetActiveZoneSet(m_uniqueId, data);
|
||||
|
||||
AppliedLayouts::instance().ApplyLayout(m_uniqueId, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "ZoneSet.h"
|
||||
|
||||
#include "FancyZonesData.h"
|
||||
#include <FancyZonesLib/FancyZonesData/CustomLayouts.h>
|
||||
#include "FancyZonesDataTypes.h"
|
||||
#include "FancyZonesWindowProperties.h"
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#include "trace.h"
|
||||
#include "FancyZonesLib/ZoneSet.h"
|
||||
#include "FancyZonesLib/Settings.h"
|
||||
#include "FancyZonesLib/FancyZonesData.h"
|
||||
#include "FancyZonesData/AppZoneHistory.h"
|
||||
#include "FancyZonesLib/FancyZonesData/AppliedLayouts.h"
|
||||
#include "FancyZonesLib/FancyZonesData/CustomLayouts.h"
|
||||
#include "FancyZonesLib/FancyZonesData/LayoutHotkeys.h"
|
||||
#include "FancyZonesLib/FancyZonesDataTypes.h"
|
||||
@@ -145,10 +145,9 @@ 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>(AppZoneHistory::instance().GetFullAppZoneHistory().size());
|
||||
const auto& customZones = CustomLayouts::instance().GetAllLayouts();
|
||||
const auto& devices = data.GetDeviceInfoMap();
|
||||
const auto& layouts = AppliedLayouts::instance().GetAppliedLayoutMap();
|
||||
auto quickKeysCount = LayoutHotkeys::instance().GetHotkeysCount();
|
||||
|
||||
std::unique_ptr<INT32[]> customZonesArray(new (std::nothrow) INT32[customZones.size()]);
|
||||
@@ -157,7 +156,7 @@ void Trace::FancyZones::DataChanged() noexcept
|
||||
return;
|
||||
}
|
||||
|
||||
auto getCustomZoneCount = [&data](const std::variant<FancyZonesDataTypes::CanvasLayoutInfo, FancyZonesDataTypes::GridLayoutInfo>& layoutInfo) -> int {
|
||||
auto getCustomZoneCount = [](const std::variant<FancyZonesDataTypes::CanvasLayoutInfo, FancyZonesDataTypes::GridLayoutInfo>& layoutInfo) -> int {
|
||||
if (std::holds_alternative<FancyZonesDataTypes::GridLayoutInfo>(layoutInfo))
|
||||
{
|
||||
const auto& info = std::get<FancyZonesDataTypes::GridLayoutInfo>(layoutInfo);
|
||||
@@ -181,9 +180,9 @@ void Trace::FancyZones::DataChanged() noexcept
|
||||
|
||||
// ActiveZoneSetsList
|
||||
std::wstring activeZoneSetInfo;
|
||||
for (const auto& [id, device] : devices)
|
||||
for (const auto& [id, layout] : layouts)
|
||||
{
|
||||
const FancyZonesDataTypes::ZoneSetLayoutType type = device.activeZoneSet.type;
|
||||
const FancyZonesDataTypes::ZoneSetLayoutType type = layout.type;
|
||||
if (!activeZoneSetInfo.empty())
|
||||
{
|
||||
activeZoneSetInfo += L"; ";
|
||||
@@ -193,19 +192,16 @@ void Trace::FancyZones::DataChanged() noexcept
|
||||
int zoneCount = -1;
|
||||
if (type == FancyZonesDataTypes::ZoneSetLayoutType::Custom)
|
||||
{
|
||||
auto guid = FancyZonesUtils::GuidFromString(device.activeZoneSet.uuid);
|
||||
if (guid)
|
||||
auto guid = layout.uuid;
|
||||
const auto& activeCustomZone = customZones.find(guid);
|
||||
if (activeCustomZone != customZones.end())
|
||||
{
|
||||
const auto& activeCustomZone = customZones.find(guid.value());
|
||||
if (activeCustomZone != customZones.end())
|
||||
{
|
||||
zoneCount = getCustomZoneCount(activeCustomZone->second.info);
|
||||
}
|
||||
}
|
||||
zoneCount = getCustomZoneCount(activeCustomZone->second.info);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
zoneCount = device.zoneCount;
|
||||
zoneCount = layout.zoneCount;
|
||||
}
|
||||
|
||||
if (zoneCount != -1)
|
||||
@@ -226,7 +222,7 @@ void Trace::FancyZones::DataChanged() noexcept
|
||||
TraceLoggingInt32(appsHistorySize, AppsInHistoryCountKey),
|
||||
TraceLoggingInt32(static_cast<int>(customZones.size()), CustomZoneSetCountKey),
|
||||
TraceLoggingInt32Array(customZonesArray.get(), static_cast<int>(customZones.size()), NumberOfZonesForEachCustomZoneSetKey),
|
||||
TraceLoggingInt32(static_cast<int>(devices.size()), ActiveZoneSetsCountKey),
|
||||
TraceLoggingInt32(static_cast<int>(layouts.size()), ActiveZoneSetsCountKey),
|
||||
TraceLoggingWideString(activeZoneSetInfo.c_str(), ActiveZoneSetsListKey),
|
||||
TraceLoggingInt32(static_cast<int>(quickKeysCount), LayoutUsingQuickKeyCountKey));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user