using System;
using System.Drawing;
using System.Collections.Generic;
// The 'windowHandle' parameter will contain the window handle for the:
// - Active window when run by hotkey
// - Trigger target when run by a Trigger rule
// - TitleBar Button owner when run by a TitleBar Button
// - Jump List owner when run from a Taskbar Jump List
// - Currently focused window if none of these match
public static class DisplayFusionFunction
{
public static void Run(IntPtr windowHandle)
{
// Get the current monitor id from the current mouse position
uint monitor = BFS.Monitor.GetMonitorIDByXY(BFS.Input.GetMousePositionX(), BFS.Input.GetMousePositionY());
// Get the visible windows on that monitor
List<IntPtr> windows = new List<IntPtr>();
foreach(IntPtr window in BFS.Window.GetVisibleWindowHandlesByMonitor(monitor))
{
if(IsDisplayFusionWindowOrHiddenExplorerWindow(window))
continue;
windows.Add(window);
}
// Compute the bounds for the windows
List<Rectangle> bounds = GetWindowBounds(windows.Count, monitor);
// Loop through each window, and set it's bounds to the computed bounds
for(int i = 0; (i < windows.Count) && (i < bounds.Count); i++)
BFS.Window.SetSizeAndLocation(windows[i], bounds[i].X, bounds[i].Y, bounds[i].Width, bounds[i].Height);
}
// This function takes the bounds of the current monitor, then figures out where each window should be to stack them nicely
private static List<Rectangle> GetWindowBounds(int numberOfWindows, uint monitor)
{
Rectangle bounds = BFS.Monitor.GetMonitorWorkAreaByID(monitor);
List<Rectangle> windowBounds = new List<Rectangle>();
if (numberOfWindows == 1)
{
windowBounds.Add(bounds);
}
else
{
int rows = (numberOfWindows <= 8) ? 2 : 3;
if (numberOfWindows == 2)
rows = 1;
int leftover = numberOfWindows % rows;
int cols = (numberOfWindows + leftover) / rows;
int topCols = numberOfWindows % cols;
for (int i = 0; i < numberOfWindows; i++)
{
if (i < topCols)
{
windowBounds.Add(new Rectangle(bounds.X + bounds.Width * i / topCols, bounds.Y, bounds.Width / topCols, bounds.Height / rows));
}
else
{
int currentCol = (i - topCols) % cols;
int currentRow = i / cols;
if (topCols > 0)
currentRow = (i + (cols - topCols)) / cols;
windowBounds.Add(new Rectangle(bounds.X + bounds.Width * currentCol / cols, bounds.Y + bounds.Height * currentRow / rows, bounds.Width / cols, bounds.Height / rows));
}
}
}
return windowBounds;
}
private static bool IsDisplayFusionWindowOrHiddenExplorerWindow(IntPtr window)
{
//ignore any DisplayFusion windows (title bar buttons, etc.)
//ignore pesky hidden explorer.exe windows
if((BFS.Window.GetClass(window).StartsWith("DF", StringComparison.OrdinalIgnoreCase)) ||
(BFS.Window.GetClass(window).Equals("EdgeUiInputTopWndClass", StringComparison.OrdinalIgnoreCase)) ||
(BFS.Window.GetClass(window).Equals("EdgeUiInputWndClass", StringComparison.OrdinalIgnoreCase)) ||
(BFS.Window.GetClass(window).Equals("NativeHWNDHost", StringComparison.OrdinalIgnoreCase)) ||
(BFS.Window.GetClass(window).Equals("ModeInputWnd", StringComparison.OrdinalIgnoreCase)) ||
(BFS.Window.GetClass(window).Equals("MetroGhostWindow", StringComparison.OrdinalIgnoreCase)) ||
(BFS.Window.GetClass(window).Equals("ImmersiveLauncher", StringComparison.OrdinalIgnoreCase)) ||
(BFS.Window.GetClass(window).Equals("ApplicationManager_ImmersiveShellWindow", StringComparison.OrdinalIgnoreCase)) ||
(BFS.Window.GetClass(window).Equals("Shell_TrayWnd", StringComparison.OrdinalIgnoreCase)) ||
(BFS.Window.GetClass(window).Equals("WorkerW", StringComparison.OrdinalIgnoreCase)) ||
(BFS.Window.GetClass(window).Equals("Progman", StringComparison.OrdinalIgnoreCase)) ||
(BFS.Window.GetClass(window).Equals("SearchPane", StringComparison.OrdinalIgnoreCase)))
{
return true;
}
return false;
}
}