[FancyZones] Remove Editor tmp files paths cmd args and make Editor 'debugable' easier (#4279)

* Remove Editor cmd args - tmp files
Add 'Debug mode' startup for Editor

* Remove fixed device info string

* Move if file exist check

* Add enum to improve readability

* Introduce ParseDeviceMode enum

* Organize strings

* Move title to localizable strings
This commit is contained in:
stefansjfw 2020-07-06 17:40:25 +02:00 committed by GitHub
parent 3d623506a8
commit 70405045d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 136 additions and 105 deletions

View File

@ -154,7 +154,7 @@ namespace FancyZonesEditor.Models
try
{
string jsonString = JsonSerializer.Serialize(deletedLayouts, options);
File.WriteAllText(Settings.CustomZoneSetsTmpFile, jsonString);
File.WriteAllText(Settings.DeletedCustomZoneSetsTmpFile, jsonString);
}
catch (Exception ex)
{
@ -169,7 +169,7 @@ namespace FancyZonesEditor.Models
try
{
FileStream inputStream = File.Open(Settings.CustomZoneSetsTmpFile, FileMode.Open);
FileStream inputStream = File.Open(Settings.FancyZonesSettingsFile, FileMode.Open);
JsonDocument jsonObject = JsonDocument.Parse(inputStream, options: default);
JsonElement.ArrayEnumerator customZoneSetsEnumerator = jsonObject.RootElement.GetProperty("custom-zone-sets").EnumerateArray();

View File

@ -6,7 +6,6 @@ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Text.Json;
using System.Windows;
@ -21,13 +20,24 @@ namespace FancyZonesEditor
{
private enum CmdArgs
{
X_Y_Width_Height = 1,
ActiveZoneSetTmpFile,
AppliedZoneSetTmpFile,
CustomZoneSetsTmpFile,
WorkAreaSize = 1,
PowerToysPID,
}
private enum WorkAreaCmdArgElements
{
X = 0,
Y,
Width,
Height,
}
private enum ParseDeviceMode
{
Prod,
Debug,
}
private static CanvasLayoutModel _blankCustomModel;
private readonly CanvasLayoutModel _focusModel;
private readonly GridLayoutModel _rowsModel;
@ -43,7 +53,30 @@ namespace FancyZonesEditor
public const ushort _blankCustomModelId = 0xFFFA;
public const ushort _lastDefinedId = _blankCustomModelId;
private const int _defaultDPI = 96;
// Localizable strings
private const string ErrorMessageBoxTitle = "FancyZones Editor Error";
private const string ErrorParsingDeviceInfo = "Error parsing device info data.";
private const string ErrorInvalidArgs = "FancyZones Editor arguments are invalid.";
private const string ErrorNonStandaloneApp = "FancyZones Editor should not be run as standalone application.";
// Non-localizable strings
private const string ZonesSettingsFile = "\\Microsoft\\PowerToys\\FancyZones\\zones-settings.json";
private const string ActiveZoneSetsTmpFileName = "FancyZonesActiveZoneSets.json";
private const string AppliedZoneSetsTmpFileName = "FancyZonesAppliedZoneSets.json";
private const string DeletedCustomZoneSetsTmpFileName = "FancyZonesDeletedCustomZoneSets.json";
private const string LayoutTypeBlankStr = "blank";
private const string NullUuidStr = "null";
// DeviceInfo JSON tags
private const string DeviceIdJsonTag = "device-id";
private const string ActiveZoneSetJsonTag = "active-zoneset";
private const string UuidJsonTag = "uuid";
private const string TypeJsonTag = "type";
private const string EditorShowSpacingJsonTag = "editor-show-spacing";
private const string EditorSpacingJsonTag = "editor-spacing";
private const string EditorZoneCountJsonTag = "editor-zone-count";
// hard coded data for all the "Priority Grid" configurations that are unique to "Grid"
private static readonly byte[][] _priorityData = new byte[][]
@ -81,6 +114,15 @@ namespace FancyZonesEditor
public Settings()
{
string tmpDirPath = Path.GetTempPath();
ActiveZoneSetTmpFile = tmpDirPath + ActiveZoneSetsTmpFileName;
AppliedZoneSetTmpFile = tmpDirPath + AppliedZoneSetsTmpFileName;
DeletedCustomZoneSetsTmpFile = tmpDirPath + DeletedCustomZoneSetsTmpFileName;
var localAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
FancyZonesSettingsFile = localAppDataDir + ZonesSettingsFile;
ParseCommandLineArgs();
// Initialize the five default layout models: Focus, Columns, Rows, Grid, and PriorityGrid
@ -222,26 +264,13 @@ namespace FancyZonesEditor
public static LayoutType ActiveZoneSetLayoutType { get; private set; }
public static string ActiveZoneSetTmpFile
{
get { return _activeZoneSetTmpFile; }
}
public static string ActiveZoneSetTmpFile { get; private set; }
private static string _activeZoneSetTmpFile;
public static string AppliedZoneSetTmpFile { get; private set; }
public static string AppliedZoneSetTmpFile
{
get { return _appliedZoneSetTmpFile; }
}
public static string DeletedCustomZoneSetsTmpFile { get; private set; }
private static string _appliedZoneSetTmpFile;
public static string CustomZoneSetsTmpFile
{
get { return _customZoneSetsTmpFile; }
}
private static string _customZoneSetsTmpFile;
public static string FancyZonesSettingsFile { get; private set; }
public static int PowerToysPID
{
@ -357,20 +386,27 @@ namespace FancyZonesEditor
}
}
private void ParseDeviceInfoData()
private void ParseDeviceInfoData(ParseDeviceMode mode = ParseDeviceMode.Prod)
{
try
{
FileStream inputStream = File.Open(Settings.ActiveZoneSetTmpFile, FileMode.Open);
var jsonObject = JsonDocument.Parse(inputStream, options: default).RootElement;
string layoutType = LayoutTypeBlankStr;
ActiveZoneSetUUid = NullUuidStr;
JsonElement jsonObject = default(JsonElement);
UniqueKey = jsonObject.GetProperty("device-id").GetString();
ActiveZoneSetUUid = jsonObject.GetProperty("active-zoneset").GetProperty("uuid").GetString();
string layoutType = jsonObject.GetProperty("active-zoneset").GetProperty("type").GetString();
if (ActiveZoneSetUUid == "null" || layoutType == "blank")
if (File.Exists(Settings.ActiveZoneSetTmpFile))
{
// Default selection is Focus
FileStream inputStream = File.Open(Settings.ActiveZoneSetTmpFile, FileMode.Open);
jsonObject = JsonDocument.Parse(inputStream, options: default).RootElement;
inputStream.Close();
UniqueKey = jsonObject.GetProperty(DeviceIdJsonTag).GetString();
ActiveZoneSetUUid = jsonObject.GetProperty(ActiveZoneSetJsonTag).GetProperty(UuidJsonTag).GetString();
layoutType = jsonObject.GetProperty(ActiveZoneSetJsonTag).GetProperty(TypeJsonTag).GetString();
}
if (mode == ParseDeviceMode.Debug || ActiveZoneSetUUid == NullUuidStr || layoutType == LayoutTypeBlankStr)
{
// Default or there is no active layout on current device
ActiveZoneSetLayoutType = LayoutType.Focus;
_showSpacing = true;
_spacing = 16;
@ -400,16 +436,14 @@ namespace FancyZonesEditor
break;
}
_showSpacing = jsonObject.GetProperty("editor-show-spacing").GetBoolean();
_spacing = jsonObject.GetProperty("editor-spacing").GetInt32();
_zoneCount = jsonObject.GetProperty("editor-zone-count").GetInt32();
_showSpacing = jsonObject.GetProperty(EditorShowSpacingJsonTag).GetBoolean();
_spacing = jsonObject.GetProperty(EditorSpacingJsonTag).GetInt32();
_zoneCount = jsonObject.GetProperty(EditorZoneCountJsonTag).GetInt32();
}
inputStream.Close();
}
catch (Exception ex)
{
LayoutModel.ShowExceptionMessageBox("Error parsing device info data", ex);
LayoutModel.ShowExceptionMessageBox(ErrorParsingDeviceInfo, ex);
}
}
@ -418,24 +452,43 @@ namespace FancyZonesEditor
WorkArea = SystemParameters.WorkArea;
string[] args = Environment.GetCommandLineArgs();
if (args.Length == 6)
if (args.Length == 2)
{
var parsedLocation = args[(int)CmdArgs.X_Y_Width_Height].Split('_');
var x = int.Parse(parsedLocation[0]);
var y = int.Parse(parsedLocation[1]);
var width = int.Parse(parsedLocation[2]);
var height = int.Parse(parsedLocation[3]);
if (args[1].Equals("Debug"))
{
ParseDeviceInfoData(ParseDeviceMode.Debug);
}
else
{
MessageBox.Show(ErrorInvalidArgs, ErrorMessageBoxTitle);
((App)Application.Current).Shutdown();
}
}
else if (args.Length == 3)
{
var parsedLocation = args[(int)CmdArgs.WorkAreaSize].Split('_');
if (parsedLocation.Length != 4)
{
MessageBox.Show(ErrorInvalidArgs, ErrorMessageBoxTitle);
((App)Application.Current).Shutdown();
}
var x = int.Parse(parsedLocation[(int)WorkAreaCmdArgElements.X]);
var y = int.Parse(parsedLocation[(int)WorkAreaCmdArgElements.Y]);
var width = int.Parse(parsedLocation[(int)WorkAreaCmdArgElements.Width]);
var height = int.Parse(parsedLocation[(int)WorkAreaCmdArgElements.Height]);
WorkArea = new Rect(x, y, width, height);
_activeZoneSetTmpFile = args[(int)CmdArgs.ActiveZoneSetTmpFile];
_appliedZoneSetTmpFile = args[(int)CmdArgs.AppliedZoneSetTmpFile];
_customZoneSetsTmpFile = args[(int)CmdArgs.CustomZoneSetsTmpFile];
int.TryParse(args[(int)CmdArgs.PowerToysPID], out _powerToysPID);
ParseDeviceInfoData();
}
else
{
MessageBox.Show(ErrorNonStandaloneApp, ErrorMessageBoxTitle);
((App)Application.Current).Shutdown();
}
}
public IList<LayoutModel> DefaultModels { get; }

View File

@ -552,7 +552,6 @@ void FancyZones::ToggleEditor() noexcept
std::to_wstring(height);
const auto& fancyZonesData = JSONHelpers::FancyZonesDataInstance();
fancyZonesData.CustomZoneSetsToJsonFile(ZoneWindowUtils::GetCustomZoneSetsTmpPath());
const auto deviceInfo = fancyZonesData.FindDeviceInfo(zoneWindow->UniqueId());
if (!deviceInfo.has_value())
@ -565,10 +564,7 @@ void FancyZones::ToggleEditor() noexcept
const std::wstring params =
/*1*/ editorLocation + L" " +
/*2*/ L"\"" + ZoneWindowUtils::GetActiveZoneSetTmpPath() + L"\" " +
/*3*/ L"\"" + ZoneWindowUtils::GetAppliedZoneSetTmpPath() + L"\" " +
/*4*/ L"\"" + ZoneWindowUtils::GetCustomZoneSetsTmpPath() + L"\" " +
/*5*/ L"\"" + std::to_wstring(GetCurrentProcessId()) + L"\"";
/*2*/ L"\"" + std::to_wstring(GetCurrentProcessId()) + L"\"";
SHELLEXECUTEINFO sei{ sizeof(sei) };
sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI };
@ -990,7 +986,7 @@ void FancyZones::OnEditorExitEvent() noexcept
{
// Collect information about changes in zone layout after editor exited.
JSONHelpers::FancyZonesDataInstance().ParseDeviceInfoFromTmpFile(ZoneWindowUtils::GetActiveZoneSetTmpPath());
JSONHelpers::FancyZonesDataInstance().ParseDeletedCustomZoneSetsFromTmpFile(ZoneWindowUtils::GetCustomZoneSetsTmpPath());
JSONHelpers::FancyZonesDataInstance().ParseDeletedCustomZoneSetsFromTmpFile(ZoneWindowUtils::GetDeletedCustomZoneSetsTmpPath());
JSONHelpers::FancyZonesDataInstance().ParseCustomZoneSetFromTmpFile(ZoneWindowUtils::GetAppliedZoneSetTmpPath());
JSONHelpers::FancyZonesDataInstance().SaveFancyZonesData();

View File

@ -763,15 +763,6 @@ namespace JSONHelpers
return customZoneSetsJSON;
}
void FancyZonesData::CustomZoneSetsToJsonFile(std::wstring_view filePath) const
{
std::scoped_lock lock{ dataLock };
const auto& customZoneSetsJson = SerializeCustomZoneSets();
json::JsonObject root{};
root.SetNamedValue(L"custom-zone-sets", customZoneSetsJson);
json::to_file(filePath, root);
}
void FancyZonesData::LoadFancyZonesData()
{
std::scoped_lock lock{ dataLock };

View File

@ -258,7 +258,6 @@ namespace JSONHelpers
json::JsonArray SerializeDeviceInfos() const;
bool ParseCustomZoneSets(const json::JsonObject& fancyZonesDataJSON);
json::JsonArray SerializeCustomZoneSets() const;
void CustomZoneSetsToJsonFile(std::wstring_view filePath) const;
void LoadFancyZonesData();
void SaveFancyZonesData() const;

View File

@ -8,60 +8,52 @@
#include <ShellScalingApi.h>
#include <mutex>
#include <fileapi.h>
#include <gdiplus.h>
namespace ZoneWindowUtils
{
const std::wstring& GetActiveZoneSetTmpPath()
const wchar_t ActiveZoneSetsTmpFileName[] = L"FancyZonesActiveZoneSets.json";
const wchar_t AppliedZoneSetsTmpFileName[] = L"FancyZonesAppliedZoneSets.json";
const wchar_t DeletedCustomZoneSetsTmpFileName[] = L"FancyZonesDeletedCustomZoneSets.json";
const std::wstring& GetTempDirPath()
{
static std::wstring activeZoneSetTmpFileName;
static std::wstring tmpDirPath;
static std::once_flag flag;
std::call_once(flag, []() {
wchar_t fileName[L_tmpnam_s];
wchar_t buffer[MAX_PATH];
if (_wtmpnam_s(fileName, L_tmpnam_s) != 0)
abort();
auto charsWritten = GetTempPath(MAX_PATH, buffer);
if (charsWritten > MAX_PATH || (charsWritten == 0))
{
abort();
}
activeZoneSetTmpFileName = std::wstring{ fileName };
tmpDirPath = std::wstring{ buffer };
});
return tmpDirPath;
}
const std::wstring& GetActiveZoneSetTmpPath()
{
static std::wstring activeZoneSetTmpFileName = GetTempDirPath() + ActiveZoneSetsTmpFileName;
return activeZoneSetTmpFileName;
}
const std::wstring& GetAppliedZoneSetTmpPath()
{
static std::wstring appliedZoneSetTmpFileName;
static std::once_flag flag;
std::call_once(flag, []() {
wchar_t fileName[L_tmpnam_s];
if (_wtmpnam_s(fileName, L_tmpnam_s) != 0)
abort();
appliedZoneSetTmpFileName = std::wstring{ fileName };
});
static std::wstring appliedZoneSetTmpFileName = GetTempDirPath() + AppliedZoneSetsTmpFileName;
return appliedZoneSetTmpFileName;
}
const std::wstring& GetCustomZoneSetsTmpPath()
const std::wstring& GetDeletedCustomZoneSetsTmpPath()
{
static std::wstring customZoneSetsTmpFileName;
static std::once_flag flag;
std::call_once(flag, []() {
wchar_t fileName[L_tmpnam_s];
if (_wtmpnam_s(fileName, L_tmpnam_s) != 0)
abort();
customZoneSetsTmpFileName = std::wstring{ fileName };
});
return customZoneSetsTmpFileName;
static std::wstring deletedCustomZoneSetsTmpFileName = GetTempDirPath() + DeletedCustomZoneSetsTmpFileName;
return deletedCustomZoneSetsTmpFileName;
}
std::wstring GenerateUniqueId(HMONITOR monitor, PCWSTR deviceId, PCWSTR virtualDesktopId)

View File

@ -6,7 +6,7 @@ namespace ZoneWindowUtils
{
const std::wstring& GetActiveZoneSetTmpPath();
const std::wstring& GetAppliedZoneSetTmpPath();
const std::wstring& GetCustomZoneSetsTmpPath();
const std::wstring& GetDeletedCustomZoneSetsTmpPath();
std::wstring GenerateUniqueId(HMONITOR monitor, PCWSTR deviceId, PCWSTR virtualDesktopId);
}

View File

@ -86,11 +86,11 @@ namespace FancyZonesUnitTests
Assert::IsFalse(ZoneWindowUtils::GetActiveZoneSetTmpPath().empty());
Assert::IsFalse(ZoneWindowUtils::GetAppliedZoneSetTmpPath().empty());
Assert::IsFalse(ZoneWindowUtils::GetCustomZoneSetsTmpPath().empty());
Assert::IsFalse(ZoneWindowUtils::GetDeletedCustomZoneSetsTmpPath().empty());
Assert::IsFalse(std::filesystem::exists(ZoneWindowUtils::GetActiveZoneSetTmpPath()));
Assert::IsFalse(std::filesystem::exists(ZoneWindowUtils::GetAppliedZoneSetTmpPath()));
Assert::IsFalse(std::filesystem::exists(ZoneWindowUtils::GetCustomZoneSetsTmpPath()));
Assert::IsFalse(std::filesystem::exists(ZoneWindowUtils::GetDeletedCustomZoneSetsTmpPath()));
m_fancyZonesData.SetSettingsModulePath(L"FancyZonesUnitTests");
m_fancyZonesData.clear_data();
@ -101,7 +101,7 @@ namespace FancyZonesUnitTests
//cleanup temp files if were created
std::filesystem::remove(ZoneWindowUtils::GetActiveZoneSetTmpPath());
std::filesystem::remove(ZoneWindowUtils::GetAppliedZoneSetTmpPath());
std::filesystem::remove(ZoneWindowUtils::GetCustomZoneSetsTmpPath());
std::filesystem::remove(ZoneWindowUtils::GetDeletedCustomZoneSetsTmpPath());
m_zoneWindow = nullptr;
}
@ -295,7 +295,7 @@ namespace FancyZonesUnitTests
//save required data
const auto activeZoneSetTempPath = ZoneWindowUtils::GetActiveZoneSetTmpPath();
const auto appliedZoneSetTempPath = ZoneWindowUtils::GetAppliedZoneSetTmpPath();
const auto deletedZonesTempPath = ZoneWindowUtils::GetCustomZoneSetsTmpPath();
const auto deletedZonesTempPath = ZoneWindowUtils::GetDeletedCustomZoneSetsTmpPath();
const ZoneSetLayoutType type = ZoneSetLayoutType::Custom;
const auto customSetGuid = Helpers::CreateGuidString();
@ -341,7 +341,7 @@ namespace FancyZonesUnitTests
//save required data
const auto activeZoneSetTempPath = ZoneWindowUtils::GetActiveZoneSetTmpPath();
const auto appliedZoneSetTempPath = ZoneWindowUtils::GetAppliedZoneSetTmpPath();
const auto deletedZonesTempPath = ZoneWindowUtils::GetCustomZoneSetsTmpPath();
const auto deletedZonesTempPath = ZoneWindowUtils::GetDeletedCustomZoneSetsTmpPath();
const ZoneSetLayoutType type = ZoneSetLayoutType::Custom;
const auto customSetGuid = Helpers::CreateGuidString();