[FancyZones] Split zones-settings: devices -> applied layouts (#15779)

This commit is contained in:
Seraphima Zykova
2022-01-27 15:21:15 +03:00
committed by GitHub
parent 792a04cf48
commit 03c36b4f65
41 changed files with 1461 additions and 1362 deletions

View File

@@ -84,37 +84,32 @@ namespace FancyZonesEditor
FancyZonesEditorIO.ParseCommandLineArguments();
}
var parseResult = FancyZonesEditorIO.ParseZoneSettings();
// 10ms retry loop with 1 second timeout
if (!parseResult.Result)
{
CancellationTokenSource ts = new CancellationTokenSource();
Task t = Task.Run(() =>
{
while (!parseResult.Result && !ts.IsCancellationRequested)
{
Task.Delay(10).Wait();
parseResult = FancyZonesEditorIO.ParseZoneSettings();
}
});
try
{
bool result = t.Wait(1000, ts.Token);
ts.Cancel();
}
catch (OperationCanceledException)
{
ts.Dispose();
}
}
// Error message if parsing failed
var parseResult = FancyZonesEditorIO.ParseAppliedLayouts();
if (!parseResult.Result)
{
Logger.LogError(ParsingErrorReportTag + ": " + parseResult.Message + "; " + ParsingErrorDataTag + ": " + parseResult.MalformedData);
MessageBox.Show(parseResult.Message, FancyZonesEditor.Properties.Resources.Error_Parsing_Zones_Settings_Title, MessageBoxButton.OK);
MessageBox.Show(parseResult.Message, FancyZonesEditor.Properties.Resources.Error_Parsing_Data_Title, MessageBoxButton.OK);
}
parseResult = FancyZonesEditorIO.ParseCustomLayouts();
if (!parseResult.Result)
{
Logger.LogError(ParsingErrorReportTag + ": " + parseResult.Message + "; " + ParsingErrorDataTag + ": " + parseResult.MalformedData);
MessageBox.Show(parseResult.Message, FancyZonesEditor.Properties.Resources.Error_Parsing_Data_Title, MessageBoxButton.OK);
}
parseResult = FancyZonesEditorIO.ParseLayoutHotkeys();
if (!parseResult.Result)
{
Logger.LogError(ParsingErrorReportTag + ": " + parseResult.Message + "; " + ParsingErrorDataTag + ": " + parseResult.MalformedData);
MessageBox.Show(parseResult.Message, FancyZonesEditor.Properties.Resources.Error_Parsing_Data_Title, MessageBoxButton.OK);
}
parseResult = FancyZonesEditorIO.ParseLayoutTemplates();
if (!parseResult.Result)
{
Logger.LogError(ParsingErrorReportTag + ": " + parseResult.Message + "; " + ParsingErrorDataTag + ": " + parseResult.MalformedData);
MessageBox.Show(parseResult.Message, FancyZonesEditor.Properties.Resources.Error_Parsing_Data_Title, MessageBoxButton.OK);
}
MainWindowSettingsModel settings = ((App)Current).MainWindowSettings;

View File

@@ -33,6 +33,7 @@ namespace FancyZonesEditor
App.FancyZonesEditorIO.SerializeLayoutTemplates();
App.FancyZonesEditorIO.SerializeCustomLayouts();
App.FancyZonesEditorIO.SerializeAppliedLayouts();
Close();
}

View File

@@ -250,7 +250,7 @@ namespace FancyZonesEditor
model.Persist();
App.Overlay.SetLayoutSettings(App.Overlay.Monitors[App.Overlay.CurrentDesktop], model);
App.FancyZonesEditorIO.SerializeZoneSettings();
App.FancyZonesEditorIO.SerializeAppliedLayouts();
App.FancyZonesEditorIO.SerializeCustomLayouts();
}
@@ -272,7 +272,7 @@ namespace FancyZonesEditor
{
_settings.SetAppliedModel(model);
App.Overlay.SetLayoutSettings(App.Overlay.Monitors[App.Overlay.CurrentDesktop], model);
App.FancyZonesEditorIO.SerializeZoneSettings();
App.FancyZonesEditorIO.SerializeAppliedLayouts();
App.FancyZonesEditorIO.SerializeCustomLayouts();
}
}
@@ -282,7 +282,7 @@ namespace FancyZonesEditor
Logger.LogTrace();
CancelLayoutChanges();
App.FancyZonesEditorIO.SerializeZoneSettings();
App.FancyZonesEditorIO.SerializeAppliedLayouts();
App.FancyZonesEditorIO.SerializeCustomLayouts();
App.FancyZonesEditorIO.SerializeLayoutHotkeys();
App.FancyZonesEditorIO.SerializeLayoutTemplates();
@@ -428,7 +428,7 @@ namespace FancyZonesEditor
App.Overlay.SetLayoutSettings(App.Overlay.Monitors[App.Overlay.CurrentDesktop], model);
}
App.FancyZonesEditorIO.SerializeZoneSettings();
App.FancyZonesEditorIO.SerializeAppliedLayouts();
App.FancyZonesEditorIO.SerializeCustomLayouts();
App.FancyZonesEditorIO.SerializeLayoutTemplates();
App.FancyZonesEditorIO.SerializeLayoutHotkeys();
@@ -475,7 +475,7 @@ namespace FancyZonesEditor
}
}
App.FancyZonesEditorIO.SerializeZoneSettings();
App.FancyZonesEditorIO.SerializeAppliedLayouts();
App.FancyZonesEditorIO.SerializeCustomLayouts();
model.Delete();
}

View File

@@ -375,6 +375,15 @@ namespace FancyZonesEditor.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to An error occurred while parsing applied layouts..
/// </summary>
public static string Error_Parsing_Applied_Layouts_Message {
get {
return ResourceManager.GetString("Error_Parsing_Applied_Layouts_Message", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An error occurred while parsing custom layouts..
/// </summary>
@@ -384,6 +393,15 @@ namespace FancyZonesEditor.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Editor data parsing error..
/// </summary>
public static string Error_Parsing_Data_Title {
get {
return ResourceManager.GetString("Error_Parsing_Data_Title", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Error parsing device info data..
/// </summary>
@@ -411,24 +429,6 @@ namespace FancyZonesEditor.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to A layout that contained invalid data has been removed..
/// </summary>
public static string Error_Parsing_Zones_Settings_Message {
get {
return ResourceManager.GetString("Error_Parsing_Zones_Settings_Message", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Editor data parsing error..
/// </summary>
public static string Error_Parsing_Zones_Settings_Title {
get {
return ResourceManager.GetString("Error_Parsing_Zones_Settings_Title", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Error persisting custom layout.
/// </summary>

View File

@@ -304,11 +304,11 @@
<value>Delete zone</value>
<comment>A tooltip on a button that allows the user to delete a zone</comment>
</data>
<data name="Error_Parsing_Zones_Settings_Title" xml:space="preserve">
<data name="Error_Parsing_Data_Title" xml:space="preserve">
<value>Editor data parsing error.</value>
</data>
<data name="Error_Parsing_Zones_Settings_Message" xml:space="preserve">
<value>A layout that contained invalid data has been removed.</value>
<data name="Error_Parsing_Applied_Layouts_Message" xml:space="preserve">
<value>An error occurred while parsing applied layouts.</value>
</data>
<data name="Apply_Layout" xml:space="preserve">
<value>Apply layout</value>

View File

@@ -10,6 +10,7 @@ using System.IO;
using System.IO.Abstractions;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows;
using FancyZonesEditor.Logs;
using FancyZonesEditor.Models;
@@ -28,7 +29,7 @@ namespace FancyZonesEditor.Utils
private const string CustomJsonTag = "custom";
// Non-localizable strings: Files
private const string ZonesSettingsFile = "\\Microsoft\\PowerToys\\FancyZones\\zones-settings.json";
private const string AppliedLayoutsFile = "\\Microsoft\\PowerToys\\FancyZones\\applied-layouts.json";
private const string LayoutHotkeysFile = "\\Microsoft\\PowerToys\\FancyZones\\layout-hotkeys.json";
private const string LayoutTemplatesFile = "\\Microsoft\\PowerToys\\FancyZones\\layout-templates.json";
private const string CustomLayoutsFile = "\\Microsoft\\PowerToys\\FancyZones\\custom-layouts.json";
@@ -48,9 +49,9 @@ namespace FancyZonesEditor.Utils
WriteIndented = true,
};
private List<DeviceWrapper> _unusedDevices = new List<DeviceWrapper>();
private List<AppliedLayoutWrapper> _unusedLayouts = new List<AppliedLayoutWrapper>();
public string FancyZonesSettingsFile { get; private set; }
public string FancyZonesAppliedLayoutsFile { get; private set; }
public string FancyZonesLayoutHotkeysFile { get; private set; }
@@ -110,27 +111,33 @@ namespace FancyZonesEditor.Utils
}
}
// zones-settings: devices
private struct DeviceWrapper
// applied-layouts.json
private struct AppliedLayoutWrapper
{
public struct ActiveZoneSetWrapper
public struct LayoutWrapper
{
public string Uuid { get; set; }
public string Type { get; set; }
public bool ShowSpacing { get; set; }
public int Spacing { get; set; }
public int ZoneCount { get; set; }
public int SensitivityRadius { get; set; }
}
public string DeviceId { get; set; }
public ActiveZoneSetWrapper ActiveZoneset { get; set; }
public LayoutWrapper AppliedLayout { get; set; }
}
public bool EditorShowSpacing { get; set; }
public int EditorSpacing { get; set; }
public int EditorZoneCount { get; set; }
public int EditorSensitivityRadius { get; set; }
// applied-layouts.json
private struct AppliedLayoutsListWrapper
{
public List<AppliedLayoutWrapper> AppliedLayouts { get; set; }
}
// custom-layouts.json
@@ -228,12 +235,6 @@ namespace FancyZonesEditor.Utils
public List<LayoutHotkeyWrapper> LayoutHotkeys { get; set; }
}
// zones-settings
private struct ZoneSettingsWrapper
{
public List<DeviceWrapper> Devices { get; set; }
}
private struct EditorParams
{
public int ProcessId { get; set; }
@@ -262,7 +263,7 @@ namespace FancyZonesEditor.Utils
public FancyZonesEditorIO()
{
var localAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
FancyZonesSettingsFile = localAppDataDir + ZonesSettingsFile;
FancyZonesAppliedLayoutsFile = localAppDataDir + AppliedLayoutsFile;
FancyZonesLayoutHotkeysFile = localAppDataDir + LayoutHotkeysFile;
FancyZonesLayoutTemplatesFile = localAppDataDir + LayoutTemplatesFile;
FancyZonesCustomLayoutsFile = localAppDataDir + CustomLayoutsFile;
@@ -513,61 +514,43 @@ namespace FancyZonesEditor.Utils
}
}
public ParsingResult ParseZoneSettings()
public ParsingResult ParseAppliedLayouts()
{
Logger.LogTrace();
_unusedDevices.Clear();
_unusedLayouts.Clear();
if (_fileSystem.File.Exists(FancyZonesSettingsFile))
if (_fileSystem.File.Exists(FancyZonesAppliedLayoutsFile))
{
ZoneSettingsWrapper zoneSettings;
AppliedLayoutsListWrapper appliedLayouts;
string settingsString = string.Empty;
try
{
settingsString = ReadFile(FancyZonesSettingsFile);
zoneSettings = JsonSerializer.Deserialize<ZoneSettingsWrapper>(settingsString, _options);
settingsString = ReadFile(FancyZonesAppliedLayoutsFile);
appliedLayouts = JsonSerializer.Deserialize<AppliedLayoutsListWrapper>(settingsString, _options);
}
catch (Exception ex)
{
Logger.LogError("Zone settings parsing error", ex);
Logger.LogError("Applied layouts parsing error", ex);
return new ParsingResult(false, ex.Message, settingsString);
}
try
{
bool devicesParsingResult = SetDevices(zoneSettings.Devices);
if (!devicesParsingResult)
bool parsingResult = SetAppliedLayouts(appliedLayouts.AppliedLayouts);
if (!parsingResult)
{
return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Zones_Settings_Message, settingsString);
return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Applied_Layouts_Message, settingsString);
}
}
catch (Exception ex)
{
Logger.LogError("Zone settings parsing error", ex);
Logger.LogError("Applied layouts parsing error", ex);
return new ParsingResult(false, ex.Message, settingsString);
}
}
var parsingCustomLayoutsResult = ParseCustomLayouts();
if (!parsingCustomLayoutsResult.Result)
{
return parsingCustomLayoutsResult;
}
var parsingHotkeysResult = ParseLayoutHotkeys();
if (!parsingHotkeysResult.Result)
{
return parsingHotkeysResult;
}
var parsingTemplatesResult = ParseLayoutTemplates();
if (!parsingTemplatesResult.Result)
{
return parsingTemplatesResult;
}
return new ParsingResult(true);
}
@@ -690,14 +673,14 @@ namespace FancyZonesEditor.Utils
return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Custom_Layouts_Message);
}
public void SerializeZoneSettings()
public void SerializeAppliedLayouts()
{
Logger.LogTrace();
ZoneSettingsWrapper zoneSettings = new ZoneSettingsWrapper { };
zoneSettings.Devices = new List<DeviceWrapper>();
AppliedLayoutsListWrapper layouts = new AppliedLayoutsListWrapper { };
layouts.AppliedLayouts = new List<AppliedLayoutWrapper>();
// Serialize used devices
// Serialize used layouts
foreach (var monitor in App.Overlay.Monitors)
{
LayoutSettings zoneset = monitor.Settings;
@@ -706,35 +689,35 @@ namespace FancyZonesEditor.Utils
continue;
}
zoneSettings.Devices.Add(new DeviceWrapper
layouts.AppliedLayouts.Add(new AppliedLayoutWrapper
{
DeviceId = monitor.Device.Id,
ActiveZoneset = new DeviceWrapper.ActiveZoneSetWrapper
AppliedLayout = new AppliedLayoutWrapper.LayoutWrapper
{
Uuid = zoneset.ZonesetUuid,
Type = LayoutTypeToJsonTag(zoneset.Type),
ShowSpacing = zoneset.ShowSpacing,
Spacing = zoneset.Spacing,
ZoneCount = zoneset.ZoneCount,
SensitivityRadius = zoneset.SensitivityRadius,
},
EditorShowSpacing = zoneset.ShowSpacing,
EditorSpacing = zoneset.Spacing,
EditorZoneCount = zoneset.ZoneCount,
EditorSensitivityRadius = zoneset.SensitivityRadius,
});
}
// Serialize unused devices
foreach (var device in _unusedDevices)
// Serialize unused layouts
foreach (var device in _unusedLayouts)
{
zoneSettings.Devices.Add(device);
layouts.AppliedLayouts.Add(device);
}
try
{
string jsonString = JsonSerializer.Serialize(zoneSettings, _options);
_fileSystem.File.WriteAllText(FancyZonesSettingsFile, jsonString);
string jsonString = JsonSerializer.Serialize(layouts, _options);
_fileSystem.File.WriteAllText(FancyZonesAppliedLayoutsFile, jsonString);
}
catch (Exception ex)
{
Logger.LogError("Serialize zone settings error", ex);
Logger.LogError("Serialize applied layouts error", ex);
App.ShowExceptionMessageBox(Properties.Resources.Error_Applying_Layout, ex);
}
}
@@ -918,29 +901,45 @@ namespace FancyZonesEditor.Utils
{
Logger.LogTrace();
Stream inputStream = _fileSystem.File.Open(fileName, FileMode.Open);
using (StreamReader reader = new StreamReader(inputStream))
var attempts = 0;
while (attempts < 10)
{
string data = reader.ReadToEnd();
inputStream.Close();
return data;
try
{
Stream inputStream = _fileSystem.File.Open(fileName, FileMode.Open);
using (StreamReader reader = new StreamReader(inputStream))
{
string data = reader.ReadToEnd();
inputStream.Close();
return data;
}
}
catch (Exception)
{
Logger.LogError("File reading error, retry");
Task.Delay(10).Wait();
}
attempts++;
}
return string.Empty;
}
private bool SetDevices(List<DeviceWrapper> devices)
private bool SetAppliedLayouts(List<AppliedLayoutWrapper> layouts)
{
Logger.LogTrace();
if (devices == null)
if (layouts == null)
{
return false;
}
bool result = true;
var monitors = App.Overlay.Monitors;
foreach (var device in devices)
foreach (var layout in layouts)
{
if (device.DeviceId == null || device.DeviceId.Length == 0 || device.ActiveZoneset.Uuid == null || device.ActiveZoneset.Uuid.Length == 0)
if (layout.DeviceId == null || layout.DeviceId.Length == 0 || layout.AppliedLayout.Uuid == null || layout.AppliedLayout.Uuid.Length == 0)
{
result = false;
continue;
@@ -950,21 +949,21 @@ namespace FancyZonesEditor.Utils
foreach (Monitor monitor in monitors)
{
string deviceIdSaved = monitor.Device.Id.Substring(0, monitor.Device.Id.LastIndexOf("_"));
string deviceIdReadFromSettings = device.DeviceId.Substring(0, device.DeviceId.LastIndexOf("_"));
string deviceIdReadFromSettings = layout.DeviceId.Substring(0, layout.DeviceId.LastIndexOf("_"));
string virtualDesktopIdSaved = monitor.Device.Id.Substring(monitor.Device.Id.LastIndexOf("_") + 1);
string virtualDesktopIdReadFromSettings = device.DeviceId.Substring(device.DeviceId.LastIndexOf("_") + 1);
string virtualDesktopIdReadFromSettings = layout.DeviceId.Substring(layout.DeviceId.LastIndexOf("_") + 1);
if (deviceIdSaved == deviceIdReadFromSettings && (virtualDesktopIdSaved == virtualDesktopIdReadFromSettings || virtualDesktopIdReadFromSettings == DefaultVirtualDesktopGuid))
{
var settings = new LayoutSettings
{
ZonesetUuid = device.ActiveZoneset.Uuid,
ShowSpacing = device.EditorShowSpacing,
Spacing = device.EditorSpacing,
Type = JsonTagToLayoutType(device.ActiveZoneset.Type),
ZoneCount = device.EditorZoneCount,
SensitivityRadius = device.EditorSensitivityRadius,
ZonesetUuid = layout.AppliedLayout.Uuid,
ShowSpacing = layout.AppliedLayout.ShowSpacing,
Spacing = layout.AppliedLayout.Spacing,
Type = JsonTagToLayoutType(layout.AppliedLayout.Type),
ZoneCount = layout.AppliedLayout.ZoneCount,
SensitivityRadius = layout.AppliedLayout.SensitivityRadius,
};
monitor.Settings = settings;
@@ -975,7 +974,7 @@ namespace FancyZonesEditor.Utils
if (unused)
{
_unusedDevices.Add(device);
_unusedLayouts.Add(layout);
}
}