using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
// DisplayFusion Scripted Function, created with Anthropic Fable 5
// Cascades all visible top-level windows of the currently focused application,
// replicating the classic "Cascade windows" behavior removed in Windows 11.
// Windows are stacked diagonally on the monitor containing the focused window.
public static class DisplayFusionFunction
{
public static void Run(IntPtr windowHandle)
{
// Get the focused window; fall back to the handle DisplayFusion passes in
IntPtr focused = BFS.Window.GetFocusedWindow();
if (focused == IntPtr.Zero)
focused = windowHandle;
if (focused == IntPtr.Zero)
return;
// Identify the owning application by process ID
uint processId = BFS.Application.GetAppIDByWindow(focused);
if (processId == 0)
return;
// Collect all candidate windows belonging to this process
List<IntPtr> windows = new List<IntPtr>();
foreach (IntPtr handle in BFS.Window.GetVisibleAndMinimizedWindowHandles())
{
if (BFS.Application.GetAppIDByWindow(handle) != processId)
continue;
// Skip tool windows, borderless popups, and windows without a title
if (string.IsNullOrEmpty(BFS.Window.GetText(handle)))
continue;
windows.Add(handle);
}
if (windows.Count == 0)
return;
// Cascade on the monitor that contains the focused window
Rectangle workArea = BFS.Monitor.GetMonitorWorkAreaByWindow(focused);
// Classic cascade metrics: offset roughly one title bar height per step,
// window sized to a large fraction of the work area
int offset = 32; // approximate title bar height at 100% DPI
int width = (int)(workArea.Width * 0.6);
int height = (int)(workArea.Height * 0.6);
// Sort by Z-order is not directly exposed, so keep enumeration order
// but move the focused window to the end so it lands on top
windows.Remove(focused);
windows.Add(focused);
int x = workArea.X;
int y = workArea.Y;
foreach (IntPtr handle in windows)
{
// Restore minimized or maximized windows so they can be positioned
if (BFS.Window.IsMinimized(handle) || BFS.Window.IsMaximized(handle))
BFS.Window.Restore(handle);
// Wrap around if the cascade would run off the work area
if (x + width > workArea.Right || y + height > workArea.Bottom)
{
x = workArea.X;
y = workArea.Y;
}
BFS.Window.SetSizeAndLocation(handle, x, y, width, height);
BFS.Window.Focus(handle);
x += offset;
y += offset;
}
// Leave the originally focused window active and on top
BFS.Window.Focus(focused);
}
}