farmcontrol-ui/src/desktop/windows-work-area.js
Tom Butcher d28bed7136
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good
Enhance window management and navigation handling
- Added `isFullscreen` context to `DashboardNavigation` for improved UI responsiveness.
- Updated navigation class logic to conditionally apply styles based on fullscreen state.
- Refined window control logic in `window.js` to handle maximize/unmaximize actions more reliably, including asynchronous state synchronization on Windows.
- Introduced adjustments for window frame dimensions in `windows-work-area.js` to account for Win32 DWM overhangs, ensuring accurate maximized state detection and clamping.
2026-08-04 01:57:51 +01:00

111 lines
2.6 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 = {
x: -8,
y: 0,
width: 16,
height: 8
}
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) {
return {
x: workArea.x + WIN32_FRAME_OVERHANG.x,
y: workArea.y + WIN32_FRAME_OVERHANG.y,
width: workArea.width + WIN32_FRAME_OVERHANG.width,
height: workArea.height + WIN32_FRAME_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))
)
}
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)
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
}