summaryrefslogtreecommitdiff
path: root/main.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-06-29 16:13:11 -0300
committerGabriel Schneider <[email protected]>2026-06-29 16:27:08 -0300
commitee7c1940d8256a20ca7198ad1e0d51ac09f3bfe3 (patch)
tree9b08b794a0215be2f2159561503fcf53ac4171ac /main.zig
parenta44d2c53cae8f39975a7e2ecb7c254618aec4ae8 (diff)
downloadpardes-ee7c1940d8256a20ca7198ad1e0d51ac09f3bfe3.tar.gz
pardes-ee7c1940d8256a20ca7198ad1e0d51ac09f3bfe3.zip
resizing handlerterm
Diffstat (limited to 'main.zig')
-rw-r--r--main.zig69
1 files changed, 63 insertions, 6 deletions
diff --git a/main.zig b/main.zig
index 1181daf7..5d8cb228 100644
--- a/main.zig
+++ b/main.zig
@@ -64,6 +64,20 @@ fn fork_pty(argv: [:0]const u8, ws: std.posix.winsize) std.Io.File {
return f;
}
+// TIOCGWINSZ: ask the kernel what size the pty currently thinks it is.
+fn pty_get_size(pty: std.Io.File) std.posix.winsize {
+ var ws: std.posix.winsize = .{ .row = 0, .col = 0, .xpixel = 0, .ypixel = 0 };
+ _ = std.posix.system.ioctl(pty.handle, std.posix.T.IOCGWINSZ, @intFromPtr(&ws));
+ return ws;
+}
+
+// TIOCSWINSZ: set the pty size; the kernel raises SIGWINCH in the child (bash)
+// so it (and anything running in it) reflows to the new grid.
+fn pty_set_size(pty: std.Io.File, rows: u16, cols: u16) void {
+ const ws: std.posix.winsize = .{ .row = rows, .col = cols, .xpixel = 0, .ypixel = 0 };
+ _ = std.posix.system.ioctl(pty.handle, std.posix.T.IOCSWINSZ, @intFromPtr(&ws));
+}
+
fn readPty(io: std.Io, gpa: std.mem.Allocator, pty: std.Io.File, loop: *Loop) !void {
var read_buf: [0x1000]u8 = undefined;
var reader = pty.readerStreaming(io, &read_buf);
@@ -79,14 +93,20 @@ fn readPty(io: std.Io, gpa: std.mem.Allocator, pty: std.Io.File, loop: *Loop) !v
try loop.postEvent(.quit);
}
-const nrows = 64;
-const ncols = 100;
const term_x_padding = 3;
pub fn main(init: std.process.Init) !void {
const io = init.io;
const gpa = init.gpa;
+ // live grid size of the embedded terminal; recomputed on every resize.
+ // seeded so the pty/ghostty have something before the first winsize event.
+ var nrows: u16 = 64;
+ var ncols: u16 = 100;
+
+ // how many winsize events we've handled; shown on the debug panel.
+ var resize_count: usize = 0;
+
var term: ghostty_vt.Terminal = try .init(gpa, .{
.cols = ncols,
.rows = nrows,
@@ -123,6 +143,14 @@ pub fn main(init: std.process.Init) !void {
try loop.start();
defer loop.stop();
+ // start() only spawns the tty-read thread; it does NOT wire up resize
+ // delivery. Without this, the only winsize event we ever see is the initial
+ // one ttyRun posts, so the terminal never tracks the window after startup.
+ // installResizeHandler registers the SIGWINCH handler that posts a winsize
+ // event on every resize. (vaxis resets it automatically if the terminal
+ // later negotiates in-band resize via queryTerminal.)
+ try loop.installResizeHandler();
+
var pty_reader = try io.concurrent(readPty, .{ io, gpa, pty_master, &loop });
defer _ = pty_reader.cancel(io) catch {};
defer pty_master.close(io);
@@ -145,6 +173,9 @@ pub fn main(init: std.process.Init) !void {
if (mouse.button == .left and mouse.col <= term_x_padding) {
term.screens.active.scroll(.{ .delta_row = -(mouse.row) });
}
+
+ if (mouse.button == .left and mouse.col > term_x_padding) {}
+
if (mouse.button == .right and mouse.col <= term_x_padding) {
term.screens.active.scroll(.{ .delta_row = mouse.row });
}
@@ -190,7 +221,27 @@ pub fn main(init: std.process.Init) !void {
defer gpa.free(bytes);
term_stream.nextSlice(bytes);
},
- .winsize => |ws| try vx.resize(gpa, tty.writer(), ws),
+ .winsize => |ws| {
+ resize_count += 1;
+
+ // 1. let vaxis resize its own screen buffers
+ try vx.resize(gpa, tty.writer(), ws);
+
+ // 2. carve a new grid out of the window. layout is: left
+ // scrollbar gutter, then the terminal pane and the debug pane
+ // side by side, each wrapped in a 1-cell border. so the two
+ // panes split the leftover width, minus 4 cols of borders.
+ const usable: u16 = if (ws.cols > term_x_padding + 4) ws.cols - term_x_padding - 4 else 2;
+ // ncols = @max(1, usable / 2);
+ ncols = usable;
+ nrows = @max(1, if (ws.rows > 2) ws.rows - 2 else 1);
+
+ // 3. push it to ghostty's emulator grid
+ try term.resize(gpa, ncols, nrows);
+
+ // 4. push it to the pty so bash (and its children) reflow
+ pty_set_size(pty_master, nrows, ncols);
+ },
.quit => break,
else => {},
}
@@ -231,22 +282,28 @@ pub fn main(init: std.process.Init) !void {
const win_dbg = win.child(.{
.border = .{ .where = .all },
- .x_off = ncols + 2 + term_x_padding,
+ .x_off = (ncols / 2) + 2 + term_x_padding,
.height = nrows + 2,
- .width = ncols + 2,
+ .width = (ncols / 2) + 2,
});
win_child.clear();
_ = win_child.printSegment(.{ .text = tty_str }, .{});
win_child.showCursor(term.screens.active.cursor.x, term.screens.active.cursor.y);
+ const pty_ws = pty_get_size(pty_master);
const dbg_str = try std.fmt.bufPrintSentinel(
&dbg_print_buf,
- "c {} {}\npty pid {}\n wow it's working! debugging things will show here\n scroll {}/{} vis: {}\n",
+ "c {} {}\npty pid {}\n grid {}x{} pty {}x{}\n resizes={}\n scroll {}/{} vis: {}\n",
.{
pty_master.handle,
term.screens.active.cursor.x,
term.screens.active.cursor.y,
+ ncols,
+ nrows,
+ pty_ws.col,
+ pty_ws.row,
+ resize_count,
term.screens.active.pages.scrollbar().offset,
term.screens.active.pages.scrollbar().total,
term.screens.active.pages.scrollbar().len,