Commit 66c8e0e
Eric Bower
·
2026-04-08 20:22:43 -0400 EDT
parent bdbf795
feat: change pty window size when new leader is set When we set a new client leader we send a Resize event request from the daemon to the client. So now whenever a user types into their stdin we set the new leader and then resize the window.
2 files changed,
+31,
-26
+1,
-0
| ... | ... | @@ -80,6 +80,7 @@ pub fn appendMessage( | |
| 80 | 80 | tag: Tag, | |
| 81 | 81 | data: []const u8, | |
| 82 | 82 | ) !void { | |
| 83 | + | std.log.info("sending ipc message tag={s}", .{@tagName(tag)}); | |
| 83 | 84 | const header = Header{ | |
| 84 | 85 | .tag = tag, | |
| 85 | 86 | .len = @intCast(data.len), |
+30,
-26
| ... | ... | @@ -319,11 +319,6 @@ const Cfg = struct { | |
| 319 | 319 | } | |
| 320 | 320 | }; | |
| 321 | 321 | ||
| 322 | - | const EnsureSessionResult = struct { | |
| 323 | - | created: bool, | |
| 324 | - | is_daemon: bool, | |
| 325 | - | }; | |
| 326 | - | ||
| 327 | 322 | /// Daemon is responsible for managing a zmx session. | |
| 328 | 323 | /// | |
| 329 | 324 | /// It holds all the state for a running session. Instead of a single daemon for all sessions, we |
| ... | ... | @@ -354,6 +349,11 @@ const Daemon = struct { | |
| 354 | 349 | task_command: ?[]const []const u8 = null, | |
| 355 | 350 | pty_write_buf: std.ArrayList(u8) = .empty, | |
| 356 | 351 | ||
| 352 | + | const EnsureSessionResult = struct { | |
| 353 | + | created: bool, | |
| 354 | + | is_daemon: bool, | |
| 355 | + | }; | |
| 356 | + | ||
| 357 | 357 | pub fn deinit(self: *Daemon) void { | |
| 358 | 358 | self.clients.deinit(self.alloc); | |
| 359 | 359 | self.pty_write_buf.deinit(self.alloc); |
| ... | ... | @@ -384,6 +384,15 @@ const Daemon = struct { | |
| 384 | 384 | return false; | |
| 385 | 385 | } | |
| 386 | 386 | ||
| 387 | + | fn setLeader(self: *Daemon, client: *Client) !void { | |
| 388 | + | std.log.info("setting new leader client_fd={d}", .{client.socket_fd}); | |
| 389 | + | self.leader_client_fd = client.socket_fd; | |
| 390 | + | // Send a resize message to the client so it can send us back their window size | |
| 391 | + | // so we can resize the pty and ghostty state. | |
| 392 | + | try ipc.appendMessage(self.alloc, &client.write_buf, .Resize, ""); | |
| 393 | + | client.has_pending_output = true; | |
| 394 | + | } | |
| 395 | + | ||
| 387 | 396 | /// Runs in the forked child. Either execs or returns an error (caller | |
| 388 | 397 | /// must exit on error -- returning would fall through to parent code). | |
| 389 | 398 | fn execChild(self: *Daemon) !noreturn { |
| ... | ... | @@ -598,11 +607,7 @@ const Daemon = struct { | |
| 598 | 607 | const isNewline = std.mem.indexOfScalar(u8, payload, '\r') != null; | |
| 599 | 608 | const isUpArrow = std.mem.eql(u8, payload, "\x1b[A") or util.isUpArrow(payload); | |
| 600 | 609 | if (isNewline or isUpArrow) { | |
| 601 | - | std.log.info( | |
| 602 | - | "setting new leader session={s} client_fd={d}", | |
| 603 | - | .{ self.session_name, client.socket_fd }, | |
| 604 | - | ); | |
| 605 | - | self.leader_client_fd = client.socket_fd; | |
| 610 | + | try self.setLeader(client); | |
| 606 | 611 | self.queuePtyInput(payload); | |
| 607 | 612 | return; | |
| 608 | 613 | } |
| ... | ... | @@ -623,11 +628,7 @@ const Daemon = struct { | |
| 623 | 628 | defer client.alloc.free(output); | |
| 624 | 629 | // if there's no text output then this client is effectively read-only until they type | |
| 625 | 630 | if (output.len > 0) { | |
| 626 | - | std.log.info( | |
| 627 | - | "setting new leader session={s} client_fd={d}", | |
| 628 | - | .{ self.session_name, client.socket_fd }, | |
| 629 | - | ); | |
| 630 | - | self.leader_client_fd = client.socket_fd; | |
| 631 | + | try self.setLeader(client); | |
| 631 | 632 | // new leader is set to this client so send *entire* payload | |
| 632 | 633 | self.queuePtyInput(payload); | |
| 633 | 634 | } |
| ... | ... | @@ -669,11 +670,7 @@ const Daemon = struct { | |
| 669 | 670 | ||
| 670 | 671 | // no leader is set so set one | |
| 671 | 672 | if (self.leader_client_fd == null) { | |
| 672 | - | std.log.info( | |
| 673 | - | "setting new leader session={s} client_fd={d}", | |
| 674 | - | .{ self.session_name, client.socket_fd }, | |
| 675 | - | ); | |
| 676 | - | self.leader_client_fd = client.socket_fd; | |
| 673 | + | try self.setLeader(client); | |
| 677 | 674 | } | |
| 678 | 675 | ||
| 679 | 676 | // only resize if leader |
| ... | ... | @@ -704,11 +701,7 @@ const Daemon = struct { | |
| 704 | 701 | ) !void { | |
| 705 | 702 | if (payload.len != @sizeOf(ipc.Resize)) return; | |
| 706 | 703 | if (self.leader_client_fd == null) { | |
| 707 | - | std.log.info( | |
| 708 | - | "setting new leader session={s} client_fd={d}", | |
| 709 | - | .{ self.session_name, client.socket_fd }, | |
| 710 | - | ); | |
| 711 | - | self.leader_client_fd = client.socket_fd; | |
| 704 | + | try self.setLeader(client); | |
| 712 | 705 | } | |
| 713 | 706 | // only leader can resize | |
| 714 | 707 | if (self.leader_client_fd != client.socket_fd) return; |
| ... | ... | @@ -1020,7 +1013,7 @@ fn wait(cfg: *Cfg, session_names: std.ArrayList([]const u8)) !void { | |
| 1020 | 1013 | } | |
| 1021 | 1014 | } | |
| 1022 | 1015 | ||
| 1023 | - | std.Thread.sleep(3000 * std.time.ns_per_ms); | |
| 1016 | + | std.Thread.sleep(1000 * std.time.ns_per_ms); | |
| 1024 | 1017 | } | |
| 1025 | 1018 | } | |
| 1026 | 1019 |
| ... | ... | @@ -1529,6 +1522,17 @@ fn clientLoop(client_sock_fd: i32) !void { | |
| 1529 | 1522 | try stdout_buf.appendSlice(alloc, msg.payload); | |
| 1530 | 1523 | } | |
| 1531 | 1524 | }, | |
| 1525 | + | .Resize => { | |
| 1526 | + | // daemon is asking for the client's window size usually in response | |
| 1527 | + | // to this client being set as leader. | |
| 1528 | + | const next_size = ipc.getTerminalSize(posix.STDOUT_FILENO); | |
| 1529 | + | try ipc.appendMessage( | |
| 1530 | + | alloc, | |
| 1531 | + | &sock_write_buf, | |
| 1532 | + | .Resize, | |
| 1533 | + | std.mem.asBytes(&next_size), | |
| 1534 | + | ); | |
| 1535 | + | }, | |
| 1532 | 1536 | else => {}, | |
| 1533 | 1537 | } | |
| 1534 | 1538 | } |