From c1cb22299598eef5d4a1d8f18b17bce643dcb34a Mon Sep 17 00:00:00 2001 From: webadderall <131426131+webadderall@users.noreply.github.com> Date: Fri, 20 Mar 2026 20:18:41 +1100 Subject: [PATCH] Fix HUD overlay height sizing --- electron/electron-env.d.ts | 1 + electron/preload.ts | 3 ++ electron/windows.ts | 39 ++++++++++++++++++++++++-- src/components/launch/LaunchWindow.tsx | 30 +++++++++++++++----- 4 files changed, 63 insertions(+), 10 deletions(-) diff --git a/electron/electron-env.d.ts b/electron/electron-env.d.ts index b5a14efd..6ae43fe3 100644 --- a/electron/electron-env.d.ts +++ b/electron/electron-env.d.ts @@ -28,6 +28,7 @@ interface Window { hudOverlayClose: () => void; setHudOverlayExpanded: (expanded: boolean) => void; setHudOverlayCompactWidth: (width: number) => void; + setHudOverlayMeasuredHeight: (height: number, expanded: boolean) => void; getHudOverlayCaptureProtection: () => Promise<{ success: boolean; enabled: boolean }>; setHudOverlayCaptureProtection: ( enabled: boolean, diff --git a/electron/preload.ts b/electron/preload.ts index 6686e9fb..06659046 100644 --- a/electron/preload.ts +++ b/electron/preload.ts @@ -13,6 +13,9 @@ contextBridge.exposeInMainWorld("electronAPI", { setHudOverlayCompactWidth: (width: number) => { ipcRenderer.send("set-hud-overlay-compact-width", width); }, + setHudOverlayMeasuredHeight: (height: number, expanded: boolean) => { + ipcRenderer.send("set-hud-overlay-measured-height", height, expanded); + }, getHudOverlayCaptureProtection: () => { return ipcRenderer.invoke("get-hud-overlay-capture-protection"); }, diff --git a/electron/windows.ts b/electron/windows.ts index f6d8aaf0..f5ca03cf 100644 --- a/electron/windows.ts +++ b/electron/windows.ts @@ -29,10 +29,12 @@ const HUD_EDGE_MARGIN_DIP = 16; const HUD_SHADOW_BLEED_DIP = 36; const HUD_MIN_WINDOW_WIDTH = 560; const HUD_COMPACT_HEIGHT = 96; -const HUD_EXPANDED_HEIGHT = 520 + HUD_SHADOW_BLEED_DIP; +const HUD_MIN_EXPANDED_HEIGHT = 520 + HUD_SHADOW_BLEED_DIP; let hudOverlayExpanded = false; let hudOverlayCompactWidth = HUD_MIN_WINDOW_WIDTH; +let hudOverlayCompactHeight = HUD_COMPACT_HEIGHT; +let hudOverlayExpandedHeight = HUD_MIN_EXPANDED_HEIGHT; function isHudOverlayCaptureProtectionSupported(): boolean { return process.platform !== "linux"; @@ -86,7 +88,11 @@ function getHudOverlayBounds(expanded: boolean) { maxWindowWidth, Math.max(HUD_MIN_WINDOW_WIDTH, Math.round(hudOverlayCompactWidth)), ); - const windowHeight = expanded ? HUD_EXPANDED_HEIGHT : HUD_COMPACT_HEIGHT; + const maxWindowHeight = Math.max(HUD_COMPACT_HEIGHT, workArea.height - HUD_EDGE_MARGIN_DIP * 2); + const desiredHeight = expanded + ? Math.max(HUD_MIN_EXPANDED_HEIGHT, Math.round(hudOverlayExpandedHeight)) + : Math.max(HUD_COMPACT_HEIGHT, Math.round(hudOverlayCompactHeight)); + const windowHeight = Math.min(maxWindowHeight, desiredHeight); const bottomClearanceDip = Math.round((HUD_BOTTOM_CLEARANCE_CM / CM_PER_INCH) * DIP_PER_INCH); const screenBottom = bounds.y + bounds.height; const workAreaBottom = workArea.y + workArea.height; @@ -152,6 +158,33 @@ ipcMain.on("set-hud-overlay-compact-width", (_event, width: number) => { applyHudOverlayBounds(hudOverlayExpanded); }); +ipcMain.on("set-hud-overlay-measured-height", (_event, height: number, expanded: boolean) => { + if (!Number.isFinite(height)) { + return; + } + + const primaryDisplay = getScreen().getPrimaryDisplay(); + const maxWindowHeight = Math.max( + HUD_COMPACT_HEIGHT, + primaryDisplay.workArea.height - HUD_EDGE_MARGIN_DIP * 2, + ); + const nextHeight = Math.min(maxWindowHeight, Math.max(HUD_COMPACT_HEIGHT, Math.round(height))); + + if (expanded) { + if (nextHeight === hudOverlayExpandedHeight) { + return; + } + hudOverlayExpandedHeight = Math.max(HUD_MIN_EXPANDED_HEIGHT, nextHeight); + } else { + if (nextHeight === hudOverlayCompactHeight) { + return; + } + hudOverlayCompactHeight = nextHeight; + } + + applyHudOverlayBounds(hudOverlayExpanded); +}); + ipcMain.handle("get-hud-overlay-capture-protection", () => { const enabled = loadHudOverlayCaptureProtectionSetting(); @@ -189,7 +222,7 @@ export function createHudOverlayWindow(): BrowserWindow { height: initialBounds.height, minWidth: HUD_MIN_WINDOW_WIDTH, minHeight: HUD_COMPACT_HEIGHT, - maxHeight: HUD_EXPANDED_HEIGHT, + maxHeight: Math.max(HUD_COMPACT_HEIGHT, getScreen().getPrimaryDisplay().workArea.height - HUD_EDGE_MARGIN_DIP * 2), x: initialBounds.x, y: initialBounds.y, frame: false, diff --git a/src/components/launch/LaunchWindow.tsx b/src/components/launch/LaunchWindow.tsx index 0ab81fa2..36f5438a 100644 --- a/src/components/launch/LaunchWindow.tsx +++ b/src/components/launch/LaunchWindow.tsx @@ -175,6 +175,7 @@ export function LaunchWindow() { const [hideHudFromCapture, setHideHudFromCapture] = useState(true); const [platform, setPlatform] = useState(null); const dropdownRef = useRef(null); + const hudContentRef = useRef(null); const hudBarRef = useRef(null); const webcamPreviewRef = useRef(null); @@ -360,32 +361,46 @@ export function LaunchWindow() { }, [activeDropdown]); useEffect(() => { + const hudContent = hudContentRef.current; const hudBar = hudBarRef.current; - if (!hudBar || typeof ResizeObserver === "undefined") { + if (!hudContent || !hudBar || typeof ResizeObserver === "undefined") { return; } let frameId = 0; - const reportWidth = () => { + const reportHudSize = () => { frameId = 0; const measuredWidth = Math.ceil( - Math.max(hudBar.getBoundingClientRect().width, hudBar.scrollWidth) + 24, + Math.max( + hudBar.getBoundingClientRect().width, + hudBar.scrollWidth, + hudContent.getBoundingClientRect().width, + hudContent.scrollWidth, + ) + 24, + ); + const measuredHeight = Math.ceil( + Math.max(hudContent.getBoundingClientRect().height, hudContent.scrollHeight) + 24, ); window.electronAPI.setHudOverlayCompactWidth(measuredWidth); + window.electronAPI.setHudOverlayMeasuredHeight( + measuredHeight, + activeDropdown !== "none", + ); }; - const scheduleWidthReport = () => { + const scheduleHudSizeReport = () => { if (frameId !== 0) { cancelAnimationFrame(frameId); } - frameId = requestAnimationFrame(reportWidth); + frameId = requestAnimationFrame(reportHudSize); }; - scheduleWidthReport(); + scheduleHudSizeReport(); const resizeObserver = new ResizeObserver(() => { - scheduleWidthReport(); + scheduleHudSizeReport(); }); + resizeObserver.observe(hudContent); resizeObserver.observe(hudBar); return () => { @@ -633,6 +648,7 @@ export function LaunchWindow() { ref={dropdownRef} >
{/* Only the visible HUD content should become interactive. */}