9bb6d57515
* [FancyZones] Remove obsolete code The field `m_zoneSets` is unused, and may be removed. * [FancyZones] Remove obsolete code The field `m_windows` is unused, and may be removed. * [FancyZones] Move adjustment of `RECT` to utils.cpp By doing so, also fix a bug where a non-`WS_SIZEBOX` window (a window that should not be resized) was resized (and not properly resized) if it was zoned into more than one zone. * [FancyZones] Complete rename `ZoneWindow` -> `WorkArea` Fix leftovers from "[FancyZones] Rename ZoneWindow -> WorkArea (#12223)" * [FancyZones] Refer to the move/size action as dragging * [FancyZones] Rename `ActiveZoneSet` -> `ZoneSet` There is only one zone set used by a work area. * [FancyZones] Rename `zoneUuid` -> `layoutUuid` The variable holds the UUID of the layout (not of a zone). Co-authored-by: float4 <float4-unspecified-mail>
314 lines
8.3 KiB
C++
314 lines
8.3 KiB
C++
#include "pch.h"
|
|
#include "util.h"
|
|
|
|
#include <sstream>
|
|
|
|
#include "FancyZonesDataTypes.h"
|
|
|
|
// Non-Localizable strings
|
|
namespace NonLocalizable
|
|
{
|
|
const wchar_t BlankStr[] = L"blank";
|
|
const wchar_t ColumnsStr[] = L"columns";
|
|
const wchar_t CustomStr[] = L"custom";
|
|
const wchar_t FocusStr[] = L"focus";
|
|
const wchar_t GridStr[] = L"grid";
|
|
const wchar_t PriorityGridStr[] = L"priority-grid";
|
|
const wchar_t RowsStr[] = L"rows";
|
|
const wchar_t TypeToStringErrorStr[] = L"TypeToString_ERROR";
|
|
}
|
|
|
|
namespace
|
|
{
|
|
// From Settings.cs
|
|
constexpr int c_focusModelId = 0xFFFF;
|
|
constexpr int c_rowsModelId = 0xFFFE;
|
|
constexpr int c_columnsModelId = 0xFFFD;
|
|
constexpr int c_gridModelId = 0xFFFC;
|
|
constexpr int c_priorityGridModelId = 0xFFFB;
|
|
constexpr int c_blankCustomModelId = 0xFFFA;
|
|
}
|
|
|
|
namespace FancyZonesDataTypes
|
|
{
|
|
std::wstring TypeToString(ZoneSetLayoutType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case ZoneSetLayoutType::Blank:
|
|
return NonLocalizable::BlankStr;
|
|
case ZoneSetLayoutType::Focus:
|
|
return NonLocalizable::FocusStr;
|
|
case ZoneSetLayoutType::Columns:
|
|
return NonLocalizable::ColumnsStr;
|
|
case ZoneSetLayoutType::Rows:
|
|
return NonLocalizable::RowsStr;
|
|
case ZoneSetLayoutType::Grid:
|
|
return NonLocalizable::GridStr;
|
|
case ZoneSetLayoutType::PriorityGrid:
|
|
return NonLocalizable::PriorityGridStr;
|
|
case ZoneSetLayoutType::Custom:
|
|
return NonLocalizable::CustomStr;
|
|
default:
|
|
return NonLocalizable::TypeToStringErrorStr;
|
|
}
|
|
}
|
|
|
|
ZoneSetLayoutType TypeFromString(const std::wstring& typeStr)
|
|
{
|
|
if (typeStr == NonLocalizable::FocusStr)
|
|
{
|
|
return ZoneSetLayoutType::Focus;
|
|
}
|
|
else if (typeStr == NonLocalizable::ColumnsStr)
|
|
{
|
|
return ZoneSetLayoutType::Columns;
|
|
}
|
|
else if (typeStr == NonLocalizable::RowsStr)
|
|
{
|
|
return ZoneSetLayoutType::Rows;
|
|
}
|
|
else if (typeStr == NonLocalizable::GridStr)
|
|
{
|
|
return ZoneSetLayoutType::Grid;
|
|
}
|
|
else if (typeStr == NonLocalizable::PriorityGridStr)
|
|
{
|
|
return ZoneSetLayoutType::PriorityGrid;
|
|
}
|
|
else if (typeStr == NonLocalizable::CustomStr)
|
|
{
|
|
return ZoneSetLayoutType::Custom;
|
|
}
|
|
else
|
|
{
|
|
return ZoneSetLayoutType::Blank;
|
|
}
|
|
}
|
|
|
|
GridLayoutInfo::GridLayoutInfo(const Minimal& info) :
|
|
m_rows(info.rows),
|
|
m_columns(info.columns)
|
|
{
|
|
m_rowsPercents.resize(m_rows, 0);
|
|
m_columnsPercents.resize(m_columns, 0);
|
|
m_cellChildMap.resize(m_rows, {});
|
|
for (auto& cellRow : m_cellChildMap)
|
|
{
|
|
cellRow.resize(m_columns, 0);
|
|
}
|
|
}
|
|
|
|
GridLayoutInfo::GridLayoutInfo(const Full& info) :
|
|
m_rows(info.rows),
|
|
m_columns(info.columns),
|
|
m_rowsPercents(info.rowsPercents),
|
|
m_columnsPercents(info.columnsPercents),
|
|
m_cellChildMap(info.cellChildMap)
|
|
{
|
|
m_rowsPercents.resize(m_rows, 0);
|
|
m_columnsPercents.resize(m_columns, 0);
|
|
m_cellChildMap.resize(m_rows, {});
|
|
for (auto& cellRow : m_cellChildMap)
|
|
{
|
|
cellRow.resize(m_columns, 0);
|
|
}
|
|
}
|
|
|
|
int GridLayoutInfo::zoneCount() const
|
|
{
|
|
int high = 0;
|
|
for (const auto& row : m_cellChildMap)
|
|
{
|
|
for (int val : row)
|
|
{
|
|
high = max(high, val);
|
|
}
|
|
}
|
|
|
|
return high + 1;
|
|
}
|
|
|
|
std::optional<DeviceIdData> DeviceIdData::ParseDeviceId(const std::wstring& str)
|
|
{
|
|
FancyZonesDataTypes::DeviceIdData data;
|
|
|
|
std::wstring temp;
|
|
std::wstringstream wss(str);
|
|
|
|
/*
|
|
Important fix for device info that contains a '_' in the name:
|
|
1. first search for '#'
|
|
2. Then split the remaining string by '_'
|
|
*/
|
|
|
|
// Step 1: parse the name until the #, then to the '_'
|
|
if (str.find(L'#') != std::string::npos)
|
|
{
|
|
std::getline(wss, temp, L'#');
|
|
|
|
data.deviceName = temp;
|
|
|
|
if (!std::getline(wss, temp, L'_'))
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
data.deviceName += L"#" + temp;
|
|
}
|
|
else if (std::getline(wss, temp, L'_') && !temp.empty())
|
|
{
|
|
data.deviceName = temp;
|
|
}
|
|
else
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
// Step 2: parse the rest of the id
|
|
std::vector<std::wstring> parts;
|
|
while (std::getline(wss, temp, L'_'))
|
|
{
|
|
parts.push_back(temp);
|
|
}
|
|
|
|
if (parts.size() != 3 && parts.size() != 4)
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
/*
|
|
Refer to FancyZonesUtils::GenerateUniqueId parts contain:
|
|
1. monitor id [string]
|
|
2. width of device [int]
|
|
3. height of device [int]
|
|
4. virtual desktop id (GUID) [string]
|
|
*/
|
|
try
|
|
{
|
|
for (const auto& c : parts[0])
|
|
{
|
|
std::stoi(std::wstring(&c));
|
|
}
|
|
|
|
for (const auto& c : parts[1])
|
|
{
|
|
std::stoi(std::wstring(&c));
|
|
}
|
|
|
|
data.width = std::stoi(parts[0]);
|
|
data.height = std::stoi(parts[1]);
|
|
}
|
|
catch (const std::exception&)
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
if (!SUCCEEDED(CLSIDFromString(parts[2].c_str(), &data.virtualDesktopId)))
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
if (parts.size() == 4)
|
|
{
|
|
data.monitorId = parts[3]; //could be empty
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
bool DeviceIdData::IsValidDeviceId(const std::wstring& str)
|
|
{
|
|
std::wstring monitorName;
|
|
std::wstring temp;
|
|
std::vector<std::wstring> parts;
|
|
std::wstringstream wss(str);
|
|
|
|
/*
|
|
Important fix for device info that contains a '_' in the name:
|
|
1. first search for '#'
|
|
2. Then split the remaining string by '_'
|
|
*/
|
|
|
|
// Step 1: parse the name until the #, then to the '_'
|
|
if (str.find(L'#') != std::string::npos)
|
|
{
|
|
std::getline(wss, temp, L'#');
|
|
|
|
monitorName = temp;
|
|
|
|
if (!std::getline(wss, temp, L'_'))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
monitorName += L"#" + temp;
|
|
parts.push_back(monitorName);
|
|
}
|
|
|
|
// Step 2: parse the rest of the id
|
|
while (std::getline(wss, temp, L'_'))
|
|
{
|
|
parts.push_back(temp);
|
|
}
|
|
|
|
if (parts.size() != 4)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Refer to FancyZonesUtils::GenerateUniqueId parts contain:
|
|
1. monitor id [string]
|
|
2. width of device [int]
|
|
3. height of device [int]
|
|
4. virtual desktop id (GUID) [string]
|
|
*/
|
|
try
|
|
{
|
|
//check if resolution contain only digits
|
|
for (const auto& c : parts[1])
|
|
{
|
|
std::stoi(std::wstring(&c));
|
|
}
|
|
for (const auto& c : parts[2])
|
|
{
|
|
std::stoi(std::wstring(&c));
|
|
}
|
|
}
|
|
catch (const std::exception&)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!FancyZonesUtils::IsValidGuid(parts[3]) || parts[0].empty())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
std::wstring DeviceIdData::toString() const
|
|
{
|
|
wil::unique_cotaskmem_string virtualDesktopIdStr;
|
|
if (!SUCCEEDED(StringFromCLSID(virtualDesktopId, &virtualDesktopIdStr)))
|
|
{
|
|
return std::wstring();
|
|
}
|
|
|
|
std::wstring result = deviceName + L"_" + std::to_wstring(width) + L"_" + std::to_wstring(height) + L"_" + virtualDesktopIdStr.get();
|
|
if (!monitorId.empty())
|
|
{
|
|
result += L"_" + monitorId;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool DeviceIdData::isEqualWithNullVirtualDesktopId(const DeviceIdData& other) const
|
|
{
|
|
return deviceName.compare(other.deviceName) == 0 && width == other.width && height == other.height && (virtualDesktopId == other.virtualDesktopId || virtualDesktopId == GUID_NULL || other.virtualDesktopId == GUID_NULL) && monitorId.compare(other.monitorId) == 0;
|
|
}
|
|
}
|