Arrange Multiple Windows (Grid / Cascade)
snap_window moves one window to a half or quarter, and the
Window Tiling / Layout Geometry Planner planner computes rectangles but does not move anything.
arrange_grid and arrange_cascade close the loop: given a list of window
titles they compute a layout and actually move every matching window — tile a set
of app windows into a grid, or fan them out in a diagonal cascade, in one call.
They build on the layout planner for the geometry and reuse the same injectable
mover / screen_size seams as snap_window, so the arrangement logic is
fully unit-testable without real windows. The default mover is Win32 today (other
platforms are a no-op until their backend lands). Imports no PySide6.
Headless API
from je_auto_control import arrange_grid, arrange_cascade
# Tile three editors into an auto-shaped grid (here 2x2, first 3 cells).
arrange_grid(["Editor", "Browser", "Terminal"])
# Or an explicit 1x3 row with an 8px gutter.
arrange_grid(["Left", "Mid", "Right"], rows=1, cols=3, gap=8)
# Fan windows out diagonally.
arrange_cascade(["Doc 1", "Doc 2", "Doc 3"], offset=40)
arrange_grid tiles the titles into an rows × cols grid (defaulting
to a near-square auto-shape for the window count) with an optional gap;
arrange_cascade staggers each window offset pixels down-right of the
previous, sized to 60% of the work area. Both return the number of windows
actually moved and leave any windows beyond the grid capacity untouched.
Executor commands
AC_arrange_grid (titles JSON array + rows / cols / gap) and
AC_arrange_cascade (titles + offset), each returning
{moved, count}. They are exposed as the MCP tools ac_arrange_grid /
ac_arrange_cascade (side-effecting) and as Script Builder commands under
Window.