mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-15 11:17:53 +01:00
519 lines
21 KiB
C++
519 lines
21 KiB
C++
#include "pch.h"
|
|
#include "WorkspacesData.h"
|
|
|
|
#include <common/SettingsAPI/settings_helpers.h>
|
|
|
|
namespace NonLocalizable
|
|
{
|
|
const inline wchar_t ModuleKey[] = L"Workspaces";
|
|
}
|
|
|
|
namespace WorkspacesData
|
|
{
|
|
std::wstring WorkspacesFile()
|
|
{
|
|
std::wstring settingsFolderPath = PTSettingsHelper::get_module_save_folder_location(NonLocalizable::ModuleKey);
|
|
return settingsFolderPath + L"\\workspaces.json";
|
|
}
|
|
|
|
std::wstring TempWorkspacesFile()
|
|
{
|
|
std::wstring settingsFolderPath = PTSettingsHelper::get_module_save_folder_location(NonLocalizable::ModuleKey);
|
|
return settingsFolderPath + L"\\temp-workspaces.json";
|
|
}
|
|
|
|
RECT WorkspacesProject::Application::Position::toRect() const noexcept
|
|
{
|
|
return RECT{ .left = x, .top = y, .right = x + width, .bottom = y + height };
|
|
}
|
|
|
|
namespace WorkspacesProjectJSON
|
|
{
|
|
namespace ApplicationJSON
|
|
{
|
|
namespace PositionJSON
|
|
{
|
|
namespace NonLocalizable
|
|
{
|
|
const static wchar_t* XAxisID = L"X";
|
|
const static wchar_t* YAxisID = L"Y";
|
|
const static wchar_t* WidthID = L"width";
|
|
const static wchar_t* HeightID = L"height";
|
|
}
|
|
|
|
json::JsonObject ToJson(const WorkspacesProject::Application::Position& position)
|
|
{
|
|
json::JsonObject json{};
|
|
json.SetNamedValue(NonLocalizable::XAxisID, json::value(position.x));
|
|
json.SetNamedValue(NonLocalizable::YAxisID, json::value(position.y));
|
|
json.SetNamedValue(NonLocalizable::WidthID, json::value(position.width));
|
|
json.SetNamedValue(NonLocalizable::HeightID, json::value(position.height));
|
|
return json;
|
|
}
|
|
|
|
std::optional<WorkspacesProject::Application::Position> FromJson(const json::JsonObject& json)
|
|
{
|
|
WorkspacesProject::Application::Position result;
|
|
try
|
|
{
|
|
result.x = static_cast<int>(json.GetNamedNumber(NonLocalizable::XAxisID, 0));
|
|
result.y = static_cast<int>(json.GetNamedNumber(NonLocalizable::YAxisID, 0));
|
|
result.width = static_cast<int>(json.GetNamedNumber(NonLocalizable::WidthID, 0));
|
|
result.height = static_cast<int>(json.GetNamedNumber(NonLocalizable::HeightID, 0));
|
|
}
|
|
catch (const winrt::hresult_error&)
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
namespace NonLocalizable
|
|
{
|
|
const static wchar_t* AppNameID = L"application";
|
|
const static wchar_t* AppPathID = L"application-path";
|
|
const static wchar_t* AppPackageFullNameID = L"package-full-name";
|
|
const static wchar_t* AppUserModelId = L"app-user-model-id";
|
|
const static wchar_t* AppTitleID = L"title";
|
|
const static wchar_t* CommandLineArgsID = L"command-line-arguments";
|
|
const static wchar_t* ElevatedID = L"is-elevated";
|
|
const static wchar_t* CanLaunchElevatedID = L"can-launch-elevated";
|
|
const static wchar_t* MinimizedID = L"minimized";
|
|
const static wchar_t* MaximizedID = L"maximized";
|
|
const static wchar_t* PositionID = L"position";
|
|
const static wchar_t* MonitorID = L"monitor";
|
|
}
|
|
|
|
json::JsonObject ToJson(const WorkspacesProject::Application& data)
|
|
{
|
|
json::JsonObject json{};
|
|
json.SetNamedValue(NonLocalizable::AppNameID, json::value(data.name));
|
|
json.SetNamedValue(NonLocalizable::AppPathID, json::value(data.path));
|
|
json.SetNamedValue(NonLocalizable::AppTitleID, json::value(data.title));
|
|
json.SetNamedValue(NonLocalizable::AppPackageFullNameID, json::value(data.packageFullName));
|
|
json.SetNamedValue(NonLocalizable::AppUserModelId, json::value(data.appUserModelId));
|
|
json.SetNamedValue(NonLocalizable::CommandLineArgsID, json::value(data.commandLineArgs));
|
|
json.SetNamedValue(NonLocalizable::ElevatedID, json::value(data.isElevated));
|
|
json.SetNamedValue(NonLocalizable::CanLaunchElevatedID, json::value(data.canLaunchElevated));
|
|
json.SetNamedValue(NonLocalizable::MinimizedID, json::value(data.isMinimized));
|
|
json.SetNamedValue(NonLocalizable::MaximizedID, json::value(data.isMaximized));
|
|
json.SetNamedValue(NonLocalizable::PositionID, PositionJSON::ToJson(data.position));
|
|
json.SetNamedValue(NonLocalizable::MonitorID, json::value(data.monitor));
|
|
|
|
return json;
|
|
}
|
|
|
|
std::optional<WorkspacesProject::Application> FromJson(const json::JsonObject& json)
|
|
{
|
|
WorkspacesProject::Application result;
|
|
try
|
|
{
|
|
if (json.HasKey(NonLocalizable::AppNameID))
|
|
{
|
|
result.name = json.GetNamedString(NonLocalizable::AppNameID);
|
|
}
|
|
|
|
result.path = json.GetNamedString(NonLocalizable::AppPathID);
|
|
result.title = json.GetNamedString(NonLocalizable::AppTitleID);
|
|
if (json.HasKey(NonLocalizable::AppPackageFullNameID))
|
|
{
|
|
result.packageFullName = json.GetNamedString(NonLocalizable::AppPackageFullNameID);
|
|
}
|
|
|
|
if (json.HasKey(NonLocalizable::AppUserModelId))
|
|
{
|
|
result.appUserModelId = json.GetNamedString(NonLocalizable::AppUserModelId);
|
|
}
|
|
|
|
result.commandLineArgs = json.GetNamedString(NonLocalizable::CommandLineArgsID);
|
|
|
|
if (json.HasKey(NonLocalizable::ElevatedID))
|
|
{
|
|
result.isElevated = json.GetNamedBoolean(NonLocalizable::ElevatedID);
|
|
}
|
|
|
|
if (json.HasKey(NonLocalizable::CanLaunchElevatedID))
|
|
{
|
|
result.canLaunchElevated = json.GetNamedBoolean(NonLocalizable::CanLaunchElevatedID);
|
|
}
|
|
|
|
result.isMaximized = json.GetNamedBoolean(NonLocalizable::MaximizedID);
|
|
result.isMinimized = json.GetNamedBoolean(NonLocalizable::MinimizedID);
|
|
result.monitor = static_cast<int>(json.GetNamedNumber(NonLocalizable::MonitorID));
|
|
if (json.HasKey(NonLocalizable::PositionID))
|
|
{
|
|
auto position = PositionJSON::FromJson(json.GetNamedObject(NonLocalizable::PositionID));
|
|
if (!position.has_value())
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
result.position = position.value();
|
|
}
|
|
}
|
|
catch (const winrt::hresult_error&)
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
namespace MonitorJSON
|
|
{
|
|
namespace MonitorRectJSON
|
|
{
|
|
namespace NonLocalizable
|
|
{
|
|
const static wchar_t* TopID = L"top";
|
|
const static wchar_t* LeftID = L"left";
|
|
const static wchar_t* WidthID = L"width";
|
|
const static wchar_t* HeightID = L"height";
|
|
}
|
|
|
|
json::JsonObject ToJson(const WorkspacesProject::Monitor::MonitorRect& data)
|
|
{
|
|
json::JsonObject json{};
|
|
json.SetNamedValue(NonLocalizable::TopID, json::value(data.top));
|
|
json.SetNamedValue(NonLocalizable::LeftID, json::value(data.left));
|
|
json.SetNamedValue(NonLocalizable::WidthID, json::value(data.width));
|
|
json.SetNamedValue(NonLocalizable::HeightID, json::value(data.height));
|
|
|
|
return json;
|
|
}
|
|
|
|
std::optional<WorkspacesProject::Monitor::MonitorRect> FromJson(const json::JsonObject& json)
|
|
{
|
|
WorkspacesProject::Monitor::MonitorRect result;
|
|
try
|
|
{
|
|
result.top = static_cast<int>(json.GetNamedNumber(NonLocalizable::TopID));
|
|
result.left = static_cast<int>(json.GetNamedNumber(NonLocalizable::LeftID));
|
|
result.width = static_cast<int>(json.GetNamedNumber(NonLocalizable::WidthID));
|
|
result.height = static_cast<int>(json.GetNamedNumber(NonLocalizable::HeightID));
|
|
}
|
|
catch (const winrt::hresult_error&)
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
namespace NonLocalizable
|
|
{
|
|
const static wchar_t* MonitorID = L"id";
|
|
const static wchar_t* InstanceID = L"instance-id";
|
|
const static wchar_t* NumberID = L"monitor-number";
|
|
const static wchar_t* DpiID = L"dpi";
|
|
const static wchar_t* MonitorRectDpiAwareID = L"monitor-rect-dpi-aware";
|
|
const static wchar_t* MonitorRectDpiUnawareID = L"monitor-rect-dpi-unaware";
|
|
}
|
|
|
|
json::JsonObject ToJson(const WorkspacesProject::Monitor& data)
|
|
{
|
|
json::JsonObject json{};
|
|
json.SetNamedValue(NonLocalizable::MonitorID, json::value(data.id));
|
|
json.SetNamedValue(NonLocalizable::InstanceID, json::value(data.instanceId));
|
|
json.SetNamedValue(NonLocalizable::NumberID, json::value(data.number));
|
|
json.SetNamedValue(NonLocalizable::DpiID, json::value(data.dpi));
|
|
json.SetNamedValue(NonLocalizable::MonitorRectDpiAwareID, MonitorRectJSON::ToJson(data.monitorRectDpiAware));
|
|
json.SetNamedValue(NonLocalizable::MonitorRectDpiUnawareID, MonitorRectJSON::ToJson(data.monitorRectDpiUnaware));
|
|
|
|
return json;
|
|
}
|
|
|
|
std::optional<WorkspacesProject::Monitor> FromJson(const json::JsonObject& json)
|
|
{
|
|
WorkspacesProject::Monitor result;
|
|
try
|
|
{
|
|
result.id = json.GetNamedString(NonLocalizable::MonitorID);
|
|
result.instanceId = json.GetNamedString(NonLocalizable::InstanceID);
|
|
result.number = static_cast<int>(json.GetNamedNumber(NonLocalizable::NumberID));
|
|
result.dpi = static_cast<int>(json.GetNamedNumber(NonLocalizable::DpiID));
|
|
auto rectDpiAware = MonitorRectJSON::FromJson(json.GetNamedObject(NonLocalizable::MonitorRectDpiAwareID));
|
|
if (!rectDpiAware.has_value())
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
auto rectDpiUnaware = MonitorRectJSON::FromJson(json.GetNamedObject(NonLocalizable::MonitorRectDpiUnawareID));
|
|
if (!rectDpiUnaware.has_value())
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
result.monitorRectDpiAware = rectDpiAware.value();
|
|
result.monitorRectDpiUnaware = rectDpiUnaware.value();
|
|
}
|
|
catch (const winrt::hresult_error&)
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
namespace NonLocalizable
|
|
{
|
|
const static wchar_t* IdID = L"id";
|
|
const static wchar_t* NameID = L"name";
|
|
const static wchar_t* CreationTimeID = L"creation-time";
|
|
const static wchar_t* LastLaunchedTimeID = L"last-launched-time";
|
|
const static wchar_t* IsShortcutNeededID = L"is-shortcut-needed";
|
|
const static wchar_t* MoveExistingWindowsID = L"move-existing-windows";
|
|
const static wchar_t* MonitorConfigurationID = L"monitor-configuration";
|
|
const static wchar_t* AppsID = L"applications";
|
|
}
|
|
|
|
json::JsonObject ToJson(const WorkspacesProject& data)
|
|
{
|
|
json::JsonObject json{};
|
|
|
|
json::JsonArray appsArray{};
|
|
for (const auto& app : data.apps)
|
|
{
|
|
appsArray.Append(ApplicationJSON::ToJson(app));
|
|
}
|
|
|
|
json::JsonArray monitorsArray{};
|
|
for (const auto& monitor : data.monitors)
|
|
{
|
|
monitorsArray.Append(MonitorJSON::ToJson(monitor));
|
|
}
|
|
|
|
json.SetNamedValue(NonLocalizable::IdID, json::value(data.id));
|
|
json.SetNamedValue(NonLocalizable::NameID, json::value(data.name));
|
|
json.SetNamedValue(NonLocalizable::CreationTimeID, json::value(static_cast<long>(data.creationTime)));
|
|
if (data.lastLaunchedTime.has_value())
|
|
{
|
|
json.SetNamedValue(NonLocalizable::LastLaunchedTimeID, json::value(static_cast<long>(data.lastLaunchedTime.value())));
|
|
}
|
|
json.SetNamedValue(NonLocalizable::IsShortcutNeededID, json::value(data.isShortcutNeeded));
|
|
json.SetNamedValue(NonLocalizable::MoveExistingWindowsID, json::value(data.moveExistingWindows));
|
|
json.SetNamedValue(NonLocalizable::MonitorConfigurationID, monitorsArray);
|
|
json.SetNamedValue(NonLocalizable::AppsID, appsArray);
|
|
return json;
|
|
}
|
|
|
|
std::optional<WorkspacesProject> FromJson(const json::JsonObject& json)
|
|
{
|
|
WorkspacesProject result{};
|
|
|
|
try
|
|
{
|
|
result.id = json.GetNamedString(NonLocalizable::IdID);
|
|
result.name = json.GetNamedString(NonLocalizable::NameID);
|
|
result.creationTime = static_cast<time_t>(json.GetNamedNumber(NonLocalizable::CreationTimeID));
|
|
|
|
if (json.HasKey(NonLocalizable::LastLaunchedTimeID))
|
|
{
|
|
result.lastLaunchedTime = static_cast<time_t>(json.GetNamedNumber(NonLocalizable::LastLaunchedTimeID));
|
|
}
|
|
|
|
if (json.HasKey(NonLocalizable::IsShortcutNeededID))
|
|
{
|
|
result.isShortcutNeeded = json.GetNamedBoolean(NonLocalizable::IsShortcutNeededID);
|
|
}
|
|
|
|
if (json.HasKey(NonLocalizable::MoveExistingWindowsID))
|
|
{
|
|
result.moveExistingWindows = json.GetNamedBoolean(NonLocalizable::MoveExistingWindowsID);
|
|
}
|
|
|
|
auto appsArray = json.GetNamedArray(NonLocalizable::AppsID);
|
|
for (uint32_t i = 0; i < appsArray.Size(); ++i)
|
|
{
|
|
auto obj = ApplicationJSON::FromJson(appsArray.GetObjectAt(i));
|
|
if (!obj.has_value())
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
result.apps.push_back(obj.value());
|
|
}
|
|
|
|
auto monitorsArray = json.GetNamedArray(NonLocalizable::MonitorConfigurationID);
|
|
for (uint32_t i = 0; i < monitorsArray.Size(); ++i)
|
|
{
|
|
auto obj = MonitorJSON::FromJson(monitorsArray.GetObjectAt(i));
|
|
if (!obj.has_value())
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
result.monitors.push_back(obj.value());
|
|
}
|
|
}
|
|
catch (const winrt::hresult_error&)
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
namespace WorkspacesListJSON
|
|
{
|
|
namespace NonLocalizable
|
|
{
|
|
const static wchar_t* WorkspacesID = L"workspaces";
|
|
}
|
|
|
|
json::JsonObject ToJson(const std::vector<WorkspacesProject>& data)
|
|
{
|
|
json::JsonObject json{};
|
|
json::JsonArray projectsArray{};
|
|
|
|
for (const auto& project : data)
|
|
{
|
|
projectsArray.Append(WorkspacesProjectJSON::ToJson(project));
|
|
}
|
|
|
|
json.SetNamedValue(NonLocalizable::WorkspacesID, projectsArray);
|
|
return json;
|
|
}
|
|
|
|
std::optional<std::vector<WorkspacesProject>> FromJson(const json::JsonObject& json)
|
|
{
|
|
std::vector<WorkspacesProject> result{};
|
|
|
|
try
|
|
{
|
|
auto array = json.GetNamedArray(NonLocalizable::WorkspacesID);
|
|
for (uint32_t i = 0; i < array.Size(); ++i)
|
|
{
|
|
auto obj = WorkspacesProjectJSON::FromJson(array.GetObjectAt(i));
|
|
if (obj.has_value())
|
|
{
|
|
result.push_back(obj.value());
|
|
}
|
|
else
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
}
|
|
}
|
|
catch (const winrt::hresult_error&)
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
namespace AppLaunchInfoJSON
|
|
{
|
|
namespace NonLocalizable
|
|
{
|
|
const static wchar_t* ApplicationID = L"application";
|
|
const static wchar_t* StateID = L"state";
|
|
}
|
|
|
|
json::JsonObject ToJson(const LaunchingAppState& data)
|
|
{
|
|
json::JsonObject json{};
|
|
json.SetNamedValue(NonLocalizable::ApplicationID, WorkspacesProjectJSON::ApplicationJSON::ToJson(data.application));
|
|
json.SetNamedValue(NonLocalizable::StateID, json::value(static_cast<int>(data.state)));
|
|
return json;
|
|
}
|
|
|
|
std::optional<LaunchingAppState> FromJson(const json::JsonObject& json)
|
|
{
|
|
LaunchingAppState result{};
|
|
|
|
try
|
|
{
|
|
auto app = WorkspacesProjectJSON::ApplicationJSON::FromJson(json.GetNamedObject(NonLocalizable::ApplicationID));
|
|
if (!app.has_value())
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
result.application = app.value();
|
|
result.state = static_cast<LaunchingState>(json.GetNamedNumber(NonLocalizable::StateID));
|
|
}
|
|
catch (const winrt::hresult_error&)
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
namespace AppLaunchInfoListJSON
|
|
{
|
|
namespace NonLocalizable
|
|
{
|
|
const static wchar_t* AppLaunchInfoID = L"appLaunchInfos";
|
|
}
|
|
|
|
json::JsonObject ToJson(const LaunchingAppStateMap& data)
|
|
{
|
|
json::JsonObject json{};
|
|
json::JsonArray appLaunchInfoArray{};
|
|
for (const auto& appLaunchInfo : data)
|
|
{
|
|
appLaunchInfoArray.Append(AppLaunchInfoJSON::ToJson(appLaunchInfo.second));
|
|
}
|
|
|
|
json.SetNamedValue(NonLocalizable::AppLaunchInfoID, appLaunchInfoArray);
|
|
return json;
|
|
}
|
|
|
|
std::optional<LaunchingAppStateMap> FromJson(const json::JsonObject& json)
|
|
{
|
|
LaunchingAppStateMap result{};
|
|
|
|
try
|
|
{
|
|
auto array = json.GetNamedArray(NonLocalizable::AppLaunchInfoID);
|
|
for (uint32_t i = 0; i < array.Size(); ++i)
|
|
{
|
|
auto obj = AppLaunchInfoJSON::FromJson(array.GetObjectAt(i));
|
|
if (obj.has_value())
|
|
{
|
|
result.insert({ obj.value().application, obj.value() });
|
|
}
|
|
else
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
}
|
|
}
|
|
catch (const winrt::hresult_error&)
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
namespace AppLaunchDataJSON
|
|
{
|
|
namespace NonLocalizable
|
|
{
|
|
const static wchar_t* AppsID = L"apps";
|
|
const static wchar_t* ProcessID = L"processId";
|
|
}
|
|
|
|
json::JsonObject ToJson(const AppLaunchData& data)
|
|
{
|
|
json::JsonObject json{};
|
|
json.SetNamedValue(NonLocalizable::AppsID, AppLaunchInfoListJSON::ToJson(data.appsStateList));
|
|
json.SetNamedValue(NonLocalizable::ProcessID, json::value(data.launcherProcessID));
|
|
return json;
|
|
}
|
|
}
|
|
}
|