Repository: PowerToys
Issue: [FancyZones] Priority grid zone positions are not consistent
Labels: Issue-Bug,FancyZones-Dragging&UI,Product-FancyZones,Priority-3

<!--
**Important: When reporting BSODs or security issues, DO NOT attach memory dumps, logs, or traces to Github issues**.
Instead, send dumps/traces to secure@microsoft.com, referencing this GitHub issue.
-->

# Environment
```
Windows build number: 19041.172
PowerToys version: Master/0.16.0
PowerToy module for which you are reporting the bug (if applicable): FancyZones
```

# Steps to reproduce
With the _'During zone layout changes, windows assigned to a zone will match new size/position'_ setting enabled: Use the Priority Grid template layout with two zones. Add a window to the 'priority' zone (the largest zone). Add a new zone. The window will no longer be in the priority zone and will now be in the non-priority zone to the left. This occurs whenever a new zone is added to the left of the priority zone.

# Expected behavior
Windows added to the priority zone should remain in the priority zone when the number of zones are increased or decreased.

In general, when the zone count is increased or decreased windows should stay in the zone that most closely matches the position they're currently in, as is when increasing/decreasing zones they move around unintuitively.

This is because zone numbering is simply done from top-left to bottom-right without considering what position these zones are in when the zone count is higher or lower.

# Actual behavior
See the below screenshots, I am using the priority grid layout with 2 zones, I add a third zone, Visual Studio moves from the priority zone to the leftside non-priority zone. File explorer, not in the priority zone moves into the priority zone.

# Screenshots
2 zones:
![image](https://user-images.githubusercontent.com/58787893/78282667-2f30b500-750c-11ea-8295-48e8d060e0c4.png)

3 zones:
![image](https://user-images.githubusercontent.com/58787893/78282831-7159f680-750c-11ea-9333-042f5b1b41db.png)

# Proposed fix
The layout info for the priority grid is defined in ZoneSet.cpp, here is a code snippet for 2 and 3 zones:

```C++
        /* 2 */
        JSONHelpers::GridLayoutInfo(JSONHelpers::GridLayoutInfo::Full{
            .rows = 1,
            .columns = 2,
            .rowsPercents = { 10000 },
            .columnsPercents = { 6667, 3333 },
            .cellChildMap = { { 0, 1 } } }),
        /* 3 */
        JSONHelpers::GridLayoutInfo(JSONHelpers::GridLayoutInfo::Full{
            .rows = 1,
            .columns = 3,
            .rowsPercents = { 10000 },
            .columnsPercents = { 2500, 5000, 2500 },
            .cellChildMap = { { 0, 1, 2 } } }),
```

The `cellChildMap` for each layout should be changed such that zone positions stay consistent across zone counts. In this example the `cellChildMap` for 3 zones should be `.cellChildMap = { { 2, 0, 1 } }`. This would keep the windows in the priority zone in the priority zone, windows on the right hand side of the screen would remain on the right, and a new zone would be added on the left.

As well as this change a new overload method for `ZoneSet::AddZone` would need adding. Currently this method simply sets the zone's Id in a top-left to top-right fashion:

```C++
IFACEMETHODIMP ZoneSet::AddZone(winrt::com_ptr<IZone> zone) noexcept
{
    m_zones.emplace_back(zone);

    // Important not to set Id 0 since we store it in the HWND using SetProp.
    // SetProp(0) doesn't really work.
    zone->SetId(m_zones.size());
    return S_OK;
}
```

The new method should also take in the `cellChild` value and use that for the Id instead, something like this:

```C++
IFACEMETHODIMP ZoneSet::AddZone(winrt::com_ptr<IZone> zone, integer cellChild) noexcept
{
    m_zones.emplace_back(zone);

    zone->SetId(cellChild + 1);
    return S_OK;
}
```