Commit 7381df3
이영수
·
2026-06-28 09:25:44 -0400 EDT
parent 4e2d02b
fix: forward real terminal pixel size instead of hardcoding 0x0 (#174)
ipc.Resize only carried rows/cols, and getTerminalSize() dropped the
ws_xpixel/ws_ypixel fields read from TIOCGWINSZ. The daemon's three
TIOCSWINSZ call sites (spawnPty, handleInit, handleResize) then hardcoded
ws_xpixel/ws_ypixel to 0 on the inner pty, regardless of what the real
terminal reported.
This breaks Kitty graphics-protocol image sizing for anything running
inside a zmx session, since image dimensions in cells get computed from
a pixel-per-cell ratio that is always 0. nvim plugins like snacks.nvim
report `{cell}: 0 x 0 pixels` and scale images to nothing before sending
them to the terminal.
Add xpixel/ypixel to ipc.Resize, populate them from the real
ioctl(TIOCGWINSZ) result on the client side, and thread them through to
the daemon's TIOCSWINSZ calls instead of hardcoding 0.
2 files changed,
+9,
-7
+3,
-1
| ... | ... | @@ -38,12 +38,14 @@ pub const Header = packed struct { | |
| 38 | 38 | pub const Resize = packed struct { | |
| 39 | 39 | rows: u16, | |
| 40 | 40 | cols: u16, | |
| 41 | + | xpixel: u16 = 0, | |
| 42 | + | ypixel: u16 = 0, | |
| 41 | 43 | }; | |
| 42 | 44 | ||
| 43 | 45 | pub fn getTerminalSize(fd: i32) Resize { | |
| 44 | 46 | var ws: cross.c.struct_winsize = undefined; | |
| 45 | 47 | if (cross.c.ioctl(fd, cross.c.TIOCGWINSZ, &ws) == 0 and ws.ws_row > 0 and ws.ws_col > 0) { | |
| 46 | - | return .{ .rows = ws.ws_row, .cols = ws.ws_col }; | |
| 48 | + | return .{ .rows = ws.ws_row, .cols = ws.ws_col, .xpixel = ws.ws_xpixel, .ypixel = ws.ws_ypixel }; | |
| 47 | 49 | } | |
| 48 | 50 | return .{ .rows = 24, .cols = 160 }; | |
| 49 | 51 | } |
+6,
-6
| ... | ... | @@ -702,8 +702,8 @@ const Daemon = struct { | |
| 702 | 702 | var ws: cross.c.struct_winsize = .{ | |
| 703 | 703 | .ws_row = size.rows, | |
| 704 | 704 | .ws_col = size.cols, | |
| 705 | - | .ws_xpixel = 0, | |
| 706 | - | .ws_ypixel = 0, | |
| 705 | + | .ws_xpixel = size.xpixel, | |
| 706 | + | .ws_ypixel = size.ypixel, | |
| 707 | 707 | }; | |
| 708 | 708 | ||
| 709 | 709 | var master_fd: c_int = undefined; |
| ... | ... | @@ -978,8 +978,8 @@ const Daemon = struct { | |
| 978 | 978 | var ws: cross.c.struct_winsize = .{ | |
| 979 | 979 | .ws_row = resize.rows, | |
| 980 | 980 | .ws_col = resize.cols, | |
| 981 | - | .ws_xpixel = 0, | |
| 982 | - | .ws_ypixel = 0, | |
| 981 | + | .ws_xpixel = resize.xpixel, | |
| 982 | + | .ws_ypixel = resize.ypixel, | |
| 983 | 983 | }; | |
| 984 | 984 | _ = cross.c.ioctl(pty_fd, cross.c.TIOCSWINSZ, &ws); | |
| 985 | 985 | // Disable prompt_redraw before resize. The daemon's internal terminal |
| ... | ... | @@ -1017,8 +1017,8 @@ const Daemon = struct { | |
| 1017 | 1017 | var ws: cross.c.struct_winsize = .{ | |
| 1018 | 1018 | .ws_row = resize.rows, | |
| 1019 | 1019 | .ws_col = resize.cols, | |
| 1020 | - | .ws_xpixel = 0, | |
| 1021 | - | .ws_ypixel = 0, | |
| 1020 | + | .ws_xpixel = resize.xpixel, | |
| 1021 | + | .ws_ypixel = resize.ypixel, | |
| 1022 | 1022 | }; | |
| 1023 | 1023 | _ = cross.c.ioctl(pty_fd, cross.c.TIOCSWINSZ, &ws); | |
| 1024 | 1024 | // Disable prompt_redraw before resize (same rationale as handleInit). |