Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,10 @@ private void OnStartup(object sender, StartupEventArgs e)

_themeManager = new ThemeManager(this);

FancyZonesEditorIO.ParseCommandLineArguments();
if (!FancyZonesEditorIO.ParseParams().Result)
{
FancyZonesEditorIO.ParseCommandLineArguments();
}

var parseResult = FancyZonesEditorIO.ParseZoneSettings();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class FancyZonesEditorIO

// Non-localizable strings: Files
private const string ZonesSettingsFile = "\\Microsoft\\PowerToys\\FancyZones\\zones-settings.json";
private const string ParamsFile = "\\Microsoft\\PowerToys\\FancyZones\\editor-parameters.json";

// Non-localizable string: Multi-monitor id
private const string MultiMonitorId = "FancyZones#MultiMonitorDevice";
Expand All @@ -39,6 +40,8 @@ public class FancyZonesEditorIO

public string FancyZonesSettingsFile { get; private set; }

public string FancyZonesEditorParamsFile { get; private set; }

private enum CmdArgs
{
PowerToysPID = 0,
Expand All @@ -53,27 +56,29 @@ private enum CmdArgs

private struct NativeMonitorData
{
public string Id { get; set; }
public string MonitorId { get; set; }

public int Dpi { get; set; }

public int X { get; set; }
public int LeftCoordinate { get; set; }

public int TopCoordinate { get; set; }

public int Y { get; set; }
public bool IsSelected { get; set; }

public override string ToString()
{
var sb = new StringBuilder();

sb.Append("ID: ");
sb.AppendLine(Id);
sb.AppendLine(MonitorId);
sb.Append("DPI: ");
sb.AppendLine(Dpi.ToString());

sb.Append("X: ");
sb.AppendLine(X.ToString());
sb.AppendLine(LeftCoordinate.ToString());
sb.Append("Y: ");
sb.AppendLine(Y.ToString());
sb.AppendLine(TopCoordinate.ToString());

return sb.ToString();
}
Expand Down Expand Up @@ -152,6 +157,15 @@ private struct ZoneSettingsWrapper
public List<CustomLayoutWrapper> CustomZoneSets { get; set; }
}

private struct EditorParams
{
public int ProcessId { get; set; }

public bool SpanZonesAcrossMonitors { get; set; }

public List<NativeMonitorData> Monitors { get; set; }
}

public struct ParsingResult
{
public bool Result { get; }
Expand All @@ -172,6 +186,7 @@ public FancyZonesEditorIO()
{
var localAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
FancyZonesSettingsFile = localAppDataDir + ZonesSettingsFile;
FancyZonesEditorParamsFile = localAppDataDir + ParamsFile;
}

// All strings in this function shouldn't be localized.
Expand Down Expand Up @@ -239,14 +254,14 @@ public static void ParseCommandLineArguments()
for (int i = 0; i < count; i++)
{
var nativeData = default(NativeMonitorData);
nativeData.Id = argsParts[(int)CmdArgs.MonitorId + (i * monitorArgsCount)];
nativeData.MonitorId = argsParts[(int)CmdArgs.MonitorId + (i * monitorArgsCount)];
nativeData.Dpi = int.Parse(argsParts[(int)CmdArgs.DPI + (i * monitorArgsCount)]);
nativeData.X = int.Parse(argsParts[(int)CmdArgs.MonitorLeft + (i * monitorArgsCount)]);
nativeData.Y = int.Parse(argsParts[(int)CmdArgs.MonitorTop + (i * monitorArgsCount)]);
nativeData.LeftCoordinate = int.Parse(argsParts[(int)CmdArgs.MonitorLeft + (i * monitorArgsCount)]);
nativeData.TopCoordinate = int.Parse(argsParts[(int)CmdArgs.MonitorTop + (i * monitorArgsCount)]);

nativeMonitorData.Add(nativeData);

if (nativeData.X == 0 && nativeData.Y == 0)
if (nativeData.LeftCoordinate == 0 && nativeData.TopCoordinate == 0)
{
primaryMonitorDPI = nativeData.Dpi;
}
Expand All @@ -266,15 +281,15 @@ public static void ParseCommandLineArguments()
{
foreach (NativeMonitorData nativeData in nativeMonitorData)
{
var splittedId = nativeData.Id.Split('_');
var splittedId = nativeData.MonitorId.Split('_');
int width = int.Parse(splittedId[1]);
int height = int.Parse(splittedId[2]);

Rect bounds = new Rect(nativeData.X, nativeData.Y, width, height);
bool isPrimary = nativeData.X == 0 && nativeData.Y == 0;
Rect bounds = new Rect(nativeData.LeftCoordinate, nativeData.TopCoordinate, width, height);
bool isPrimary = nativeData.LeftCoordinate == 0 && nativeData.TopCoordinate == 0;

Monitor monitor = new Monitor(bounds, bounds, isPrimary);
monitor.Device.Id = nativeData.Id;
monitor.Device.Id = nativeData.MonitorId;
monitor.Device.Dpi = nativeData.Dpi;

monitors.Add(monitor);
Expand All @@ -293,10 +308,10 @@ public static void ParseCommandLineArguments()
foreach (NativeMonitorData nativeData in nativeMonitorData)
{
// Can't do an exact match since the rounding algorithm used by the framework is different from ours
if (scaledBoundX >= (nativeData.X - 1) && scaledBoundX <= (nativeData.X + 1) &&
scaledBoundY >= (nativeData.Y - 1) && scaledBoundY <= (nativeData.Y + 1))
if (scaledBoundX >= (nativeData.LeftCoordinate - 1) && scaledBoundX <= (nativeData.LeftCoordinate + 1) &&
scaledBoundY >= (nativeData.TopCoordinate - 1) && scaledBoundY <= (nativeData.TopCoordinate + 1))
{
monitor.Device.Id = nativeData.Id;
monitor.Device.Id = nativeData.MonitorId;
monitor.Device.Dpi = nativeData.Dpi;
matchFound = true;
break;
Expand Down Expand Up @@ -329,6 +344,111 @@ public static void ParseCommandLineArguments()
}
}

public ParsingResult ParseParams()
{
if (_fileSystem.File.Exists(FancyZonesEditorParamsFile))
{
string data = string.Empty;

try
{
data = ReadFile(FancyZonesEditorParamsFile);
EditorParams editorParams = JsonSerializer.Deserialize<EditorParams>(data, _options);

// Process ID
App.PowerToysPID = editorParams.ProcessId;

// Span zones across monitors
App.Overlay.SpanZonesAcrossMonitors = editorParams.SpanZonesAcrossMonitors;

if (!App.Overlay.SpanZonesAcrossMonitors)
{
// Monitors count
if (editorParams.Monitors.Count != App.Overlay.DesktopsCount)
{
MessageBox.Show(Properties.Resources.Error_Invalid_Arguments, Properties.Resources.Error_Message_Box_Title);
((App)Application.Current).Shutdown();
}

string targetMonitorName = string.Empty;

double primaryMonitorDPI = 96f;
double minimalUsedMonitorDPI = double.MaxValue;
foreach (NativeMonitorData nativeData in editorParams.Monitors)
{
if (nativeData.LeftCoordinate == 0 && nativeData.TopCoordinate == 0)
{
primaryMonitorDPI = nativeData.Dpi;
}

if (minimalUsedMonitorDPI > nativeData.Dpi)
{
minimalUsedMonitorDPI = nativeData.Dpi;
}

if (nativeData.IsSelected)
{
targetMonitorName = nativeData.MonitorId;
}
}

var monitors = App.Overlay.Monitors;
double identifyScaleFactor = minimalUsedMonitorDPI / primaryMonitorDPI;
double scaleFactor = 96f / primaryMonitorDPI;

// Update monitors data
foreach (Monitor monitor in monitors)
{
bool matchFound = false;
monitor.Scale(scaleFactor);

double scaledBoundX = (int)(monitor.Device.UnscaledBounds.X * identifyScaleFactor);
double scaledBoundY = (int)(monitor.Device.UnscaledBounds.Y * identifyScaleFactor);

foreach (NativeMonitorData nativeData in editorParams.Monitors)
{
// Can't do an exact match since the rounding algorithm used by the framework is different from ours
if (scaledBoundX >= (nativeData.LeftCoordinate - 1) && scaledBoundX <= (nativeData.LeftCoordinate + 1) &&
scaledBoundY >= (nativeData.TopCoordinate - 1) && scaledBoundY <= (nativeData.TopCoordinate + 1))
{
monitor.Device.Id = nativeData.MonitorId;
monitor.Device.Dpi = nativeData.Dpi;
matchFound = true;
break;
}
}

if (matchFound == false)
{
MessageBox.Show(string.Format(Properties.Resources.Error_Monitor_Match_Not_Found, monitor.Device.UnscaledBounds.ToString()));
}
}

// Set active desktop
for (int i = 0; i < monitors.Count; i++)
{
var monitor = monitors[i];
if (monitor.Device.Id == targetMonitorName)
{
App.Overlay.CurrentDesktop = i;
break;
}
}
}
}
catch (Exception ex)
{
return new ParsingResult(false, ex.Message, data);
}

return new ParsingResult(true);
}
else
{
return new ParsingResult(false);
}
}

public ParsingResult ParseZoneSettings()
{
if (_fileSystem.File.Exists(FancyZonesSettingsFile))
Expand All @@ -338,7 +458,7 @@ public ParsingResult ParseZoneSettings()

try
{
settingsString = ReadZoneSettings(FancyZonesSettingsFile);
settingsString = ReadFile(FancyZonesSettingsFile);
zoneSettings = JsonSerializer.Deserialize<ZoneSettingsWrapper>(settingsString, _options);
}
catch (Exception ex)
Expand Down Expand Up @@ -493,7 +613,7 @@ public void SerializeZoneSettings()
}
}

private string ReadZoneSettings(string fileName)
private string ReadFile(string fileName)
{
Stream inputStream = _fileSystem.File.Open(fileName, FileMode.Open);
StreamReader reader = new StreamReader(inputStream);
Expand Down
26 changes: 11 additions & 15 deletions src/modules/fancyzones/lib/FancyZones.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,12 @@ void FancyZones::ToggleEditor() noexcept
return;
}

wil::unique_cotaskmem_string virtualDesktopId;
if (!SUCCEEDED(StringFromCLSID(m_currentDesktopId, &virtualDesktopId)))
{
return;
}

/*
* Divider: /
* Parts:
Expand All @@ -639,10 +645,8 @@ void FancyZones::ToggleEditor() noexcept
std::wstring params;
const std::wstring divider = L"/";
params += std::to_wstring(GetCurrentProcessId()) + divider; /* Process id */

const bool spanZonesAcrossMonitors = m_settings->GetSettings()->spanZonesAcrossMonitors;
params += std::to_wstring(spanZonesAcrossMonitors) + divider; /* Span zones */

std::vector<std::pair<HMONITOR, MONITORINFOEX>> allMonitors;
allMonitors = FancyZonesUtils::GetAllMonitorInfo<&MONITORINFOEX::rcWork>();

Expand All @@ -657,25 +661,15 @@ void FancyZones::ToggleEditor() noexcept
HMONITOR monitor = monitorData.first;
auto monitorInfo = monitorData.second;

std::wstring monitorId;
std::wstring deviceId = FancyZonesUtils::GetDisplayDeviceId(monitorInfo.szDevice, displayDeviceIdxMap);
wil::unique_cotaskmem_string virtualDesktopId;
if (SUCCEEDED(StringFromCLSID(m_currentDesktopId, &virtualDesktopId)))
{
monitorId = FancyZonesUtils::GenerateUniqueId(monitor, deviceId, virtualDesktopId.get());
}
else
{
continue;
}
std::wstring monitorId = FancyZonesUtils::GenerateUniqueId(monitor, deviceId, virtualDesktopId.get());

if (monitor == targetMonitor)
{
params += monitorId + divider; /* Monitor id where the Editor should be opened */
}

monitorsDataStr += std::move(monitorId) + divider; /* Monitor id */

UINT dpiX = 0;
UINT dpiY = 0;
if (GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY) == S_OK)
Expand All @@ -690,13 +684,15 @@ void FancyZones::ToggleEditor() noexcept
prevDpiY = dpiY;
}

monitorsDataStr += std::to_wstring(monitorInfo.rcMonitor.left) + divider;
monitorsDataStr += std::to_wstring(monitorInfo.rcMonitor.top) + divider;
monitorsDataStr += std::to_wstring(monitorInfo.rcMonitor.left) + divider; /* Top coordinate */
monitorsDataStr += std::to_wstring(monitorInfo.rcMonitor.top) + divider; /* Left coordinate */
}

params += std::to_wstring(allMonitors.size()) + divider; /* Monitors count */
params += monitorsDataStr;

FancyZonesDataInstance().SaveFancyZonesEditorParameters(spanZonesAcrossMonitors, virtualDesktopId.get(), targetMonitor); /* Write parameters to json file */

if (showDpiWarning)
{
// We must show the message box in a separate thread, since this code is called from a low-level
Expand Down
Loading