Fix full-screen window snapping on secondary monitors (#557)

This commit is contained in:
Jeffrey
2026-04-24 21:18:46 +02:00
committed by GitHub
parent 797a232b17
commit dd492b523d

View File

@@ -14,16 +14,52 @@ function Show-MainWindow {
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
private struct POINT { public int x, y; }
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern System.IntPtr MonitorFromWindow(System.IntPtr hwnd, uint dwFlags);
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern bool GetMonitorInfo(System.IntPtr hMonitor, ref MONITORINFO lpmi);
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
private struct RECT {
public int Left, Top, Right, Bottom;
}
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private struct MONITORINFO {
public int cbSize;
public RECT rcMonitor;
public RECT rcWork;
public uint dwFlags;
}
public static System.IntPtr WmGetMinMaxInfoHook(
System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) {
if (msg == 0x0024) { // WM_GETMINMAXINFO
var wa = System.Windows.Forms.Screen.FromHandle(hwnd).WorkingArea;
var mmi = (MINMAXINFO)System.Runtime.InteropServices.Marshal.PtrToStructure(
lParam, typeof(MINMAXINFO));
mmi.ptMaxPosition.x = wa.Left;
mmi.ptMaxPosition.y = wa.Top;
const uint MONITOR_DEFAULTTONEAREST = 0x00000002;
var monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
var monitorInfo = new MONITORINFO();
monitorInfo.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(MONITORINFO));
if (monitor != System.IntPtr.Zero && GetMonitorInfo(monitor, ref monitorInfo)) {
mmi.ptMaxPosition.x = monitorInfo.rcWork.Left - monitorInfo.rcMonitor.Left;
mmi.ptMaxPosition.y = monitorInfo.rcWork.Top - monitorInfo.rcMonitor.Top;
mmi.ptMaxSize.x = monitorInfo.rcWork.Right - monitorInfo.rcWork.Left;
mmi.ptMaxSize.y = monitorInfo.rcWork.Bottom - monitorInfo.rcWork.Top;
}
else {
var screen = System.Windows.Forms.Screen.FromHandle(hwnd);
var wa = screen.WorkingArea;
var bounds = screen.Bounds;
mmi.ptMaxPosition.x = wa.Left - bounds.Left;
mmi.ptMaxPosition.y = wa.Top - bounds.Top;
mmi.ptMaxSize.x = wa.Width;
mmi.ptMaxSize.y = wa.Height;
}
System.Runtime.InteropServices.Marshal.StructureToPtr(mmi, lParam, true);
}
return System.IntPtr.Zero;
@@ -66,19 +102,28 @@ function Show-MainWindow {
$normalWindowShadow = $mainBorder.Effect
$initialNormalMaxWidth = 1400.0
$convertScreenPointToDip = {
param(
[double]$x,
[double]$y
)
$source = [System.Windows.PresentationSource]::FromVisual($window)
if ($null -eq $source -or $null -eq $source.CompositionTarget) {
return [System.Windows.Point]::new($x, $y)
}
return $source.CompositionTarget.TransformFromDevice.Transform([System.Windows.Point]::new($x, $y))
}
$convertScreenPixelsToDip = {
param(
[double]$width,
[double]$height
)
$source = [System.Windows.PresentationSource]::FromVisual($window)
if ($null -eq $source -or $null -eq $source.CompositionTarget) {
return [System.Windows.Size]::new($width, $height)
}
$topLeft = $source.CompositionTarget.TransformFromDevice.Transform([System.Windows.Point]::new(0, 0))
$bottomRight = $source.CompositionTarget.TransformFromDevice.Transform([System.Windows.Point]::new($width, $height))
$topLeft = & $convertScreenPointToDip 0 0
$bottomRight = & $convertScreenPointToDip $width $height
return [System.Windows.Size]::new($bottomRight.X - $topLeft.X, $bottomRight.Y - $topLeft.Y)
}
@@ -122,9 +167,10 @@ function Show-MainWindow {
return
}
$workingAreaTopLeftDip = & $convertScreenPointToDip $screen.WorkingArea.Left $screen.WorkingArea.Top
$workingAreaDip = & $convertScreenPixelsToDip $screen.WorkingArea.Width $screen.WorkingArea.Height
$window.Width = [Math]::Min($initialNormalMaxWidth, $workingAreaDip.Width)
$window.Left = $screen.WorkingArea.Left + (($workingAreaDip.Width - $window.Width) / 2)
$window.Left = $workingAreaTopLeftDip.X + (($workingAreaDip.Width - $window.Width) / 2)
}
$window.Add_SourceInitialized({