- commit
- 8640be5
- parent
- 6e33c6b
- author
- Eric Bower
- date
- 2025-11-26 20:09:54 -0500 EST
feat: handle resize events
1 files changed,
+41,
-0
+41,
-0
1@@ -40,6 +40,29 @@ const c = switch (builtin.os.tag) {
2 }),
3 };
4
5+var sigwinch_received: std.atomic.Value(bool) = std.atomic.Value(bool).init(false);
6+
7+fn handleSigwinch(_: i32, _: *const posix.siginfo_t, _: ?*anyopaque) callconv(.c) void {
8+ sigwinch_received.store(true, .release);
9+}
10+
11+fn setupSigwinchHandler() void {
12+ const act: posix.Sigaction = .{
13+ .handler = .{ .sigaction = handleSigwinch },
14+ .mask = posix.sigemptyset(),
15+ .flags = posix.SA.SIGINFO,
16+ };
17+ posix.sigaction(posix.SIG.WINCH, &act, null);
18+}
19+
20+fn getTerminalSize() ?ipc.Resize {
21+ var ws: c.struct_winsize = undefined;
22+ if (c.ioctl(posix.STDOUT_FILENO, c.TIOCGWINSZ, &ws) == 0) {
23+ return .{ .rows = ws.ws_row, .cols = ws.ws_col };
24+ }
25+ return null;
26+}
27+
28 const Client = struct {
29 alloc: std.mem.Allocator,
30 socket_fd: i32,
31@@ -415,6 +438,13 @@ fn clientLoop(_: *Cfg, client_sock_fd: i32) !void {
32 const alloc = std.heap.c_allocator;
33 defer posix.close(client_sock_fd);
34
35+ setupSigwinchHandler();
36+
37+ // Send initial terminal size
38+ if (getTerminalSize()) |size| {
39+ ipc.send(client_sock_fd, .Resize, std.mem.asBytes(&size)) catch {};
40+ }
41+
42 var poll_fds = try std.ArrayList(posix.pollfd).initCapacity(alloc, 2);
43 defer poll_fds.deinit(alloc);
44
45@@ -431,6 +461,16 @@ fn clientLoop(_: *Cfg, client_sock_fd: i32) !void {
46 _ = try posix.fcntl(stdin_fd, posix.F.SETFL, flags | posix.SOCK.NONBLOCK);
47
48 while (true) {
49+ // Check for pending SIGWINCH
50+ if (sigwinch_received.swap(false, .acq_rel)) {
51+ if (getTerminalSize()) |size| {
52+ ipc.send(client_sock_fd, .Resize, std.mem.asBytes(&size)) catch |err| switch (err) {
53+ error.BrokenPipe, error.ConnectionResetByPeer => return,
54+ else => return err,
55+ };
56+ }
57+ }
58+
59 poll_fds.clearRetainingCapacity();
60
61 try poll_fds.append(alloc, .{
62@@ -454,6 +494,7 @@ fn clientLoop(_: *Cfg, client_sock_fd: i32) !void {
63 }
64
65 _ = posix.poll(poll_fds.items, -1) catch |err| {
66+ if (err == error.Interrupted) continue; // EINTR from signal, loop again
67 return err;
68 };
69