// DisplayFusion Scripted Function
// Toggles the focused window between the leftmost and center monitor,
// scaling size and position to fit the target monitor's work area.
// Windows on the rightmost monitor are left in place.
// Generated with Anthropic Fable 5.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
public static class DisplayFusionFunction
{
[DllImport("user32.dll")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter,
int X, int Y, int cx, int cy, uint uFlags);
private const uint SWP_NOZORDER = 0x0004;
private const uint SWP_NOACTIVATE = 0x0010;
private const uint SWP_ASYNCWINDOWPOS = 0x4000;
// In-memory lock state, persists between runs while DisplayFusion
// keeps the compiled function loaded. No disk I/O.
private static readonly object SyncRoot = new object();
private static readonly Dictionary<IntPtr, long> LastMoveTicks = new Dictionary<IntPtr, long>();
public static void Run(IntPtr windowHandle)
{
if (windowHandle == IntPtr.Zero)
return;
// Reject re-triggers arriving within this window
int quietPeriodMs = 500;
lock (SyncRoot)
{
long lastTicks;
if (LastMoveTicks.TryGetValue(windowHandle, out lastTicks))
{
double elapsedMs = TimeSpan.FromTicks(DateTime.UtcNow.Ticks - lastTicks).TotalMilliseconds;
if (elapsedMs >= 0 && elapsedMs < quietPeriodMs)
return;
}
LastMoveTicks[windowHandle] = DateTime.UtcNow.Ticks;
}
// Sort monitors left to right by X position
Rectangle[] monitors = BFS.Monitor.GetMonitorWorkAreas()
.OrderBy(m => m.X)
.ToArray();
int leftmostIndex = 0;
int centerIndex = monitors.Length / 2;
int rightmostIndex = monitors.Length - 1;
Rectangle window = BFS.Window.GetBounds(windowHandle);
Point windowCenter = new Point(
window.X + (window.Width / 2),
window.Y + (window.Height / 2));
int currentIndex = -1;
for (int i = 0; i < monitors.Length; i++)
{
if (monitors[i].Contains(windowCenter))
{
currentIndex = i;
break;
}
}
if (currentIndex == -1)
currentIndex = leftmostIndex;
// Windows on the rightmost monitor stay where they are
if (currentIndex == rightmostIndex)
return;
int targetIndex = (currentIndex == leftmostIndex) ? centerIndex : leftmostIndex;
if (targetIndex == currentIndex)
return;
Rectangle current = monitors[currentIndex];
Rectangle target = monitors[targetIndex];
double scaleX = (double)target.Width / current.Width;
double scaleY = (double)target.Height / current.Height;
int windowX = target.X + (int)Math.Round((window.X - current.X) * scaleX);
int windowY = target.Y + (int)Math.Round((window.Y - current.Y) * scaleY);
int windowW = (int)Math.Round(window.Width * scaleX);
int windowH = (int)Math.Round(window.Height * scaleY);
if (windowW > target.Width)
windowW = target.Width;
if (windowH > target.Height)
windowH = target.Height;
if (windowX + windowW > target.Right)
windowX = target.Right - windowW;
if (windowY + windowH > target.Bottom)
windowY = target.Bottom - windowH;
if (windowX < target.X)
windowX = target.X;
if (windowY < target.Y)
windowY = target.Y;
// Async move: posts the request and returns immediately
SetWindowPos(windowHandle, IntPtr.Zero, windowX, windowY, windowW, windowH,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_ASYNCWINDOWPOS);
lock (SyncRoot)
{
LastMoveTicks[windowHandle] = DateTime.UtcNow.Ticks;
}
}
}