summaryrefslogtreecommitdiff
path: root/src/detached/server.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/detached/server.zig')
-rw-r--r--src/detached/server.zig25
1 files changed, 19 insertions, 6 deletions
diff --git a/src/detached/server.zig b/src/detached/server.zig
index 8fc7b96e..5374bf73 100644
--- a/src/detached/server.zig
+++ b/src/detached/server.zig
@@ -150,6 +150,8 @@ pub const Session = struct {
worker_gpa: std.mem.Allocator,
io: std.Io,
core: *pardes.Pardes,
+ /// PARDES_TEST_CLOCK's virtual time (host_io.testClock).
+ test_clock: ?u64 = null,
listener: c_int = -1,
path_buf: [sun_path_len]u8 = undefined,
path_len: usize = 0,
@@ -355,8 +357,14 @@ pub const Session = struct {
return @ptrCast(@alignCast(ctx.?));
}
+ fn clockNow(ctx: ?*anyopaque) u64 {
+ const s = of(ctx);
+ return s.test_clock orelse host_io.monotonicNs();
+ }
+
const vtable: host_io.Host.VTable = .{
.wait_input = waitInput,
+ .now = clockNow,
.present = present,
.poll_frame = pollFrame,
.spawn = spawn,
@@ -767,7 +775,7 @@ pub const Session = struct {
fn sendFrame(s: *Session, c: *Client, surface: *const pardes.Surface) void {
const cells = surface.cells;
- const want = wire.frameBound(surface.cols, surface.rows) + wire.layersBound(&surface.body_layers, &surface.tag_layers);
+ const want = wire.frameBound(surface.cols, surface.rows) + wire.layersBound(&surface.body_layers, &surface.tag_layers, surface.regionList());
s.scratch.ensureTotalCapacity(s.gpa, want) catch return s.close(c, .oom);
const prev: []const pardes.Cell = if (c.need_full or c.mirror.items.len != cells.len)
&.{}
@@ -787,6 +795,8 @@ pub const Session = struct {
prev,
&surface.body_layers,
&surface.tag_layers,
+ surface.regionList(),
+ surface.chrome,
) catch |err| {
log.debug("frame {d}x{d} not encodable: {t}", .{ surface.cols, surface.rows, err });
return;
@@ -867,8 +877,9 @@ pub const Session = struct {
pardes.turn.rest();
nap(if (timeout_ms == 0) 16 else timeout_ms);
pardes.turn.wake();
- // An animating frame's wait is the frame: tick it.
- if (timeout_ms != 0) s.core.update(.tick);
+ if (timeout_ms != 0) if (s.test_clock) |*virtual| {
+ virtual.* = @max(virtual.*, s.core.nextWake() orelse virtual.*);
+ };
return;
}
var timeout: c_int = if (timeout_ms == 0) -1 else @intCast(@min(timeout_ms, std.math.maxInt(c_int)));
@@ -878,9 +889,10 @@ pub const Session = struct {
const ready = libc.poll(&fds, @intCast(n), timeout);
pardes.turn.wake();
if (ready > 0) s.dispatch(fds[0..n], src[0..n]);
- // Animating, the frame's time is up: advance it. There is no other
- // tick in a detached session, and without it an animation never ends.
- if (timeout_ms != 0 and monotonicMs() -| now >= timeout_ms) s.core.update(.tick);
+ // The core's wake ran out; the pump advances it from `now`.
+ if (timeout_ms != 0 and monotonicMs() -| now >= timeout_ms) if (s.test_clock) |*virtual| {
+ virtual.* = @max(virtual.*, s.core.nextWake() orelse virtual.*);
+ };
_ = s.drainCompletions(true);
s.takeExits();
s.expire(monotonicMs());
@@ -1212,6 +1224,7 @@ pub fn run(init: std.process.Init, opts: pardes.Options, name: []const u8) !void
.cols = options.cols,
.rows = options.rows,
.prompt_rcs = host_io.Shell.prepare(),
+ .test_clock = host_io.testClock(),
};
defer session.core.deinit();
defer session.deinit();