GameWindowManager class creates and manages game windows in both native mode (single window with canvas rendering) and overlay mode (transparent overlay for external RetroArch process). It handles window animations, state persistence, and IPC communication.
Constructor
Path to the preload script for window security context
Native mode windows
createNativeGameWindow()
Create a game window in native mode — the game renders inside the BrowserWindow via WebGL canvas. Single window, single title bar.Game object from LibraryService
Worker client managing the emulation utility process
Audio/video info from the core (base resolution, aspect ratio, sample rate)
Whether to load autosave (slot 99) on boot (default: false)
BrowserWindow
If
cardScreenBounds is provided, the window animates from the card position to its final size using a hero transition.Window sizing and aspect ratio
Native windows automatically size themselves based on the core’s reported aspect ratio:State persistence
Window position, size, and fullscreen state are saved per-system:Zero-copy frame transfer
Native windows use SharedArrayBuffer for zero-copy video/audio data transfer:Shutdown animation
Native windows implement a graceful shutdown sequence:- User clicks close → window intercepts
closeevent - Save window state immediately (before animation)
- Pause emulation and save SRAM + autosave (slot 99)
- Send
game:prepare-closeto renderer - Renderer plays shutdown animation → sends
game-window:ready-to-close - Main process animates window close (fade + shrink)
- Window destroys after animation completes
Overlay mode windows (legacy)
createGameWindow()
Create an overlay game window for external RetroArch process. Transparent frameless window that tracks the RetroArch window position.Game object from LibraryService
BrowserWindow
startTrackingRetroArchWindow()
Start tracking an external RetroArch window to overlay controls.Game ID
RetroArch process ID
void
Polls every 200ms to:
- Query RetroArch window bounds via JXA (macOS only)
- Match overlay window position and size
- Detect fullscreen mode and adjust title bar offset
- Show/hide controls based on cursor position
- Close overlay if RetroArch exits (5 consecutive query failures)
This mode is legacy. New games use native mode (
createNativeGameWindow) instead.stopTracking()
Stop tracking a RetroArch window.Game ID
void
Window control
closeGameWindow()
Close a specific game window.Game ID
void
closeAllGameWindows()
Close all game windows (e.g., on app quit).void
getGameWindow()
Get the BrowserWindow instance for a game.Game ID
BrowserWindow | undefined
destroy()
Clean up all windows and IPC listeners. Called on app quit.void
IPC handlers
GameWindowManager automatically sets up these IPC handlers for renderer control:game-window:minimize
Minimize the game window.game-window:maximize
Toggle maximize/unmaximize.game-window:close
Close the game window (triggers shutdown animation in native mode).game-window:toggle-fullscreen
Toggle fullscreen mode.game-window:set-click-through
Set whether the window should forward mouse events (for overlay mode).Whether to ignore mouse events
game-window:set-traffic-light-visible
Show/hide macOS traffic light buttons.Whether buttons should be visible
game-window:ready-to-close
Renderer signals that the shutdown animation has completed and the window is ready to destroy.game:input
Forward input from renderer to emulation worker.Controller port (0-3)
Button ID (from libretro button constants)
Whether button is pressed or released
Events sent to renderer
Game windows receive these events from the main process:game:loaded
Sent when the window finishes loading with the game data.game:mode
Sent to indicate the window mode.game:av-info
Sent with audio/video info from the core (native mode only).game:ready-for-boot
Sent when the window is ready to start the boot animation (after hero transition completes).game:prepare-close
Sent when the user closes the window, before the shutdown animation.game:video-frame
Fallback video frame delivery when SharedArrayBuffer is not available.game:audio-samples
Audio samples from the worker.game:emulation-error
Fatal emulation error.overlay:show-controls
Show/hide overlay controls based on cursor position (overlay mode only).Usage example
Performance considerations
See the Architecture guide for performance considerations and restrictions on game window rendering:- No
backdrop-filterorbackdrop-bluroverlays - No expensive CSS effects during gameplay
- Frame delivery synced to
requestAnimationFrame
Source reference
- Implementation:
apps/desktop/src/main/GameWindowManager.ts:23 - Usage example:
apps/desktop/src/main/ipc/handlers.ts:24