Processing Ajax...

Title
Close Dialog

Message

Confirm
Close Dialog

Confirm
Close Dialog

Responsive Window Tiler

Description
This script will tile the open windows on the monitor.
Language
C#.net
Minimum Version
Created By
RubenFixit
Contributors
-
Date Created
Jun 10, 2019
Date Last Modified
Jun 10, 2019

Scripted Function (Macro) Code

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;
    }
}