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

@ -356,23 +356,39 @@ public sealed class LandblockBuildOriginTests
"src",
"AcDream.App",
"Rendering",
"GameWindow.cs"));
"GameWindowLifetime.cs"));
int sessionStage = source.IndexOf(
"new ResourceShutdownStage(\"session lifetime\"",
"new ResourceShutdownStage(\"host and session barriers\"",
StringComparison.Ordinal);
Assert.True(sessionStage >= 0);
int sessionOperation = source.IndexOf(
"new(\"live session\", () =>",
"Hard(\"live session\", () => DisposeLiveSession(ingress.LiveSession))",
sessionStage,
StringComparison.Ordinal);
Assert.True(sessionOperation > sessionStage);
int sessionDispose = source.IndexOf(
"controller.Dispose()",
int dependentStage = source.IndexOf(
"new ResourceShutdownStage(\"session dependents\"",
sessionOperation,
StringComparison.Ordinal);
Assert.True(sessionDispose > sessionOperation);
Assert.True(dependentStage > sessionOperation);
int streamerDispose = source.IndexOf(
"Hard(\"streamer\", () => live.Streamer?.Dispose())",
dependentStage,
StringComparison.Ordinal);
Assert.True(streamerDispose > dependentStage);
int helper = source.IndexOf(
"private static void DisposeLiveSession(LiveSessionController? controller)",
StringComparison.Ordinal);
Assert.True(helper > streamerDispose);
int sessionDispose = source.IndexOf(
"controller.Dispose()",
helper,
StringComparison.Ordinal);
Assert.True(sessionDispose > helper);
int disposalCompletionBarrier = source.IndexOf(
"if (!controller.IsDisposalComplete)",
@ -380,24 +396,10 @@ public sealed class LandblockBuildOriginTests
StringComparison.Ordinal);
Assert.True(disposalCompletionBarrier > sessionDispose);
int sessionReferenceRelease = source.IndexOf(
"_liveSessionController = null;",
disposalCompletionBarrier,
Assert.Contains(
"Live-session disposal was deferred by a reentrant lifecycle callback.",
source[disposalCompletionBarrier..],
StringComparison.Ordinal);
Assert.True(sessionReferenceRelease > disposalCompletionBarrier);
int dependentStage = source.IndexOf(
"new ResourceShutdownStage(\"session dependents\"",
sessionReferenceRelease,
StringComparison.Ordinal);
Assert.True(dependentStage > sessionReferenceRelease);
int streamerDispose = source.IndexOf(
"new(\"streamer\", () => _streamer?.Dispose())",
dependentStage,
StringComparison.Ordinal);
Assert.True(streamerDispose > dependentStage);
}
private static LandblockBuild EmptyBuild(uint landblockId, LandblockBuildOrigin origin) =>