Fixed

  • CMD key stuck after CMD+Tab — modifier key state is now seeded from NSEvent.modifierFlags (hardware truth) on focus gain instead of GLFW’s cached state. GLFW misses key-up events that fire while another window owns focus (e.g. CMD released in the App Switcher), leaving the key stuck as pressed indefinitely and causing every subsequent keystroke to fire as a CMD+key combo.

  • Hard hang at 3–4 GB requiring kill -9 — a soft memory ceiling (GOMEMLIMIT, default 1536 MB) tells the GC to run more aggressively as the heap approaches the limit, preventing the runaway growth that combined with Metal’s nextDrawable timeout to produce the hang. Configurable via memory_limit_mb under [performance]; set to 0 to disable.

  • Scrollback allocation pressure — the scrollback ring buffer now reuses evicted row slices in-place instead of allocating a fresh []Cell on every scrolled line. Eliminates the steady-state allocation stream for busy terminals (compiler output, streaming tools), materially reducing GC pressure on the game loop thread.

  • Display change geometry corruption — layout is now committed only after window size and DPI have been stable for 3 consecutive frames following a display-change notification, instead of immediately on the first frame. Adapts to the actual duration of EDID negotiation (HDMI docks, lid close/open, resolution changes, multi-monitor DPI transitions) rather than a fixed frame count.

  • Crash on HDMI disconnectebiten.Monitor() can return nil transiently while the display is being reconfigured; calling .DeviceScaleFactor() on a nil monitor caused a panic. All in-game-loop call sites now fall back to the last known DPI when the monitor is unavailable.

Changed

  • [performance] memory_limit_mb = 1536 — new config field for the soft memory ceiling (MB). Set to 0 for unlimited (previous behaviour).