import { BrowserWindow } from 'electron'; import { RuntimeOptionState, WindowGeometry } from '../../types'; import { updateOverlayWindowBounds } from './overlay-window'; type OverlayLayer = 'visible' | 'invisible'; export interface OverlayManager { getMainWindow: () => BrowserWindow | null; setMainWindow: (window: BrowserWindow | null) => void; getInvisibleWindow: () => BrowserWindow | null; setInvisibleWindow: (window: BrowserWindow | null) => void; getOverlayWindow: (layer: OverlayLayer) => BrowserWindow | null; setOverlayWindowBounds: (layer: OverlayLayer, geometry: WindowGeometry) => void; getVisibleOverlayVisible: () => boolean; setVisibleOverlayVisible: (visible: boolean) => void; getInvisibleOverlayVisible: () => boolean; setInvisibleOverlayVisible: (visible: boolean) => void; getOverlayWindows: () => BrowserWindow[]; broadcastToOverlayWindows: (channel: string, ...args: unknown[]) => void; } export function createOverlayManager(): OverlayManager { let mainWindow: BrowserWindow | null = null; let invisibleWindow: BrowserWindow | null = null; let visibleOverlayVisible = false; let invisibleOverlayVisible = false; return { getMainWindow: () => mainWindow, setMainWindow: (window) => { mainWindow = window; }, getInvisibleWindow: () => invisibleWindow, setInvisibleWindow: (window) => { invisibleWindow = window; }, getOverlayWindow: (layer) => (layer === 'visible' ? mainWindow : invisibleWindow), setOverlayWindowBounds: (layer, geometry) => { updateOverlayWindowBounds(geometry, layer === 'visible' ? mainWindow : invisibleWindow); }, getVisibleOverlayVisible: () => visibleOverlayVisible, setVisibleOverlayVisible: (visible) => { visibleOverlayVisible = visible; }, getInvisibleOverlayVisible: () => invisibleOverlayVisible, setInvisibleOverlayVisible: (visible) => { invisibleOverlayVisible = visible; }, getOverlayWindows: () => { const windows: BrowserWindow[] = []; if (mainWindow && !mainWindow.isDestroyed()) { windows.push(mainWindow); } if (invisibleWindow && !invisibleWindow.isDestroyed()) { windows.push(invisibleWindow); } return windows; }, broadcastToOverlayWindows: (channel, ...args) => { const windows: BrowserWindow[] = []; if (mainWindow && !mainWindow.isDestroyed()) { windows.push(mainWindow); } if (invisibleWindow && !invisibleWindow.isDestroyed()) { windows.push(invisibleWindow); } for (const window of windows) { window.webContents.send(channel, ...args); } }, }; } export function broadcastRuntimeOptionsChangedRuntime( getRuntimeOptionsState: () => RuntimeOptionState[], broadcastToOverlayWindows: (channel: string, ...args: unknown[]) => void, ): void { broadcastToOverlayWindows('runtime-options:changed', getRuntimeOptionsState()); } export function setOverlayDebugVisualizationEnabledRuntime( currentEnabled: boolean, nextEnabled: boolean, setState: (enabled: boolean) => void, broadcastToOverlayWindows: (channel: string, ...args: unknown[]) => void, ): boolean { if (currentEnabled === nextEnabled) return false; setState(nextEnabled); broadcastToOverlayWindows('overlay-debug-visualization:set', nextEnabled); return true; }