[FancyZones]Monitor identification (#19077)

* moved monitors identifying

* changed device id

* get wmi info

* convert old data

* save/load applied layouts

* changed monitor identification

* id comparison

* save/load app zone history

* moved com and security init

* update ids in editor

* lib fix

* updated tests

* changed comparison

* tests

* updated id comparison

* updated log

* moved definition

* spell check

* resolve conflicts

* refactoring

* update serial numbers if possible
This commit is contained in:
Seraphima Zykova
2022-07-01 17:29:02 +02:00
committed by GitHub
parent 3cb0638c7e
commit 35bb4280d0
30 changed files with 1084 additions and 408 deletions

View File

@@ -667,6 +667,8 @@ globals
GNumber
google
GPTR
GSM
gsuberland
gtm
gui
guiddef
@@ -2103,6 +2105,7 @@ Udp
uefi
UHash
UIA
uid
Uid
uint
uintptr

View File

@@ -110,7 +110,7 @@
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>shcore.lib;shlwapi.lib;DbgHelp.lib;uxtheme.lib;dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>shcore.lib;shlwapi.lib;DbgHelp.lib;uxtheme.lib;dwmapi.lib;wbemuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
@@ -128,7 +128,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>shcore.lib;shlwapi.lib;DbgHelp.lib;uxtheme.lib;dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>shcore.lib;shlwapi.lib;DbgHelp.lib;uxtheme.lib;dwmapi.lib;wbemuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>

View File

@@ -2,6 +2,7 @@
#include "EditorParameters.h"
#include <FancyZonesLib/FancyZonesWindowProperties.h>
#include <FancyZonesLib/MonitorUtils.h>
#include <FancyZonesLib/on_thread_executor.h>
#include <FancyZonesLib/Settings.h>
#include <FancyZonesLib/VirtualDesktop.h>
@@ -22,6 +23,8 @@ namespace JsonUtils
struct MonitorInfo
{
std::wstring monitorName;
std::wstring monitorInstanceId;
std::wstring monitorSerialNumber;
std::wstring virtualDesktop;
int dpi;
int top;
@@ -37,6 +40,8 @@ namespace JsonUtils
json::JsonObject result{};
result.SetNamedValue(NonLocalizable::EditorParametersIds::MonitorNameId, json::value(monitor.monitorName));
result.SetNamedValue(NonLocalizable::EditorParametersIds::MonitorInstanceId, json::value(monitor.monitorInstanceId));
result.SetNamedValue(NonLocalizable::EditorParametersIds::MonitorSerialNumberId, json::value(monitor.monitorSerialNumber));
result.SetNamedValue(NonLocalizable::EditorParametersIds::VirtualDesktopId, json::value(monitor.virtualDesktop));
result.SetNamedValue(NonLocalizable::EditorParametersIds::Dpi, json::value(monitor.dpi));
result.SetNamedValue(NonLocalizable::EditorParametersIds::TopCoordinate, json::value(monitor.top));
@@ -82,7 +87,7 @@ bool EditorParameters::Save() noexcept
const auto virtualDesktopIdStr = FancyZonesUtils::GuidToString(VirtualDesktop::instance().GetCurrentVirtualDesktopId());
if (!virtualDesktopIdStr)
{
Logger::error(L"Save editor params: no virtual desktop id");
Logger::error(L"Save editor params: invalid virtual desktop id");
return false;
}
@@ -124,13 +129,7 @@ bool EditorParameters::Save() noexcept
}
else
{
// device id map for correct device ids
std::unordered_map<std::wstring, DWORD> displayDeviceIdxMap;
std::vector<std::pair<HMONITOR, MONITORINFOEX>> allMonitors;
dpiUnawareThread.submit(OnThreadExecutor::task_t{ [&]() {
allMonitors = FancyZonesUtils::GetAllMonitorInfo<&MONITORINFOEX::rcWork>();
} }).wait();
auto monitors = MonitorUtils::IdentifyMonitors();
HMONITOR targetMonitor{};
if (FancyZonesSettings::settings().use_cursorpos_editor_startupscreen)
@@ -150,21 +149,29 @@ bool EditorParameters::Save() noexcept
return false;
}
for (auto& monitorData : allMonitors)
for (auto& monitorData : monitors)
{
HMONITOR monitor = monitorData.first;
auto monitorInfo = monitorData.second;
HMONITOR monitor = monitorData.monitor;
MONITORINFOEX monitorInfo{};
dpiUnawareThread.submit(OnThreadExecutor::task_t{ [&] {
monitorInfo.cbSize = sizeof(monitorInfo);
if (!GetMonitorInfo(monitor, &monitorInfo))
{
return;
}
} }).wait();
JsonUtils::MonitorInfo monitorJson;
std::wstring deviceId = FancyZonesUtils::GetDisplayDeviceId(monitorInfo.szDevice, displayDeviceIdxMap);
if (monitor == targetMonitor)
{
monitorJson.isSelected = true; /* Is monitor selected for the main editor window opening */
}
monitorJson.monitorName = FancyZonesUtils::TrimDeviceId(deviceId);
monitorJson.monitorName = monitorData.deviceId.id;
monitorJson.monitorInstanceId = monitorData.deviceId.instanceId;
monitorJson.monitorSerialNumber = monitorData.serialNumber;
monitorJson.virtualDesktop = virtualDesktopIdStr.value();
UINT dpi = 0;

View File

@@ -6,6 +6,8 @@ namespace NonLocalizable
{
const static wchar_t* Dpi = L"dpi";
const static wchar_t* MonitorNameId = L"monitor";
const static wchar_t* MonitorInstanceId = L"monitor-instance-id";
const static wchar_t* MonitorSerialNumberId = L"monitor-serial-number";
const static wchar_t* VirtualDesktopId = L"virtual-desktop";
const static wchar_t* TopCoordinate = L"top-coordinate";
const static wchar_t* LeftCoordinate = L"left-coordinate";

View File

@@ -146,7 +146,7 @@ public:
LRESULT WndProc(HWND, UINT, WPARAM, LPARAM) noexcept;
void OnDisplayChange(DisplayChangeType changeType) noexcept;
void AddWorkArea(HMONITOR monitor, const std::wstring& deviceId) noexcept;
void AddWorkArea(HMONITOR monitor, const FancyZonesDataTypes::WorkAreaId& id) noexcept;
protected:
static LRESULT CALLBACK s_WndProc(HWND, UINT, WPARAM, LPARAM) noexcept;
@@ -250,6 +250,22 @@ FancyZones::Run() noexcept
}
}
// Initialize COM. Needed for WMI monitor identifying
HRESULT comInitHres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(comInitHres))
{
Logger::error(L"Failed to initialize COM library. {}", get_last_error_or_default(comInitHres));
return;
}
// Initialize security. Needed for WMI monitor identifying
HRESULT comSecurityInitHres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
if (FAILED(comSecurityInitHres))
{
Logger::error(L"Failed to initialize security. {}", get_last_error_or_default(comSecurityInitHres));
return;
}
m_dpiUnawareThread.submit(OnThreadExecutor::task_t{ [] {
SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE);
SetThreadDpiHostingBehavior(DPI_HOSTING_BEHAVIOR_MIXED);
@@ -278,6 +294,8 @@ FancyZones::Destroy() noexcept
DestroyWindow(m_window);
m_window = nullptr;
}
CoUninitialize();
}
// IFancyZonesCallback
@@ -674,6 +692,11 @@ void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept
if (changeType == DisplayChangeType::Initialization)
{
RegisterVirtualDesktopUpdates();
// id format of applied-layouts and app-zone-history was changed in 0.60
auto monitors = MonitorUtils::IdentifyMonitors();
AppliedLayouts::instance().AdjustWorkAreaIds(monitors);
AppZoneHistory::instance().AdjustWorkAreaIds(monitors);
}
}
@@ -689,7 +712,7 @@ void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept
}
}
void FancyZones::AddWorkArea(HMONITOR monitor, const std::wstring& deviceId) noexcept
void FancyZones::AddWorkArea(HMONITOR monitor, const FancyZonesDataTypes::WorkAreaId& id) noexcept
{
if (m_workAreaHandler.IsNewWorkArea(VirtualDesktop::instance().GetCurrentVirtualDesktopId(), monitor))
{
@@ -699,26 +722,14 @@ void FancyZones::AddWorkArea(HMONITOR monitor, const std::wstring& deviceId) noe
Logger::debug(L"Add new work area on virtual desktop {}", virtualDesktopIdStr.get());
}
FancyZonesDataTypes::DeviceIdData uniqueId;
uniqueId.virtualDesktopId = VirtualDesktop::instance().GetCurrentVirtualDesktopId();
if (monitor)
{
uniqueId.deviceName = FancyZonesUtils::TrimDeviceId(deviceId);
}
else
{
uniqueId.deviceName = ZonedWindowProperties::MultiMonitorDeviceID;
}
FancyZonesDataTypes::DeviceIdData parentId{};
FancyZonesDataTypes::WorkAreaId parentId{};
auto parentArea = m_workAreaHandler.GetWorkArea(VirtualDesktop::instance().GetPreviousVirtualDesktopId(), monitor);
if (parentArea)
{
parentId = parentArea->UniqueId();
}
auto workArea = MakeWorkArea(m_hinstance, monitor, uniqueId, parentId);
auto workArea = MakeWorkArea(m_hinstance, monitor, id, parentId);
if (workArea)
{
m_workAreaHandler.AddWorkArea(VirtualDesktop::instance().GetCurrentVirtualDesktopId(), monitor, workArea);
@@ -745,34 +756,23 @@ void FancyZones::UpdateWorkAreas() noexcept
{
if (FancyZonesSettings::settings().spanZonesAcrossMonitors)
{
AddWorkArea(nullptr, {});
FancyZonesDataTypes::WorkAreaId workAreaId;
workAreaId.virtualDesktopId = VirtualDesktop::instance().GetCurrentVirtualDesktopId();
workAreaId.monitorId = { .deviceId = ZonedWindowProperties::MultiMonitorDeviceID };
AddWorkArea(nullptr, workAreaId);
}
else
{
// Mapping between display device name and device index (operating system identifies each display device with an index value).
std::unordered_map<std::wstring, DWORD> displayDeviceIdxMap;
struct capture
auto monitors = MonitorUtils::IdentifyMonitors();
for (const auto& monitor : monitors)
{
FancyZones* fancyZones;
std::unordered_map<std::wstring, DWORD>* displayDeviceIdx;
};
FancyZonesDataTypes::WorkAreaId workAreaId;
workAreaId.virtualDesktopId = VirtualDesktop::instance().GetCurrentVirtualDesktopId();
workAreaId.monitorId = monitor;
auto callback = [](HMONITOR monitor, HDC, RECT*, LPARAM data) -> BOOL {
capture* params = reinterpret_cast<capture*>(data);
MONITORINFOEX mi{ { .cbSize = sizeof(mi) } };
if (GetMonitorInfoW(monitor, &mi))
{
auto& displayDeviceIdxMap = *(params->displayDeviceIdx);
FancyZones* fancyZones = params->fancyZones;
std::wstring deviceId = FancyZonesUtils::GetDisplayDeviceId(mi.szDevice, displayDeviceIdxMap);
fancyZones->AddWorkArea(monitor, deviceId);
}
return TRUE;
};
capture capture{ this, &displayDeviceIdxMap };
EnumDisplayMonitors(nullptr, nullptr, callback, reinterpret_cast<LPARAM>(&capture));
AddWorkArea(monitor.monitor, workAreaId);
}
}
}

View File

@@ -8,6 +8,7 @@
#include <FancyZonesLib/GuidUtils.h>
#include <FancyZonesLib/FancyZonesWindowProperties.h>
#include <FancyZonesLib/JsonHelpers.h>
#include <FancyZonesLib/MonitorUtils.h>
#include <FancyZonesLib/VirtualDesktop.h>
#include <FancyZonesLib/util.h>
@@ -16,7 +17,7 @@ namespace JsonUtils
struct AppZoneHistoryJSON
{
private:
static std::optional<FancyZonesDataTypes::DeviceIdData> DeviceIdFromJson(const json::JsonObject& json)
static std::optional<FancyZonesDataTypes::WorkAreaId> DeviceIdFromJson(const json::JsonObject& json)
{
try
{
@@ -24,6 +25,8 @@ namespace JsonUtils
{
json::JsonObject device = json.GetNamedObject(NonLocalizable::AppZoneHistoryIds::DeviceID);
std::wstring monitor = device.GetNamedString(NonLocalizable::AppZoneHistoryIds::MonitorID).c_str();
std::wstring monitorInstance = device.GetNamedString(NonLocalizable::AppZoneHistoryIds::MonitorInstanceID, L"").c_str();
std::wstring monitorSerialNumber = device.GetNamedString(NonLocalizable::AppZoneHistoryIds::MonitorSerialNumberID, L"").c_str();
std::wstring virtualDesktop = device.GetNamedString(NonLocalizable::AppZoneHistoryIds::VirtualDesktopID).c_str();
auto virtualDesktopGuid = FancyZonesUtils::GuidFromString(virtualDesktop);
@@ -32,8 +35,25 @@ namespace JsonUtils
return std::nullopt;
}
return FancyZonesDataTypes::DeviceIdData{
.deviceName = monitor,
FancyZonesDataTypes::DeviceId deviceId{};
if (monitorInstance.empty())
{
// old data
deviceId = MonitorUtils::Display::ConvertObsoleteDeviceId(monitor);
}
else
{
deviceId.id = monitor;
deviceId.instanceId = monitorInstance;
}
FancyZonesDataTypes::MonitorId monitorId{
.deviceId = deviceId,
.serialNumber = monitorSerialNumber
};
return FancyZonesDataTypes::WorkAreaId{
.monitorId = monitorId,
.virtualDesktopId = virtualDesktopGuid.value(),
};
}
@@ -46,8 +66,8 @@ namespace JsonUtils
return std::nullopt;
}
return FancyZonesDataTypes::DeviceIdData{
.deviceName = bcDeviceId->deviceName,
return FancyZonesDataTypes::WorkAreaId{
.monitorId = { .deviceId = MonitorUtils::Display::ConvertObsoleteDeviceId(bcDeviceId->deviceName) },
.virtualDesktopId = bcDeviceId->virtualDesktopId,
};
}
@@ -80,7 +100,7 @@ namespace JsonUtils
return std::nullopt;
}
data.deviceId = deviceIdOpt.value();
data.workAreaId = deviceIdOpt.value();
data.zoneSetUuid = json.GetNamedString(NonLocalizable::AppZoneHistoryIds::LayoutIdID);
if (!FancyZonesUtils::IsValidGuid(data.zoneSetUuid))
@@ -152,8 +172,11 @@ namespace JsonUtils
}
json::JsonObject device{};
device.SetNamedValue(NonLocalizable::AppZoneHistoryIds::MonitorID, json::value(data.deviceId.deviceName));
auto virtualDesktopStr = FancyZonesUtils::GuidToString(data.deviceId.virtualDesktopId);
device.SetNamedValue(NonLocalizable::AppZoneHistoryIds::MonitorID, json::value(data.workAreaId.monitorId.deviceId.id));
device.SetNamedValue(NonLocalizable::AppZoneHistoryIds::MonitorInstanceID, json::value(data.workAreaId.monitorId.deviceId.instanceId));
device.SetNamedValue(NonLocalizable::AppZoneHistoryIds::MonitorSerialNumberID, json::value(data.workAreaId.monitorId.serialNumber));
auto virtualDesktopStr = FancyZonesUtils::GuidToString(data.workAreaId.virtualDesktopId);
if (virtualDesktopStr)
{
device.SetNamedValue(NonLocalizable::AppZoneHistoryIds::VirtualDesktopID, json::value(virtualDesktopStr.value()));
@@ -255,9 +278,9 @@ void AppZoneHistory::SaveData()
auto updatedVector = dataVector;
for (auto& data : updatedVector)
{
if (!VirtualDesktop::instance().IsVirtualDesktopIdSavedInRegistry(data.deviceId.virtualDesktopId))
if (!VirtualDesktop::instance().IsVirtualDesktopIdSavedInRegistry(data.workAreaId.virtualDesktopId))
{
data.deviceId.virtualDesktopId = GUID_NULL;
data.workAreaId.virtualDesktopId = GUID_NULL;
dirtyFlag = true;
}
}
@@ -275,9 +298,40 @@ void AppZoneHistory::SaveData()
}
}
bool AppZoneHistory::SetAppLastZones(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring& zoneSetId, const ZoneIndexSet& zoneIndexSet)
void AppZoneHistory::AdjustWorkAreaIds(const std::vector<FancyZonesDataTypes::MonitorId>& ids)
{
if (IsAnotherWindowOfApplicationInstanceZoned(window, deviceId))
bool dirtyFlag = false;
for (auto iter = m_history.begin(); iter != m_history.end(); ++iter)
{
auto& [app, data] = *iter;
for (auto& dataIter = data.begin(); dataIter != data.end(); ++dataIter)
{
auto& dataMonitorId = dataIter->workAreaId.monitorId;
if (dataMonitorId.serialNumber.empty() && !dataMonitorId.deviceId.isDefault())
{
for (const auto& monitorId : ids)
{
if (dataMonitorId.deviceId.id == monitorId.deviceId.id && dataMonitorId.deviceId.instanceId == monitorId.deviceId.instanceId)
{
dataMonitorId.serialNumber = monitorId.serialNumber;
dirtyFlag = true;
break;
}
}
}
}
}
if (dirtyFlag)
{
SaveData();
}
}
bool AppZoneHistory::SetAppLastZones(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId, const std::wstring& zoneSetId, const ZoneIndexSet& zoneIndexSet)
{
if (IsAnotherWindowOfApplicationInstanceZoned(window, workAreaId))
{
return false;
}
@@ -288,7 +342,7 @@ bool AppZoneHistory::SetAppLastZones(HWND window, const FancyZonesDataTypes::Dev
return false;
}
Logger::info(L"Add app zone history, device: {}, layout: {}", deviceId.toString(), zoneSetId);
Logger::info(L"Add app zone history, device: {}, layout: {}", workAreaId.toString(), zoneSetId);
DWORD processId = 0;
GetWindowThreadProcessId(window, &processId);
@@ -299,7 +353,7 @@ bool AppZoneHistory::SetAppLastZones(HWND window, const FancyZonesDataTypes::Dev
auto& perDesktopData = history->second;
for (auto& data : perDesktopData)
{
if (data.deviceId == deviceId)
if (data.workAreaId == workAreaId)
{
// application already has history on this work area, update it with new window position
data.processIdToHandleMap[processId] = window;
@@ -315,7 +369,7 @@ bool AppZoneHistory::SetAppLastZones(HWND window, const FancyZonesDataTypes::Dev
processIdToHandleMap[processId] = window;
FancyZonesDataTypes::AppZoneHistoryData data{ .processIdToHandleMap = processIdToHandleMap,
.zoneSetUuid = zoneSetId,
.deviceId = deviceId,
.workAreaId = workAreaId,
.zoneIndexSet = zoneIndexSet };
if (m_history.contains(processPath))
@@ -333,9 +387,9 @@ bool AppZoneHistory::SetAppLastZones(HWND window, const FancyZonesDataTypes::Dev
return true;
}
bool AppZoneHistory::RemoveAppLastZone(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring_view& zoneSetId)
bool AppZoneHistory::RemoveAppLastZone(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId, const std::wstring_view& zoneSetId)
{
Logger::info(L"Add app zone history, device: {}, layout: {}", deviceId.toString(), zoneSetId);
Logger::info(L"Add app zone history, device: {}, layout: {}", workAreaId.toString(), zoneSetId);
auto processPath = get_process_path_waiting_uwp(window);
if (!processPath.empty())
@@ -346,9 +400,9 @@ 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 == deviceId && data->zoneSetUuid == zoneSetId)
if (data->workAreaId == workAreaId && data->zoneSetUuid == zoneSetId)
{
if (!IsAnotherWindowOfApplicationInstanceZoned(window, deviceId))
if (!IsAnotherWindowOfApplicationInstanceZoned(window, workAreaId))
{
DWORD processId = 0;
GetWindowThreadProcessId(window, &processId);
@@ -396,7 +450,7 @@ const AppZoneHistory::TAppZoneHistoryMap& AppZoneHistory::GetFullAppZoneHistory(
return m_history;
}
std::optional<FancyZonesDataTypes::AppZoneHistoryData> AppZoneHistory::GetZoneHistory(const std::wstring& appPath, const FancyZonesDataTypes::DeviceIdData& deviceId) const noexcept
std::optional<FancyZonesDataTypes::AppZoneHistoryData> AppZoneHistory::GetZoneHistory(const std::wstring& appPath, const FancyZonesDataTypes::WorkAreaId& workAreaId) const noexcept
{
auto app = appPath;
auto pos = appPath.find_last_of('\\');
@@ -405,10 +459,10 @@ std::optional<FancyZonesDataTypes::AppZoneHistoryData> AppZoneHistory::GetZoneHi
app = appPath.substr(pos + 1);
}
auto srcVirtualDesktopIDStr = FancyZonesUtils::GuidToString(deviceId.virtualDesktopId);
auto srcVirtualDesktopIDStr = FancyZonesUtils::GuidToString(workAreaId.virtualDesktopId);
if (srcVirtualDesktopIDStr)
{
Logger::debug(L"Get {} zone history on monitor: {}, virtual desktop: {}", app, deviceId.deviceName, srcVirtualDesktopIDStr.value());
Logger::debug(L"Get {} zone history on monitor: {}, virtual desktop: {}", app, workAreaId.toString(), srcVirtualDesktopIDStr.value());
}
auto iter = m_history.find(appPath);
@@ -421,15 +475,15 @@ std::optional<FancyZonesDataTypes::AppZoneHistoryData> AppZoneHistory::GetZoneHi
auto historyVector = iter->second;
for (const auto& history : historyVector)
{
if (history.deviceId.deviceName == deviceId.deviceName)
if (history.workAreaId == workAreaId)
{
auto vdStr = FancyZonesUtils::GuidToString(history.deviceId.virtualDesktopId);
auto vdStr = FancyZonesUtils::GuidToString(history.workAreaId.virtualDesktopId);
if (vdStr)
{
Logger::debug(L"App zone history found on the device {} with virtual desktop {}", history.deviceId.deviceName, vdStr.value());
Logger::debug(L"App zone history found on the device {} with virtual desktop {}", history.workAreaId.toString(), vdStr.value());
}
if (history.deviceId.virtualDesktopId == deviceId.virtualDesktopId || history.deviceId.virtualDesktopId == GUID_NULL)
if (history.workAreaId.virtualDesktopId == workAreaId.virtualDesktopId || history.workAreaId.virtualDesktopId == GUID_NULL)
{
return history;
}
@@ -439,7 +493,7 @@ std::optional<FancyZonesDataTypes::AppZoneHistoryData> AppZoneHistory::GetZoneHi
return std::nullopt;
}
bool AppZoneHistory::IsAnotherWindowOfApplicationInstanceZoned(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId) const noexcept
bool AppZoneHistory::IsAnotherWindowOfApplicationInstanceZoned(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId) const noexcept
{
auto processPath = get_process_path_waiting_uwp(window);
if (!processPath.empty())
@@ -450,7 +504,7 @@ bool AppZoneHistory::IsAnotherWindowOfApplicationInstanceZoned(HWND window, cons
auto& perDesktopData = history->second;
for (auto& data : perDesktopData)
{
if (data.deviceId == deviceId)
if (data.workAreaId == workAreaId)
{
DWORD processId = 0;
GetWindowThreadProcessId(window, &processId);
@@ -473,7 +527,7 @@ bool AppZoneHistory::IsAnotherWindowOfApplicationInstanceZoned(HWND window, cons
return false;
}
void AppZoneHistory::UpdateProcessIdToHandleMap(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId)
void AppZoneHistory::UpdateProcessIdToHandleMap(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId)
{
auto processPath = get_process_path_waiting_uwp(window);
if (!processPath.empty())
@@ -484,7 +538,7 @@ void AppZoneHistory::UpdateProcessIdToHandleMap(HWND window, const FancyZonesDat
auto& perDesktopData = history->second;
for (auto& data : perDesktopData)
{
if (data.deviceId == deviceId)
if (data.workAreaId == workAreaId)
{
DWORD processId = 0;
GetWindowThreadProcessId(window, &processId);
@@ -496,7 +550,7 @@ void AppZoneHistory::UpdateProcessIdToHandleMap(HWND window, const FancyZonesDat
}
}
ZoneIndexSet AppZoneHistory::GetAppLastZoneIndexSet(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring_view& zoneSetId) const
ZoneIndexSet AppZoneHistory::GetAppLastZoneIndexSet(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId, const std::wstring_view& zoneSetId) const
{
auto processPath = get_process_path_waiting_uwp(window);
if (processPath.empty())
@@ -505,7 +559,7 @@ ZoneIndexSet AppZoneHistory::GetAppLastZoneIndexSet(HWND window, const FancyZone
return {};
}
auto srcVirtualDesktopIDStr = FancyZonesUtils::GuidToString(deviceId.virtualDesktopId);
auto srcVirtualDesktopIDStr = FancyZonesUtils::GuidToString(workAreaId.virtualDesktopId);
auto app = processPath;
auto pos = processPath.find_last_of('\\');
if (pos != std::string::npos && pos + 1 < processPath.length())
@@ -515,7 +569,7 @@ ZoneIndexSet AppZoneHistory::GetAppLastZoneIndexSet(HWND window, const FancyZone
if (srcVirtualDesktopIDStr)
{
Logger::debug(L"Get {} zone history on monitor: {}, virtual desktop: {}", app, deviceId.deviceName, srcVirtualDesktopIDStr.value());
Logger::debug(L"Get {} zone history on monitor: {}, virtual desktop: {}", app, workAreaId.toString(), srcVirtualDesktopIDStr.value());
}
auto history = m_history.find(processPath);
@@ -527,15 +581,15 @@ ZoneIndexSet AppZoneHistory::GetAppLastZoneIndexSet(HWND window, const FancyZone
const auto& perDesktopData = history->second;
for (const auto& data : perDesktopData)
{
if (data.zoneSetUuid == zoneSetId && data.deviceId.deviceName == deviceId.deviceName)
if (data.zoneSetUuid == zoneSetId && data.workAreaId == workAreaId)
{
auto vdStr = FancyZonesUtils::GuidToString(data.deviceId.virtualDesktopId);
auto vdStr = FancyZonesUtils::GuidToString(data.workAreaId.virtualDesktopId);
if (vdStr)
{
Logger::debug(L"App zone history found on the device {} with virtual desktop {}", data.deviceId.deviceName, vdStr.value());
Logger::debug(L"App zone history found on the device {} with virtual desktop {}", data.workAreaId.toString(), vdStr.value());
}
if (data.deviceId.virtualDesktopId == deviceId.virtualDesktopId || data.deviceId.virtualDesktopId == GUID_NULL)
if (data.workAreaId.virtualDesktopId == workAreaId.virtualDesktopId || data.workAreaId.virtualDesktopId == GUID_NULL)
{
return data.zoneIndexSet;
}
@@ -573,9 +627,9 @@ void AppZoneHistory::SyncVirtualDesktops()
{
for (auto& data : perDesktopData)
{
if (data.deviceId.virtualDesktopId == GUID_NULL)
if (data.workAreaId.virtualDesktopId == GUID_NULL)
{
data.deviceId.virtualDesktopId = savedInRegistryVirtualDesktopID.value();
data.workAreaId.virtualDesktopId = savedInRegistryVirtualDesktopID.value();
dirtyFlag = true;
}
}
@@ -598,9 +652,9 @@ void AppZoneHistory::RemoveDeletedVirtualDesktops(const std::vector<GUID>& activ
auto& perDesktopData = it->second;
for (auto desktopIt = std::begin(perDesktopData); desktopIt != std::end(perDesktopData);)
{
if (desktopIt->deviceId.virtualDesktopId != GUID_NULL && !active.contains(desktopIt->deviceId.virtualDesktopId))
if (desktopIt->workAreaId.virtualDesktopId != GUID_NULL && !active.contains(desktopIt->workAreaId.virtualDesktopId))
{
auto virtualDesktopIdStr = FancyZonesUtils::GuidToString(desktopIt->deviceId.virtualDesktopId);
auto virtualDesktopIdStr = FancyZonesUtils::GuidToString(desktopIt->workAreaId.virtualDesktopId);
if (virtualDesktopIdStr)
{
Logger::info(L"Remove Virtual Desktop id {} from app-zone-history", virtualDesktopIdStr.value());

View File

@@ -17,6 +17,8 @@ namespace NonLocalizable
const static wchar_t* DeviceIdID = L"device-id";
const static wchar_t* DeviceID = L"device";
const static wchar_t* MonitorID = L"monitor";
const static wchar_t* MonitorInstanceID = L"monitor-instance";
const static wchar_t* MonitorSerialNumberID = L"serial-number";
const static wchar_t* VirtualDesktopID = L"virtual-desktop";
}
}
@@ -39,18 +41,19 @@ public:
void LoadData();
void SaveData();
void AdjustWorkAreaIds(const std::vector<FancyZonesDataTypes::MonitorId>& ids);
bool SetAppLastZones(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring& zoneSetId, const ZoneIndexSet& zoneIndexSet);
bool RemoveAppLastZone(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring_view& zoneSetId);
bool SetAppLastZones(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId, const std::wstring& zoneSetId, const ZoneIndexSet& zoneIndexSet);
bool RemoveAppLastZone(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId, const std::wstring_view& zoneSetId);
void RemoveApp(const std::wstring& appPath);
const TAppZoneHistoryMap& GetFullAppZoneHistory() const noexcept;
std::optional<FancyZonesDataTypes::AppZoneHistoryData> GetZoneHistory(const std::wstring& appPath, const FancyZonesDataTypes::DeviceIdData& deviceId) const noexcept;
std::optional<FancyZonesDataTypes::AppZoneHistoryData> GetZoneHistory(const std::wstring& appPath, const FancyZonesDataTypes::WorkAreaId& workAreaId) const noexcept;
bool IsAnotherWindowOfApplicationInstanceZoned(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId) const noexcept;
void UpdateProcessIdToHandleMap(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId);
ZoneIndexSet GetAppLastZoneIndexSet(HWND window, const FancyZonesDataTypes::DeviceIdData& deviceId, const std::wstring_view& zoneSetId) const;
bool IsAnotherWindowOfApplicationInstanceZoned(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId) const noexcept;
void UpdateProcessIdToHandleMap(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId);
ZoneIndexSet GetAppLastZoneIndexSet(HWND window, const FancyZonesDataTypes::WorkAreaId& workAreaId, const std::wstring_view& zoneSetId) const;
void SyncVirtualDesktops();
void RemoveDeletedVirtualDesktops(const std::vector<GUID>& activeDesktops);

View File

@@ -9,6 +9,7 @@
#include <FancyZonesLib/FancyZonesData/LayoutDefaults.h>
#include <FancyZonesLib/FancyZonesWinHookEventIDs.h>
#include <FancyZonesLib/JsonHelpers.h>
#include <FancyZonesLib/MonitorUtils.h>
#include <FancyZonesLib/VirtualDesktop.h>
#include <FancyZonesLib/util.h>
@@ -72,7 +73,7 @@ namespace JsonUtils
struct AppliedLayoutsJSON
{
private:
static std::optional<FancyZonesDataTypes::DeviceIdData> DeviceIdFromJson(const json::JsonObject& json)
static std::optional<FancyZonesDataTypes::WorkAreaId> WorkAreaIdFromJson(const json::JsonObject& json)
{
try
{
@@ -80,6 +81,8 @@ namespace JsonUtils
{
json::JsonObject device = json.GetNamedObject(NonLocalizable::AppliedLayoutsIds::DeviceID);
std::wstring monitor = device.GetNamedString(NonLocalizable::AppliedLayoutsIds::MonitorID).c_str();
std::wstring monitorInstance = device.GetNamedString(NonLocalizable::AppliedLayoutsIds::MonitorInstanceID, L"").c_str();
std::wstring monitorSerialNumber = device.GetNamedString(NonLocalizable::AppliedLayoutsIds::MonitorSerialNumberID, L"").c_str();
std::wstring virtualDesktop = device.GetNamedString(NonLocalizable::AppliedLayoutsIds::VirtualDesktopID).c_str();
auto virtualDesktopGuid = FancyZonesUtils::GuidFromString(virtualDesktop);
@@ -88,8 +91,25 @@ namespace JsonUtils
return std::nullopt;
}
return FancyZonesDataTypes::DeviceIdData{
.deviceName = monitor,
FancyZonesDataTypes::DeviceId deviceId{};
if (monitorInstance.empty())
{
// old data
deviceId = MonitorUtils::Display::ConvertObsoleteDeviceId(monitor);
}
else
{
deviceId.id = monitor;
deviceId.instanceId = monitorInstance;
}
FancyZonesDataTypes::MonitorId monitorId{
.deviceId = deviceId,
.serialNumber = monitorSerialNumber
};
return FancyZonesDataTypes::WorkAreaId{
.monitorId = monitorId,
.virtualDesktopId = virtualDesktopGuid.value(),
};
}
@@ -102,8 +122,8 @@ namespace JsonUtils
return std::nullopt;
}
return FancyZonesDataTypes::DeviceIdData{
.deviceName = bcDeviceId->deviceName,
return FancyZonesDataTypes::WorkAreaId{
.monitorId = { .deviceId = MonitorUtils::Display::ConvertObsoleteDeviceId(bcDeviceId->deviceName) },
.virtualDesktopId = bcDeviceId->virtualDesktopId,
};
}
@@ -115,7 +135,7 @@ namespace JsonUtils
}
public:
FancyZonesDataTypes::DeviceIdData deviceId;
FancyZonesDataTypes::WorkAreaId workAreaId;
Layout data;
static std::optional<AppliedLayoutsJSON> FromJson(const json::JsonObject& json)
@@ -124,7 +144,7 @@ namespace JsonUtils
{
AppliedLayoutsJSON result;
auto deviceIdOpt = DeviceIdFromJson(json);
auto deviceIdOpt = WorkAreaIdFromJson(json);
if (!deviceIdOpt.has_value())
{
return std::nullopt;
@@ -136,7 +156,7 @@ namespace JsonUtils
return std::nullopt;
}
result.deviceId = std::move(deviceIdOpt.value());
result.workAreaId = std::move(deviceIdOpt.value());
result.data = std::move(layout.value());
return result;
}
@@ -149,9 +169,11 @@ namespace JsonUtils
static json::JsonObject ToJson(const AppliedLayoutsJSON& value)
{
json::JsonObject device{};
device.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorID, json::value(value.deviceId.deviceName));
device.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorID, json::value(value.workAreaId.monitorId.deviceId.id));
device.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorInstanceID, json::value(value.workAreaId.monitorId.deviceId.instanceId));
device.SetNamedValue(NonLocalizable::AppliedLayoutsIds::MonitorSerialNumberID, json::value(value.workAreaId.monitorId.serialNumber));
auto virtualDesktopStr = FancyZonesUtils::GuidToString(value.deviceId.virtualDesktopId);
auto virtualDesktopStr = FancyZonesUtils::GuidToString(value.workAreaId.virtualDesktopId);
if (virtualDesktopStr)
{
device.SetNamedValue(NonLocalizable::AppliedLayoutsIds::VirtualDesktopID, json::value(virtualDesktopStr.value()));
@@ -176,9 +198,9 @@ namespace JsonUtils
{
// skip default layouts in case if they were applied to different resolutions on the same monitor.
// NOTE: keep the default layout check for users who update PT version from the v0.57
if (!map.contains(obj->deviceId) && !isLayoutDefault(obj->data))
if (!map.contains(obj->workAreaId) && !isLayoutDefault(obj->data))
{
map[obj->deviceId] = std::move(obj->data);
map[obj->workAreaId] = std::move(obj->data);
}
}
}
@@ -194,7 +216,7 @@ namespace JsonUtils
for (const auto& [id, data] : map)
{
AppliedLayoutsJSON obj{};
obj.deviceId = id;
obj.workAreaId = id;
obj.data = data;
layoutArray.Append(AppliedLayoutsJSON::ToJson(obj));
}
@@ -268,6 +290,41 @@ void AppliedLayouts::SaveData()
}
}
void AppliedLayouts::AdjustWorkAreaIds(const std::vector<FancyZonesDataTypes::MonitorId>& ids)
{
bool dirtyFlag = false;
std::vector<std::pair<FancyZonesDataTypes::WorkAreaId, std::wstring>> replaceWithSerialNumber{};
for (auto iter = m_layouts.begin(); iter != m_layouts.end(); ++iter)
{
const auto& [id, layout] = *iter;
if (id.monitorId.serialNumber.empty() && !id.monitorId.deviceId.isDefault())
{
for (const auto& monitorId : ids)
{
if (id.monitorId.deviceId.id == monitorId.deviceId.id && id.monitorId.deviceId.instanceId == monitorId.deviceId.instanceId)
{
replaceWithSerialNumber.push_back({ id, monitorId.serialNumber });
dirtyFlag = true;
break;
}
}
}
}
for (const auto& id : replaceWithSerialNumber)
{
auto mapEntry = m_layouts.extract(id.first);
mapEntry.key().monitorId.serialNumber = id.second;
m_layouts.insert(std::move(mapEntry));
}
if (dirtyFlag)
{
SaveData();
}
}
void AppliedLayouts::SyncVirtualDesktops()
{
// Explorer persists current virtual desktop identifier to registry on a per session basis,
@@ -292,7 +349,7 @@ void AppliedLayouts::SyncVirtualDesktops()
bool dirtyFlag = false;
std::vector<FancyZonesDataTypes::DeviceIdData> replaceWithCurrentId{};
std::vector<FancyZonesDataTypes::WorkAreaId> replaceWithCurrentId{};
for (const auto& [id, data] : m_layouts)
{
@@ -351,7 +408,7 @@ void AppliedLayouts::RemoveDeletedVirtualDesktops(const std::vector<GUID>& activ
}
}
std::optional<Layout> AppliedLayouts::GetDeviceLayout(const FancyZonesDataTypes::DeviceIdData& id) const noexcept
std::optional<Layout> AppliedLayouts::GetDeviceLayout(const FancyZonesDataTypes::WorkAreaId& id) const noexcept
{
auto iter = m_layouts.find(id);
if (iter != m_layouts.end())
@@ -367,19 +424,19 @@ const AppliedLayouts::TAppliedLayoutsMap& AppliedLayouts::GetAppliedLayoutMap()
return m_layouts;
}
bool AppliedLayouts::IsLayoutApplied(const FancyZonesDataTypes::DeviceIdData& id) const noexcept
bool AppliedLayouts::IsLayoutApplied(const FancyZonesDataTypes::WorkAreaId& id) const noexcept
{
auto iter = m_layouts.find(id);
return iter != m_layouts.end();
}
bool AppliedLayouts::ApplyLayout(const FancyZonesDataTypes::DeviceIdData& deviceId, Layout layout)
bool AppliedLayouts::ApplyLayout(const FancyZonesDataTypes::WorkAreaId& deviceId, Layout layout)
{
m_layouts[deviceId] = std::move(layout);
return true;
}
bool AppliedLayouts::ApplyDefaultLayout(const FancyZonesDataTypes::DeviceIdData& deviceId)
bool AppliedLayouts::ApplyDefaultLayout(const FancyZonesDataTypes::WorkAreaId& deviceId)
{
Logger::info(L"Set default layout on {}", deviceId.toString());
@@ -408,7 +465,7 @@ bool AppliedLayouts::ApplyDefaultLayout(const FancyZonesDataTypes::DeviceIdData&
return true;
}
bool AppliedLayouts::CloneLayout(const FancyZonesDataTypes::DeviceIdData& srcId, const FancyZonesDataTypes::DeviceIdData& dstId)
bool AppliedLayouts::CloneLayout(const FancyZonesDataTypes::WorkAreaId& srcId, const FancyZonesDataTypes::WorkAreaId& dstId)
{
if (srcId == dstId || m_layouts.find(srcId) == m_layouts.end())
{

View File

@@ -18,6 +18,8 @@ namespace NonLocalizable
const static wchar_t* DeviceIdID = L"device-id";
const static wchar_t* DeviceID = L"device";
const static wchar_t* MonitorID = L"monitor";
const static wchar_t* MonitorInstanceID = L"monitor-instance";
const static wchar_t* MonitorSerialNumberID = L"serial-number";
const static wchar_t* VirtualDesktopID = L"virtual-desktop";
const static wchar_t* AppliedLayoutID = L"applied-layout";
const static wchar_t* UuidID = L"uuid";
@@ -32,7 +34,7 @@ namespace NonLocalizable
class AppliedLayouts
{
public:
using TAppliedLayoutsMap = std::unordered_map<FancyZonesDataTypes::DeviceIdData, Layout>;
using TAppliedLayoutsMap = std::unordered_map<FancyZonesDataTypes::WorkAreaId, Layout>;
static AppliedLayouts& instance();
@@ -47,18 +49,19 @@ public:
void LoadData();
void SaveData();
void AdjustWorkAreaIds(const std::vector<FancyZonesDataTypes::MonitorId>& ids);
void SyncVirtualDesktops();
void RemoveDeletedVirtualDesktops(const std::vector<GUID>& activeDesktops);
std::optional<Layout> GetDeviceLayout(const FancyZonesDataTypes::DeviceIdData& id) const noexcept;
std::optional<Layout> GetDeviceLayout(const FancyZonesDataTypes::WorkAreaId& id) const noexcept;
const TAppliedLayoutsMap& GetAppliedLayoutMap() const noexcept;
bool IsLayoutApplied(const FancyZonesDataTypes::DeviceIdData& id) const noexcept;
bool IsLayoutApplied(const FancyZonesDataTypes::WorkAreaId& id) const noexcept;
bool ApplyLayout(const FancyZonesDataTypes::DeviceIdData& deviceId, Layout layout);
bool ApplyDefaultLayout(const FancyZonesDataTypes::DeviceIdData& deviceId);
bool CloneLayout(const FancyZonesDataTypes::DeviceIdData& srcId, const FancyZonesDataTypes::DeviceIdData& dstId);
bool ApplyLayout(const FancyZonesDataTypes::WorkAreaId& deviceId, Layout layout);
bool ApplyDefaultLayout(const FancyZonesDataTypes::WorkAreaId& deviceId);
bool CloneLayout(const FancyZonesDataTypes::WorkAreaId& srcId, const FancyZonesDataTypes::WorkAreaId& dstId);
private:
AppliedLayouts();

View File

@@ -129,7 +129,23 @@ namespace FancyZonesDataTypes
return high + 1;
}
std::wstring DeviceIdData::toString() const
std::wstring DeviceId::toString() const noexcept
{
return id + L"_" + instanceId;
}
bool DeviceId::isDefault() const noexcept
{
static const std::wstring defaultMonitorId = L"Default_Monitor";
return id == defaultMonitorId;
}
std::wstring MonitorId::toString() const noexcept
{
return deviceId.toString() + L"_" + serialNumber;
}
std::wstring WorkAreaId::toString() const noexcept
{
wil::unique_cotaskmem_string virtualDesktopIdStr;
if (!SUCCEEDED(StringFromCLSID(virtualDesktopId, &virtualDesktopIdStr)))
@@ -137,7 +153,7 @@ namespace FancyZonesDataTypes
return std::wstring();
}
std::wstring result = deviceName + L"_" + virtualDesktopIdStr.get();
std::wstring result = monitorId.toString() + L"_" + virtualDesktopIdStr.get();
return result;
}

View File

@@ -113,12 +113,30 @@ namespace FancyZonesDataTypes
ZoneSetLayoutType type;
};
struct DeviceIdData
struct DeviceId
{
std::wstring deviceName = L"FallbackDevice";
std::wstring id;
std::wstring instanceId;
bool isDefault() const noexcept;
std::wstring toString() const noexcept;
};
struct MonitorId
{
HMONITOR monitor;
DeviceId deviceId;
std::wstring serialNumber;
std::wstring toString() const noexcept;
};
struct WorkAreaId
{
MonitorId monitorId;
GUID virtualDesktopId;
std::wstring toString() const;
std::wstring toString() const noexcept;
};
struct AppZoneHistoryData
@@ -126,7 +144,7 @@ namespace FancyZonesDataTypes
std::unordered_map<DWORD, HWND> processIdToHandleMap; // Maps process id(DWORD) of application to zoned window handle(HWND)
std::wstring zoneSetUuid;
DeviceIdData deviceId;
WorkAreaId workAreaId;
ZoneIndexSet zoneIndexSet;
};
@@ -144,33 +162,86 @@ namespace FancyZonesDataTypes
return lhs.type == rhs.type && lhs.uuid == rhs.uuid;
}
inline bool operator==(const DeviceIdData& lhs, const DeviceIdData& rhs)
{
return lhs.deviceName.compare(rhs.deviceName) == 0 && (lhs.virtualDesktopId == rhs.virtualDesktopId || lhs.virtualDesktopId == GUID_NULL || rhs.virtualDesktopId == GUID_NULL);
}
inline bool operator!=(const DeviceIdData& lhs, const DeviceIdData& rhs)
{
return !(lhs == rhs);
}
inline bool operator<(const DeviceIdData& lhs, const DeviceIdData& rhs)
{
return lhs.deviceName.compare(rhs.deviceName) < 0;
}
inline bool operator==(const DeviceInfoData& lhs, const DeviceInfoData& rhs)
{
return lhs.activeZoneSet == rhs.activeZoneSet && lhs.showSpacing == rhs.showSpacing && lhs.spacing == rhs.spacing && lhs.zoneCount == rhs.zoneCount && lhs.sensitivityRadius == rhs.sensitivityRadius;
}
inline bool operator==(const DeviceId& lhs, const DeviceId& rhs)
{
if (lhs.isDefault())
{
return lhs.instanceId == rhs.instanceId;
}
return lhs.id == rhs.id;
}
inline bool operator<(const DeviceId& lhs, const DeviceId& rhs)
{
return lhs.id < rhs.id || lhs.instanceId < rhs.instanceId;
}
inline bool operator==(const MonitorId& lhs, const MonitorId& rhs)
{
if (lhs.monitor && rhs.monitor)
{
return lhs.monitor == rhs.monitor;
}
if (!lhs.serialNumber.empty() || !rhs.serialNumber.empty())
{
bool serialNumbersEqual = lhs.serialNumber == rhs.serialNumber;
if (!serialNumbersEqual)
{
return false;
}
}
return lhs.deviceId == rhs.deviceId;
}
inline bool operator==(const WorkAreaId& lhs, const WorkAreaId& rhs)
{
bool vdEqual = (lhs.virtualDesktopId == rhs.virtualDesktopId || lhs.virtualDesktopId == GUID_NULL || rhs.virtualDesktopId == GUID_NULL);
return vdEqual && lhs.monitorId == rhs.monitorId;
}
inline bool operator!=(const WorkAreaId& lhs, const WorkAreaId& rhs)
{
bool vdEqual = (lhs.virtualDesktopId == rhs.virtualDesktopId || lhs.virtualDesktopId == GUID_NULL || rhs.virtualDesktopId == GUID_NULL);
return !vdEqual || lhs.monitorId != rhs.monitorId;
}
inline bool operator<(const WorkAreaId& lhs, const WorkAreaId& rhs)
{
if (lhs.monitorId.monitor && rhs.monitorId.monitor)
{
return lhs.monitorId.monitor < rhs.monitorId.monitor;
}
if (lhs.virtualDesktopId != GUID_NULL || rhs.virtualDesktopId != GUID_NULL)
{
return lhs.virtualDesktopId.Data1 < rhs.virtualDesktopId.Data1 ||
lhs.virtualDesktopId.Data2 < rhs.virtualDesktopId.Data2 ||
lhs.virtualDesktopId.Data3 < rhs.virtualDesktopId.Data3;
}
if (!lhs.monitorId.serialNumber.empty() || rhs.monitorId.serialNumber.empty())
{
return lhs.monitorId.serialNumber < rhs.monitorId.serialNumber;
}
return lhs.monitorId.deviceId < rhs.monitorId.deviceId;
}
}
namespace std
{
template<>
struct hash<FancyZonesDataTypes::DeviceIdData>
struct hash<FancyZonesDataTypes::WorkAreaId>
{
size_t operator()(const FancyZonesDataTypes::DeviceIdData& Value) const
size_t operator()(const FancyZonesDataTypes::WorkAreaId& Value) const
{
return 0;
}

View File

@@ -10,6 +10,7 @@
#include <FancyZonesLib/FancyZonesData/LayoutDefaults.h>
#include <FancyZonesLib/FancyZonesData/LayoutHotkeys.h>
#include <FancyZonesLib/FancyZonesData/LayoutTemplates.h>
#include <FancyZonesLib/MonitorUtils.h>
#include <common/logger/logger.h>
@@ -272,8 +273,8 @@ namespace
return std::nullopt;
}
data.deviceId = FancyZonesDataTypes::DeviceIdData{
.deviceName = deviceId->deviceName,
data.workAreaId = FancyZonesDataTypes::WorkAreaId{
.monitorId = { .deviceId = MonitorUtils::Display::ConvertObsoleteDeviceId(deviceId->deviceName) },
.virtualDesktopId = deviceId->virtualDesktopId
};
data.zoneSetUuid = json.GetNamedString(NonLocalizable::ZoneSetUuidStr);

View File

@@ -1,47 +1,278 @@
#include "pch.h"
#include "MonitorUtils.h"
#include <WbemCli.h>
#include <comutil.h>
#include <FancyZonesLib/WindowUtils.h>
#include <FancyZonesLib/util.h>
#include <common/logger/logger.h>
#include <common/utils/winapi_error.h>
namespace MonitorUtils
{
constexpr int CUSTOM_POSITIONING_LEFT_TOP_PADDING = 16;
inline int RectWidth(const RECT& rect)
namespace WMI
{
return rect.right - rect.left;
}
inline int RectHeight(const RECT& rect)
{
return rect.bottom - rect.top;
}
RECT FitOnScreen(const RECT& windowRect, const RECT& originMonitorRect, const RECT& destMonitorRect)
{
// New window position on active monitor. If window fits the screen, this will be final position.
int left = destMonitorRect.left + (windowRect.left - originMonitorRect.left);
int top = destMonitorRect.top + (windowRect.top - originMonitorRect.top);
int W = RectWidth(windowRect);
int H = RectHeight(windowRect);
if ((left < destMonitorRect.left) || (left + W > destMonitorRect.right))
FancyZonesDataTypes::DeviceId SplitWMIDeviceId(const std::wstring& str) noexcept
{
// Set left window border to left border of screen (add padding). Resize window width if needed.
left = destMonitorRect.left + CUSTOM_POSITIONING_LEFT_TOP_PADDING;
W = min(W, RectWidth(destMonitorRect) - CUSTOM_POSITIONING_LEFT_TOP_PADDING);
}
if ((top < destMonitorRect.top) || (top + H > destMonitorRect.bottom))
{
// Set top window border to top border of screen (add padding). Resize window height if needed.
top = destMonitorRect.top + CUSTOM_POSITIONING_LEFT_TOP_PADDING;
H = min(H, RectHeight(destMonitorRect) - CUSTOM_POSITIONING_LEFT_TOP_PADDING);
// format: DISPLAY\{device id}\{instance id}
// example: DISPLAY\GSM0001\4&125707d6&0&UID28741_0
// output: { GSM0001, 4&125707d6&0&UID28741 }
size_t nameStartPos = str.find_first_of('\\');
size_t uidStartPos = str.find_last_of('\\');
size_t uidEndPos = str.find_last_of('_');
if (nameStartPos == std::string::npos || uidStartPos == std::string::npos || uidEndPos == std::string::npos)
{
return { .id = str };
}
return { .id = str.substr(nameStartPos + 1, uidStartPos - nameStartPos - 1), .instanceId = str.substr(uidStartPos + 1, uidEndPos - uidStartPos - 1) };
}
return { .left = left,
.top = top,
.right = left + W,
.bottom = top + H };
std::wstring GetWMIProp(IWbemClassObject* wbemClassObj, std::wstring_view prop)
{
if (!wbemClassObj)
{
return {};
}
VARIANT vtProp{};
// Get the value of the Name property
auto hres = wbemClassObj->Get(prop.data(), 0, &vtProp, 0, 0);
if (FAILED(hres))
{
Logger::error(L"Get {} Error code = {} ", prop, get_last_error_or_default(hres));
return {};
}
std::wstring result{};
switch (vtProp.vt)
{
case VT_BSTR: //BSTR
{
result = vtProp.bstrVal;
}
break;
case VT_ARRAY: // parray
case 8195: // also parray
{
std::u32string str(static_cast<const char32_t*>(vtProp.parray->pvData));
std::wstring wstr;
for (const char32_t& c : str)
{
wstr += (wchar_t)c;
}
result = wstr;
}
break;
default:
break;
}
VariantClear(&vtProp);
return result;
}
std::vector<FancyZonesDataTypes::MonitorId> GetHardwareMonitorIds()
{
HRESULT hres;
// Obtain the initial locator to Windows Management
// on a particular host computer.
IWbemLocator* pLocator = 0;
hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLocator);
if (FAILED(hres))
{
Logger::error(L"Failed to create IWbemLocator object. {}", get_last_error_or_default(hres));
return {};
}
IWbemServices* pServices = 0;
hres = pLocator->ConnectServer(_bstr_t(L"ROOT\\WMI"), NULL, NULL, 0, NULL, 0, 0, &pServices);
if (FAILED(hres))
{
Logger::error(L"Could not connect WMI server. {}", get_last_error_or_default(hres));
pLocator->Release();
return {};
}
// Set the IWbemServices proxy so that impersonation
// of the user (client) occurs.
hres = CoSetProxyBlanket(pServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
if (FAILED(hres))
{
Logger::error(L"Could not set proxy blanket. {}", get_last_error_or_default(hres));
pServices->Release();
pLocator->Release();
return {};
}
// Use the IWbemServices pointer to make requests of WMI.
// Make requests here:
IEnumWbemClassObject* pEnumerator = NULL;
hres = pServices->ExecQuery(bstr_t("WQL"), bstr_t("SELECT * FROM WmiMonitorID"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
if (FAILED(hres))
{
Logger::error(L"Query for monitors failed. {}", get_last_error_or_default(hres));
pServices->Release();
pLocator->Release();
return {};
}
IWbemClassObject* pClassObject;
ULONG uReturn = 0;
std::vector<FancyZonesDataTypes::MonitorId> result{};
while (pEnumerator)
{
hres = pEnumerator->Next(WBEM_INFINITE, 1, &pClassObject, &uReturn);
if (0 == uReturn)
{
break;
}
LPSAFEARRAY pFieldArray = NULL;
hres = pClassObject->GetNames(NULL, WBEM_FLAG_ALWAYS, NULL, &pFieldArray);
if (FAILED(hres))
{
Logger::error(L"Failed to get field names. {}", get_last_error_or_default(hres));
break;
}
auto name = GetWMIProp(pClassObject, L"InstanceName");
FancyZonesDataTypes::MonitorId data{};
data.deviceId = SplitWMIDeviceId(name);
data.serialNumber = GetWMIProp(pClassObject, L"SerialNumberID");
Logger::info(L"InstanceName: {}", name);
Logger::info(L"Serial number: {}", data.serialNumber);
result.emplace_back(std::move(data));
pClassObject->Release();
pClassObject = NULL;
}
pServices->Release();
pLocator->Release();
pEnumerator->Release();
return result;
}
}
namespace Display
{
FancyZonesDataTypes::DeviceId SplitDisplayDeviceId(const std::wstring& str) noexcept
{
// format: \\?\DISPLAY#{device id}#{instance id}#{some other id}
// example: \\?\DISPLAY#GSM1388#4&125707d6&0&UID8388688#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
// output: { GSM1388, 4&125707d6&0&UID8388688 }
size_t nameStartPos = str.find_first_of('#');
size_t uidStartPos = str.find('#', nameStartPos + 1);
size_t uidEndPos = str.find('#', uidStartPos + 1);
if (nameStartPos == std::string::npos || uidStartPos == std::string::npos || uidEndPos == std::string::npos)
{
return { str, L"" };
}
return { .id = str.substr(nameStartPos + 1, uidStartPos - nameStartPos - 1), .instanceId = str.substr(uidStartPos + 1, uidEndPos - uidStartPos - 1) };
}
FancyZonesDataTypes::DeviceId ConvertObsoleteDeviceId(const std::wstring& str) noexcept
{
// format: {device id}#{instance id}
// example: GSM1388#4&125707d6&0&UID8388688
// output: { GSM1388, 4&125707d6&0&UID8388688 }
size_t dividerPos = str.find_first_of('#');
if (dividerPos == std::string::npos)
{
return { str, L"" };
}
return { .id = str.substr(0, dividerPos), .instanceId = str.substr(dividerPos + 1) };
}
std::vector<FancyZonesDataTypes::MonitorId> GetDisplays()
{
auto allMonitors = FancyZonesUtils::GetAllMonitorInfo<&MONITORINFOEX::rcWork>();
std::unordered_map<std::wstring, DWORD> displayDeviceIdxMap;
std::vector<FancyZonesDataTypes::MonitorId> result{};
for (auto& monitorData : allMonitors)
{
auto monitorInfo = monitorData.second;
DISPLAY_DEVICE displayDevice{ .cb = sizeof(displayDevice) };
std::wstring deviceId;
auto enumRes = EnumDisplayDevicesW(monitorInfo.szDevice, displayDeviceIdxMap[monitorInfo.szDevice], &displayDevice, EDD_GET_DEVICE_INTERFACE_NAME);
if (!enumRes)
{
Logger::error(L"EnumDisplayDevicesW error: {}", get_last_error_or_default(GetLastError()));
continue;
}
Logger::info(L"Display: {}", displayDevice.DeviceID);
result.push_back({ .monitor = monitorData.first, .deviceId = SplitDisplayDeviceId(displayDevice.DeviceID) });
}
return result;
}
}
namespace
{
inline int RectWidth(const RECT& rect)
{
return rect.right - rect.left;
}
inline int RectHeight(const RECT& rect)
{
return rect.bottom - rect.top;
}
RECT FitOnScreen(const RECT& windowRect, const RECT& originMonitorRect, const RECT& destMonitorRect)
{
// New window position on active monitor. If window fits the screen, this will be final position.
int left = destMonitorRect.left + (windowRect.left - originMonitorRect.left);
int top = destMonitorRect.top + (windowRect.top - originMonitorRect.top);
int W = RectWidth(windowRect);
int H = RectHeight(windowRect);
if ((left < destMonitorRect.left) || (left + W > destMonitorRect.right))
{
// Set left window border to left border of screen (add padding). Resize window width if needed.
left = destMonitorRect.left + CUSTOM_POSITIONING_LEFT_TOP_PADDING;
W = min(W, RectWidth(destMonitorRect) - CUSTOM_POSITIONING_LEFT_TOP_PADDING);
}
if ((top < destMonitorRect.top) || (top + H > destMonitorRect.bottom))
{
// Set top window border to top border of screen (add padding). Resize window height if needed.
top = destMonitorRect.top + CUSTOM_POSITIONING_LEFT_TOP_PADDING;
H = min(H, RectHeight(destMonitorRect) - CUSTOM_POSITIONING_LEFT_TOP_PADDING);
}
return { .left = left,
.top = top,
.right = left + W,
.bottom = top + H };
}
}
void OpenWindowOnActiveMonitor(HWND window, HMONITOR monitor) noexcept
@@ -73,4 +304,25 @@ namespace MonitorUtils
}
}
}
std::vector<FancyZonesDataTypes::MonitorId> IdentifyMonitors() noexcept
{
Logger::info(L"Identifying monitors");
auto displays = Display::GetDisplays();
auto monitors = WMI::GetHardwareMonitorIds();
for (const auto& monitor : monitors)
{
for (auto& display : displays)
{
if (monitor.deviceId.id == display.deviceId.id)
{
display.serialNumber = monitor.serialNumber;
}
}
}
return displays;
}
}

View File

@@ -1,6 +1,22 @@
#pragma once
#include <FancyZonesLib/FancyZonesDataTypes.h>
namespace MonitorUtils
{
namespace Display
{
std::vector<FancyZonesDataTypes::MonitorId> GetDisplays();
FancyZonesDataTypes::DeviceId SplitDisplayDeviceId(const std::wstring& str) noexcept;
FancyZonesDataTypes::DeviceId ConvertObsoleteDeviceId(const std::wstring& str) noexcept;
}
namespace WMI
{
std::vector<FancyZonesDataTypes::MonitorId> GetHardwareMonitorIds();
FancyZonesDataTypes::DeviceId SplitWMIDeviceId(const std::wstring& str) noexcept;
}
std::vector<FancyZonesDataTypes::MonitorId> IdentifyMonitors() noexcept;
void OpenWindowOnActiveMonitor(HWND window, HMONITOR monitor) noexcept;
};

View File

@@ -120,7 +120,7 @@ WorkArea::~WorkArea()
windowPool.FreeZonesOverlayWindow(m_window);
}
bool WorkArea::Init(HINSTANCE hinstance, const FancyZonesDataTypes::DeviceIdData& uniqueId, const FancyZonesDataTypes::DeviceIdData& parentUniqueId)
bool WorkArea::Init(HINSTANCE hinstance, const FancyZonesDataTypes::WorkAreaId& uniqueId, const FancyZonesDataTypes::WorkAreaId& parentUniqueId)
{
m_uniqueId = uniqueId;
InitializeZoneSets(parentUniqueId);
@@ -378,13 +378,9 @@ void WorkArea::FlashZones() noexcept
#pragma region private
void WorkArea::InitializeZoneSets(const FancyZonesDataTypes::DeviceIdData& parentUniqueId) noexcept
void WorkArea::InitializeZoneSets(const FancyZonesDataTypes::WorkAreaId& parentUniqueId) noexcept
{
wil::unique_cotaskmem_string virtualDesktopId;
if (SUCCEEDED(StringFromCLSID(m_uniqueId.virtualDesktopId, &virtualDesktopId)))
{
Logger::debug(L"Initialize layout on the virtual desktop {}", virtualDesktopId.get());
}
Logger::info(L"Initialize layout on {}", m_uniqueId.toString());
bool isLayoutAlreadyApplied = AppliedLayouts::instance().IsLayoutApplied(m_uniqueId);
if (!isLayoutAlreadyApplied)

View File

@@ -13,7 +13,7 @@ public:
~WorkArea();
public:
bool Init(HINSTANCE hinstance, const FancyZonesDataTypes::DeviceIdData& uniqueId, const FancyZonesDataTypes::DeviceIdData& parentUniqueId);
bool Init(HINSTANCE hinstance, const FancyZonesDataTypes::WorkAreaId& uniqueId, const FancyZonesDataTypes::WorkAreaId& parentUniqueId);
inline bool InitWorkAreaRect(HMONITOR monitor)
{
m_monitor = monitor;
@@ -42,7 +42,7 @@ public:
return true;
}
FancyZonesDataTypes::DeviceIdData UniqueId() const noexcept { return { m_uniqueId }; }
FancyZonesDataTypes::WorkAreaId UniqueId() const noexcept { return { m_uniqueId }; }
IZoneSet* ZoneSet() const noexcept { return m_zoneSet.get(); }
ZoneIndexSet GetWindowZoneIndexes(HWND window) const noexcept;
@@ -72,7 +72,7 @@ protected:
static LRESULT CALLBACK s_WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) noexcept;
private:
void InitializeZoneSets(const FancyZonesDataTypes::DeviceIdData& parentUniqueId) noexcept;
void InitializeZoneSets(const FancyZonesDataTypes::WorkAreaId& parentUniqueId) noexcept;
void CalculateZoneSet(OverlappingZonesAlgorithm overlappingAlgorithm) noexcept;
void UpdateActiveZoneSet(_In_opt_ IZoneSet* zoneSet) noexcept;
LRESULT WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept;
@@ -82,7 +82,7 @@ private:
HMONITOR m_monitor{};
FancyZonesUtils::Rect m_workAreaRect{};
FancyZonesDataTypes::DeviceIdData m_uniqueId;
FancyZonesDataTypes::WorkAreaId m_uniqueId;
HWND m_window{}; // Hidden tool window used to represent current monitor desktop work area.
HWND m_windowMoveSize{};
winrt::com_ptr<IZoneSet> m_zoneSet;
@@ -93,7 +93,7 @@ private:
std::unique_ptr<ZonesOverlay> m_zonesOverlay;
};
inline std::shared_ptr<WorkArea> MakeWorkArea(HINSTANCE hinstance, HMONITOR monitor, const FancyZonesDataTypes::DeviceIdData& uniqueId, const FancyZonesDataTypes::DeviceIdData& parentUniqueId) noexcept
inline std::shared_ptr<WorkArea> MakeWorkArea(HINSTANCE hinstance, HMONITOR monitor, const FancyZonesDataTypes::WorkAreaId& uniqueId, const FancyZonesDataTypes::WorkAreaId& parentUniqueId) noexcept
{
auto self = std::make_shared<WorkArea>(hinstance);
if (!self->InitWorkAreaRect(monitor))

View File

@@ -16,63 +16,8 @@
namespace FancyZonesUtils
{
std::wstring TrimDeviceId(const std::wstring& deviceId)
{
// We're interested in the unique part between the first and last #'s
// Example input: \\?\DISPLAY#DELA026#5&10a58c63&0&UID16777488#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
// Example output: DELA026#5&10a58c63&0&UID16777488
static const std::wstring defaultDeviceId = L"FallbackDevice";
if (deviceId.empty())
{
return defaultDeviceId;
}
size_t start = deviceId.find(L'#');
size_t end = deviceId.rfind(L'#');
if (start != std::wstring::npos && end != std::wstring::npos && start != end)
{
size_t size = end - (start + 1);
return deviceId.substr(start + 1, size);
}
else
{
return defaultDeviceId;
}
}
typedef BOOL(WINAPI* GetDpiForMonitorInternalFunc)(HMONITOR, UINT, UINT*, UINT*);
std::wstring GetDisplayDeviceId(const std::wstring& device, std::unordered_map<std::wstring, DWORD>& displayDeviceIdxMap)
{
DISPLAY_DEVICE displayDevice{ .cb = sizeof(displayDevice) };
std::wstring deviceId;
while (EnumDisplayDevicesW(device.c_str(), displayDeviceIdxMap[device], &displayDevice, EDD_GET_DEVICE_INTERFACE_NAME))
{
++displayDeviceIdxMap[device];
Logger::info(L"Get display device: {}", displayDevice.DeviceID);
// Only take active monitors (presented as being "on" by the respective GDI view) and monitors that don't
// represent a pseudo device used to mirror application drawing.
if (WI_IsFlagSet(displayDevice.StateFlags, DISPLAY_DEVICE_ACTIVE) &&
WI_IsFlagClear(displayDevice.StateFlags, DISPLAY_DEVICE_MIRRORING_DRIVER))
{
deviceId = displayDevice.DeviceID;
break;
}
}
if (deviceId.empty())
{
Logger::info(L"Didn't find display device, set default");
deviceId = GetSystemMetrics(SM_REMOTESESSION) ?
L"\\\\?\\DISPLAY#REMOTEDISPLAY#" :
L"\\\\?\\DISPLAY#LOCALDISPLAY#";
}
return deviceId;
}
UINT GetDpiForMonitor(HMONITOR monitor) noexcept
{
UINT dpi{};
@@ -206,37 +151,6 @@ namespace FancyZonesUtils
return std::nullopt;
}
std::wstring GenerateUniqueId(HMONITOR monitor, const std::wstring& deviceId, const std::wstring& virtualDesktopId)
{
MONITORINFOEXW mi;
mi.cbSize = sizeof(mi);
if (!virtualDesktopId.empty() && GetMonitorInfo(monitor, &mi))
{
Rect const monitorRect(mi.rcMonitor);
// Unique identifier format: <parsed-device-id>_<width>_<height>_<virtual-desktop-id>
return TrimDeviceId(deviceId) +
L'_' +
virtualDesktopId;
}
return {};
}
std::wstring GenerateUniqueIdAllMonitorsArea(const std::wstring& virtualDesktopId)
{
std::wstring result{ ZonedWindowProperties::MultiMonitorDeviceID };
RECT combinedResolution = GetAllMonitorsCombinedRect<&MONITORINFO::rcMonitor>();
result += L'_';
result += std::to_wstring(combinedResolution.right - combinedResolution.left);
result += L'_';
result += std::to_wstring(combinedResolution.bottom - combinedResolution.top);
result += L'_';
result += virtualDesktopId;
return result;
}
size_t ChooseNextZoneByPosition(DWORD vkCode, RECT windowRect, const std::vector<RECT>& zoneRects) noexcept
{
using complex = std::complex<double>;

View File

@@ -168,8 +168,6 @@ namespace FancyZonesUtils
return result;
}
std::wstring GetDisplayDeviceId(const std::wstring& device, std::unordered_map<std::wstring, DWORD>& displayDeviceIdxMap);
UINT GetDpiForMonitor(HMONITOR monitor) noexcept;
void OrderMonitors(std::vector<std::pair<HMONITOR, RECT>>& monitorInfo);
@@ -177,10 +175,6 @@ namespace FancyZonesUtils
std::optional<GUID> GuidFromString(const std::wstring& str) noexcept;
std::optional<std::wstring> GuidToString(const GUID& guid) noexcept;
std::wstring GenerateUniqueId(HMONITOR monitor, const std::wstring& devideId, const std::wstring& virtualDesktopId);
std::wstring GenerateUniqueIdAllMonitorsArea(const std::wstring& virtualDesktopId);
std::wstring TrimDeviceId(const std::wstring& deviceId);
RECT PrepareRectForCycling(RECT windowRect, RECT workAreaRect, DWORD vkCode) noexcept;
size_t ChooseNextZoneByPosition(DWORD vkCode, RECT windowRect, const std::vector<RECT>& zoneRects) noexcept;
}

View File

@@ -33,7 +33,7 @@
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalDependencies>gdiplus.lib;dwmapi.lib;shlwapi.lib;uxtheme.lib;shcore.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>gdiplus.lib;dwmapi.lib;shlwapi.lib;uxtheme.lib;shcore.lib;wbemuuid.lib;comsuppw.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>

View File

@@ -102,22 +102,22 @@ namespace FancyZonesUnitTests
Assert::AreEqual((size_t)2, AppZoneHistory::instance().GetFullAppZoneHistory().size());
{
FancyZonesDataTypes::DeviceIdData id{
.deviceName = L"monitor-1",
FancyZonesDataTypes::WorkAreaId id{
.monitorId = { .deviceId = { .id = L"monitor-1" } },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{72FA9FC0-26A6-4B37-A834-491C148DFC58}").value()
};
Assert::IsTrue(AppZoneHistory::instance().GetZoneHistory(L"app-1", id).has_value());
}
{
FancyZonesDataTypes::DeviceIdData id{
.deviceName = L"monitor-2",
FancyZonesDataTypes::WorkAreaId id{
.monitorId = { .deviceId = { .id = L"monitor-2" } },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{72FA9FC0-26A6-4B37-A834-491C148DFC58}").value()
};
Assert::IsTrue(AppZoneHistory::instance().GetZoneHistory(L"app-1", id).has_value());
}
{
FancyZonesDataTypes::DeviceIdData id{
.deviceName = L"monitor-1",
FancyZonesDataTypes::WorkAreaId id{
.monitorId = { .deviceId = { .id = L"monitor-1" } },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{72FA9FC0-26A6-4B37-A834-491C148DFC58}").value()
};
Assert::IsTrue(AppZoneHistory::instance().GetZoneHistory(L"app-2", id).has_value());
@@ -197,8 +197,8 @@ namespace FancyZonesUnitTests
Assert::AreEqual((size_t)1, AppZoneHistory::instance().GetFullAppZoneHistory().size());
{
FancyZonesDataTypes::DeviceIdData id{
.deviceName = L"monitor-1",
FancyZonesDataTypes::WorkAreaId id{
.monitorId = { .deviceId = { .id = L"monitor-1" } },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{72FA9FC0-26A6-4B37-A834-491C148DFC58}").value()
};
Assert::IsTrue(AppZoneHistory::instance().GetZoneHistory(L"app-1", id).has_value());
@@ -208,103 +208,136 @@ namespace FancyZonesUnitTests
TEST_METHOD (AppLastZoneInvalidWindow)
{
const std::wstring zoneSetId = L"{2FEC41DA-3A0B-4E31-9CE1-9473C65D99F2}";
const FancyZonesDataTypes::DeviceIdData deviceId{ L"DELA026#5&10a58c63&0&UID16777488_2194_1234_{39B25DD2-130D-4B5D-8851-4791D66B1539}" };
const FancyZonesDataTypes::WorkAreaId workAreaId{
.monitorId = { .deviceId = { .id = L"DELA026", .instanceId = L"5&10a58c63&0&UID16777488" } },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}").value()
};
const auto window = Mocks::Window();
Assert::IsTrue(std::vector<ZoneIndex>{} == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, deviceId, zoneSetId));
Assert::IsTrue(std::vector<ZoneIndex>{} == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, workAreaId, zoneSetId));
const int expectedZoneIndex = 1;
Assert::IsFalse(AppZoneHistory::instance().SetAppLastZones(window, deviceId, zoneSetId, { expectedZoneIndex }));
Assert::IsFalse(AppZoneHistory::instance().SetAppLastZones(window, workAreaId, zoneSetId, { expectedZoneIndex }));
}
TEST_METHOD (AppLastZoneNullWindow)
{
const std::wstring zoneSetId = L"{2FEC41DA-3A0B-4E31-9CE1-9473C65D99F2}";
const FancyZonesDataTypes::DeviceIdData deviceId{ L"DELA026#5&10a58c63&0&UID16777488_2194_1234_{39B25DD2-130D-4B5D-8851-4791D66B1539}" };
const FancyZonesDataTypes::WorkAreaId workAreaId{
.monitorId = { .deviceId = { .id = L"DELA026", .instanceId = L"5&10a58c63&0&UID16777488" } },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}").value()
};
const auto window = nullptr;
const int expectedZoneIndex = 1;
Assert::IsFalse(AppZoneHistory::instance().SetAppLastZones(window, deviceId, zoneSetId, { expectedZoneIndex }));
Assert::IsFalse(AppZoneHistory::instance().SetAppLastZones(window, workAreaId, zoneSetId, { expectedZoneIndex }));
}
TEST_METHOD (AppLastdeviceIdTest)
{
const std::wstring zoneSetId = L"{2FEC41DA-3A0B-4E31-9CE1-9473C65D99F2}";
const FancyZonesDataTypes::DeviceIdData deviceId1{ L"DELA026#5&10a58c63&0&UID16777488_2194_1234_{39B25DD2-130D-4B5D-8851-4791D66B1539}" };
const FancyZonesDataTypes::DeviceIdData deviceId2{ L"DELA026#5&10a58c63&0&UID16777489_2194_1234_{39B25DD2-130D-4B5D-8851-4791D66B1539}" };
const FancyZonesDataTypes::WorkAreaId workAreaId1{
.monitorId = { .deviceId = { .id = L"DELA026", .instanceId = L"5&10a58c63&0&UID16777488" } },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}").value()
};
const FancyZonesDataTypes::WorkAreaId workAreaId2{
.monitorId = { .deviceId = { .id = L"DELA027", .instanceId = L"5&10a58c63&0&UID16777489" } },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}").value()
};
const auto window = Mocks::WindowCreate(m_hInst);
const int expectedZoneIndex = 10;
Assert::IsTrue(AppZoneHistory::instance().SetAppLastZones(window, deviceId1, zoneSetId, { expectedZoneIndex }));
Assert::IsTrue(std::vector<ZoneIndex>{ expectedZoneIndex } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, deviceId1, zoneSetId));
Assert::IsTrue(std::vector<ZoneIndex>{} == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, deviceId2, zoneSetId));
Assert::IsTrue(AppZoneHistory::instance().SetAppLastZones(window, workAreaId1, zoneSetId, { expectedZoneIndex }));
Assert::IsTrue(std::vector<ZoneIndex>{ expectedZoneIndex } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, workAreaId1, zoneSetId));
Assert::IsTrue(std::vector<ZoneIndex>{} == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, workAreaId2, zoneSetId));
}
TEST_METHOD (AppLastZoneSetIdTest)
{
const std::wstring zoneSetId1 = L"{B7A1F5A9-9DC2-4505-84AB-993253839093}";
const std::wstring zoneSetId2 = L"{B7A1F5A9-9DC2-4505-84AB-993253839094}";
const FancyZonesDataTypes::DeviceIdData deviceId{ L"DELA026#5&10a58c63&0&UID16777488_2194_1234_{39B25DD2-130D-4B5D-8851-4791D66B1539}" };
const FancyZonesDataTypes::WorkAreaId workAreaId{
.monitorId = { .deviceId = { .id = L"DELA026", .instanceId = L"5&10a58c63&0&UID16777488" } },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}").value()
};
const auto window = Mocks::WindowCreate(m_hInst);
const int expectedZoneIndex = 10;
Assert::IsTrue(AppZoneHistory::instance().SetAppLastZones(window, deviceId, zoneSetId1, { expectedZoneIndex }));
Assert::IsTrue(std::vector<ZoneIndex>{ expectedZoneIndex } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, deviceId, zoneSetId1));
Assert::IsTrue(std::vector<ZoneIndex>{} == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, deviceId, zoneSetId2));
Assert::IsTrue(AppZoneHistory::instance().SetAppLastZones(window, workAreaId, zoneSetId1, { expectedZoneIndex }));
Assert::IsTrue(std::vector<ZoneIndex>{ expectedZoneIndex } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, workAreaId, zoneSetId1));
Assert::IsTrue(std::vector<ZoneIndex>{} == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, workAreaId, zoneSetId2));
}
TEST_METHOD (AppLastZoneRemoveWindow)
{
const std::wstring zoneSetId = L"{B7A1F5A9-9DC2-4505-84AB-993253839093}";
const FancyZonesDataTypes::DeviceIdData deviceId{ L"DELA026#5&10a58c63&0&UID16777488_2194_1234_{39B25DD2-130D-4B5D-8851-4791D66B1539}" };
const FancyZonesDataTypes::WorkAreaId workAreaId{
.monitorId = { .deviceId = { .id = L"DELA026", .instanceId = L"5&10a58c63&0&UID16777488" } },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}").value()
};
const auto window = Mocks::WindowCreate(m_hInst);
Assert::IsTrue(AppZoneHistory::instance().SetAppLastZones(window, deviceId, zoneSetId, { 1 }));
Assert::IsTrue(AppZoneHistory::instance().RemoveAppLastZone(window, deviceId, zoneSetId));
Assert::IsTrue(std::vector<ZoneIndex>{} == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, deviceId, zoneSetId));
Assert::IsTrue(AppZoneHistory::instance().SetAppLastZones(window, workAreaId, zoneSetId, { 1 }));
Assert::IsTrue(AppZoneHistory::instance().RemoveAppLastZone(window, workAreaId, zoneSetId));
Assert::IsTrue(std::vector<ZoneIndex>{} == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, workAreaId, zoneSetId));
}
TEST_METHOD (AppLastZoneRemoveUnknownWindow)
{
const std::wstring zoneSetId = L"{2FEC41DA-3A0B-4E31-9CE1-9473C65D99F2}";
const FancyZonesDataTypes::DeviceIdData deviceId{ L"DELA026#5&10a58c63&0&UID16777488_2194_1234_{39B25DD2-130D-4B5D-8851-4791D66B1539}" };
const FancyZonesDataTypes::WorkAreaId workAreaId{
.monitorId = { .deviceId = { .id = L"DELA026", .instanceId = L"5&10a58c63&0&UID16777488" } },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}").value()
};
const auto window = Mocks::WindowCreate(m_hInst);
Assert::IsFalse(AppZoneHistory::instance().RemoveAppLastZone(window, deviceId, zoneSetId));
Assert::IsTrue(std::vector<ZoneIndex>{} == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, deviceId, zoneSetId));
Assert::IsFalse(AppZoneHistory::instance().RemoveAppLastZone(window, workAreaId, zoneSetId));
Assert::IsTrue(std::vector<ZoneIndex>{} == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, workAreaId, zoneSetId));
}
TEST_METHOD (AppLastZoneRemoveUnknownZoneSetId)
{
const std::wstring zoneSetIdToInsert = L"{2FEC41DA-3A0B-4E31-9CE1-9473C65D99F2}";
const std::wstring zoneSetIdToRemove = L"{2FEC41DA-3A0B-4E31-9CE1-9473C65D99F1}";
const FancyZonesDataTypes::DeviceIdData deviceId{ L"DELA026#5&10a58c63&0&UID16777488_2194_1234_{39B25DD2-130D-4B5D-8851-4791D66B1539}" };
const FancyZonesDataTypes::WorkAreaId workAreaId{
.monitorId = { .deviceId = { .id = L"DELA026", .instanceId = L"5&10a58c63&0&UID16777488" } },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}").value()
};
const auto window = Mocks::WindowCreate(m_hInst);
Assert::IsTrue(AppZoneHistory::instance().SetAppLastZones(window, deviceId, zoneSetIdToInsert, { 1 }));
Assert::IsFalse(AppZoneHistory::instance().RemoveAppLastZone(window, deviceId, zoneSetIdToRemove));
Assert::IsTrue(std::vector<ZoneIndex>{ 1 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, deviceId, zoneSetIdToInsert));
Assert::IsTrue(AppZoneHistory::instance().SetAppLastZones(window, workAreaId, zoneSetIdToInsert, { 1 }));
Assert::IsFalse(AppZoneHistory::instance().RemoveAppLastZone(window, workAreaId, zoneSetIdToRemove));
Assert::IsTrue(std::vector<ZoneIndex>{ 1 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, workAreaId, zoneSetIdToInsert));
}
TEST_METHOD (AppLastZoneRemoveUnknownWindowId)
{
const std::wstring zoneSetId = L"{2FEC41DA-3A0B-4E31-9CE1-9473C65D99F2}";
const FancyZonesDataTypes::DeviceIdData deviceIdToInsert{ L"DELA026#5&10a58c63&0&UID16777488_2194_1234_{39B25DD2-130D-4B5D-8851-4791D66B1539}" };
const FancyZonesDataTypes::DeviceIdData deviceIdToRemove{ L"DELA026#5&10a58c63&0&UID16777489_2194_1234_{39B25DD2-130D-4B5D-8851-4791D66B1539}" };
const FancyZonesDataTypes::WorkAreaId workAreaIdToInsert{
.monitorId = { .deviceId = { .id = L"DELA026", .instanceId = L"5&10a58c63&0&UID16777488" } },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}").value()
};
const FancyZonesDataTypes::WorkAreaId workAreaIdToRemove{
.monitorId = { .deviceId = { .id = L"DELA027", .instanceId = L"5&10a58c63&0&UID16777489" } },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}").value()
};
const auto window = Mocks::WindowCreate(m_hInst);
Assert::IsTrue(AppZoneHistory::instance().SetAppLastZones(window, deviceIdToInsert, zoneSetId, { 1 }));
Assert::IsFalse(AppZoneHistory::instance().RemoveAppLastZone(window, deviceIdToRemove, zoneSetId));
Assert::IsTrue(std::vector<ZoneIndex>{ 1 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, deviceIdToInsert, zoneSetId));
Assert::IsTrue(AppZoneHistory::instance().SetAppLastZones(window, workAreaIdToInsert, zoneSetId, { 1 }));
Assert::IsFalse(AppZoneHistory::instance().RemoveAppLastZone(window, workAreaIdToRemove, zoneSetId));
Assert::IsTrue(std::vector<ZoneIndex>{ 1 } == AppZoneHistory::instance().GetAppLastZoneIndexSet(window, workAreaIdToInsert, zoneSetId));
}
TEST_METHOD (AppLastZoneRemoveNullWindow)
{
const std::wstring zoneSetId = L"{2FEC41DA-3A0B-4E31-9CE1-9473C65D99F2}";
const FancyZonesDataTypes::DeviceIdData deviceId{ L"DELA026#5&10a58c63&0&UID16777488_2194_1234_{39B25DD2-130D-4B5D-8851-4791D66B1539}" };
const FancyZonesDataTypes::WorkAreaId workAreaId{
.monitorId = { .deviceId = { .id = L"DELA026", .instanceId = L"5&10a58c63&0&UID16777488" } },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}").value()
};
const auto window = Mocks::WindowCreate(m_hInst);
Assert::IsFalse(AppZoneHistory::instance().RemoveAppLastZone(nullptr, deviceId, zoneSetId));
Assert::IsFalse(AppZoneHistory::instance().RemoveAppLastZone(nullptr, workAreaId, zoneSetId));
}
};
}

View File

@@ -23,6 +23,7 @@ namespace FancyZonesUnitTests
{
std::filesystem::remove_all(AppliedLayouts::AppliedLayoutsFileName());
std::filesystem::remove_all(PTSettingsHelper::get_module_save_folder_location(m_testFolder));
AppliedLayouts::instance().LoadData(); // clean data
}
TEST_METHOD (AppliedLayoutsParse)
@@ -58,11 +59,12 @@ namespace FancyZonesUnitTests
AppliedLayouts::instance().LoadData();
Assert::AreEqual((size_t)1, AppliedLayouts::instance().GetAppliedLayoutMap().size());
FancyZonesDataTypes::DeviceIdData id{
.deviceName = L"DELA026#5&10a58c63&0&UID16777488",
FancyZonesDataTypes::WorkAreaId id{
.monitorId = { .deviceId = { .id = L"DELA026", .instanceId = L"5&10a58c63&0&UID16777488" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}").value()
};
Assert::IsTrue(AppliedLayouts::instance().GetDeviceLayout(id).has_value());
Assert::IsTrue(AppliedLayouts::instance().IsLayoutApplied(id));
}
TEST_METHOD(AppliedLayoutsParseDataWithResolution)
@@ -94,11 +96,12 @@ namespace FancyZonesUnitTests
AppliedLayouts::instance().LoadData();
Assert::AreEqual((size_t)1, AppliedLayouts::instance().GetAppliedLayoutMap().size());
FancyZonesDataTypes::DeviceIdData id{
.deviceName = L"DELA026#5&10a58c63&0&UID16777488",
FancyZonesDataTypes::WorkAreaId id{
.monitorId = { .deviceId = { .id = L"DELA026", .instanceId = L"5&10a58c63&0&UID16777488" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}").value()
};
Assert::IsTrue(AppliedLayouts::instance().GetDeviceLayout(id).has_value());
Assert::IsTrue(AppliedLayouts::instance().IsLayoutApplied(id));
}
TEST_METHOD (AppliedLayoutsParseDataWithResolution2)
@@ -147,11 +150,12 @@ namespace FancyZonesUnitTests
AppliedLayouts::instance().LoadData();
Assert::AreEqual((size_t)1, AppliedLayouts::instance().GetAppliedLayoutMap().size());
FancyZonesDataTypes::DeviceIdData id{
.deviceName = L"DELA026#5&10a58c63&0&UID16777488",
FancyZonesDataTypes::WorkAreaId id{
.monitorId = { .deviceId = { .id = L"DELA026", .instanceId = L"5&10a58c63&0&UID16777488" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}").value()
};
Assert::IsTrue(AppliedLayouts::instance().GetDeviceLayout(id).has_value());
Assert::IsTrue(AppliedLayouts::instance().IsLayoutApplied(id));
}
TEST_METHOD (AppliedLayoutsParseDataWithResolution3)
@@ -202,11 +206,12 @@ namespace FancyZonesUnitTests
AppliedLayouts::instance().LoadData();
Assert::AreEqual((size_t)1, AppliedLayouts::instance().GetAppliedLayoutMap().size());
FancyZonesDataTypes::DeviceIdData id{
.deviceName = L"DELA026#5&10a58c63&0&UID16777488",
FancyZonesDataTypes::WorkAreaId id{
.monitorId = { .deviceId = { .id = L"DELA026", .instanceId = L"5&10a58c63&0&UID16777488" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}").value()
};
Assert::IsTrue(AppliedLayouts::instance().GetDeviceLayout(id).has_value());
Assert::IsTrue(AppliedLayouts::instance().IsLayoutApplied(id));
}
TEST_METHOD (AppliedLayoutsParseEmpty)
@@ -262,8 +267,8 @@ namespace FancyZonesUnitTests
AppliedLayouts::instance().LoadData();
Assert::AreEqual((size_t)1, AppliedLayouts::instance().GetAppliedLayoutMap().size());
FancyZonesDataTypes::DeviceIdData id{
.deviceName = L"VSC9636#5&37ac4db&0&UID160005",
FancyZonesDataTypes::WorkAreaId id{
.monitorId = { .deviceId = { .id = L"VSC9636", .instanceId = L"5&37ac4db&0&UID160005" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value()
};
Assert::IsTrue(AppliedLayouts::instance().GetDeviceLayout(id).has_value());
@@ -295,12 +300,12 @@ namespace FancyZonesUnitTests
TEST_METHOD (CloneDeviceInfo)
{
FancyZonesDataTypes::DeviceIdData deviceSrc{
.deviceName = L"Device1",
FancyZonesDataTypes::WorkAreaId deviceSrc{
.monitorId = { .deviceId = { .id = L"Device1", .instanceId = L"" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value()
};
FancyZonesDataTypes::DeviceIdData deviceDst{
.deviceName = L"Device2",
FancyZonesDataTypes::WorkAreaId deviceDst{
.monitorId = { .deviceId = { .id = L"Device2", .instanceId = L"" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value()
};
@@ -323,12 +328,12 @@ namespace FancyZonesUnitTests
TEST_METHOD (CloneDeviceInfoIntoUnknownDevice)
{
FancyZonesDataTypes::DeviceIdData deviceSrc{
.deviceName = L"Device1",
FancyZonesDataTypes::WorkAreaId deviceSrc{
.monitorId = { .deviceId = { .id = L"Device1", .instanceId = L"" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value()
};
FancyZonesDataTypes::DeviceIdData deviceDst{
.deviceName = L"Device2",
FancyZonesDataTypes::WorkAreaId deviceDst{
.monitorId = { .deviceId = { .id = L"Device2", .instanceId = L"" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value()
};
@@ -350,12 +355,12 @@ namespace FancyZonesUnitTests
TEST_METHOD (CloneDeviceInfoFromUnknownDevice)
{
FancyZonesDataTypes::DeviceIdData deviceSrc{
.deviceName = L"Device1",
FancyZonesDataTypes::WorkAreaId deviceSrc{
.monitorId = { .deviceId = { .id = L"Device1", .instanceId = L"" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value()
};
FancyZonesDataTypes::DeviceIdData deviceDst{
.deviceName = L"Device2",
FancyZonesDataTypes::WorkAreaId deviceDst{
.monitorId = { .deviceId = { .id = L"Device2", .instanceId = L"" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value()
};
@@ -370,12 +375,12 @@ namespace FancyZonesUnitTests
TEST_METHOD (CloneDeviceInfoNullVirtualDesktopId)
{
FancyZonesDataTypes::DeviceIdData deviceSrc{
.deviceName = L"Device1",
FancyZonesDataTypes::WorkAreaId deviceSrc{
.monitorId = { .deviceId = { .id = L"Device1", .instanceId = L"" }, .serialNumber = L"" },
.virtualDesktopId = GUID_NULL
};
FancyZonesDataTypes::DeviceIdData deviceDst{
.deviceName = L"Device2",
FancyZonesDataTypes::WorkAreaId deviceDst{
.monitorId = { .deviceId = { .id = L"Device2", .instanceId = L"" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value()
};
@@ -399,8 +404,8 @@ namespace FancyZonesUnitTests
TEST_METHOD (ApplyLayout)
{
// prepare
FancyZonesDataTypes::DeviceIdData deviceId {
.deviceName = L"DELA026#5&10a58c63&0&UID16777488",
FancyZonesDataTypes::WorkAreaId deviceId {
.monitorId = { .deviceId = { .id = L"DELA026", .instanceId = L"5&10a58c63&0&UID16777488" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}").value()
};
@@ -430,8 +435,8 @@ namespace FancyZonesUnitTests
TEST_METHOD (ApplyLayoutReplace)
{
// prepare
FancyZonesDataTypes::DeviceIdData deviceId{
.deviceName = L"DELA026#5&10a58c63&0&UID16777488",
FancyZonesDataTypes::WorkAreaId deviceId{
.monitorId = { .deviceId = { .id = L"DELA026", .instanceId = L"5&10a58c63&0&UID16777488" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}").value()
};
@@ -482,8 +487,8 @@ namespace FancyZonesUnitTests
TEST_METHOD (ApplyDefaultLayout)
{
FancyZonesDataTypes::DeviceIdData expected{
.deviceName = L"Device",
FancyZonesDataTypes::WorkAreaId expected{
.monitorId = { .deviceId = { .id = L"Device", .instanceId = L"" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{00000000-0000-0000-0000-000000000000}").value()
};
@@ -497,8 +502,8 @@ namespace FancyZonesUnitTests
TEST_METHOD (ApplyDefaultLayoutWithNullVirtualDesktopId)
{
FancyZonesDataTypes::DeviceIdData expected{
.deviceName = L"Device",
FancyZonesDataTypes::WorkAreaId expected{
.monitorId = { .deviceId = { .id = L"Device", .instanceId = L"" }, .serialNumber = L"" },
.virtualDesktopId = GUID_NULL
};
@@ -509,5 +514,35 @@ namespace FancyZonesUnitTests
Assert::IsFalse(actualMap.find(expected) == actualMap.end());
}
TEST_METHOD (IsLayoutApplied)
{
// prepare
FancyZonesDataTypes::WorkAreaId id{
.monitorId = { .deviceId = { .id = L"device", .instanceId = L"instance-id" }, .serialNumber = L"serial-number" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
AppliedLayouts::instance().ApplyLayout(id, Layout{});
// test
Assert::IsTrue(AppliedLayouts::instance().IsLayoutApplied(id));
}
TEST_METHOD (IsLayoutApplied2)
{
// prepare
FancyZonesDataTypes::WorkAreaId id1{
.monitorId = { .deviceId = { .id = L"device-1", .instanceId = L"instance-id-1" }, .serialNumber = L"serial-number-1" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
AppliedLayouts::instance().ApplyLayout(id1, Layout{});
// test
FancyZonesDataTypes::WorkAreaId id2{
.monitorId = { .deviceId = { .id = L"device-2", .instanceId = L"instance-id-2" }, .serialNumber = L"serial-number-2" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{F21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
Assert::IsFalse(AppliedLayouts::instance().IsLayoutApplied(id2));
}
};
}

View File

@@ -741,15 +741,9 @@ namespace FancyZonesUnitTests
TEST_CLASS (DeviceInfoUnitTests)
{
private:
FancyZonesDataTypes::DeviceIdData m_defaultDeviceId{ .deviceName = L"AOC2460#4&fe3a015&0&UID65793", .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{33A2B101-06E0-437B-A61E-CDBECF502907}").value() };
DeviceInfoJSON m_defaultDeviceInfo = DeviceInfoJSON{ BackwardsCompatibility::DeviceIdData::ParseDeviceId(L"AOC2460#4&fe3a015&0&UID65793_1920_1080_{33A2B101-06E0-437B-A61E-CDBECF502907}").value(), DeviceInfoData{ ZoneSetData{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Custom }, true, 16, 3 } };
json::JsonObject m_defaultJson = json::JsonObject::Parse(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}");
TEST_METHOD_INITIALIZE(Init)
{
CLSIDFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}", &m_defaultDeviceId.virtualDesktopId);
}
public:
TEST_METHOD (FromJson)
{
@@ -792,8 +786,6 @@ namespace FancyZonesUnitTests
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 FancyZonesDataTypes::DeviceIdData m_defaultDeviceId = FancyZonesDataTypes::DeviceIdData{ .deviceName = L"AOC2460#4&fe3a015&0&UID65793", .virtualDesktopId = FancyZonesUtils::GuidFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}").value() };
TEST_METHOD_INITIALIZE(Init)
{
std::filesystem::remove_all(PTSettingsHelper::get_module_save_folder_location(m_moduleName));

View File

@@ -37,7 +37,7 @@
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>gdiplus.lib;dwmapi.lib;shlwapi.lib;uxtheme.lib;shcore.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>gdiplus.lib;dwmapi.lib;shlwapi.lib;uxtheme.lib;shcore.lib;wbemuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
@@ -55,6 +55,7 @@
<ClCompile Include="Util.Spec.cpp" />
<ClCompile Include="Util.cpp" />
<ClCompile Include="WorkArea.Spec.cpp" />
<ClCompile Include="WorkAreaIdTests.Spec.cpp" />
<ClCompile Include="Zone.Spec.cpp" />
<ClCompile Include="ZoneSet.Spec.cpp" />
</ItemGroup>

View File

@@ -57,6 +57,9 @@
<ClCompile Include="AppliedLayoutsTests.Spec.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="WorkAreaIdTests.Spec.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">

View File

@@ -41,28 +41,6 @@ namespace FancyZonesUnitTests
TEST_CLASS(UtilUnitTests)
{
TEST_METHOD (TestTrimDeviceId)
{
// We're interested in the unique part between the first and last #'s
// Example input: \\?\DISPLAY#DELA026#5&10a58c63&0&UID16777488#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
// Example output: DELA026#5&10a58c63&0&UID16777488
const std::wstring input = L"\\\\?\\DISPLAY#DELA026#5&10a58c63&0&UID16777488#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}";
const std::wstring actual = TrimDeviceId(input);
const std::wstring expected = L"DELA026#5&10a58c63&0&UID16777488";
Assert::AreEqual(expected, actual);
}
TEST_METHOD(TestTrimInvalidDeviceId)
{
// We're interested in the unique part between the first and last #'s
// Example input: \\?\DISPLAY#DELA026#5&10a58c63&0&UID16777488#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
// Example output: DELA026#5&10a58c63&0&UID16777488
const std::wstring input = L"AnInvalidDeviceId";
const std::wstring actual = TrimDeviceId(input);
const std::wstring expected = L"FallbackDevice";
Assert::AreEqual(expected, actual);
}
TEST_METHOD(TestParseDeviceId01)
{
const std::wstring input = L"AOC0001#5&37ac4db&0&UID160002_1536_960_{E0A2904E-889C-4532-95B1-28FE15C16F66}";

View File

@@ -23,12 +23,14 @@ namespace FancyZonesUnitTests
TEST_CLASS (WorkAreaCreationUnitTests)
{
FancyZonesDataTypes::DeviceIdData m_uniqueId;
FancyZonesDataTypes::DeviceIdData m_emptyUniqueId;
FancyZonesDataTypes::WorkAreaId m_uniqueId;
FancyZonesDataTypes::WorkAreaId m_emptyUniqueId;
TEST_METHOD_INITIALIZE(Init)
{
m_uniqueId.deviceName = L"DELA026#5&10a58c63&0&UID16777488";
m_uniqueId.monitorId.deviceId.id = L"DELA026";
m_uniqueId.monitorId.deviceId.instanceId = L"5&10a58c63&0&UID16777488";
m_uniqueId.monitorId.serialNumber = L"serial-number";
auto res = CLSIDFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}", &m_uniqueId.virtualDesktopId);
Assert::IsTrue(SUCCEEDED(res));
@@ -70,8 +72,10 @@ namespace FancyZonesUnitTests
{
using namespace FancyZonesDataTypes;
FancyZonesDataTypes::DeviceIdData parentUniqueId;
parentUniqueId.deviceName = L"DELA026#5&10a58c63&0&UID16777488";
FancyZonesDataTypes::WorkAreaId parentUniqueId;
parentUniqueId.monitorId.deviceId.id = L"DELA026";
parentUniqueId.monitorId.deviceId.instanceId = L"5&10a58c63&0&UID16777488";
parentUniqueId.monitorId.serialNumber = L"serial-number";
parentUniqueId.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{61FA9FC0-26A6-4B37-A834-491C148DFC57}").value();
Layout layout{
@@ -104,15 +108,17 @@ namespace FancyZonesUnitTests
TEST_CLASS (WorkAreaUnitTests)
{
FancyZonesDataTypes::DeviceIdData m_uniqueId;
FancyZonesDataTypes::DeviceIdData m_parentUniqueId; // default empty
FancyZonesDataTypes::WorkAreaId m_uniqueId;
FancyZonesDataTypes::WorkAreaId m_parentUniqueId; // default empty
HINSTANCE m_hInst{};
HMONITOR m_monitor{};
TEST_METHOD_INITIALIZE(Init)
{
m_uniqueId.deviceName = L"DELA026#5&10a58c63&0&UID16777488";
m_uniqueId.monitorId.deviceId.id = L"DELA026";
m_uniqueId.monitorId.deviceId.instanceId = L"5&10a58c63&0&UID16777488";
m_uniqueId.monitorId.serialNumber = L"serial-number";
CLSIDFromString(L"{39B25DD2-130D-4B5D-8851-4791D66B1539}", &m_uniqueId.virtualDesktopId);
AppZoneHistory::instance().LoadData();

View File

@@ -0,0 +1,212 @@
#include "pch.h"
#include <FancyZonesLib/FancyZonesDataTypes.h>
#include <FancyZonesLib/util.h>
#include <FancyZonesTests/UnitTests/Util.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace FancyZonesUnitTests
{
TEST_CLASS (WorkAreaIdComparison)
{
TEST_METHOD (MonitorHandleSame)
{
auto monitor = Mocks::Monitor();
FancyZonesDataTypes::WorkAreaId id1{
.monitorId = { .monitor = monitor, .deviceId = { .id = L"device-1", .instanceId = L"instance-id-1" }, .serialNumber = L"serial-number-1" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
FancyZonesDataTypes::WorkAreaId id2{
.monitorId = { .monitor = monitor, .deviceId = { .id = L"device-2", .instanceId = L"instance-id-2" }, .serialNumber = L"serial-number-2" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
Assert::IsTrue(id1 == id2);
}
TEST_METHOD (MonitorHandleDifferent)
{
FancyZonesDataTypes::WorkAreaId id1{
.monitorId = { .monitor = Mocks::Monitor(), .deviceId = { .id = L"device", .instanceId = L"instance-id" }, .serialNumber = L"serial-number" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
FancyZonesDataTypes::WorkAreaId id2{
.monitorId = { .monitor = Mocks::Monitor(), .deviceId = { .id = L"device", .instanceId = L"instance-id" }, .serialNumber = L"serial-number" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
Assert::IsFalse(id1 == id2);
}
TEST_METHOD (VirtualDesktopNull)
{
FancyZonesDataTypes::WorkAreaId id1{
.monitorId = { .deviceId = { .id = L"device", .instanceId = L"instance-id" }, .serialNumber = L"serial-number" },
.virtualDesktopId = GUID_NULL
};
FancyZonesDataTypes::WorkAreaId id2{
.monitorId = { .deviceId = { .id = L"device", .instanceId = L"instance-id" }, .serialNumber = L"serial-number" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
Assert::IsTrue(id1 == id2);
}
TEST_METHOD (VirtualDesktopDifferent)
{
FancyZonesDataTypes::WorkAreaId id1{
.monitorId = { .deviceId = { .id = L"device", .instanceId = L"instance-id" }, .serialNumber = L"serial-number" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{F21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
FancyZonesDataTypes::WorkAreaId id2{
.monitorId = { .deviceId = { .id = L"device", .instanceId = L"instance-id" }, .serialNumber = L"serial-number" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
Assert::IsFalse(id1 == id2);
}
TEST_METHOD (NoSerialNumber)
{
FancyZonesDataTypes::WorkAreaId id1{
.monitorId = { .deviceId = { .id = L"device", .instanceId = L"instance-id" }, .serialNumber = L"serial-number" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
FancyZonesDataTypes::WorkAreaId id2{
.monitorId = { .deviceId = { .id = L"device", .instanceId = L"instance-id" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
Assert::IsFalse(id1 == id2);
}
TEST_METHOD (NoSerialNumber2)
{
FancyZonesDataTypes::WorkAreaId id1{
.monitorId = { .deviceId = { .id = L"device", .instanceId = L"instance-id" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
FancyZonesDataTypes::WorkAreaId id2{
.monitorId = { .deviceId = { .id = L"device", .instanceId = L"instance-id" }, .serialNumber = L"serial-number" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
Assert::IsFalse(id1 == id2);
}
TEST_METHOD (DifferentSerialNumber)
{
FancyZonesDataTypes::WorkAreaId id1{
.monitorId = { .deviceId = { .id = L"device", .instanceId = L"instance-id" }, .serialNumber = L"serial-number" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
FancyZonesDataTypes::WorkAreaId id2{
.monitorId = { .deviceId = { .id = L"device", .instanceId = L"instance-id" }, .serialNumber = L"another-serial-number" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
Assert::IsFalse(id1 == id2);
}
TEST_METHOD (DefaultMonitorIdDifferentInstanceId)
{
FancyZonesDataTypes::WorkAreaId id1{
.monitorId = { .deviceId = { .id = L"Default_Monitor", .instanceId = L"instance-id" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
FancyZonesDataTypes::WorkAreaId id2{
.monitorId = { .deviceId = { .id = L"Default_Monitor", .instanceId = L"another-instance-id" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
Assert::IsFalse(id1 == id2);
}
TEST_METHOD (DefaultMonitorIdSameInstanceId)
{
FancyZonesDataTypes::WorkAreaId id1{
.monitorId = { .deviceId = { .id = L"Default_Monitor", .instanceId = L"instance-id" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
FancyZonesDataTypes::WorkAreaId id2{
.monitorId = { .deviceId = { .id = L"Default_Monitor", .instanceId = L"instance-id" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
Assert::IsTrue(id1 == id2);
}
TEST_METHOD (DifferentId)
{
FancyZonesDataTypes::WorkAreaId id1{
.monitorId = { .deviceId = { .id = L"device-1", .instanceId = L"instance-id" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
FancyZonesDataTypes::WorkAreaId id2{
.monitorId = { .deviceId = { .id = L"device-2", .instanceId = L"instance-id" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
Assert::IsFalse(id1 == id2);
}
TEST_METHOD (SameIdDifferentInstance)
{
FancyZonesDataTypes::WorkAreaId id1{
.monitorId = { .deviceId = { .id = L"device", .instanceId = L"instance-id-1" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
FancyZonesDataTypes::WorkAreaId id2{
.monitorId = { .deviceId = { .id = L"device", .instanceId = L"instance-id-2" }, .serialNumber = L"" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
Assert::IsTrue(id1 == id2);
}
TEST_METHOD (SameIdDifferentSerialNumbers)
{
FancyZonesDataTypes::WorkAreaId id1{
.monitorId = { .deviceId = { .id = L"device-1", .instanceId = L"instance-id-1" }, .serialNumber = L"serial-number-1" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
FancyZonesDataTypes::WorkAreaId id2{
.monitorId = { .deviceId = { .id = L"device-1", .instanceId = L"instance-id-2" }, .serialNumber = L"serial-number-2" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
Assert::IsFalse(id1 == id2);
}
TEST_METHOD (DifferentIdSameSerialNumbers)
{
FancyZonesDataTypes::WorkAreaId id1{
.monitorId = { .deviceId = { .id = L"device-1", .instanceId = L"instance-id-1" }, .serialNumber = L"serial-number-1" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
FancyZonesDataTypes::WorkAreaId id2{
.monitorId = { .deviceId = { .id = L"device-2", .instanceId = L"instance-id-2" }, .serialNumber = L"serial-number-1" },
.virtualDesktopId = FancyZonesUtils::GuidFromString(L"{E21F6F29-76FD-4FC1-8970-17AB8AD64847}").value()
};
Assert::IsFalse(id1 == id2);
}
};
}

View File

@@ -13,6 +13,10 @@ namespace FancyZonesEditor.Utils
{
public string MonitorName { get; set; }
public string MonitorInstanceId { get; set; }
public string MonitorSerialNumber { get; set; }
public Size MonitorSize { get; set; }
public string VirtualDesktopId { get; set; }
@@ -23,9 +27,11 @@ namespace FancyZonesEditor.Utils
public int Dpi { get; set; }
public Device(string monitorName, string virtualDesktopId, int dpi, Rect workArea, Size monitorSize)
public Device(string monitorName, string monitorInstanceId, string monitorSerialNumber, string virtualDesktopId, int dpi, Rect workArea, Size monitorSize)
{
MonitorName = monitorName;
MonitorInstanceId = monitorInstanceId;
MonitorSerialNumber = monitorSerialNumber;
VirtualDesktopId = virtualDesktopId;
Dpi = dpi;
WorkAreaRect = workArea;
@@ -48,6 +54,8 @@ namespace FancyZonesEditor.Utils
var sb = new StringBuilder();
sb.AppendFormat(CultureInfo.InvariantCulture, "MonitorName: {0}{1}", MonitorName, Environment.NewLine);
sb.AppendFormat(CultureInfo.InvariantCulture, "Monitor InstanceId {0}{1}", MonitorInstanceId, Environment.NewLine);
sb.AppendFormat(CultureInfo.InvariantCulture, "Monitor Serial Number {0}{1}", MonitorSerialNumber, Environment.NewLine);
sb.AppendFormat(CultureInfo.InvariantCulture, "Virtual desktop: {0}{1}", VirtualDesktopId, Environment.NewLine);
sb.AppendFormat(CultureInfo.InvariantCulture, "DPI: {0}{1}", Dpi, Environment.NewLine);

View File

@@ -41,10 +41,10 @@ namespace FancyZonesEditor.Models
Window.Height = workArea.Height;
}
public Monitor(string monitorName, string virtualDesktop, int dpi, Rect workArea, Size monitorSize)
public Monitor(string monitorName, string monitorInstanceId, string monitorSerialNumber, string virtualDesktop, int dpi, Rect workArea, Size monitorSize)
: this(workArea, monitorSize)
{
Device = new Device(monitorName, virtualDesktop, dpi, workArea, monitorSize);
Device = new Device(monitorName, monitorInstanceId, monitorSerialNumber, virtualDesktop, dpi, workArea, monitorSize);
}
public void Scale(double scaleFactor)

View File

@@ -77,6 +77,10 @@ namespace FancyZonesEditor.Utils
{
public string Monitor { get; set; }
public string MonitorInstanceId { get; set; }
public string MonitorSerialNumber { get; set; }
public string VirtualDesktop { get; set; }
public int Dpi { get; set; }
@@ -128,6 +132,10 @@ namespace FancyZonesEditor.Utils
{
public string Monitor { get; set; }
public string MonitorInstance { get; set; }
public string SerialNumber { get; set; }
public string VirtualDesktop { get; set; }
}
@@ -309,6 +317,7 @@ namespace FancyZonesEditor.Utils
if (!App.Overlay.SpanZonesAcrossMonitors)
{
string targetMonitorId = string.Empty;
string targetMonitorSerialNumber = string.Empty;
string targetVirtualDesktop = string.Empty;
foreach (NativeMonitorData nativeData in editorParams.Monitors)
@@ -317,6 +326,7 @@ namespace FancyZonesEditor.Utils
if (nativeData.IsSelected)
{
targetMonitorId = nativeData.Monitor;
targetMonitorSerialNumber = nativeData.MonitorSerialNumber;
targetVirtualDesktop = nativeData.VirtualDesktop;
}
@@ -324,6 +334,8 @@ namespace FancyZonesEditor.Utils
var monitor = new Monitor(workArea, monitorSize);
monitor.Device.MonitorName = nativeData.Monitor;
monitor.Device.MonitorInstanceId = nativeData.MonitorInstanceId;
monitor.Device.MonitorSerialNumber = nativeData.MonitorSerialNumber;
monitor.Device.VirtualDesktopId = nativeData.VirtualDesktop;
monitor.Device.Dpi = nativeData.Dpi;
@@ -335,7 +347,9 @@ namespace FancyZonesEditor.Utils
for (int i = 0; i < monitors.Count; i++)
{
var monitor = monitors[i];
if (monitor.Device.MonitorName == targetMonitorId && monitor.Device.VirtualDesktopId == targetVirtualDesktop)
if (monitor.Device.MonitorName == targetMonitorId &&
monitor.Device.MonitorSerialNumber == targetMonitorSerialNumber &&
monitor.Device.VirtualDesktopId == targetVirtualDesktop)
{
App.Overlay.CurrentDesktop = i;
break;
@@ -554,6 +568,8 @@ namespace FancyZonesEditor.Utils
Device = new AppliedLayoutWrapper.DeviceIdWrapper
{
Monitor = monitor.Device.MonitorName,
MonitorInstance = monitor.Device.MonitorInstanceId,
SerialNumber = monitor.Device.MonitorSerialNumber,
VirtualDesktop = monitor.Device.VirtualDesktopId,
},
@@ -818,7 +834,10 @@ namespace FancyZonesEditor.Utils
bool unused = true;
foreach (Monitor monitor in monitors)
{
if (monitor.Device.MonitorName == layout.Device.Monitor && (monitor.Device.VirtualDesktopId == layout.Device.VirtualDesktop || layout.Device.VirtualDesktop == DefaultVirtualDesktopGuid))
if (monitor.Device.MonitorName == layout.Device.Monitor &&
monitor.Device.MonitorSerialNumber == layout.Device.SerialNumber &&
(monitor.Device.VirtualDesktopId == layout.Device.VirtualDesktop ||
layout.Device.VirtualDesktop == DefaultVirtualDesktopGuid))
{
var settings = new LayoutSettings
{