summaryrefslogtreecommitdiff
path: root/src/detached/client.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/detached/client.zig')
-rw-r--r--src/detached/client.zig32
1 files changed, 27 insertions, 5 deletions
diff --git a/src/detached/client.zig b/src/detached/client.zig
index ba533751..8c9a2560 100644
--- a/src/detached/client.zig
+++ b/src/detached/client.zig
@@ -103,8 +103,12 @@ pub const Client = struct {
grid: std.ArrayListUnmanaged(pardes.Cell) = .empty,
cursor: ?wire.Cursor = null,
pointer_shape: pardes.Surface.PointerShape = .arrow,
- body_layers: [pardes.MAX_PANES]pardes.BodyLayer = @splat(.{}),
- tag_layers: [pardes.MAX_TAG_LAYERS]pardes.TagLayer = @splat(.{}),
+ body_layers: [pardes.MAX_PANES]pardes.Layer = @splat(.{}),
+ tag_layers: [pardes.MAX_TAG_LAYERS]pardes.Layer = @splat(.{}),
+ /// The session's placed regions, as its last frame gave them.
+ regions: std.ArrayListUnmanaged(pardes.Region) = .empty,
+ /// The palette its chrome is drawn in, as its last frame gave it.
+ chrome: pardes.Chrome = .{},
in: std.ArrayListUnmanaged(u8) = .empty,
out: std.ArrayListUnmanaged(u8) = .empty,
/// Bytes of `in` belonging to the message `next` returned last. Compacted at
@@ -182,6 +186,7 @@ pub const Client = struct {
layer.* = .{};
}
for (&c.tag_layers) |*layer| c.gpa.free(layer.cells);
+ c.regions.deinit(c.gpa);
c.in.deinit(c.gpa);
c.out.deinit(c.gpa);
}
@@ -319,7 +324,7 @@ pub const Client = struct {
try c.reshape(f.cols, f.rows);
}
try f.apply(c.grid.items);
- f.applyLayers(c.gpa, &c.body_layers, &c.tag_layers) catch |err| return switch (err) {
+ f.applyLayers(c.gpa, &c.body_layers, &c.tag_layers, &c.regions, &c.chrome) catch |err| return switch (err) {
error.OutOfMemory => error.Closed,
else => @as(wire.Error, @errorCast(err)),
};
@@ -996,6 +1001,12 @@ test "detached session: a frontend that dies takes nothing with it" {
}
test "detached session: a frontend speaking another protocol is refused, loudly" {
+ // The protocol before this one (v7 carried one-row tags and no regions)
+ // and the one after.
+ for ([_]u16{ wire.version - 1, wire.version + 1 }) |claimed| try refusedHello(claimed);
+}
+
+fn refusedHello(claimed: u16) !void {
var h: Harness = undefined;
try h.init(60, 16);
defer h.deinit();
@@ -1007,7 +1018,7 @@ test "detached session: a frontend speaking another protocol is refused, loudly"
defer _ = libc.close(fd);
var buf: [64]u8 = undefined;
const hello = try wire.encodeClient(&buf, .{
- .hello = .{ .version = wire.version + 1, .cols = 60, .rows = 16 },
+ .hello = .{ .version = claimed, .cols = 60, .rows = 16 },
});
try testing.expectEqual(@as(isize, @intCast(hello.len)), libc.send(fd, hello.ptr, hello.len, nosignal));
@@ -1025,6 +1036,17 @@ test "detached session: a frontend speaking another protocol is refused, loudly"
try testing.expect(!h.core.quit);
}
+test "detached frontend: a session speaking another protocol is not attached to" {
+ for ([_]u16{ wire.version - 1, wire.version + 1 }) |claimed| {
+ var c: Client = .{ .gpa = testing.allocator };
+ defer c.deinit();
+ var buf: [64]u8 = undefined;
+ try c.in.appendSlice(testing.allocator, try wire.encodeServer(&buf, .{ .welcome = .{ .version = claimed, .slot = 0, .cols = 60, .rows = 16 } }));
+ try testing.expectError(error.Ungreeted, c.next());
+ try testing.expect(!c.attached());
+ }
+}
+
test "detached session: a peer that sends garbage is dropped, not obeyed" {
var h: Harness = undefined;
try h.init(60, 16);
@@ -1282,7 +1304,7 @@ fn pumpUntilNotice(h: *Harness, c: *Client, want: []const u8) !bool {
try c.wait(5);
while (try c.next()) |_| {}
for (&c.tag_layers) |*layer| {
- if (layer.cols == 0 or layer.kind != .notice) continue;
+ if (layer.rows == 0 or layer.kind != .notice) continue;
var n: usize = 0;
for (layer.cells[0..layer.cols]) |cell| {
const g = cell.grapheme();