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 {
private static int minWindowWidthPxl = 860;
private static int minWinDowHeightPxl = 360;
public static void Run(IntPtr windowHandle) {
// Get the current monitor id from the current mouse position
uint monitorId = 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(monitorId)) {
if(IsDisplayFusionWindowOrHiddenExplorerWindow(window))
continue;
windows.Add(window);
}
// Compute the bounds for the windows
List<Rectangle> winBounds;
Rectangle monitorWorkArea = BFS.Monitor.GetMonitorWorkAreaByID(monitorId);
if (monitorWorkArea.Width > monitorWorkArea.Height) {
winBounds = GetLandscapeWindowBounds(windows.Count, monitorWorkArea);
} else {
winBounds = GetPortraitWindowBounds(windows.Count, monitorWorkArea);
}
// Loop through each window, and set it's bounds to the computed bounds
for(int i = 0; (i < windows.Count) && (i < winBounds.Count); i++)
BFS.Window.SetSizeAndLocation(windows[i], winBounds[i].X, winBounds[i].Y, winBounds[i].Width, winBounds[i].Height);
}
// Creates a list of window bounds so that the windows will be tiled by columns and add rows as needed.
private static List<Rectangle> GetLandscapeWindowBounds(int numberOfWindows, Rectangle workArea) {
List<Rectangle> winBounds = new List<Rectangle>();
if (numberOfWindows == 1) {
winBounds.Add(workArea);
} else {
int maxCols = workArea.Width / minWindowWidthPxl;
int cols;
if (numberOfWindows >= maxCols) {
cols = maxCols;
} else {
cols = numberOfWindows;
}
int winWidth = workArea.Width / cols;
int curColNumRows = 1;
for (int col = 0; col < cols; col++) {
int remainingWins = numberOfWindows % (cols - col);
if (remainingWins == 0) {
curColNumRows = numberOfWindows / (cols - col);
} else {
curColNumRows = (numberOfWindows / (cols - col)) + 1;
}
int winHeight = workArea.Height / curColNumRows;
for (int row = 0; row < curColNumRows; row++) {
winBounds.Add(new Rectangle(workArea.X + (winWidth * col), workArea.Y + (winHeight * row), winWidth, winHeight));
numberOfWindows--;
}
}
}
return winBounds;
}
// Creates a list of window bounds so that the windows will be tiled by rows and add columns as needed.
private static List<Rectangle> GetPortraitWindowBounds(int numberOfWindows, Rectangle workArea) {
List<Rectangle> winBounds = new List<Rectangle>();
if (numberOfWindows == 1) {
winBounds.Add(workArea);
} else {
int maxRows = workArea.Height / minWinDowHeightPxl;
int rows;
if (numberOfWindows >= maxRows) {
rows = maxRows;
} else {
rows = numberOfWindows;
}
int winHeight = workArea.Height / rows;
int curRowNumCols = 1;
for (int row = 0; row < rows; row++) {
int remainingWins = numberOfWindows % (rows - row);
if (remainingWins == 0) {
curRowNumCols = numberOfWindows / (rows - row);
} else {
curRowNumCols = (numberOfWindows / (rows - row)) + 1;
}
int winWidth = workArea.Width / curRowNumCols;
for (int col = 0; col < curRowNumCols; col++) {
winBounds.Add(new Rectangle(workArea.X + (winWidth * col), workArea.Y + (winHeight * row), winWidth, winHeight));
numberOfWindows--;
}
}
}
return winBounds;
}
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;
}
}