Detect terminated / hung target and reflect it in the UI

The Injection panel kept showing "Attached" after the game exited. Now it tracks
target liveness each frame (InjectionPanel::tick from the main loop, independent of
panel visibility):
- a SYNCHRONIZE|QUERY process handle taken at inject time -> WaitForSingleObject
  detects the process exiting (Terminated);
- the hook heartbeat stalling for ~2 s while the process still exists flags a
  distinct Hung state (games here can freeze without exiting).

The panel shows a clear colored banner per state and disables the subsystem
hook/unhook controls and the synthetic-input toggle when the target isn't alive.
game_hwnd() returns null once Terminated, so the Video and Audio panels drop to
idle instead of chasing a dead window.

Verified: x64 build + ctest 7/7 green; host launches and renders the panels without
regression (screenshot smoke test). The interactive terminated/hung visual against a
real game is best confirmed in a live session (ImGui injection can't be GUI-scripted).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-21 01:05:49 +02:00
parent 61049a620c
commit b3e8a1adc6
4 changed files with 136 additions and 34 deletions

View File

@@ -75,18 +75,6 @@ is removed from this list once done — so the top item is always next. The
self-verifiable tooling / UI / input items come first; the game-pipeline items that
need a real game (and Remote Play) to fully validate come last.
- **Detect a terminated target and reflect it in the UI.** The Injection panel keeps
showing "Attached" after the game exits. Add a **Terminated** state: the host
already knows the target pid and tracks a DLL heartbeat (`InjectionPanel`); on top
of that, hold the `OpenProcess` handle from injection (or re-open with
`PROCESS_QUERY_LIMITED_INFORMATION`) and poll `GetExitCodeProcess` /
`WaitForSingleObject(h, 0)` each tick. When the process is gone, switch to
Terminated, gray out / disable the per-subsystem controls and mirror toggles, and
show a clear banner; the Video and Audio panels should drop to idle (their hook
channels are stale) rather than freezing on the last live frame/state. Note a live
process isn't proof it's running — also flag a **stalled heartbeat** (no advance
for ~2 s while the process still exists) as a distinct "hung / not responding"
state, since games here can freeze without exiting.
- **Re-attach to a relaunched target.** A killed-and-relaunched game gets a new pid,
but the UI still holds the stale one. In the Terminated state, remember the
target's image name (the panel already keeps the selected exe name) and offer a