Skip to content

FancyZones: apply edited custom layout spacing/sensitivity/zone count to active work areas immediately - #49433

Open
MuyuanMS wants to merge 1 commit into
microsoft:mainfrom
MuyuanMS:fix/44058-fancyzones-custom-layout-edit-apply
Open

FancyZones: apply edited custom layout spacing/sensitivity/zone count to active work areas immediately#49433
MuyuanMS wants to merge 1 commit into
microsoft:mainfrom
MuyuanMS:fix/44058-fancyzones-custom-layout-edit-apply

Conversation

@MuyuanMS

Copy link
Copy Markdown
Contributor

Summary of the Pull Request

When a custom layout is edited in the FancyZones editor while windows are already snapped to it, changes to the layout's scalar properties — spacing between zones, highlight/activation sensitivity radius, and zone count (for canvas layouts) — were not applied to already-active work areas until PowerToys (or FancyZones) was restarted. Only the grid shape/edges refreshed live.

This PR makes those scalar edits take effect immediately on existing work areas, resolving the remaining gap in issue 44058.

PR Checklist

Detailed Description of the Pull Request / Additional comments

Root cause

For a Custom-type layout, WorkArea::CalculateZoneSet builds its Layout from AppliedLayouts::GetDeviceLayout(), which returns a snapshot from applied-layouts.json. The zone shape is read live from the CustomLayouts store, but the scalar properties (spacing, sensitivityRadius, and zoneCount) were taken from that stale applied-layouts snapshot. So when the editor updated the custom layout and fired WM_PRIV_CUSTOM_LAYOUTS_FILE_UPDATE, the existing work areas re-laid-out their grid geometry but kept the old spacing/sensitivity/zone count.

The fix

In WorkArea::CalculateZoneSet, for Custom-type layouts, re-derive the scalar properties from the live CustomLayouts store instead of the stale snapshot:

if (const auto refreshed = CustomLayouts::instance().GetLayout(appliedLayout->uuid))
{
    appliedLayout = refreshed;
}

CustomLayouts::GetLayout returns the canonical LayoutData used by the apply path (it derives grid zone count from zoneCount() and canvas zone count from zones.size()), so the refreshed values exactly match what a fresh apply would produce.

Why this is low-risk:

  • Scoped strictly to Custom layouts; templated layouts (Grid/Columns/etc.) are untouched.
  • At initial apply-time, the live store and the applied-layouts snapshot are equal, so behavior is unchanged for the common case — only a genuine edit of an already-applied custom layout changes the outcome (which is the intended fix).

This complements the editor-side RefreshLayouts() call (which refreshes zone shape) so that all properties of an edited custom layout now apply live.

Validation Steps Performed

Automated: Added EditedCustomLayoutSpacingRefreshesExistingWorkArea in FancyZonesTests/UnitTests/WorkArea.Spec.cpp. It creates a work area on a grid custom layout, asserts adjacent zones are flush, then edits the custom layout's spacing, re-initializes the layout via InitLayout(), and asserts the new spacing gap is present on the existing zones. Built the FancyZones unit tests and ran the WorkArea suite — all pass.

Manual (end-to-end):

  1. Create a grid custom layout in the FancyZones editor and apply it.
  2. Snap a window into one of its zones.
  3. Re-open the editor, edit the layout: change the edge position and the space between zones (and optionally sensitivity), then Save.
  4. Before this fix: the zone edges move, but the spacing between snapped windows keeps the old gap until PowerToys is restarted.
  5. After this fix: the new spacing (and sensitivity) are applied to the already-snapped/active work area immediately, with no restart.

…to active work areas immediately

When a custom layout is edited in the FancyZones editor, active work areas already
using that layout only refreshed the grid shape/edges. Scalar properties (spacing,
sensitivity radius, and zone count) were read from a stale applied-layouts snapshot,
so edits to them did not take effect on existing windows until PowerToys/FancyZones
was restarted.

WorkArea::CalculateZoneSet now re-derives the scalar properties from the live
CustomLayouts store (CustomLayouts::instance().GetLayout(uuid)) for Custom-type
layouts, matching the values used on the apply path. Scoped to Custom layouts only;
at apply-time the values equal the snapshot, so only genuine edits change behavior.

Adds a regression test (EditedCustomLayoutSpacingRefreshesExistingWorkArea) that
creates a work area, edits the custom layout spacing, re-inits the layout, and
asserts the new spacing gap is applied to existing zones.

Co-authored-by: Copilot <[email protected]>
Copilot-Session: 19f7171d-0ca4-48dc-95ef-e50f505a9097

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a FancyZones refresh gap where editing an already-applied custom layout would update zone geometry but leave scalar properties (spacing / sensitivity radius / canvas zone count) stale until restart or re-apply. It updates the runtime refresh path so active work areas rehydrate these values from the live custom-layouts.json store and ensures the module triggers a layout refresh when that store changes.

Changes:

  • In WorkArea::CalculateZoneSet, for Custom layouts, refresh LayoutData from CustomLayouts::GetLayout(uuid) before constructing the Layout, so scalar properties reflect the edited layout immediately.
  • In FancyZones message handling, refresh active layouts when custom-layouts.json changes (WM_PRIV_CUSTOM_LAYOUTS_FILE_UPDATE).
  • Add a regression unit test that edits custom grid spacing and verifies an existing WorkArea reflects the new spacing after InitLayout().

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
src/modules/fancyzones/FancyZonesTests/UnitTests/WorkArea.Spec.cpp Adds a regression test that validates edited custom-layout spacing is applied to an already-created work area after refresh.
src/modules/fancyzones/FancyZonesLib/WorkArea.cpp Refreshes LayoutData for custom layouts from the live CustomLayouts store during zone set calculation.
src/modules/fancyzones/FancyZonesLib/FancyZones.cpp Calls RefreshLayouts() on WM_PRIV_CUSTOM_LAYOUTS_FILE_UPDATE so active work areas re-init after custom layouts reload.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Product-FancyZones Refers to the FancyZones PowerToy

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Layout Changes to Currently Applied Layout Not Applied Immediately After Editing

2 participants