DartPotato is a game about surviving in real time, so leaving it running while a player is actually looking at the Steam overlay instead of the game is a bad experience — you tab into your friends list for two seconds and come back to a corpse. Steam's own controller-support review flagged exactly this. Fixing it properly took three attempts across two days, and we shipped the least clever one.
Attempt one: just catch the keypress
Shift+Tab opens the overlay, so the obvious first move is to catch that key combo in the
game and pause. It doesn't work, and the reason is worth knowing: Steam's overlay injects
into the process and hooks input at the OS level. It never creates a focusable
window, so a browser blur event never fires for it — and its keyboard hook
consumes Shift+Tab below Chromium, so neither a page keydown handler nor Electron's
own before-input-event ever sees the key at all. We tried both. Neither could
ever have worked, structurally.
Attempt two: window focus loss
The overlay doesn't fire a page blur, but the surrounding OS window can still lose focus in
some configurations, and alt-tabbing away is something we want to pause on anyway. So we
wired up two things: the page's own blur event (covers the plain browser build
and plain alt-tab), and a main-process window.on('blur') forwarded over IPC,
which is the more reliable signal in the packaged Electron build since the overlay grabs
input without necessarily disturbing window focus the same way every time.
While we were in there, we also caught a real bug this surfaced: the overlay swallows
keyup as well as keydown. A player holding Shift to dash when the
overlay opens never gets the matching key-up, so the game kept thinking Shift was held
forever after they closed it again. Blur now releases all held inputs, not just pauses.
This shipped and works. But it only handles losing window focus — Steam's own controller-support review specifically called out a player navigating the overlay with a controller, where the game window can stay focused the entire time.
Attempt three: ask Steam directly, natively
Steam's own SDK exposes exactly the signal we want —
ISteamUtils::BOverlayNeedsPresent() — but the JS wrapper library we use for
Steam integration doesn't surface it: no GameOverlayActivated callback in its
event enum, no friends namespace, and it ships a prebuilt binary with no source
to extend. So we built a small native addon (N-API) to call that one function directly, the
same approach that already worked for detecting the controller's Home button.
Getting it to even compile took a missing include path in the native build config. Once it built, the raw signal turned out to be too noisy to use as-is: it fires for toast notifications, not just the full overlay, and produces an idle "still true" blip roughly every six seconds even with nothing open — both of which caused pauses at essentially random moments during normal play. We gated on the rate of the flag toggling within a trailing window instead of the raw boolean, since a real overlay open produces a dense burst of rapid toggling that idle noise never does.
We disabled it. Not "commented out and forgotten" — a deliberate kill switch, falling back cleanly to the blur-based pausing from attempt two, which is the same thing that runs when the native addon isn't even built at all. The honest tradeoff: a keyboard-only player opening the overlay via Shift+Tab specifically, with the window staying focused, won't auto-pause. Every controller path, every alt-tab, and every other pause trigger is unaffected.
Three engineering days for a feature that shipped disabled sounds like a loss. We'd call it a fairly cheap one — the alternative was shipping the noisy version and letting players find the random mid-fight pauses for us.