farmcontrol-ui/src/desktop/windows-work-area.js
Tom Butcher b2c116c78a
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good
Update Windows frame overhang constants for improved window rendering
- Adjusted the CEF frame overhang constants to better align with native window dimensions, enhancing the accuracy of window positioning and rendering in the application.
- Increased the width and height values to accommodate changes in window management.
2026-08-09 15:58:26 +01:00

124 lines
2.9 KiB
JavaScript

import { Screen } from 'electrobun/bun'
const FRAME_TOLERANCE_PX = 4
// Win32 DWM invisible borders sit outside the client work area; Electrobun's
// maximized frame includes those overhangs, so we treat this adjusted rect as
// the canonical "maximized to work area" geometry.
const WIN32_FRAME_OVERHANG_NATIVE = {
x: -8,
y: 0,
width: 16,
height: 8
}
const WIN32_FRAME_OVERHANG_CEF = {
x: -12,
y: 0,
width: 24,
height: 12
}
function getWin32FrameOverhang(window) {
return window?.renderer === 'cef'
? WIN32_FRAME_OVERHANG_CEF
: WIN32_FRAME_OVERHANG_NATIVE
}
function framesMatch(a, b, tolerance = FRAME_TOLERANCE_PX) {
return (
Math.abs(a.x - b.x) <= tolerance &&
Math.abs(a.y - b.y) <= tolerance &&
Math.abs(a.width - b.width) <= tolerance &&
Math.abs(a.height - b.height) <= tolerance
)
}
function getMaximizedWorkAreaFrame(workArea, window) {
const overhang = getWin32FrameOverhang(window)
return {
x: workArea.x + overhang.x,
y: workArea.y + overhang.y,
width: workArea.width + overhang.width,
height: workArea.height + overhang.height
}
}
function getFrameCenter(frame) {
return {
x: frame.x + frame.width / 2,
y: frame.y + frame.height / 2
}
}
function getDisplayForFrame(frame) {
const { x, y } = getFrameCenter(frame)
const displays = Screen.getAllDisplays()
const match = displays.find(({ bounds }) => {
return (
x >= bounds.x &&
x < bounds.x + bounds.width &&
y >= bounds.y &&
y < bounds.y + bounds.height
)
})
return match ?? Screen.getPrimaryDisplay()
}
function frameCoversMonitor(frame, bounds) {
return (
frame.x <= bounds.x + FRAME_TOLERANCE_PX &&
frame.y <= bounds.y + FRAME_TOLERANCE_PX &&
frame.x + frame.width >= bounds.x + bounds.width - FRAME_TOLERANCE_PX &&
frame.y + frame.height >= bounds.y + bounds.height - FRAME_TOLERANCE_PX
)
}
export function isWindowWorkAreaMaximized(window) {
if (!window?.getFrame) {
return false
}
const frame = window.getFrame()
const { workArea } = getDisplayForFrame(frame)
return (
framesMatch(frame, workArea) ||
framesMatch(frame, getMaximizedWorkAreaFrame(workArea, window))
)
}
export function clampWindowToWorkArea(window) {
if (!window?.getFrame || !window?.setFrame) {
return false
}
if (window.isFullScreen?.()) {
return false
}
const frame = window.getFrame()
if (!frame.width || !frame.height) {
return false
}
const display = getDisplayForFrame(frame)
const { bounds, workArea } = display
const maximizedFrame = getMaximizedWorkAreaFrame(workArea, window)
if (framesMatch(frame, workArea) || framesMatch(frame, maximizedFrame)) {
return false
}
if (!frameCoversMonitor(frame, bounds)) {
return false
}
window.setFrame(
maximizedFrame.x,
maximizedFrame.y,
maximizedFrame.width,
maximizedFrame.height
)
return true
}