mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-06 03:07:04 +02:00
[FancyZones] Feature to create zone layouts spanning multiple monitors (#5289)
* Added the setting * Added a property to Editor Settings This will be used later * Fixed a bug in the previous commit * Simplified a method * Added snapping points to the editor * Simplified a method in ZoneSet * Updated ZoneSet testcases * Add a method to FancyZones / ZoneWindowHost * Almost works * The editor now launches, but FZ does not understand the results * Refactored some code * Snapping to a zone by dragging seems to work * Hotkeys seem to work * Refresh the work area handler after changing settings * Fixed zones not snapping to monitor edges when moved * Remove unused method in FancyZones.h * Fixed an issue with DPI awareness * Renamed setting to spanZonesAcrossMonitors * Renamed a function * Fixed a bug with the magnetic effect * Fix restoring window positions on layout changes
This commit is contained in:
@@ -60,8 +60,9 @@ namespace FancyZonesEditor
|
||||
/// <param name="zoneIndex">The index of the zone to track</param>
|
||||
/// <param name="isX"> Whether this is the X or Y SnappyHelper</param>
|
||||
/// <param name="mode"> One of the three modes of operation (for example: tracking left/right/both edges)</param>
|
||||
/// <param name="screenAxisOrigin"> The origin (left/top) of the screen in this (X or Y) dimension</param>
|
||||
/// <param name="screenAxisSize"> The size of the screen in this (X or Y) dimension</param>
|
||||
public SnappyHelperBase(IList<Int32Rect> zones, int zoneIndex, bool isX, ResizeMode mode, int screenAxisSize)
|
||||
public SnappyHelperBase(IList<Int32Rect> zones, int zoneIndex, bool isX, ResizeMode mode, int screenAxisOrigin, int screenAxisSize)
|
||||
{
|
||||
int zonePosition = isX ? zones[zoneIndex].X : zones[zoneIndex].Y;
|
||||
int zoneAxisSize = isX ? zones[zoneIndex].Width : zones[zoneIndex].Height;
|
||||
@@ -83,6 +84,19 @@ namespace FancyZonesEditor
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Rect singleMonitor in Settings.UsedWorkAreas)
|
||||
{
|
||||
int monitorPositionLow = (int)(isX ? singleMonitor.Left : singleMonitor.Top);
|
||||
int monitorPositionHigh = (int)(isX ? singleMonitor.Right : singleMonitor.Bottom);
|
||||
keyPositions.Add(monitorPositionLow - screenAxisOrigin);
|
||||
keyPositions.Add(monitorPositionHigh - screenAxisOrigin);
|
||||
if (mode == ResizeMode.BothEdges)
|
||||
{
|
||||
keyPositions.Add(monitorPositionLow - screenAxisOrigin - zoneAxisSize);
|
||||
keyPositions.Add(monitorPositionHigh - screenAxisOrigin - zoneAxisSize);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove duplicates and sort
|
||||
keyPositions.Sort();
|
||||
Snaps = new List<int>();
|
||||
@@ -143,8 +157,8 @@ namespace FancyZonesEditor
|
||||
get => (int)(0.08 * ScreenW);
|
||||
}
|
||||
|
||||
public SnappyHelperMagnetic(IList<Int32Rect> zones, int zoneIndex, bool isX, ResizeMode mode, int screenAxisSize)
|
||||
: base(zones, zoneIndex, isX, mode, screenAxisSize)
|
||||
public SnappyHelperMagnetic(IList<Int32Rect> zones, int zoneIndex, bool isX, ResizeMode mode, int screenAxisOrigin, int screenAxisSize)
|
||||
: base(zones, zoneIndex, isX, mode, screenAxisOrigin, screenAxisSize)
|
||||
{
|
||||
freePosition = Position;
|
||||
magnetZoneSizes = new List<int>();
|
||||
@@ -197,9 +211,11 @@ namespace FancyZonesEditor
|
||||
private SnappyHelperBase snappyX;
|
||||
private SnappyHelperBase snappyY;
|
||||
|
||||
private SnappyHelperBase NewDefaultSnappyHelper(bool isX, ResizeMode mode, int screenAxisSize)
|
||||
private SnappyHelperBase NewDefaultSnappyHelper(bool isX, ResizeMode mode)
|
||||
{
|
||||
return new SnappyHelperMagnetic(Model.Zones, ZoneIndex, isX, mode, screenAxisSize);
|
||||
int screenAxisOrigin = (int)(isX ? Settings.WorkArea.Left : Settings.WorkArea.Top);
|
||||
int screenAxisSize = (int)(isX ? Settings.WorkArea.Width : Settings.WorkArea.Height);
|
||||
return new SnappyHelperMagnetic(Model.Zones, ZoneIndex, isX, mode, screenAxisOrigin, screenAxisSize);
|
||||
}
|
||||
|
||||
private void UpdateFromSnappyHelpers()
|
||||
@@ -287,8 +303,8 @@ namespace FancyZonesEditor
|
||||
// Corner dragging
|
||||
private void Caption_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
|
||||
{
|
||||
snappyX = NewDefaultSnappyHelper(true, ResizeMode.BothEdges, (int)Settings.WorkArea.Width);
|
||||
snappyY = NewDefaultSnappyHelper(false, ResizeMode.BothEdges, (int)Settings.WorkArea.Height);
|
||||
snappyX = NewDefaultSnappyHelper(true, ResizeMode.BothEdges);
|
||||
snappyY = NewDefaultSnappyHelper(false, ResizeMode.BothEdges);
|
||||
}
|
||||
|
||||
public CanvasLayoutModel Model { get => model; set => model = value; }
|
||||
@@ -297,50 +313,50 @@ namespace FancyZonesEditor
|
||||
|
||||
private void NWResize_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
|
||||
{
|
||||
snappyX = NewDefaultSnappyHelper(true, ResizeMode.BottomEdge, (int)Settings.WorkArea.Width);
|
||||
snappyY = NewDefaultSnappyHelper(false, ResizeMode.BottomEdge, (int)Settings.WorkArea.Height);
|
||||
snappyX = NewDefaultSnappyHelper(true, ResizeMode.BottomEdge);
|
||||
snappyY = NewDefaultSnappyHelper(false, ResizeMode.BottomEdge);
|
||||
}
|
||||
|
||||
private void NEResize_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
|
||||
{
|
||||
snappyX = NewDefaultSnappyHelper(true, ResizeMode.TopEdge, (int)Settings.WorkArea.Width);
|
||||
snappyY = NewDefaultSnappyHelper(false, ResizeMode.BottomEdge, (int)Settings.WorkArea.Height);
|
||||
snappyX = NewDefaultSnappyHelper(true, ResizeMode.TopEdge);
|
||||
snappyY = NewDefaultSnappyHelper(false, ResizeMode.BottomEdge);
|
||||
}
|
||||
|
||||
private void SWResize_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
|
||||
{
|
||||
snappyX = NewDefaultSnappyHelper(true, ResizeMode.BottomEdge, (int)Settings.WorkArea.Width);
|
||||
snappyY = NewDefaultSnappyHelper(false, ResizeMode.TopEdge, (int)Settings.WorkArea.Height);
|
||||
snappyX = NewDefaultSnappyHelper(true, ResizeMode.BottomEdge);
|
||||
snappyY = NewDefaultSnappyHelper(false, ResizeMode.TopEdge);
|
||||
}
|
||||
|
||||
private void SEResize_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
|
||||
{
|
||||
snappyX = NewDefaultSnappyHelper(true, ResizeMode.TopEdge, (int)Settings.WorkArea.Width);
|
||||
snappyY = NewDefaultSnappyHelper(false, ResizeMode.TopEdge, (int)Settings.WorkArea.Height);
|
||||
snappyX = NewDefaultSnappyHelper(true, ResizeMode.TopEdge);
|
||||
snappyY = NewDefaultSnappyHelper(false, ResizeMode.TopEdge);
|
||||
}
|
||||
|
||||
// Edge dragging
|
||||
private void NResize_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
|
||||
{
|
||||
snappyX = null;
|
||||
snappyY = NewDefaultSnappyHelper(false, ResizeMode.BottomEdge, (int)Settings.WorkArea.Height);
|
||||
snappyY = NewDefaultSnappyHelper(false, ResizeMode.BottomEdge);
|
||||
}
|
||||
|
||||
private void SResize_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
|
||||
{
|
||||
snappyX = null;
|
||||
snappyY = NewDefaultSnappyHelper(false, ResizeMode.TopEdge, (int)Settings.WorkArea.Height);
|
||||
snappyY = NewDefaultSnappyHelper(false, ResizeMode.TopEdge);
|
||||
}
|
||||
|
||||
private void WResize_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
|
||||
{
|
||||
snappyX = NewDefaultSnappyHelper(true, ResizeMode.BottomEdge, (int)Settings.WorkArea.Width);
|
||||
snappyX = NewDefaultSnappyHelper(true, ResizeMode.BottomEdge);
|
||||
snappyY = null;
|
||||
}
|
||||
|
||||
private void EResize_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
|
||||
{
|
||||
snappyX = NewDefaultSnappyHelper(true, ResizeMode.TopEdge, (int)Settings.WorkArea.Width);
|
||||
snappyX = NewDefaultSnappyHelper(true, ResizeMode.TopEdge);
|
||||
snappyY = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,6 +259,8 @@ namespace FancyZonesEditor
|
||||
|
||||
public static Rect WorkArea { get; private set; }
|
||||
|
||||
public static List<Rect> UsedWorkAreas { get; private set; }
|
||||
|
||||
public static string UniqueKey { get; private set; }
|
||||
|
||||
public static string ActiveZoneSetUUid { get; private set; }
|
||||
@@ -453,6 +455,7 @@ namespace FancyZonesEditor
|
||||
private void ParseCommandLineArgs()
|
||||
{
|
||||
WorkArea = SystemParameters.WorkArea;
|
||||
UsedWorkAreas = new List<Rect> { WorkArea };
|
||||
|
||||
string[] args = Environment.GetCommandLineArgs();
|
||||
|
||||
@@ -470,20 +473,34 @@ namespace FancyZonesEditor
|
||||
}
|
||||
else if (args.Length == 3)
|
||||
{
|
||||
var parsedLocation = args[(int)CmdArgs.WorkAreaSize].Split('_');
|
||||
if (parsedLocation.Length != 4)
|
||||
UsedWorkAreas.Clear();
|
||||
foreach (var singleMonitorString in args[(int)CmdArgs.WorkAreaSize].Split('/'))
|
||||
{
|
||||
MessageBox.Show(ErrorInvalidArgs, ErrorMessageBoxTitle);
|
||||
((App)Application.Current).Shutdown();
|
||||
var parsedLocation = singleMonitorString.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]);
|
||||
|
||||
Rect thisMonitor = new Rect(x, y, width, height);
|
||||
if (UsedWorkAreas.Count == 0)
|
||||
{
|
||||
WorkArea = thisMonitor;
|
||||
}
|
||||
else
|
||||
{
|
||||
WorkArea = Rect.Union(WorkArea, thisMonitor);
|
||||
}
|
||||
|
||||
UsedWorkAreas.Add(thisMonitor);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
int.TryParse(args[(int)CmdArgs.PowerToysPID], out _powerToysPID);
|
||||
ParseDeviceInfoData();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user