refactor(app): extract focused window lifetime

Move the exact retryable shutdown manifest, typed root snapshot, terminal reporting, and native-window-last release out of GameWindow. Keep session and GPU convergence as hard barriers while reporting persistent physical callback cleanup without stranding dependent owners.

Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-22 19:43:52 +02:00
parent 5a55d08106
commit 31e6e192b3
21 changed files with 1297 additions and 572 deletions

View file

@ -152,7 +152,9 @@ public sealed class UiHost : System.IDisposable
}
/// <summary>Physically removes every retained input edge after quiescence.</summary>
public void DeactivateInput()
public void DeactivateInput() => CompleteInputShutdown(reportFailures: true);
private void CompleteInputShutdown(bool reportFailures)
{
QuiesceInput();
@ -164,11 +166,21 @@ public sealed class UiHost : System.IDisposable
.Reverse()
.Select((binding, index) => new ResourceShutdownOperation(
$"input binding {index}",
binding.Dispose))
binding.Dispose,
ResourceShutdownOperationPolicy.ReportAndContinue))
.ToArray()));
_inputShutdown.CompleteOrThrow();
if (_inputShutdown.IsComplete)
if (_inputShutdown.IsComplete && _inputShutdown.CleanupFailures.Count == 0)
_inputBindings.Clear();
if (reportFailures && _inputShutdown.CleanupFailures.Count != 0)
{
throw new AggregateException(
"Retained UI input callback cleanup completed with failures.",
_inputShutdown.CleanupFailures.Select(static failure =>
new InvalidOperationException(
$"Retained UI operation '{failure.Operation}' failed in stage '{failure.Stage}'.",
failure.Error)));
}
}
// ── Window manager forwarders (delegate to UiRoot) ─────────────────
@ -205,7 +217,7 @@ public sealed class UiHost : System.IDisposable
_disposeRequested = true;
_shutdown ??= CreateShutdownTransaction(
[DeactivateInput],
[() => CompleteInputShutdown(reportFailures: false)],
() => { },
WindowManager.Dispose,
TextRenderer.Dispose);