doc/devdocs/modules/fancyzones.md
Public overview - Microsoft Learn
FancyZones is a window manager utility that allows users to create custom layouts for organizing windows on their screen.
FancyZones consists of several interconnected components:
FancyZones is divided into several projects:
FancyZonesApp.h/cpp:
Data Management Files:
Core Functionality:
UI Components:
Data Components:
C:\Users\[username]\AppData\Local\Microsoft\PowerToys\FancyZonesFancyZones::MoveSizeUpdate functionWindowMouseSnap::MoveSizeEnd() functionFancyZones::MoveSizeUpdate functiongit clone https://github.com/microsoft/PowerToys.git
PowerToys.slnx in Visual StudioError: "The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0."
Solution: Launch the FancyZones Editor once through PowerToys Settings UI. Running the Editor directly within the project will not initialize the required configuration files.
UI tests are implemented using Windows Application Driver.
C:\Program Files (x86)\Windows Application Driver); in this case, it'll be launched automatically during tests.PowerToys.slnx in Visual Studio and build the solution.Test > Test Explorer or Ctrl+E, T).Note: notifications or other application windows, that are shown above the window under test, can disrupt the testing process.
FancyZones is currently undergoing a UI Test migration process to improve automated testing coverage. You can track the progress of this migration at:
FancyZones UI Test Migration Progress
Test > Test Explorer or Ctrl+E, T)All test cases require pre-configured user data and must reset this data before each test.
Required User Data Files:
ApplyLayoutTest.cs
CopyLayoutTests.cs
CreateLayoutTests.cs
CustomLayoutsTests.cs
DefaultLayoutsTest.cs
DeleteLayoutTests.cs
EditLayoutTests.cs
FirstLaunchTest.cs
LayoutHotkeysTests.cs
TemplateLayoutsTests.cs
LayoutApplyHotKeyTests.cs
While working on tests, you may need tools to view element accessibility data:
Note: Close helper tools while running tests. Overlapping windows can affect test results.
The optimal solution for this bug is to first comment on the user's usage issue. Let them correctly use the FancyZones feature before making further judgments. If the issue persists after proper usage, then investigate whether it's a code issue or a problem with the game itself.
To demonstrate a debugging example, I will assume it's a code issue, specifically an issue with the Editor. Please see the following debug process.
Let's first locate the corresponding code. Since the error is in the Editor, we'll start by checking the FancyZonesEditor shown in the image.
However, I currently don't know where the code for this specific UI element in the Editor is located.
We now have two approaches to find the exact code location.
First approach:
The main XAML page is usually named App.xaml or MainWindow.xaml. Let's start by locating these two files in the FancyZones Editor. Upon reviewing their contents, we find that App.xaml is primarily a wrapper file and doesn't contain much UI code. Therefore, it's highly likely that the UI code is located in MainWindow.xaml. In the preview of MainWindow.xaml, we can also see a rough outline of the UI elements.
By searching for "monitor", we found that only lines 82 and 338 contain the string "monitor".
Then, upon reviewing the code, we found that the line at 82 is part of a template. The UI element we're looking for is located within the code block around line 338.
Second approach:
We can use the AccessibilityInsights tool to inspect the specific information of the corresponding UI element.
However, the current UI element does not have an AutomationId. Let's check whether its parent or child nodes have an AutomationId value. (In fact, using ClassName could also help locate it, but elements with the same ClassName might be numerous, making AutomationId a more accurate option.) We found that the parent node "List View" has an AutomationId value. Copy this value and search for it in the code.
Accurately located at line 338.
Now that we've found the code for the UI element, let's look at where the size data for this UI element comes from. First, the text of this Text element is bound within the MonitorItemTemplate. The name of this Text element is ResolutionText, and it binds to a data property named Dimensions.
Search for code related to Dimensions across all projects in FancyZones.
We found that this string corresponds to a variable. However, the return value differs in Debug mode, so let's first examine the logic in Release mode.
We found that the variable ScreenBoundsWidth is located in the constructor of MonitorInfoModel.
Then, by searching for MonitorInfoModel, we found that this class is instantiated in the constructor of the MonitorViewModel class.
The width and height of the monitor, which are crucial, are also assigned at this point. Let's continue by checking where the data in App.Overlay.Monitors is initialized.
My idea is to examine all references to the Monitors variable and identify the initialization point based on those references.
Finally, by tracing the Add function of Monitors, we found the AddMonitor() method. This method is only called by ParseParams(), which confirms that the data originates from there.
However, by examining the context around the AddMonitor() function, we can see that the data comes from the editor-parameters.json file. Next, we will continue to investigate how this file is initialized and modified.
By searching, we found that the editor-parameters.json file has write functions in both the Editor and FancyZones projects.
The display information is retrieved through the following call stack:
UpdateWorkAreas() → IdentifyMonitors() → GetDisplays() → EnumDisplayDevicesW().
How was the UpdateWorkAreas() function identified?
It was discovered by searching for EditorParameters and noticing that when the save function is called on EditorParameters, the parameter passed is m_workAreaConfiguration.
Then, by checking the initialization location of the m_workAreaConfiguration variable, we found that it is initialized inside UpdateWorkAreas.
With this, we have successfully identified the source of the monitor resolution data displayed in the Editor's Monitors section.
Familiarize yourself with the module code through the current tasks at hand.
Bug:Issues · microsoftPowerToys
UITest Code:
Task 57329836: PowerToys UI Test FancyZone UI Test Override Windows Snap-1 - Boards
Task 57329843: PowerToys UI Test FancyZone UI Test Override Windows Snap-2 - Boards
Task 57329845: PowerToys UI Test FancyZone UI Test Override Windows Snap-3 - Boards
Task 56940387: PowerToys UI Test FancyZone UI Test Override Windows Snap-4 - Boards
UI Test Check List:
PowerToys/doc/releases/tests-checklist-template.md at releaseChecklist · microsoft/PowerToys](https://github.com/microsoft/PowerToys/blob/releaseChecklist/doc/releases/tests-checklist-template.md)
If you encounter this situation, you need to launch the FancyZones Editor once in the powertoys settings UI:
The reason is that running the Editor directly within the project will not initialize various configuration files.
There is no central configuration handler.
Editor read/write config data handler is in FancyZonesEditorCommon project.
FancyZones cpp project read/write config data handler is in FancyZonesLib project.
However, the files write and read those are C:\Users\“xxxxxx”\AppData\Local\Microsoft\PowerToys\FancyZones
You can think of the editor as a visual config editor, which is most of its functionality. Another feature is used to set the layout for the monitor displays.
When the Editor starts, it will load the config data, and when FancyZones starts, it will also load the config data. After the Editor updates the config data, it will send a data update event, and FancyZones will refresh the current data in memory upon receiving the event.
About monitor detection you can find "FancyZones::MoveSizeUpdate" function.
I believe that in the case without DPI scaling, FancyZones retrieves the window's position and does not need to know what the mouse's DPI scaling is like. If you are referring to window scaling, it is called through the system interface, and you can see the detailed code in "WindowMouseSnap::MoveSizeEnd()" function.
In "FancyZones::MoveSizeUpdate" function.
Test samples: https://github.com/microsoft/WinAppDriver/tree/master/Samples
While working on tests, you may need a tool that helps you to view the element's accessibility data, e.g. for finding the button to click. For this purpose, you could use AccessibilityInsights or WinAppDriver UI Recorder.
Note: close helper tools while running tests. Overlapping windows can affect test results.