b1c9ad85
main: thread optional ScenarioState through runTerminal
a73x 2026-04-19 13:26
Commit message
build.zig
| Old | New | ||
|---|---|---|---|
| @@ -391,6 +391,17 @@ pub fn build(b: *std.Build) void { | |||
| 391 | scenario_mod.addImport("png", png_mod); | 391 | scenario_mod.addImport("png", png_mod); |
| 392 | scenario_mod.addImport("imgdiff", imgdiff_lib_mod); | 392 | scenario_mod.addImport("imgdiff", imgdiff_lib_mod); |
| 393 | 393 | ||
| 394 | // scenario_runtime stub module (Task 3 populates) | ||
| 395 | const scenario_runtime_mod = b.createModule(.{ | ||
| 396 | .root_source_file = b.path("src/scenario_runtime.zig"), | ||
| 397 | .target = target, | ||
| 398 | .optimize = optimize, | ||
| 399 | }); | ||
| 400 | scenario_runtime_mod.addImport("scenario", scenario_mod); | ||
| 401 | |||
| 402 | exe_mod.addImport("scenario", scenario_mod); | ||
| 403 | exe_mod.addImport("scenario_runtime", scenario_runtime_mod); | ||
| 404 | |||
| 394 | const scenario_test_mod = b.createModule(.{ | 405 | const scenario_test_mod = b.createModule(.{ |
| 395 | .root_source_file = b.path("src/scenario.zig"), | 406 | .root_source_file = b.path("src/scenario.zig"), |
| 396 | .target = target, | 407 | .target = target, |
src/main.zig
| Old | New | ||
|---|---|---|---|
| @@ -1,6 +1,8 @@ | |||
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const vt = @import("vt"); | 2 | const vt = @import("vt"); |
| 3 | const pty = @import("pty"); | 3 | const pty = @import("pty"); |
| 4 | const scenario = @import("scenario"); | ||
| 5 | const scenario_runtime = @import("scenario_runtime"); | ||
| 4 | const wayland_client = @import("wayland-client"); | 6 | const wayland_client = @import("wayland-client"); |
| 5 | const frame_loop_mod = @import("frame_loop"); | 7 | const frame_loop_mod = @import("frame_loop"); |
| 6 | const renderer = @import("renderer"); | 8 | const renderer = @import("renderer"); |
| @@ -126,6 +128,16 @@ fn writeBenchJson(alloc: std.mem.Allocator, stats: FrameTimingStats, workload: ? | |||
| 126 | try out.writeAll(json_bytes); | 128 | try out.writeAll(json_bytes); |
| 127 | } | 129 | } |
| 128 | 130 | ||
| 131 | fn loopShouldRun(p: *pty.Pty, tick_ctx: ?*scenario_runtime.RunContext) bool { | ||
| 132 | if (tick_ctx) |rc| { | ||
| 133 | // Scenario mode — check state inside RunContext. Task 3 populates this field. | ||
| 134 | if (rc.state) |s| { | ||
| 135 | if (s.isDone()) return false; | ||
| 136 | } | ||
| 137 | } | ||
| 138 | return p.isChildAlive(); | ||
| 139 | } | ||
| 140 | |||
| 129 | pub fn main() !void { | 141 | pub fn main() !void { |
| 130 | var gpa: std.heap.DebugAllocator(.{}) = .init; | 142 | var gpa: std.heap.DebugAllocator(.{}) = .init; |
| 131 | defer _ = gpa.deinit(); | 143 | defer _ = gpa.deinit(); |
| @@ -167,10 +179,10 @@ pub fn main() !void { | |||
| 167 | return capture.run(alloc, args[1..]); | 179 | return capture.run(alloc, args[1..]); |
| 168 | } | 180 | } |
| 169 | 181 | ||
| 170 | return runTerminal(alloc); | 182 | return runTerminal(alloc, null); |
| 171 | } | 183 | } |
| 172 | 184 | ||
| 173 | fn runTerminal(alloc: std.mem.Allocator) !void { | 185 | fn runTerminal(alloc: std.mem.Allocator, tick_ctx: ?*scenario_runtime.RunContext) !void { |
| 174 | // === font first, to know cell size === | 186 | // === font first, to know cell size === |
| 175 | var font_lookup = try font.lookupConfiguredFont(alloc); | 187 | var font_lookup = try font.lookupConfiguredFont(alloc); |
| 176 | defer font_lookup.deinit(alloc); | 188 | defer font_lookup.deinit(alloc); |
| @@ -341,7 +353,7 @@ fn runTerminal(alloc: std.mem.Allocator) !void { | |||
| 341 | var blink_state: BlinkState = .{}; | 353 | var blink_state: BlinkState = .{}; |
| 342 | var previous_has_focus: bool = keyboard.has_focus; | 354 | var previous_has_focus: bool = keyboard.has_focus; |
| 343 | 355 | ||
| 344 | while (!window.should_close and p.isChildAlive()) { | 356 | while (!window.should_close and loopShouldRun(&p, tick_ctx)) { |
| 345 | const repeat_timeout_ms = remainingRepeatTimeoutMs(keyboard.nextRepeatDeadlineNs()); | 357 | const repeat_timeout_ms = remainingRepeatTimeoutMs(keyboard.nextRepeatDeadlineNs()); |
| 346 | const blink_timeout_ms = remainingRepeatTimeoutMs(blink_state.next_deadline_ns); | 358 | const blink_timeout_ms = remainingRepeatTimeoutMs(blink_state.next_deadline_ns); |
| 347 | const timeout = computePollTimeoutMs(repeat_timeout_ms, blink_timeout_ms, render_pending); | 359 | const timeout = computePollTimeoutMs(repeat_timeout_ms, blink_timeout_ms, render_pending); |
| @@ -3527,5 +3539,5 @@ fn runHiddenFreezeRegression(alloc: std.mem.Allocator) !void { | |||
| 3527 | var buf: [1]u8 = undefined; | 3539 | var buf: [1]u8 = undefined; |
| 3528 | _ = try stdin_file.read(&buf); | 3540 | _ = try stdin_file.read(&buf); |
| 3529 | 3541 | ||
| 3530 | return runTerminal(alloc); | 3542 | return runTerminal(alloc, null); |
| 3531 | } | 3543 | } |
src/scenario_runtime.zig
| Old | New | ||
|---|---|---|---|
| @@ -0,0 +1,5 @@ | |||
| 1 | // src/scenario_runtime.zig (STUB — Task 3 replaces) | ||
| 2 | const scenario = @import("scenario"); | ||
| 3 | pub const RunContext = struct { | ||
| 4 | state: ?*scenario.ScenarioState = null, | ||
| 5 | }; | ||