mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-15 19:27:56 +01:00
[FancyZones] Split zones-settings: devices -> applied layouts (#15779)
This commit is contained in:
3
.github/actions/spell-check/expect.txt
vendored
3
.github/actions/spell-check/expect.txt
vendored
@@ -2012,6 +2012,7 @@ tadele
|
||||
talynone
|
||||
TApp
|
||||
TApplication
|
||||
TApplied
|
||||
targ
|
||||
TARGETAPPHEADER
|
||||
TARGETDIR
|
||||
@@ -2297,7 +2298,7 @@ WINL
|
||||
winmd
|
||||
winmm
|
||||
WINMSAPP
|
||||
winnt
|
||||
WINNT
|
||||
winres
|
||||
winrt
|
||||
winsdk
|
||||
|
||||
@@ -18,8 +18,7 @@ FancyZonesApp::FancyZonesApp(const std::wstring& appName, const std::wstring& ap
|
||||
DPIAware::EnableDPIAwarenessForThisProcess();
|
||||
|
||||
m_settings = MakeFancyZonesSettings(reinterpret_cast<HINSTANCE>(&__ImageBase), appName.c_str(), appKey.c_str());
|
||||
FancyZonesDataInstance().LoadFancyZonesData();
|
||||
|
||||
|
||||
InitializeWinhookEventIds();
|
||||
m_app = MakeFancyZones(reinterpret_cast<HINSTANCE>(&__ImageBase), m_settings, std::bind(&FancyZonesApp::DisableModule, this));
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,374 @@
|
||||
#include "pch.h"
|
||||
#include <filesystem>
|
||||
|
||||
#include <FancyZonesLib/FancyZonesData.h>
|
||||
#include <FancyZonesLib/FancyZonesData/AppliedLayouts.h>
|
||||
#include <FancyZonesLib/util.h>
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
|
||||
namespace FancyZonesUnitTests
|
||||
{
|
||||
TEST_CLASS (AppliedLayoutsUnitTests)
|
||||
{
|
||||
FancyZonesData& m_fzData = FancyZonesDataInstance();
|
||||
std::wstring m_testFolder = L"FancyZonesUnitTests";
|
||||
|
||||
TEST_METHOD_INITIALIZE(Init)
|
||||
{
|
||||
m_fzData.SetSettingsModulePath(L"FancyZonesUnitTests");
|
||||
}
|
||||
|
||||
TEST_METHOD_CLEANUP(CleanUp)
|
||||
{
|
||||
std::filesystem::remove_all(AppliedLayouts::AppliedLayoutsFileName());
|
||||
std::filesystem::remove_all(PTSettingsHelper::get_module_save_folder_location(m_testFolder));
|
||||
}
|
||||
|
||||
TEST_METHOD (AppliedLayoutsParse)
|
||||
{
|
||||
// prepare
|
||||
json::JsonObject root{};
|
||||
json::JsonArray layoutsArray{};
|
||||
|
||||
{
|
||||
json::JsonObject layout{};
|
||||
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::UuidID, json::value(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}"));
|
||||
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::TypeID, json::value(FancyZonesDataTypes::TypeToString(FancyZonesDataTypes::ZoneSetLayoutType::Rows)));
|
||||
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ShowSpacingID, json::value(true));
|
||||
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SpacingID, json::value(3));
|
||||
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ZoneCountID, json::value(4));
|
||||
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SensitivityRadiusID, json::value(22));
|
||||
|
||||
json::JsonObject obj{};
|
||||
obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::DeviceIdID, json::value(L"DELA026#5&10a58c63&0&UID16777488_2194_1234_{61FA9FC0-26A6-4B37-A834-491C148DFC57}"));
|
||||
obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutID, layout);
|
||||
|
||||
layoutsArray.Append(obj);
|
||||
}
|
||||
|
||||
root.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutsArrayID, layoutsArray);
|
||||
json::to_file(AppliedLayouts::AppliedLayoutsFileName(), root);
|
||||
|
||||
// test
|
||||
AppliedLayouts::instance().LoadData();
|
||||
Assert::AreEqual((size_t)1, AppliedLayouts::instance().GetAppliedLayoutMap().size());
|
||||
|
||||
FancyZonesDataTypes::DeviceIdData id{
|
||||
.deviceName = L"DELA026#5&10a58c63&0&UID16777488",
|
||||
.width = 2194,
|
||||
.height = 1234,
|
||||
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}").value()
|
||||
};
|
||||
Assert::IsTrue(AppliedLayouts::instance().GetDeviceLayout(id).has_value());
|
||||
}
|
||||
|
||||
TEST_METHOD (AppliedLayoutsParseEmpty)
|
||||
{
|
||||
// prepare
|
||||
json::JsonObject root{};
|
||||
json::JsonArray layoutsArray{};
|
||||
root.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutsArrayID, layoutsArray);
|
||||
json::to_file(AppliedLayouts::AppliedLayoutsFileName(), root);
|
||||
|
||||
// test
|
||||
AppliedLayouts::instance().LoadData();
|
||||
Assert::IsTrue(AppliedLayouts::instance().GetAppliedLayoutMap().empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (AppliedLayoutsNoFile)
|
||||
{
|
||||
// test
|
||||
AppliedLayouts::instance().LoadData();
|
||||
Assert::IsTrue(AppliedLayouts::instance().GetAppliedLayoutMap().empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (MoveAppliedLayoutsFromZonesSettings)
|
||||
{
|
||||
// prepare
|
||||
json::JsonObject root{};
|
||||
json::JsonArray devicesArray{}, customLayoutsArray{}, templateLayoutsArray{}, quickLayoutKeysArray{};
|
||||
|
||||
{
|
||||
json::JsonObject activeZoneset{};
|
||||
activeZoneset.SetNamedValue(L"uuid", json::value(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}"));
|
||||
activeZoneset.SetNamedValue(L"type", json::value(FancyZonesDataTypes::TypeToString(FancyZonesDataTypes::ZoneSetLayoutType::Rows)));
|
||||
|
||||
json::JsonObject obj{};
|
||||
obj.SetNamedValue(L"device-id", json::value(L"VSC9636#5&37ac4db&0&UID160005_3840_2160_{00000000-0000-0000-0000-000000000000}"));
|
||||
obj.SetNamedValue(L"active-zoneset", activeZoneset);;
|
||||
obj.SetNamedValue(L"editor-show-spacing", json::value(true));
|
||||
obj.SetNamedValue(L"editor-spacing", json::value(3));
|
||||
obj.SetNamedValue(L"editor-zone-count", json::value(4));
|
||||
obj.SetNamedValue(L"editor-sensitivity-radius", json::value(22));
|
||||
|
||||
devicesArray.Append(obj);
|
||||
}
|
||||
|
||||
root.SetNamedValue(L"devices", devicesArray);
|
||||
root.SetNamedValue(L"custom-zone-sets", customLayoutsArray);
|
||||
root.SetNamedValue(L"templates", templateLayoutsArray);
|
||||
root.SetNamedValue(L"quick-layout-keys", quickLayoutKeysArray);
|
||||
json::to_file(m_fzData.GetZoneSettingsPath(m_testFolder), root);
|
||||
|
||||
// test
|
||||
m_fzData.ReplaceZoneSettingsFileFromOlderVersions();
|
||||
AppliedLayouts::instance().LoadData();
|
||||
Assert::AreEqual((size_t)1, AppliedLayouts::instance().GetAppliedLayoutMap().size());
|
||||
|
||||
FancyZonesDataTypes::DeviceIdData id{
|
||||
.deviceName = L"VSC9636#5&37ac4db&0&UID160005",
|
||||
.width = 3840,
|
||||
.height = 2160,
|
||||
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value()
|
||||
};
|
||||
Assert::IsTrue(AppliedLayouts::instance().GetDeviceLayout(id).has_value());
|
||||
}
|
||||
|
||||
TEST_METHOD (MoveAppliedLayoutsFromZonesSettingsNoAppliedLayoutsData)
|
||||
{
|
||||
// prepare
|
||||
json::JsonObject root{};
|
||||
json::JsonArray customLayoutsArray{}, templateLayoutsArray{}, quickLayoutKeysArray{};
|
||||
root.SetNamedValue(L"custom-zone-sets", customLayoutsArray);
|
||||
root.SetNamedValue(L"templates", templateLayoutsArray);
|
||||
root.SetNamedValue(L"quick-layout-keys", quickLayoutKeysArray);
|
||||
json::to_file(m_fzData.GetZoneSettingsPath(m_testFolder), root);
|
||||
|
||||
// test
|
||||
m_fzData.ReplaceZoneSettingsFileFromOlderVersions();
|
||||
AppliedLayouts::instance().LoadData();
|
||||
Assert::IsTrue(AppliedLayouts::instance().GetAppliedLayoutMap().empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (MoveAppliedLayoutsFromZonesSettingsNoFile)
|
||||
{
|
||||
// test
|
||||
m_fzData.ReplaceZoneSettingsFileFromOlderVersions();
|
||||
AppliedLayouts::instance().LoadData();
|
||||
Assert::IsTrue(AppliedLayouts::instance().GetAppliedLayoutMap().empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (CloneDeviceInfo)
|
||||
{
|
||||
FancyZonesDataTypes::DeviceIdData deviceSrc{
|
||||
.deviceName = L"Device1",
|
||||
.width = 200,
|
||||
.height = 100,
|
||||
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value()
|
||||
};
|
||||
FancyZonesDataTypes::DeviceIdData deviceDst{
|
||||
.deviceName = L"Device2",
|
||||
.width = 300,
|
||||
.height = 400,
|
||||
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value()
|
||||
};
|
||||
|
||||
Assert::IsTrue(AppliedLayouts::instance().ApplyDefaultLayout(deviceSrc));
|
||||
Assert::IsTrue(AppliedLayouts::instance().ApplyDefaultLayout(deviceDst));
|
||||
|
||||
AppliedLayouts::instance().CloneLayout(deviceSrc, deviceDst);
|
||||
|
||||
auto actualMap = AppliedLayouts::instance().GetAppliedLayoutMap();
|
||||
Assert::IsFalse(actualMap.find(deviceSrc) == actualMap.end());
|
||||
Assert::IsFalse(actualMap.find(deviceDst) == actualMap.end());
|
||||
|
||||
auto expected = AppliedLayouts::instance().GetDeviceLayout(deviceSrc);
|
||||
auto actual = AppliedLayouts::instance().GetDeviceLayout(deviceDst);
|
||||
|
||||
Assert::IsTrue(expected.has_value());
|
||||
Assert::IsTrue(actual.has_value());
|
||||
Assert::IsTrue(expected.value().uuid == actual.value().uuid);
|
||||
}
|
||||
|
||||
TEST_METHOD (CloneDeviceInfoIntoUnknownDevice)
|
||||
{
|
||||
FancyZonesDataTypes::DeviceIdData deviceSrc{
|
||||
.deviceName = L"Device1",
|
||||
.width = 200,
|
||||
.height = 100,
|
||||
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value()
|
||||
};
|
||||
FancyZonesDataTypes::DeviceIdData deviceDst{
|
||||
.deviceName = L"Device2",
|
||||
.width = 300,
|
||||
.height = 400,
|
||||
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value()
|
||||
};
|
||||
|
||||
Assert::IsTrue(AppliedLayouts::instance().ApplyDefaultLayout(deviceSrc));
|
||||
|
||||
AppliedLayouts::instance().CloneLayout(deviceSrc, deviceDst);
|
||||
|
||||
auto actualMap = AppliedLayouts::instance().GetAppliedLayoutMap();
|
||||
Assert::IsFalse(actualMap.find(deviceSrc) == actualMap.end());
|
||||
Assert::IsFalse(actualMap.find(deviceDst) == actualMap.end());
|
||||
|
||||
auto expected = AppliedLayouts::instance().GetDeviceLayout(deviceSrc);
|
||||
auto actual = AppliedLayouts::instance().GetDeviceLayout(deviceDst);
|
||||
|
||||
Assert::IsTrue(expected.has_value());
|
||||
Assert::IsTrue(actual.has_value());
|
||||
Assert::IsTrue(expected.value().uuid == actual.value().uuid);
|
||||
}
|
||||
|
||||
TEST_METHOD (CloneDeviceInfoFromUnknownDevice)
|
||||
{
|
||||
FancyZonesDataTypes::DeviceIdData deviceSrc{
|
||||
.deviceName = L"Device1",
|
||||
.width = 200,
|
||||
.height = 100,
|
||||
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value()
|
||||
};
|
||||
FancyZonesDataTypes::DeviceIdData deviceDst{
|
||||
.deviceName = L"Device2",
|
||||
.width = 300,
|
||||
.height = 400,
|
||||
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value()
|
||||
};
|
||||
|
||||
AppliedLayouts::instance().LoadData();
|
||||
Assert::IsTrue(AppliedLayouts::instance().ApplyDefaultLayout(deviceDst));
|
||||
|
||||
Assert::IsFalse(AppliedLayouts::instance().CloneLayout(deviceSrc, deviceDst));
|
||||
|
||||
Assert::IsFalse(AppliedLayouts::instance().GetDeviceLayout(deviceSrc).has_value());
|
||||
Assert::IsTrue(AppliedLayouts::instance().GetDeviceLayout(deviceDst).has_value());
|
||||
}
|
||||
|
||||
TEST_METHOD (CloneDeviceInfoNullVirtualDesktopId)
|
||||
{
|
||||
FancyZonesDataTypes::DeviceIdData deviceSrc{
|
||||
.deviceName = L"Device1",
|
||||
.width = 200,
|
||||
.height = 100,
|
||||
.virtualDesktopId = GUID_NULL
|
||||
};
|
||||
FancyZonesDataTypes::DeviceIdData deviceDst{
|
||||
.deviceName = L"Device2",
|
||||
.width = 300,
|
||||
.height = 400,
|
||||
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value()
|
||||
};
|
||||
|
||||
Assert::IsTrue(AppliedLayouts::instance().ApplyDefaultLayout(deviceSrc));
|
||||
Assert::IsTrue(AppliedLayouts::instance().ApplyDefaultLayout(deviceDst));
|
||||
|
||||
AppliedLayouts::instance().CloneLayout(deviceSrc, deviceDst);
|
||||
|
||||
auto actualMap = AppliedLayouts::instance().GetAppliedLayoutMap();
|
||||
Assert::IsFalse(actualMap.find(deviceSrc) == actualMap.end());
|
||||
Assert::IsFalse(actualMap.find(deviceDst) == actualMap.end());
|
||||
|
||||
auto expected = AppliedLayouts::instance().GetDeviceLayout(deviceSrc);
|
||||
auto actual = AppliedLayouts::instance().GetDeviceLayout(deviceDst);
|
||||
|
||||
Assert::IsTrue(expected.has_value());
|
||||
Assert::IsTrue(actual.has_value());
|
||||
Assert::IsTrue(expected.value().uuid == actual.value().uuid);
|
||||
}
|
||||
|
||||
TEST_METHOD (ApplyLayout)
|
||||
{
|
||||
// prepare
|
||||
FancyZonesDataTypes::DeviceIdData deviceId {
|
||||
.deviceName = L"DELA026#5&10a58c63&0&UID16777488",
|
||||
.width = 2194,
|
||||
.height = 1234,
|
||||
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}").value()
|
||||
};
|
||||
|
||||
// test
|
||||
FancyZonesDataTypes::ZoneSetData expectedZoneSetData {
|
||||
.uuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}",
|
||||
.type = FancyZonesDataTypes::ZoneSetLayoutType::Focus
|
||||
};
|
||||
|
||||
AppliedLayouts::instance().ApplyLayout(deviceId, expectedZoneSetData);
|
||||
|
||||
Assert::IsFalse(AppliedLayouts::instance().GetAppliedLayoutMap().empty());
|
||||
Assert::IsTrue(AppliedLayouts::instance().GetDeviceLayout(deviceId).has_value());
|
||||
}
|
||||
|
||||
TEST_METHOD (ApplyLayoutReplace)
|
||||
{
|
||||
// prepare
|
||||
FancyZonesDataTypes::DeviceIdData deviceId{
|
||||
.deviceName = L"DELA026#5&10a58c63&0&UID16777488",
|
||||
.width = 2194,
|
||||
.height = 1234,
|
||||
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}").value()
|
||||
};
|
||||
|
||||
json::JsonObject root{};
|
||||
json::JsonArray layoutsArray{};
|
||||
{
|
||||
json::JsonObject layout{};
|
||||
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::UuidID, json::value(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}"));
|
||||
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::TypeID, json::value(FancyZonesDataTypes::TypeToString(FancyZonesDataTypes::ZoneSetLayoutType::Rows)));
|
||||
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ShowSpacingID, json::value(true));
|
||||
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SpacingID, json::value(3));
|
||||
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::ZoneCountID, json::value(4));
|
||||
layout.SetNamedValue(NonLocalizable::AppliedLayoutsIds::SensitivityRadiusID, json::value(22));
|
||||
|
||||
json::JsonObject obj{};
|
||||
obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::DeviceIdID, json::value(L"DELA026#5&10a58c63&0&UID16777488_2194_1234_{61FA9FC0-26A6-4B37-A834-491C148DFC57}"));
|
||||
obj.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutID, layout);
|
||||
|
||||
layoutsArray.Append(obj);
|
||||
}
|
||||
root.SetNamedValue(NonLocalizable::AppliedLayoutsIds::AppliedLayoutsArrayID, layoutsArray);
|
||||
json::to_file(AppliedLayouts::AppliedLayoutsFileName(), root);
|
||||
AppliedLayouts::instance().LoadData();
|
||||
|
||||
// test
|
||||
FancyZonesDataTypes::ZoneSetData expectedZoneSetData {
|
||||
.uuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}",
|
||||
.type = FancyZonesDataTypes::ZoneSetLayoutType::Focus
|
||||
};
|
||||
|
||||
AppliedLayouts::instance().ApplyLayout(deviceId, expectedZoneSetData);
|
||||
|
||||
Assert::AreEqual((size_t)1, AppliedLayouts::instance().GetAppliedLayoutMap().size());
|
||||
Assert::IsTrue(AppliedLayouts::instance().GetDeviceLayout(deviceId).has_value());
|
||||
|
||||
auto actual = AppliedLayouts::instance().GetAppliedLayoutMap().find(deviceId)->second;
|
||||
Assert::AreEqual(expectedZoneSetData.uuid.c_str(), FancyZonesUtils::GuidToString(actual.uuid).value().c_str());
|
||||
Assert::IsTrue(expectedZoneSetData.type == actual.type);
|
||||
}
|
||||
|
||||
TEST_METHOD (ApplyDefaultLayout)
|
||||
{
|
||||
FancyZonesDataTypes::DeviceIdData expected{
|
||||
.deviceName = L"Device",
|
||||
.width = 200,
|
||||
.height = 100,
|
||||
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value()
|
||||
};
|
||||
|
||||
auto result = AppliedLayouts::instance().ApplyDefaultLayout(expected);
|
||||
Assert::IsTrue(result);
|
||||
|
||||
auto actualMap = AppliedLayouts::instance().GetAppliedLayoutMap();
|
||||
|
||||
Assert::IsFalse(actualMap.find(expected) == actualMap.end());
|
||||
}
|
||||
|
||||
TEST_METHOD (ApplyDefaultLayoutWithNullVirtualDesktopId)
|
||||
{
|
||||
FancyZonesDataTypes::DeviceIdData expected{
|
||||
.deviceName = L"Device",
|
||||
.width = 200,
|
||||
.height = 100,
|
||||
.virtualDesktopId = GUID_NULL
|
||||
};
|
||||
|
||||
auto result = AppliedLayouts::instance().ApplyDefaultLayout(expected);
|
||||
Assert::IsTrue(result);
|
||||
|
||||
auto actualMap = AppliedLayouts::instance().GetAppliedLayoutMap();
|
||||
|
||||
Assert::IsFalse(actualMap.find(expected) == actualMap.end());
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -96,7 +96,6 @@ namespace FancyZonesUnitTests
|
||||
|
||||
TEST_METHOD_INITIALIZE(Init)
|
||||
{
|
||||
m_fzData.clear_data();
|
||||
m_fzData.SetSettingsModulePath(L"FancyZonesUnitTests");
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
#include <filesystem>
|
||||
|
||||
#include <FancyZonesLib/FancyZones.h>
|
||||
#include <FancyZonesLib/FancyZonesData.h>
|
||||
#include <FancyZonesLib/Settings.h>
|
||||
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
@@ -63,8 +64,6 @@ namespace FancyZonesUnitTests
|
||||
winrt::com_ptr<IFancyZonesSettings> m_settings = nullptr;
|
||||
winrt::com_ptr<IFancyZonesCallback> m_fzCallback = nullptr;
|
||||
|
||||
FancyZonesData& m_fancyZonesData = FancyZonesDataInstance();
|
||||
|
||||
std::wstring serializedPowerToySettings(const Settings& settings)
|
||||
{
|
||||
PowerToysSettings::Settings ptSettings(HINSTANCE{}, L"FancyZonesUnitTests");
|
||||
@@ -111,31 +110,27 @@ namespace FancyZonesUnitTests
|
||||
}
|
||||
|
||||
TEST_METHOD_INITIALIZE(Init)
|
||||
{
|
||||
m_hInst = (HINSTANCE)GetModuleHandleW(nullptr);
|
||||
m_settings = MakeFancyZonesSettings(m_hInst, m_moduleName.c_str(), m_moduleKey.c_str());
|
||||
Assert::IsTrue(m_settings != nullptr);
|
||||
{
|
||||
m_hInst = (HINSTANCE)GetModuleHandleW(nullptr);
|
||||
m_settings = MakeFancyZonesSettings(m_hInst, m_moduleName.c_str(), m_moduleKey.c_str());
|
||||
Assert::IsTrue(m_settings != nullptr);
|
||||
|
||||
auto fancyZones = MakeFancyZones(m_hInst, m_settings, nullptr);
|
||||
Assert::IsTrue(fancyZones != nullptr);
|
||||
auto fancyZones = MakeFancyZones(m_hInst, m_settings, nullptr);
|
||||
Assert::IsTrue(fancyZones != nullptr);
|
||||
|
||||
m_fzCallback = fancyZones.as<IFancyZonesCallback>();
|
||||
Assert::IsTrue(m_fzCallback != nullptr);
|
||||
m_fzCallback = fancyZones.as<IFancyZonesCallback>();
|
||||
Assert::IsTrue(m_fzCallback != nullptr);
|
||||
}
|
||||
|
||||
m_fancyZonesData.clear_data();
|
||||
}
|
||||
TEST_METHOD_CLEANUP(Cleanup)
|
||||
{
|
||||
sendKeyboardInput(VK_SHIFT, true);
|
||||
sendKeyboardInput(VK_LWIN, true);
|
||||
sendKeyboardInput(VK_CONTROL, true);
|
||||
|
||||
TEST_METHOD_CLEANUP(Cleanup)
|
||||
{
|
||||
sendKeyboardInput(VK_SHIFT, true);
|
||||
sendKeyboardInput(VK_LWIN, true);
|
||||
sendKeyboardInput(VK_CONTROL, true);
|
||||
|
||||
auto settingsFolder = PTSettingsHelper::get_module_save_folder_location(m_moduleName);
|
||||
const auto settingsFile = settingsFolder + L"\\settings.json";
|
||||
std::filesystem::remove(settingsFile);
|
||||
std::filesystem::remove(settingsFolder);
|
||||
}
|
||||
auto settingsFolder = PTSettingsHelper::get_module_save_folder_location(m_moduleName);
|
||||
std::filesystem::remove_all(settingsFolder);
|
||||
}
|
||||
|
||||
TEST_METHOD (OnKeyDownNothingPressed)
|
||||
{
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#include <fstream>
|
||||
#include <utility>
|
||||
|
||||
#include <FancyZonesLib/FancyZonesData.h>
|
||||
#include <FancyZonesLib/FancyZonesData/AppZoneHistory.h>
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutDefaults.h>
|
||||
#include <FancyZonesLib/FancyZonesDataTypes.h>
|
||||
#include <FancyZonesLib/JsonHelpers.h>
|
||||
#include <FancyZonesLib/util.h>
|
||||
@@ -996,20 +996,20 @@ namespace FancyZonesUnitTests
|
||||
const std::wstring_view m_moduleName = L"FancyZonesUnitTests";
|
||||
const std::wstring m_defaultDeviceIdStr = L"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}";
|
||||
const std::wstring m_defaultCustomDeviceStr = L"{\"device-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"active-zoneset\": {\"type\": \"custom\", \"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\"}, \"editor-show-spacing\": true, \"editor-spacing\": 16, \"editor-zone-count\": 3}";
|
||||
const std::wstring m_defaultCustomLayoutStr = L"{\"device-id\": \"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\", \"applied-layout\": {\"type\": \"custom\", \"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\", \"show-spacing\": true, \"spacing\": 16, \"zone-count\": 3, \"sensitivity-radius\": 30}}";
|
||||
const json::JsonValue m_defaultCustomDeviceValue = json::JsonValue::Parse(m_defaultCustomDeviceStr);
|
||||
const json::JsonObject m_defaultCustomDeviceObj = json::JsonObject::Parse(m_defaultCustomDeviceStr);
|
||||
const json::JsonObject m_defaultCustomLayoutObj = json::JsonObject::Parse(m_defaultCustomLayoutStr);
|
||||
|
||||
const FancyZonesDataTypes::DeviceIdData m_defaultDeviceId = FancyZonesDataTypes::DeviceIdData::ParseDeviceId(m_defaultDeviceIdStr).value();
|
||||
|
||||
GUID m_defaultVDId;
|
||||
|
||||
HINSTANCE m_hInst{};
|
||||
FancyZonesData& m_fzData = FancyZonesDataInstance();
|
||||
|
||||
TEST_METHOD_INITIALIZE(Init)
|
||||
{
|
||||
m_hInst = (HINSTANCE)GetModuleHandleW(nullptr);
|
||||
m_fzData.clear_data();
|
||||
std::filesystem::remove_all(PTSettingsHelper::get_module_save_folder_location(m_moduleName));
|
||||
|
||||
auto guid = Helpers::StringToGuid(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}");
|
||||
@@ -1020,46 +1020,15 @@ namespace FancyZonesUnitTests
|
||||
TEST_METHOD_CLEANUP(CleanUp)
|
||||
{
|
||||
std::filesystem::remove_all(PTSettingsHelper::get_module_save_folder_location(m_moduleName));
|
||||
std::filesystem::remove_all(AppZoneHistory::AppZoneHistoryFileName());
|
||||
}
|
||||
|
||||
public:
|
||||
TEST_METHOD (FancyZonesDataPath)
|
||||
{
|
||||
FancyZonesData data;
|
||||
data.SetSettingsModulePath(m_moduleName);
|
||||
Assert::IsFalse(data.zonesSettingsFileName.empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (FancyZonesDataJsonEmpty)
|
||||
{
|
||||
FancyZonesData data;
|
||||
data.SetSettingsModulePath(m_moduleName);
|
||||
|
||||
json::JsonObject expected;
|
||||
auto actual = data.GetPersistFancyZonesJSON();
|
||||
|
||||
Assert::AreEqual(expected.Stringify().c_str(), actual.Stringify().c_str());
|
||||
}
|
||||
|
||||
TEST_METHOD (FancyZonesDataJson)
|
||||
{
|
||||
FancyZonesData data;
|
||||
data.SetSettingsModulePath(m_moduleName);
|
||||
const auto& jsonPath = data.zonesSettingsFileName;
|
||||
|
||||
json::JsonObject expected = json::JsonObject::Parse(L"{\"fancy-zones\":{\"custom-zonesets \":[{\"uuid\":\"uuid1\",\"name\":\"Custom1\",\"type\":\"custom\" }] }, \"app-zone-history\":[] }");
|
||||
json::to_file(jsonPath, expected);
|
||||
|
||||
auto actual = data.GetPersistFancyZonesJSON();
|
||||
Assert::AreEqual(expected.Stringify().c_str(), actual.Stringify().c_str());
|
||||
}
|
||||
|
||||
TEST_METHOD (FancyZonesDataDeviceInfoMapParseEmpty)
|
||||
{
|
||||
json::JsonObject deviceInfoJson;
|
||||
const auto& deviceInfoMap = ParseDeviceInfos(deviceInfoJson);
|
||||
|
||||
Assert::IsTrue(deviceInfoMap.empty());
|
||||
Assert::IsFalse(deviceInfoMap.has_value());
|
||||
}
|
||||
|
||||
TEST_METHOD (FancyZonesDataDeviceInfoMapParseValidEmpty)
|
||||
@@ -1070,7 +1039,8 @@ namespace FancyZonesUnitTests
|
||||
|
||||
const auto& deviceInfoMap = ParseDeviceInfos(deviceInfoJson);
|
||||
|
||||
Assert::IsTrue(deviceInfoMap.empty());
|
||||
Assert::IsTrue(deviceInfoMap.has_value());
|
||||
Assert::IsTrue(deviceInfoMap->empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (FancyZonesDataDeviceInfoMapParseValidAndInvalid)
|
||||
@@ -1084,7 +1054,7 @@ namespace FancyZonesUnitTests
|
||||
|
||||
const auto& deviceInfoMap = ParseDeviceInfos(deviceInfoJson);
|
||||
|
||||
Assert::AreEqual((size_t)1, deviceInfoMap.size());
|
||||
Assert::AreEqual((size_t)1, deviceInfoMap->size());
|
||||
}
|
||||
|
||||
TEST_METHOD (FancyZonesDataDeviceInfoMapParseInvalid)
|
||||
@@ -1097,7 +1067,7 @@ namespace FancyZonesUnitTests
|
||||
|
||||
const auto& deviceInfoMap = ParseDeviceInfos(deviceInfoJson);
|
||||
|
||||
Assert::IsTrue(deviceInfoMap.empty());
|
||||
Assert::IsTrue(deviceInfoMap->empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (FancyZonesDataDeviceInfoMapParseSingle)
|
||||
@@ -1109,7 +1079,7 @@ namespace FancyZonesUnitTests
|
||||
|
||||
const auto& deviceInfoMap = ParseDeviceInfos(deviceInfoJson);
|
||||
|
||||
Assert::AreEqual((size_t)1, deviceInfoMap.size());
|
||||
Assert::AreEqual((size_t)1, deviceInfoMap->size());
|
||||
}
|
||||
|
||||
TEST_METHOD (FancyZonesDataDeviceInfoMapParseMany)
|
||||
@@ -1129,21 +1099,7 @@ namespace FancyZonesUnitTests
|
||||
|
||||
const auto& deviceInfoMap = ParseDeviceInfos(expected);
|
||||
|
||||
Assert::AreEqual((size_t)10, deviceInfoMap.size());
|
||||
}
|
||||
|
||||
TEST_METHOD (FancyZonesDataSerialize)
|
||||
{
|
||||
json::JsonArray expectedDevices;
|
||||
expectedDevices.Append(m_defaultCustomDeviceObj);
|
||||
json::JsonObject expected;
|
||||
expected.SetNamedValue(L"devices", expectedDevices);
|
||||
|
||||
const auto& deviceInfoMap = ParseDeviceInfos(expected);
|
||||
|
||||
auto actual = SerializeDeviceInfos(deviceInfoMap);
|
||||
auto res = CustomAssert::CompareJsonArrays(expectedDevices, actual);
|
||||
Assert::IsTrue(res.first, res.second.c_str());
|
||||
Assert::AreEqual((size_t)10, deviceInfoMap->size());
|
||||
}
|
||||
|
||||
TEST_METHOD (AppZoneHistoryParseSingle)
|
||||
@@ -1372,449 +1328,6 @@ namespace FancyZonesUnitTests
|
||||
auto res = CustomAssert::CompareJsonArrays(expected, actual);
|
||||
Assert::IsTrue(res.first, res.second.c_str());
|
||||
}
|
||||
|
||||
TEST_METHOD (SetActiveZoneSet)
|
||||
{
|
||||
FancyZonesData data;
|
||||
data.SetSettingsModulePath(m_moduleName);
|
||||
const auto uniqueId = m_defaultDeviceId;
|
||||
|
||||
json::JsonArray devices;
|
||||
devices.Append(m_defaultCustomDeviceValue);
|
||||
json::JsonObject json;
|
||||
json.SetNamedValue(L"devices", devices);
|
||||
data.ParseDeviceInfos(json);
|
||||
|
||||
FancyZonesDataTypes::ZoneSetData expectedZoneSetData{
|
||||
.uuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}",
|
||||
.type = ZoneSetLayoutType::Focus
|
||||
};
|
||||
|
||||
data.SetActiveZoneSet(uniqueId, expectedZoneSetData);
|
||||
|
||||
auto actual = data.GetDeviceInfoMap().find(uniqueId)->second;
|
||||
Assert::AreEqual(expectedZoneSetData.uuid.c_str(), actual.activeZoneSet.uuid.c_str());
|
||||
Assert::IsTrue(expectedZoneSetData.type == actual.activeZoneSet.type);
|
||||
}
|
||||
|
||||
TEST_METHOD (SetActiveZoneSetUuidEmpty)
|
||||
{
|
||||
FancyZonesData data;
|
||||
data.SetSettingsModulePath(m_moduleName);
|
||||
const std::wstring expected = L"{39B25DD2-130D-4B5D-8851-4791D66B1539}";
|
||||
const auto uniqueId = m_defaultDeviceId;
|
||||
|
||||
json::JsonArray devices;
|
||||
devices.Append(m_defaultCustomDeviceValue);
|
||||
json::JsonObject json;
|
||||
json.SetNamedValue(L"devices", devices);
|
||||
data.ParseDeviceInfos(json);
|
||||
|
||||
FancyZonesDataTypes::ZoneSetData expectedZoneSetData{
|
||||
.uuid = L"",
|
||||
.type = ZoneSetLayoutType::Focus
|
||||
};
|
||||
|
||||
data.SetActiveZoneSet(uniqueId, expectedZoneSetData);
|
||||
|
||||
auto actual = data.GetDeviceInfoMap().find(uniqueId)->second;
|
||||
Assert::AreEqual(expectedZoneSetData.uuid.c_str(), actual.activeZoneSet.uuid.c_str());
|
||||
Assert::IsTrue(expectedZoneSetData.type == actual.activeZoneSet.type);
|
||||
}
|
||||
|
||||
TEST_METHOD (SetActiveZoneSetUniqueIdInvalid)
|
||||
{
|
||||
FancyZonesData data;
|
||||
data.SetSettingsModulePath(m_moduleName);
|
||||
|
||||
const std::wstring expected = L"{33A2B101-06E0-437B-A61E-CDBECF502906}";
|
||||
auto uniqueId = m_defaultDeviceId;
|
||||
uniqueId.deviceName = L"id-not-contained-by-device-info-map";
|
||||
|
||||
json::JsonArray devices;
|
||||
devices.Append(m_defaultCustomDeviceValue);
|
||||
json::JsonObject json;
|
||||
json.SetNamedValue(L"devices", devices);
|
||||
bool parseRes = data.ParseDeviceInfos(json);
|
||||
Assert::IsTrue(parseRes);
|
||||
|
||||
FancyZonesDataTypes::ZoneSetData zoneSetData{
|
||||
.uuid = L"new_uuid",
|
||||
.type = ZoneSetLayoutType::Focus
|
||||
};
|
||||
|
||||
data.SetActiveZoneSet(uniqueId, zoneSetData);
|
||||
|
||||
const auto& deviceInfoMap = data.GetDeviceInfoMap();
|
||||
auto actual = deviceInfoMap.find(m_defaultDeviceId)->second;
|
||||
Assert::AreEqual(expected.c_str(), actual.activeZoneSet.uuid.c_str());
|
||||
Assert::IsTrue(deviceInfoMap.end() == deviceInfoMap.find(uniqueId), L"new device info should not be added");
|
||||
}
|
||||
|
||||
TEST_METHOD (LoadFancyZonesDataFromJson)
|
||||
{
|
||||
FancyZonesData fancyZonesData;
|
||||
fancyZonesData.SetSettingsModulePath(m_moduleName);
|
||||
const auto& jsonPath = fancyZonesData.zonesSettingsFileName;
|
||||
auto savedJson = json::from_file(jsonPath);
|
||||
|
||||
if (std::filesystem::exists(jsonPath))
|
||||
{
|
||||
std::filesystem::remove(jsonPath);
|
||||
}
|
||||
|
||||
const GridLayoutInfo grid(GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{
|
||||
.rows = 1,
|
||||
.columns = 3,
|
||||
.rowsPercents = { 10000 },
|
||||
.columnsPercents = { 2500, 5000, 2500 },
|
||||
.cellChildMap = { { 0, 1, 2 } } }));
|
||||
CustomZoneSetJSON zoneSets{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", CustomLayoutData{ L"name", CustomLayoutType::Grid, grid } };
|
||||
AppZoneHistoryData data{
|
||||
.zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = L"device-id", .zoneIndexSet = { 54321 }
|
||||
};
|
||||
AppZoneHistoryJSON appZoneHistory{ L"app-path", std::vector<AppZoneHistoryData>{ data } };
|
||||
|
||||
DeviceInfoJSON deviceInfo { FancyZonesDataTypes::DeviceIdData{ L"device-id", 0, 0, m_defaultVDId }, DeviceInfoData{ ZoneSetData{ L"{33A2B101-16E1-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Custom }, true, 16, 3 } };
|
||||
LayoutQuickKeyJSON quickKeys{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", 1 };
|
||||
json::JsonArray zoneSetsArray, appZonesArray, deviceInfoArray, quickKeysArray;
|
||||
zoneSetsArray.Append(CustomZoneSetJSON::ToJson(zoneSets));
|
||||
appZonesArray.Append(AppZoneHistoryJSON::ToJson(appZoneHistory));
|
||||
deviceInfoArray.Append(DeviceInfoJSON::ToJson(deviceInfo));
|
||||
quickKeysArray.Append(LayoutQuickKeyJSON::ToJson(quickKeys));
|
||||
json::JsonObject fancyZones;
|
||||
fancyZones.SetNamedValue(L"custom-zone-sets", zoneSetsArray);
|
||||
fancyZones.SetNamedValue(L"app-zone-history", appZonesArray);
|
||||
fancyZones.SetNamedValue(L"devices", deviceInfoArray);
|
||||
fancyZones.SetNamedValue(L"quick-layout-keys", quickKeysArray);
|
||||
|
||||
json::to_file(jsonPath, fancyZones);
|
||||
|
||||
fancyZonesData.LoadFancyZonesData();
|
||||
if (savedJson)
|
||||
{
|
||||
json::to_file(jsonPath, *savedJson);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::filesystem::remove(jsonPath);
|
||||
}
|
||||
|
||||
Assert::IsFalse(fancyZonesData.GetDeviceInfoMap().empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (LoadFancyZonesDataFromCroppedJson)
|
||||
{
|
||||
FancyZonesData data;
|
||||
data.SetSettingsModulePath(m_moduleName);
|
||||
const auto& jsonPath = data.zonesSettingsFileName;
|
||||
|
||||
std::wofstream{ jsonPath.data(), std::ios::binary } << L"{ \"devices\": [{\"device-id\": \"";
|
||||
|
||||
data.LoadFancyZonesData();
|
||||
|
||||
Assert::IsTrue(data.GetDeviceInfoMap().empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (LoadFancyZonesDataFromJsonWithCyrillicSymbols)
|
||||
{
|
||||
FancyZonesData data;
|
||||
data.SetSettingsModulePath(m_moduleName);
|
||||
const auto& jsonPath = data.zonesSettingsFileName;
|
||||
|
||||
std::wofstream{ jsonPath.data(), std::ios::binary } << L"{ \"devices\": [{\"device-id\": \"кириллица\"}], \"custom-zone-sets\": []}";
|
||||
data.LoadFancyZonesData();
|
||||
|
||||
Assert::IsTrue(data.GetDeviceInfoMap().empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (LoadFancyZonesDataFromJsonWithInvalidTypes)
|
||||
{
|
||||
FancyZonesData data;
|
||||
data.SetSettingsModulePath(m_moduleName);
|
||||
const auto& jsonPath = data.zonesSettingsFileName;
|
||||
|
||||
std::wofstream{ jsonPath.data(), std::ios::binary } << L"{ \"devices\": [{\"device-id\":\"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\",\"active-zoneset\":{\"uuid\":\"{568EBC3A-C09C-483E-A64D-6F1F2AF4E48D}\",\"type\":\"columns\"},\"editor-show-spacing\":true,\"editor-spacing\":16,\"editor-zone-count\":3}], \"custom-zone-sets\": null}";
|
||||
data.LoadFancyZonesData();
|
||||
|
||||
Assert::IsFalse(data.GetDeviceInfoMap().empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (LoadFancyZonesDataFromRegistry)
|
||||
{
|
||||
FancyZonesData data;
|
||||
data.SetSettingsModulePath(m_moduleName);
|
||||
const auto& jsonPath = data.zonesSettingsFileName;
|
||||
|
||||
data.LoadFancyZonesData();
|
||||
bool actual = std::filesystem::exists(jsonPath);
|
||||
|
||||
Assert::IsTrue(actual);
|
||||
}
|
||||
|
||||
TEST_METHOD (SaveFancyZonesData)
|
||||
{
|
||||
FancyZonesData data;
|
||||
data.SetSettingsModulePath(m_moduleName);
|
||||
const auto& jsonPath = data.zonesSettingsFileName;
|
||||
|
||||
data.SaveZoneSettings();
|
||||
bool actual = std::filesystem::exists(jsonPath);
|
||||
|
||||
Assert::IsTrue(actual);
|
||||
}
|
||||
|
||||
TEST_METHOD (AddDevice)
|
||||
{
|
||||
FancyZonesDataTypes::DeviceIdData expected{
|
||||
.deviceName = L"Device",
|
||||
.width = 200,
|
||||
.height = 100,
|
||||
.virtualDesktopId = m_defaultVDId
|
||||
};
|
||||
|
||||
auto result = m_fzData.AddDevice(expected);
|
||||
Assert::IsTrue(result);
|
||||
|
||||
auto actualMap = m_fzData.GetDeviceInfoMap();
|
||||
|
||||
Assert::IsFalse(actualMap.find(expected) == actualMap.end());
|
||||
}
|
||||
|
||||
TEST_METHOD (AddDeviceWithNullVirtualDesktopId)
|
||||
{
|
||||
FancyZonesDataTypes::DeviceIdData expected{
|
||||
.deviceName = L"Device",
|
||||
.width = 200,
|
||||
.height = 100,
|
||||
.virtualDesktopId = GUID_NULL
|
||||
};
|
||||
|
||||
auto result = m_fzData.AddDevice(expected);
|
||||
Assert::IsTrue(result);
|
||||
|
||||
auto actualMap = m_fzData.GetDeviceInfoMap();
|
||||
|
||||
Assert::IsFalse(actualMap.find(expected) == actualMap.end());
|
||||
}
|
||||
|
||||
TEST_METHOD (AddDeviceDuplicate)
|
||||
{
|
||||
FancyZonesDataTypes::DeviceIdData expected{
|
||||
.deviceName = L"Device",
|
||||
.width = 200,
|
||||
.height = 100,
|
||||
.virtualDesktopId = m_defaultVDId
|
||||
};
|
||||
|
||||
auto result = m_fzData.AddDevice(expected);
|
||||
Assert::IsTrue(result);
|
||||
|
||||
auto result2 = m_fzData.AddDevice(expected);
|
||||
Assert::IsFalse(result2);
|
||||
|
||||
auto actualMap = m_fzData.GetDeviceInfoMap();
|
||||
|
||||
Assert::IsFalse(actualMap.find(expected) == actualMap.end());
|
||||
}
|
||||
|
||||
TEST_METHOD (AddDeviceWithNullVirtualDesktopIdDuplicated)
|
||||
{
|
||||
FancyZonesDataTypes::DeviceIdData expected{
|
||||
.deviceName = L"Device",
|
||||
.width = 200,
|
||||
.height = 100,
|
||||
.virtualDesktopId = GUID_NULL
|
||||
};
|
||||
|
||||
auto result = m_fzData.AddDevice(expected);
|
||||
Assert::IsTrue(result);
|
||||
|
||||
auto result2 = m_fzData.AddDevice(expected);
|
||||
Assert::IsFalse(result2);
|
||||
|
||||
auto actualMap = m_fzData.GetDeviceInfoMap();
|
||||
|
||||
Assert::IsFalse(actualMap.find(expected) == actualMap.end());
|
||||
}
|
||||
|
||||
TEST_METHOD (AddDeviceDuplicatedComparedWithNillVirtualDesktopId)
|
||||
{
|
||||
FancyZonesDataTypes::DeviceIdData device1{
|
||||
.deviceName = L"Device",
|
||||
.width = 200,
|
||||
.height = 100,
|
||||
.virtualDesktopId = m_defaultVDId
|
||||
};
|
||||
|
||||
FancyZonesDataTypes::DeviceIdData device2{
|
||||
.deviceName = L"Device",
|
||||
.width = 200,
|
||||
.height = 100,
|
||||
.virtualDesktopId = GUID_NULL
|
||||
};
|
||||
|
||||
auto result = m_fzData.AddDevice(device1);
|
||||
Assert::IsTrue(result);
|
||||
|
||||
auto result2 = m_fzData.AddDevice(device2);
|
||||
Assert::IsFalse(result2);
|
||||
|
||||
auto actualMap = m_fzData.GetDeviceInfoMap();
|
||||
|
||||
Assert::IsFalse(actualMap.find(device1) == actualMap.end());
|
||||
Assert::IsTrue(actualMap.find(device2) == actualMap.end());
|
||||
}
|
||||
|
||||
TEST_METHOD (AddDeviceDuplicatedComparedWithNillVirtualDesktopId2)
|
||||
{
|
||||
FancyZonesDataTypes::DeviceIdData device1{
|
||||
.deviceName = L"Device",
|
||||
.width = 200,
|
||||
.height = 100,
|
||||
.virtualDesktopId = m_defaultVDId
|
||||
};
|
||||
|
||||
FancyZonesDataTypes::DeviceIdData device2{
|
||||
.deviceName = L"Device",
|
||||
.width = 200,
|
||||
.height = 100,
|
||||
.virtualDesktopId = GUID_NULL
|
||||
};
|
||||
|
||||
auto result2 = m_fzData.AddDevice(device2);
|
||||
Assert::IsTrue(result2);
|
||||
|
||||
auto result1 = m_fzData.AddDevice(device1);
|
||||
Assert::IsFalse(result1);
|
||||
|
||||
auto actualMap = m_fzData.GetDeviceInfoMap();
|
||||
|
||||
Assert::IsFalse(actualMap.find(device2) == actualMap.end());
|
||||
Assert::IsTrue(actualMap.find(device1) == actualMap.end());
|
||||
}
|
||||
|
||||
TEST_METHOD(CloneDeviceInfo)
|
||||
{
|
||||
FancyZonesDataTypes::DeviceIdData deviceSrc{
|
||||
.deviceName = L"Device1",
|
||||
.width = 200,
|
||||
.height = 100,
|
||||
.virtualDesktopId = m_defaultVDId
|
||||
};
|
||||
FancyZonesDataTypes::DeviceIdData deviceDst{
|
||||
.deviceName = L"Device2",
|
||||
.width = 300,
|
||||
.height = 400,
|
||||
.virtualDesktopId = m_defaultVDId
|
||||
};
|
||||
|
||||
Assert::IsTrue(m_fzData.AddDevice(deviceSrc));
|
||||
Assert::IsTrue(m_fzData.AddDevice(deviceDst));
|
||||
|
||||
m_fzData.CloneDeviceInfo(deviceSrc, deviceDst);
|
||||
|
||||
auto actualMap = m_fzData.GetDeviceInfoMap();
|
||||
Assert::IsFalse(actualMap.find(deviceSrc) == actualMap.end());
|
||||
Assert::IsFalse(actualMap.find(deviceDst) == actualMap.end());
|
||||
|
||||
auto expected = m_fzData.FindDeviceInfo(deviceSrc);
|
||||
auto actual = m_fzData.FindDeviceInfo(deviceDst);
|
||||
|
||||
Assert::IsTrue(expected.has_value());
|
||||
Assert::IsTrue(actual.has_value());
|
||||
Assert::IsTrue(expected.value() == actual.value());
|
||||
}
|
||||
|
||||
TEST_METHOD (CloneDeviceInfoIntoUnknownDevice)
|
||||
{
|
||||
FancyZonesDataTypes::DeviceIdData deviceSrc{
|
||||
.deviceName = L"Device1",
|
||||
.width = 200,
|
||||
.height = 100,
|
||||
.virtualDesktopId = m_defaultVDId
|
||||
};
|
||||
FancyZonesDataTypes::DeviceIdData deviceDst{
|
||||
.deviceName = L"Device2",
|
||||
.width = 300,
|
||||
.height = 400,
|
||||
.virtualDesktopId = m_defaultVDId
|
||||
};
|
||||
|
||||
Assert::IsTrue(m_fzData.AddDevice(deviceSrc));
|
||||
|
||||
m_fzData.CloneDeviceInfo(deviceSrc, deviceDst);
|
||||
|
||||
auto actualMap = m_fzData.GetDeviceInfoMap();
|
||||
Assert::IsFalse(actualMap.find(deviceSrc) == actualMap.end());
|
||||
Assert::IsFalse(actualMap.find(deviceDst) == actualMap.end());
|
||||
|
||||
auto expected = m_fzData.FindDeviceInfo(deviceSrc);
|
||||
auto actual = m_fzData.FindDeviceInfo(deviceDst);
|
||||
|
||||
Assert::IsTrue(expected.has_value());
|
||||
Assert::IsTrue(actual.has_value());
|
||||
Assert::IsTrue(expected.value() == actual.value());
|
||||
}
|
||||
|
||||
TEST_METHOD (CloneDeviceInfoFromUnknownDevice)
|
||||
{
|
||||
FancyZonesDataTypes::DeviceIdData deviceSrc{
|
||||
.deviceName = L"Device1",
|
||||
.width = 200,
|
||||
.height = 100,
|
||||
.virtualDesktopId = m_defaultVDId
|
||||
};
|
||||
FancyZonesDataTypes::DeviceIdData deviceDst{
|
||||
.deviceName = L"Device2",
|
||||
.width = 300,
|
||||
.height = 400,
|
||||
.virtualDesktopId = m_defaultVDId
|
||||
};
|
||||
|
||||
Assert::IsTrue(m_fzData.AddDevice(deviceDst));
|
||||
|
||||
m_fzData.CloneDeviceInfo(deviceSrc, deviceDst);
|
||||
|
||||
auto actualMap = m_fzData.GetDeviceInfoMap();
|
||||
Assert::IsTrue(actualMap.find(deviceSrc) == actualMap.end());
|
||||
Assert::IsFalse(actualMap.find(deviceDst) == actualMap.end());
|
||||
|
||||
Assert::IsFalse(m_fzData.FindDeviceInfo(deviceSrc).has_value());
|
||||
Assert::IsTrue(m_fzData.FindDeviceInfo(deviceDst).has_value());
|
||||
}
|
||||
|
||||
TEST_METHOD(CloneDeviceInfoNullVirtualDesktopId)
|
||||
{
|
||||
FancyZonesDataTypes::DeviceIdData deviceSrc{
|
||||
.deviceName = L"Device1",
|
||||
.width = 200,
|
||||
.height = 100,
|
||||
.virtualDesktopId = GUID_NULL
|
||||
};
|
||||
FancyZonesDataTypes::DeviceIdData deviceDst{
|
||||
.deviceName = L"Device2",
|
||||
.width = 300,
|
||||
.height = 400,
|
||||
.virtualDesktopId = m_defaultVDId
|
||||
};
|
||||
|
||||
Assert::IsTrue(m_fzData.AddDevice(deviceSrc));
|
||||
Assert::IsTrue(m_fzData.AddDevice(deviceDst));
|
||||
|
||||
m_fzData.CloneDeviceInfo(deviceSrc, deviceDst);
|
||||
|
||||
auto actualMap = m_fzData.GetDeviceInfoMap();
|
||||
Assert::IsFalse(actualMap.find(deviceSrc) == actualMap.end());
|
||||
Assert::IsFalse(actualMap.find(deviceDst) == actualMap.end());
|
||||
|
||||
auto expected = m_fzData.FindDeviceInfo(deviceSrc);
|
||||
auto actual = m_fzData.FindDeviceInfo(deviceDst);
|
||||
|
||||
Assert::IsTrue(expected.has_value());
|
||||
Assert::IsTrue(actual.has_value());
|
||||
Assert::IsTrue(expected.value() == actual.value());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CLASS(EditorArgsUnitTests)
|
||||
|
||||
@@ -16,8 +16,7 @@ namespace FancyZonesUnitTests
|
||||
|
||||
TEST_METHOD_INITIALIZE(Init)
|
||||
{
|
||||
m_fzData.clear_data();
|
||||
m_fzData.SetSettingsModulePath(L"FancyZonesUnitTests");
|
||||
m_fzData.SetSettingsModulePath(m_testFolder);
|
||||
}
|
||||
|
||||
TEST_METHOD_CLEANUP(CleanUp)
|
||||
|
||||
@@ -17,8 +17,7 @@ namespace FancyZonesUnitTests
|
||||
|
||||
TEST_METHOD_INITIALIZE(Init)
|
||||
{
|
||||
m_fzData.clear_data();
|
||||
m_fzData.SetSettingsModulePath(L"FancyZonesUnitTests");
|
||||
m_fzData.SetSettingsModulePath(m_testFolder);
|
||||
}
|
||||
|
||||
TEST_METHOD_CLEANUP(CleanUp)
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AppliedLayoutsTests.Spec.cpp" />
|
||||
<ClCompile Include="AppZoneHistoryTests.Spec.cpp" />
|
||||
<ClCompile Include="CustomLayoutsTests.Spec.cpp" />
|
||||
<ClCompile Include="FancyZones.Spec.cpp" />
|
||||
|
||||
@@ -54,6 +54,9 @@
|
||||
<ClCompile Include="AppZoneHistoryTests.Spec.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AppliedLayoutsTests.Spec.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <FancyZonesLib/ZoneSet.h>
|
||||
#include <FancyZonesLib/WorkArea.h>
|
||||
#include <FancyZonesLib/FancyZones.h>
|
||||
#include <FancyZonesLib/FancyZonesData.h>
|
||||
#include <FancyZonesLib/FancyZonesData/AppliedLayouts.h>
|
||||
#include <FancyZonesLib/FancyZonesData/AppZoneHistory.h>
|
||||
#include <FancyZonesLib/FancyZonesDataTypes.h>
|
||||
#include <FancyZonesLib/JsonHelpers.h>
|
||||
@@ -35,8 +35,6 @@ namespace FancyZonesUnitTests
|
||||
OverlappingZonesAlgorithm m_overlappingAlgorithm = OverlappingZonesAlgorithm::Positional;
|
||||
bool m_showZoneText = true;
|
||||
|
||||
FancyZonesData& m_fancyZonesData = FancyZonesDataInstance();
|
||||
|
||||
void testWorkArea(winrt::com_ptr<IWorkArea> workArea)
|
||||
{
|
||||
const std::wstring expectedWorkArea = std::to_wstring(m_monitorInfo.rcMonitor.right) + L"_" + std::to_wstring(m_monitorInfo.rcMonitor.bottom);
|
||||
@@ -46,37 +44,43 @@ namespace FancyZonesUnitTests
|
||||
}
|
||||
|
||||
TEST_METHOD_INITIALIZE(Init)
|
||||
{
|
||||
m_hInst = (HINSTANCE)GetModuleHandleW(nullptr);
|
||||
{
|
||||
m_hInst = (HINSTANCE)GetModuleHandleW(nullptr);
|
||||
|
||||
m_monitor = MonitorFromPoint(POINT{ 0, 0 }, MONITOR_DEFAULTTOPRIMARY);
|
||||
m_monitorInfo.cbSize = sizeof(m_monitorInfo);
|
||||
Assert::AreNotEqual(0, GetMonitorInfoW(m_monitor, &m_monitorInfo));
|
||||
m_monitor = MonitorFromPoint(POINT{ 0, 0 }, MONITOR_DEFAULTTOPRIMARY);
|
||||
m_monitorInfo.cbSize = sizeof(m_monitorInfo);
|
||||
Assert::AreNotEqual(0, GetMonitorInfoW(m_monitor, &m_monitorInfo));
|
||||
|
||||
m_parentUniqueId.deviceName = L"DELA026#5&10a58c63&0&UID16777488";
|
||||
m_parentUniqueId.width = m_monitorInfo.rcMonitor.right - m_monitorInfo.rcMonitor.left;
|
||||
m_parentUniqueId.height = m_monitorInfo.rcMonitor.bottom - m_monitorInfo.rcMonitor.top;
|
||||
CLSIDFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}", &m_parentUniqueId.virtualDesktopId);
|
||||
m_parentUniqueId.deviceName = L"DELA026#5&10a58c63&0&UID16777488";
|
||||
m_parentUniqueId.width = m_monitorInfo.rcMonitor.right - m_monitorInfo.rcMonitor.left;
|
||||
m_parentUniqueId.height = m_monitorInfo.rcMonitor.bottom - m_monitorInfo.rcMonitor.top;
|
||||
CLSIDFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}", &m_parentUniqueId.virtualDesktopId);
|
||||
|
||||
m_uniqueId.deviceName = L"DELA026#5&10a58c63&0&UID16777488";
|
||||
m_uniqueId.width = m_monitorInfo.rcMonitor.right - m_monitorInfo.rcMonitor.left;
|
||||
m_uniqueId.height = m_monitorInfo.rcMonitor.bottom - m_monitorInfo.rcMonitor.top;
|
||||
CLSIDFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}", &m_uniqueId.virtualDesktopId);
|
||||
|
||||
m_fancyZonesData.SetSettingsModulePath(L"FancyZonesUnitTests");
|
||||
m_fancyZonesData.clear_data();
|
||||
m_uniqueId.deviceName = L"DELA026#5&10a58c63&0&UID16777488";
|
||||
m_uniqueId.width = m_monitorInfo.rcMonitor.right - m_monitorInfo.rcMonitor.left;
|
||||
m_uniqueId.height = m_monitorInfo.rcMonitor.bottom - m_monitorInfo.rcMonitor.top;
|
||||
CLSIDFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}", &m_uniqueId.virtualDesktopId);
|
||||
|
||||
auto guid = Helpers::StringToGuid(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}");
|
||||
Assert::IsTrue(guid.has_value());
|
||||
m_virtualDesktopGuid = *guid;
|
||||
|
||||
auto guid = Helpers::StringToGuid(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}");
|
||||
Assert::IsTrue(guid.has_value());
|
||||
m_virtualDesktopGuid = *guid;
|
||||
m_zoneColors = ZoneColors{
|
||||
.primaryColor = FancyZonesUtils::HexToRGB(L"#4287f5"),
|
||||
.borderColor = FancyZonesUtils::HexToRGB(L"#FFFFFF"),
|
||||
.highlightColor = FancyZonesUtils::HexToRGB(L"#42eff5"),
|
||||
.highlightOpacity = 50,
|
||||
};
|
||||
|
||||
m_zoneColors = ZoneColors{
|
||||
.primaryColor = FancyZonesUtils::HexToRGB(L"#4287f5"),
|
||||
.borderColor = FancyZonesUtils::HexToRGB(L"#FFFFFF"),
|
||||
.highlightColor = FancyZonesUtils::HexToRGB(L"#42eff5"),
|
||||
.highlightOpacity = 50,
|
||||
};
|
||||
}
|
||||
AppZoneHistory::instance().LoadData();
|
||||
AppliedLayouts::instance().LoadData();
|
||||
}
|
||||
|
||||
TEST_METHOD_CLEANUP(CleanUp)
|
||||
{
|
||||
std::filesystem::remove(AppliedLayouts::AppliedLayoutsFileName());
|
||||
std::filesystem::remove(AppZoneHistory::AppZoneHistoryFileName());
|
||||
}
|
||||
|
||||
TEST_METHOD (CreateWorkArea)
|
||||
{
|
||||
@@ -176,29 +180,26 @@ namespace FancyZonesUnitTests
|
||||
{
|
||||
using namespace FancyZonesDataTypes;
|
||||
|
||||
const ZoneSetLayoutType type = ZoneSetLayoutType::PriorityGrid;
|
||||
const int spacing = 10;
|
||||
const int zoneCount = 5;
|
||||
const auto customSetGuid = Helpers::CreateGuidString();
|
||||
const auto parentZoneSet = ZoneSetData{ customSetGuid, type };
|
||||
const auto parentDeviceInfo = DeviceInfoData{ parentZoneSet, true, spacing, zoneCount };
|
||||
m_fancyZonesData.SetDeviceInfo(m_parentUniqueId, parentDeviceInfo);
|
||||
const ZoneSetLayoutType type = ZoneSetLayoutType::PriorityGrid;
|
||||
const int spacing = 10;
|
||||
const int zoneCount = 5;
|
||||
const auto customSetGuid = Helpers::CreateGuidString();
|
||||
|
||||
auto parentWorkArea = MakeWorkArea(m_hInst, m_monitor, m_parentUniqueId, {}, m_zoneColors, m_overlappingAlgorithm, m_showZoneText);
|
||||
auto parentWorkArea = MakeWorkArea(m_hInst, m_monitor, m_parentUniqueId, {}, m_zoneColors, m_overlappingAlgorithm, m_showZoneText);
|
||||
|
||||
// newWorkArea = false - workArea won't be cloned from parent
|
||||
auto actualWorkArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm, m_showZoneText);
|
||||
// newWorkArea = false - workArea won't be cloned from parent
|
||||
auto actualWorkArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm, m_showZoneText);
|
||||
|
||||
Assert::IsNotNull(actualWorkArea->ZoneSet());
|
||||
Assert::IsNotNull(actualWorkArea->ZoneSet());
|
||||
|
||||
Assert::IsTrue(m_fancyZonesData.GetDeviceInfoMap().contains(m_uniqueId));
|
||||
auto currentDeviceInfo = m_fancyZonesData.GetDeviceInfoMap().at(m_uniqueId);
|
||||
// default values
|
||||
Assert::AreEqual(true, currentDeviceInfo.showSpacing);
|
||||
Assert::AreEqual(3, currentDeviceInfo.zoneCount);
|
||||
Assert::AreEqual(16, currentDeviceInfo.spacing);
|
||||
Assert::AreEqual(static_cast<int>(ZoneSetLayoutType::PriorityGrid), static_cast<int>(currentDeviceInfo.activeZoneSet.type));
|
||||
}
|
||||
Assert::IsTrue(AppliedLayouts::instance().GetAppliedLayoutMap().contains(m_uniqueId));
|
||||
auto currentDeviceInfo = AppliedLayouts::instance().GetAppliedLayoutMap().at(m_uniqueId);
|
||||
// default values
|
||||
Assert::AreEqual(true, currentDeviceInfo.showSpacing);
|
||||
Assert::AreEqual(3, currentDeviceInfo.zoneCount);
|
||||
Assert::AreEqual(16, currentDeviceInfo.spacing);
|
||||
Assert::AreEqual(static_cast<int>(ZoneSetLayoutType::PriorityGrid), static_cast<int>(currentDeviceInfo.type));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CLASS (WorkAreaUnitTests)
|
||||
@@ -233,11 +234,13 @@ namespace FancyZonesUnitTests
|
||||
};
|
||||
|
||||
AppZoneHistory::instance().LoadData();
|
||||
AppliedLayouts::instance().LoadData();
|
||||
}
|
||||
|
||||
TEST_METHOD_CLEANUP(CleanUp)
|
||||
{
|
||||
std::filesystem::remove(AppZoneHistory::AppZoneHistoryFileName());
|
||||
std::filesystem::remove(AppliedLayouts::AppliedLayoutsFileName());
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "pch.h"
|
||||
#include "FancyZonesLib\FancyZonesData.h"
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutDefaults.h>
|
||||
#include "FancyZonesLib\FancyZonesDataTypes.h"
|
||||
#include "FancyZonesLib\JsonHelpers.h"
|
||||
#include "FancyZonesLib\VirtualDesktop.h"
|
||||
|
||||
@@ -84,37 +84,32 @@ namespace FancyZonesEditor
|
||||
FancyZonesEditorIO.ParseCommandLineArguments();
|
||||
}
|
||||
|
||||
var parseResult = FancyZonesEditorIO.ParseZoneSettings();
|
||||
|
||||
// 10ms retry loop with 1 second timeout
|
||||
if (!parseResult.Result)
|
||||
{
|
||||
CancellationTokenSource ts = new CancellationTokenSource();
|
||||
Task t = Task.Run(() =>
|
||||
{
|
||||
while (!parseResult.Result && !ts.IsCancellationRequested)
|
||||
{
|
||||
Task.Delay(10).Wait();
|
||||
parseResult = FancyZonesEditorIO.ParseZoneSettings();
|
||||
}
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
bool result = t.Wait(1000, ts.Token);
|
||||
ts.Cancel();
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
ts.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// Error message if parsing failed
|
||||
var parseResult = FancyZonesEditorIO.ParseAppliedLayouts();
|
||||
if (!parseResult.Result)
|
||||
{
|
||||
Logger.LogError(ParsingErrorReportTag + ": " + parseResult.Message + "; " + ParsingErrorDataTag + ": " + parseResult.MalformedData);
|
||||
MessageBox.Show(parseResult.Message, FancyZonesEditor.Properties.Resources.Error_Parsing_Zones_Settings_Title, MessageBoxButton.OK);
|
||||
MessageBox.Show(parseResult.Message, FancyZonesEditor.Properties.Resources.Error_Parsing_Data_Title, MessageBoxButton.OK);
|
||||
}
|
||||
|
||||
parseResult = FancyZonesEditorIO.ParseCustomLayouts();
|
||||
if (!parseResult.Result)
|
||||
{
|
||||
Logger.LogError(ParsingErrorReportTag + ": " + parseResult.Message + "; " + ParsingErrorDataTag + ": " + parseResult.MalformedData);
|
||||
MessageBox.Show(parseResult.Message, FancyZonesEditor.Properties.Resources.Error_Parsing_Data_Title, MessageBoxButton.OK);
|
||||
}
|
||||
|
||||
parseResult = FancyZonesEditorIO.ParseLayoutHotkeys();
|
||||
if (!parseResult.Result)
|
||||
{
|
||||
Logger.LogError(ParsingErrorReportTag + ": " + parseResult.Message + "; " + ParsingErrorDataTag + ": " + parseResult.MalformedData);
|
||||
MessageBox.Show(parseResult.Message, FancyZonesEditor.Properties.Resources.Error_Parsing_Data_Title, MessageBoxButton.OK);
|
||||
}
|
||||
|
||||
parseResult = FancyZonesEditorIO.ParseLayoutTemplates();
|
||||
if (!parseResult.Result)
|
||||
{
|
||||
Logger.LogError(ParsingErrorReportTag + ": " + parseResult.Message + "; " + ParsingErrorDataTag + ": " + parseResult.MalformedData);
|
||||
MessageBox.Show(parseResult.Message, FancyZonesEditor.Properties.Resources.Error_Parsing_Data_Title, MessageBoxButton.OK);
|
||||
}
|
||||
|
||||
MainWindowSettingsModel settings = ((App)Current).MainWindowSettings;
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace FancyZonesEditor
|
||||
|
||||
App.FancyZonesEditorIO.SerializeLayoutTemplates();
|
||||
App.FancyZonesEditorIO.SerializeCustomLayouts();
|
||||
App.FancyZonesEditorIO.SerializeAppliedLayouts();
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ namespace FancyZonesEditor
|
||||
model.Persist();
|
||||
|
||||
App.Overlay.SetLayoutSettings(App.Overlay.Monitors[App.Overlay.CurrentDesktop], model);
|
||||
App.FancyZonesEditorIO.SerializeZoneSettings();
|
||||
App.FancyZonesEditorIO.SerializeAppliedLayouts();
|
||||
App.FancyZonesEditorIO.SerializeCustomLayouts();
|
||||
}
|
||||
|
||||
@@ -272,7 +272,7 @@ namespace FancyZonesEditor
|
||||
{
|
||||
_settings.SetAppliedModel(model);
|
||||
App.Overlay.SetLayoutSettings(App.Overlay.Monitors[App.Overlay.CurrentDesktop], model);
|
||||
App.FancyZonesEditorIO.SerializeZoneSettings();
|
||||
App.FancyZonesEditorIO.SerializeAppliedLayouts();
|
||||
App.FancyZonesEditorIO.SerializeCustomLayouts();
|
||||
}
|
||||
}
|
||||
@@ -282,7 +282,7 @@ namespace FancyZonesEditor
|
||||
Logger.LogTrace();
|
||||
CancelLayoutChanges();
|
||||
|
||||
App.FancyZonesEditorIO.SerializeZoneSettings();
|
||||
App.FancyZonesEditorIO.SerializeAppliedLayouts();
|
||||
App.FancyZonesEditorIO.SerializeCustomLayouts();
|
||||
App.FancyZonesEditorIO.SerializeLayoutHotkeys();
|
||||
App.FancyZonesEditorIO.SerializeLayoutTemplates();
|
||||
@@ -428,7 +428,7 @@ namespace FancyZonesEditor
|
||||
App.Overlay.SetLayoutSettings(App.Overlay.Monitors[App.Overlay.CurrentDesktop], model);
|
||||
}
|
||||
|
||||
App.FancyZonesEditorIO.SerializeZoneSettings();
|
||||
App.FancyZonesEditorIO.SerializeAppliedLayouts();
|
||||
App.FancyZonesEditorIO.SerializeCustomLayouts();
|
||||
App.FancyZonesEditorIO.SerializeLayoutTemplates();
|
||||
App.FancyZonesEditorIO.SerializeLayoutHotkeys();
|
||||
@@ -475,7 +475,7 @@ namespace FancyZonesEditor
|
||||
}
|
||||
}
|
||||
|
||||
App.FancyZonesEditorIO.SerializeZoneSettings();
|
||||
App.FancyZonesEditorIO.SerializeAppliedLayouts();
|
||||
App.FancyZonesEditorIO.SerializeCustomLayouts();
|
||||
model.Delete();
|
||||
}
|
||||
|
||||
@@ -375,6 +375,15 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to An error occurred while parsing applied layouts..
|
||||
/// </summary>
|
||||
public static string Error_Parsing_Applied_Layouts_Message {
|
||||
get {
|
||||
return ResourceManager.GetString("Error_Parsing_Applied_Layouts_Message", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to An error occurred while parsing custom layouts..
|
||||
/// </summary>
|
||||
@@ -384,6 +393,15 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Editor data parsing error..
|
||||
/// </summary>
|
||||
public static string Error_Parsing_Data_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("Error_Parsing_Data_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Error parsing device info data..
|
||||
/// </summary>
|
||||
@@ -411,24 +429,6 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to A layout that contained invalid data has been removed..
|
||||
/// </summary>
|
||||
public static string Error_Parsing_Zones_Settings_Message {
|
||||
get {
|
||||
return ResourceManager.GetString("Error_Parsing_Zones_Settings_Message", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Editor data parsing error..
|
||||
/// </summary>
|
||||
public static string Error_Parsing_Zones_Settings_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("Error_Parsing_Zones_Settings_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Error persisting custom layout.
|
||||
/// </summary>
|
||||
|
||||
@@ -304,11 +304,11 @@
|
||||
<value>Delete zone</value>
|
||||
<comment>A tooltip on a button that allows the user to delete a zone</comment>
|
||||
</data>
|
||||
<data name="Error_Parsing_Zones_Settings_Title" xml:space="preserve">
|
||||
<data name="Error_Parsing_Data_Title" xml:space="preserve">
|
||||
<value>Editor data parsing error.</value>
|
||||
</data>
|
||||
<data name="Error_Parsing_Zones_Settings_Message" xml:space="preserve">
|
||||
<value>A layout that contained invalid data has been removed.</value>
|
||||
<data name="Error_Parsing_Applied_Layouts_Message" xml:space="preserve">
|
||||
<value>An error occurred while parsing applied layouts.</value>
|
||||
</data>
|
||||
<data name="Apply_Layout" xml:space="preserve">
|
||||
<value>Apply layout</value>
|
||||
|
||||
@@ -10,6 +10,7 @@ using System.IO;
|
||||
using System.IO.Abstractions;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using FancyZonesEditor.Logs;
|
||||
using FancyZonesEditor.Models;
|
||||
@@ -28,7 +29,7 @@ namespace FancyZonesEditor.Utils
|
||||
private const string CustomJsonTag = "custom";
|
||||
|
||||
// Non-localizable strings: Files
|
||||
private const string ZonesSettingsFile = "\\Microsoft\\PowerToys\\FancyZones\\zones-settings.json";
|
||||
private const string AppliedLayoutsFile = "\\Microsoft\\PowerToys\\FancyZones\\applied-layouts.json";
|
||||
private const string LayoutHotkeysFile = "\\Microsoft\\PowerToys\\FancyZones\\layout-hotkeys.json";
|
||||
private const string LayoutTemplatesFile = "\\Microsoft\\PowerToys\\FancyZones\\layout-templates.json";
|
||||
private const string CustomLayoutsFile = "\\Microsoft\\PowerToys\\FancyZones\\custom-layouts.json";
|
||||
@@ -48,9 +49,9 @@ namespace FancyZonesEditor.Utils
|
||||
WriteIndented = true,
|
||||
};
|
||||
|
||||
private List<DeviceWrapper> _unusedDevices = new List<DeviceWrapper>();
|
||||
private List<AppliedLayoutWrapper> _unusedLayouts = new List<AppliedLayoutWrapper>();
|
||||
|
||||
public string FancyZonesSettingsFile { get; private set; }
|
||||
public string FancyZonesAppliedLayoutsFile { get; private set; }
|
||||
|
||||
public string FancyZonesLayoutHotkeysFile { get; private set; }
|
||||
|
||||
@@ -110,27 +111,33 @@ namespace FancyZonesEditor.Utils
|
||||
}
|
||||
}
|
||||
|
||||
// zones-settings: devices
|
||||
private struct DeviceWrapper
|
||||
// applied-layouts.json
|
||||
private struct AppliedLayoutWrapper
|
||||
{
|
||||
public struct ActiveZoneSetWrapper
|
||||
public struct LayoutWrapper
|
||||
{
|
||||
public string Uuid { get; set; }
|
||||
|
||||
public string Type { get; set; }
|
||||
|
||||
public bool ShowSpacing { get; set; }
|
||||
|
||||
public int Spacing { get; set; }
|
||||
|
||||
public int ZoneCount { get; set; }
|
||||
|
||||
public int SensitivityRadius { get; set; }
|
||||
}
|
||||
|
||||
public string DeviceId { get; set; }
|
||||
|
||||
public ActiveZoneSetWrapper ActiveZoneset { get; set; }
|
||||
public LayoutWrapper AppliedLayout { get; set; }
|
||||
}
|
||||
|
||||
public bool EditorShowSpacing { get; set; }
|
||||
|
||||
public int EditorSpacing { get; set; }
|
||||
|
||||
public int EditorZoneCount { get; set; }
|
||||
|
||||
public int EditorSensitivityRadius { get; set; }
|
||||
// applied-layouts.json
|
||||
private struct AppliedLayoutsListWrapper
|
||||
{
|
||||
public List<AppliedLayoutWrapper> AppliedLayouts { get; set; }
|
||||
}
|
||||
|
||||
// custom-layouts.json
|
||||
@@ -228,12 +235,6 @@ namespace FancyZonesEditor.Utils
|
||||
public List<LayoutHotkeyWrapper> LayoutHotkeys { get; set; }
|
||||
}
|
||||
|
||||
// zones-settings
|
||||
private struct ZoneSettingsWrapper
|
||||
{
|
||||
public List<DeviceWrapper> Devices { get; set; }
|
||||
}
|
||||
|
||||
private struct EditorParams
|
||||
{
|
||||
public int ProcessId { get; set; }
|
||||
@@ -262,7 +263,7 @@ namespace FancyZonesEditor.Utils
|
||||
public FancyZonesEditorIO()
|
||||
{
|
||||
var localAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||
FancyZonesSettingsFile = localAppDataDir + ZonesSettingsFile;
|
||||
FancyZonesAppliedLayoutsFile = localAppDataDir + AppliedLayoutsFile;
|
||||
FancyZonesLayoutHotkeysFile = localAppDataDir + LayoutHotkeysFile;
|
||||
FancyZonesLayoutTemplatesFile = localAppDataDir + LayoutTemplatesFile;
|
||||
FancyZonesCustomLayoutsFile = localAppDataDir + CustomLayoutsFile;
|
||||
@@ -513,61 +514,43 @@ namespace FancyZonesEditor.Utils
|
||||
}
|
||||
}
|
||||
|
||||
public ParsingResult ParseZoneSettings()
|
||||
public ParsingResult ParseAppliedLayouts()
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
_unusedDevices.Clear();
|
||||
_unusedLayouts.Clear();
|
||||
|
||||
if (_fileSystem.File.Exists(FancyZonesSettingsFile))
|
||||
if (_fileSystem.File.Exists(FancyZonesAppliedLayoutsFile))
|
||||
{
|
||||
ZoneSettingsWrapper zoneSettings;
|
||||
AppliedLayoutsListWrapper appliedLayouts;
|
||||
string settingsString = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
settingsString = ReadFile(FancyZonesSettingsFile);
|
||||
zoneSettings = JsonSerializer.Deserialize<ZoneSettingsWrapper>(settingsString, _options);
|
||||
settingsString = ReadFile(FancyZonesAppliedLayoutsFile);
|
||||
appliedLayouts = JsonSerializer.Deserialize<AppliedLayoutsListWrapper>(settingsString, _options);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Zone settings parsing error", ex);
|
||||
Logger.LogError("Applied layouts parsing error", ex);
|
||||
return new ParsingResult(false, ex.Message, settingsString);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
bool devicesParsingResult = SetDevices(zoneSettings.Devices);
|
||||
if (!devicesParsingResult)
|
||||
bool parsingResult = SetAppliedLayouts(appliedLayouts.AppliedLayouts);
|
||||
if (!parsingResult)
|
||||
{
|
||||
return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Zones_Settings_Message, settingsString);
|
||||
return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Applied_Layouts_Message, settingsString);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Zone settings parsing error", ex);
|
||||
Logger.LogError("Applied layouts parsing error", ex);
|
||||
return new ParsingResult(false, ex.Message, settingsString);
|
||||
}
|
||||
}
|
||||
|
||||
var parsingCustomLayoutsResult = ParseCustomLayouts();
|
||||
if (!parsingCustomLayoutsResult.Result)
|
||||
{
|
||||
return parsingCustomLayoutsResult;
|
||||
}
|
||||
|
||||
var parsingHotkeysResult = ParseLayoutHotkeys();
|
||||
if (!parsingHotkeysResult.Result)
|
||||
{
|
||||
return parsingHotkeysResult;
|
||||
}
|
||||
|
||||
var parsingTemplatesResult = ParseLayoutTemplates();
|
||||
if (!parsingTemplatesResult.Result)
|
||||
{
|
||||
return parsingTemplatesResult;
|
||||
}
|
||||
|
||||
return new ParsingResult(true);
|
||||
}
|
||||
|
||||
@@ -690,14 +673,14 @@ namespace FancyZonesEditor.Utils
|
||||
return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Custom_Layouts_Message);
|
||||
}
|
||||
|
||||
public void SerializeZoneSettings()
|
||||
public void SerializeAppliedLayouts()
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
ZoneSettingsWrapper zoneSettings = new ZoneSettingsWrapper { };
|
||||
zoneSettings.Devices = new List<DeviceWrapper>();
|
||||
AppliedLayoutsListWrapper layouts = new AppliedLayoutsListWrapper { };
|
||||
layouts.AppliedLayouts = new List<AppliedLayoutWrapper>();
|
||||
|
||||
// Serialize used devices
|
||||
// Serialize used layouts
|
||||
foreach (var monitor in App.Overlay.Monitors)
|
||||
{
|
||||
LayoutSettings zoneset = monitor.Settings;
|
||||
@@ -706,35 +689,35 @@ namespace FancyZonesEditor.Utils
|
||||
continue;
|
||||
}
|
||||
|
||||
zoneSettings.Devices.Add(new DeviceWrapper
|
||||
layouts.AppliedLayouts.Add(new AppliedLayoutWrapper
|
||||
{
|
||||
DeviceId = monitor.Device.Id,
|
||||
ActiveZoneset = new DeviceWrapper.ActiveZoneSetWrapper
|
||||
AppliedLayout = new AppliedLayoutWrapper.LayoutWrapper
|
||||
{
|
||||
Uuid = zoneset.ZonesetUuid,
|
||||
Type = LayoutTypeToJsonTag(zoneset.Type),
|
||||
ShowSpacing = zoneset.ShowSpacing,
|
||||
Spacing = zoneset.Spacing,
|
||||
ZoneCount = zoneset.ZoneCount,
|
||||
SensitivityRadius = zoneset.SensitivityRadius,
|
||||
},
|
||||
EditorShowSpacing = zoneset.ShowSpacing,
|
||||
EditorSpacing = zoneset.Spacing,
|
||||
EditorZoneCount = zoneset.ZoneCount,
|
||||
EditorSensitivityRadius = zoneset.SensitivityRadius,
|
||||
});
|
||||
}
|
||||
|
||||
// Serialize unused devices
|
||||
foreach (var device in _unusedDevices)
|
||||
// Serialize unused layouts
|
||||
foreach (var device in _unusedLayouts)
|
||||
{
|
||||
zoneSettings.Devices.Add(device);
|
||||
layouts.AppliedLayouts.Add(device);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string jsonString = JsonSerializer.Serialize(zoneSettings, _options);
|
||||
_fileSystem.File.WriteAllText(FancyZonesSettingsFile, jsonString);
|
||||
string jsonString = JsonSerializer.Serialize(layouts, _options);
|
||||
_fileSystem.File.WriteAllText(FancyZonesAppliedLayoutsFile, jsonString);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Serialize zone settings error", ex);
|
||||
Logger.LogError("Serialize applied layouts error", ex);
|
||||
App.ShowExceptionMessageBox(Properties.Resources.Error_Applying_Layout, ex);
|
||||
}
|
||||
}
|
||||
@@ -918,29 +901,45 @@ namespace FancyZonesEditor.Utils
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
Stream inputStream = _fileSystem.File.Open(fileName, FileMode.Open);
|
||||
using (StreamReader reader = new StreamReader(inputStream))
|
||||
var attempts = 0;
|
||||
while (attempts < 10)
|
||||
{
|
||||
string data = reader.ReadToEnd();
|
||||
inputStream.Close();
|
||||
return data;
|
||||
try
|
||||
{
|
||||
Stream inputStream = _fileSystem.File.Open(fileName, FileMode.Open);
|
||||
using (StreamReader reader = new StreamReader(inputStream))
|
||||
{
|
||||
string data = reader.ReadToEnd();
|
||||
inputStream.Close();
|
||||
return data;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Logger.LogError("File reading error, retry");
|
||||
Task.Delay(10).Wait();
|
||||
}
|
||||
|
||||
attempts++;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private bool SetDevices(List<DeviceWrapper> devices)
|
||||
private bool SetAppliedLayouts(List<AppliedLayoutWrapper> layouts)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
if (devices == null)
|
||||
if (layouts == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
var monitors = App.Overlay.Monitors;
|
||||
foreach (var device in devices)
|
||||
foreach (var layout in layouts)
|
||||
{
|
||||
if (device.DeviceId == null || device.DeviceId.Length == 0 || device.ActiveZoneset.Uuid == null || device.ActiveZoneset.Uuid.Length == 0)
|
||||
if (layout.DeviceId == null || layout.DeviceId.Length == 0 || layout.AppliedLayout.Uuid == null || layout.AppliedLayout.Uuid.Length == 0)
|
||||
{
|
||||
result = false;
|
||||
continue;
|
||||
@@ -950,21 +949,21 @@ namespace FancyZonesEditor.Utils
|
||||
foreach (Monitor monitor in monitors)
|
||||
{
|
||||
string deviceIdSaved = monitor.Device.Id.Substring(0, monitor.Device.Id.LastIndexOf("_"));
|
||||
string deviceIdReadFromSettings = device.DeviceId.Substring(0, device.DeviceId.LastIndexOf("_"));
|
||||
string deviceIdReadFromSettings = layout.DeviceId.Substring(0, layout.DeviceId.LastIndexOf("_"));
|
||||
|
||||
string virtualDesktopIdSaved = monitor.Device.Id.Substring(monitor.Device.Id.LastIndexOf("_") + 1);
|
||||
string virtualDesktopIdReadFromSettings = device.DeviceId.Substring(device.DeviceId.LastIndexOf("_") + 1);
|
||||
string virtualDesktopIdReadFromSettings = layout.DeviceId.Substring(layout.DeviceId.LastIndexOf("_") + 1);
|
||||
|
||||
if (deviceIdSaved == deviceIdReadFromSettings && (virtualDesktopIdSaved == virtualDesktopIdReadFromSettings || virtualDesktopIdReadFromSettings == DefaultVirtualDesktopGuid))
|
||||
{
|
||||
var settings = new LayoutSettings
|
||||
{
|
||||
ZonesetUuid = device.ActiveZoneset.Uuid,
|
||||
ShowSpacing = device.EditorShowSpacing,
|
||||
Spacing = device.EditorSpacing,
|
||||
Type = JsonTagToLayoutType(device.ActiveZoneset.Type),
|
||||
ZoneCount = device.EditorZoneCount,
|
||||
SensitivityRadius = device.EditorSensitivityRadius,
|
||||
ZonesetUuid = layout.AppliedLayout.Uuid,
|
||||
ShowSpacing = layout.AppliedLayout.ShowSpacing,
|
||||
Spacing = layout.AppliedLayout.Spacing,
|
||||
Type = JsonTagToLayoutType(layout.AppliedLayout.Type),
|
||||
ZoneCount = layout.AppliedLayout.ZoneCount,
|
||||
SensitivityRadius = layout.AppliedLayout.SensitivityRadius,
|
||||
};
|
||||
|
||||
monitor.Settings = settings;
|
||||
@@ -975,7 +974,7 @@ namespace FancyZonesEditor.Utils
|
||||
|
||||
if (unused)
|
||||
{
|
||||
_unusedDevices.Add(device);
|
||||
_unusedLayouts.Add(layout);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user