feat: implement mode 2048 in band resize reports

Implement mode 2048 for in-band window resize reports.

Reference: https://gist.github.com/rockorager/e695fb2924d36b2bcf1fff4a3704bd83
This commit is contained in:
Tim Culverhouse 2024-06-30 11:45:43 -05:00
parent 9b78bb8a78
commit edaeb17f3d
5 changed files with 45 additions and 1 deletions

View file

@ -32,6 +32,7 @@ Unix-likes.
| Synchronized Output (DEC 2026) | ✅ |
| Unicode Core (DEC 2027) | ✅ |
| Color Mode Updates (DEC 2031) | ✅ |
| [In-Band Resize Reports](https://gist.github.com/rockorager/e695fb2924d36b2bcf1fff4a3704bd83) | ✅ |
| Images (kitty) | ✅ |
## Usage

View file

@ -89,6 +89,8 @@ pub fn Loop(comptime T: type) type {
pub fn winsizeCallback(ptr: *anyopaque) void {
const self: *Self = @ptrCast(@alignCast(ptr));
// We will be receiving winsize updates in-band
if (self.vaxis.state.in_band_resize) return;
const winsize = Tty.getWinsize(self.tty.fd) catch return;
if (@hasField(Event, "winsize")) {
@ -286,7 +288,12 @@ pub fn handleEventGeneric(self: anytype, vx: *Vaxis, cache: *GraphemeCache, Even
.cap_da1 => {
std.Thread.Futex.wake(&vx.query_futex, 10);
},
.winsize => unreachable, // handled elsewhere for posix
.winsize => |winsize| {
vx.state.in_band_resize = true;
if (@hasField(Event, "winsize")) {
self.postEvent(.{ .winsize = winsize });
}
},
}
},
}

View file

@ -6,6 +6,7 @@ const Key = @import("Key.zig");
const Mouse = @import("Mouse.zig");
const code_point = @import("code_point");
const grapheme = @import("grapheme");
const Winsize = @import("main.zig").Winsize;
const log = std.log.scoped(.parser);
@ -470,6 +471,31 @@ inline fn parseCsi(input: []const u8, text_buf: []u8) Result {
else => return null_event,
}
},
't' => {
// XTWINOPS
// Split first into fields delimited by ';'
var iter = std.mem.splitScalar(u8, sequence[2 .. sequence.len - 1], ';');
const ps = iter.first();
if (std.mem.eql(u8, "48", ps)) {
// in band window resize
const width_char = iter.next() orelse return null_event;
const height_char = iter.next() orelse return null_event;
const width_pix = iter.next() orelse "0";
const height_pix = iter.next() orelse "0";
const winsize: Winsize = .{
.rows = std.fmt.parseUnsigned(usize, height_char, 10) catch return null_event,
.cols = std.fmt.parseUnsigned(usize, width_char, 10) catch return null_event,
.x_pixel = std.fmt.parseUnsigned(usize, width_pix, 10) catch return null_event,
.y_pixel = std.fmt.parseUnsigned(usize, height_pix, 10) catch return null_event,
};
return .{
.event = .{ .winsize = winsize },
.n = sequence.len,
};
}
return null_event;
},
'u' => {
// Kitty keyboard
// CSI unicode-key-code:alternate-key-codes ; modifiers:event-type ; text-as-codepoints u

View file

@ -85,6 +85,7 @@ state: struct {
mouse: bool = false,
pixel_mouse: bool = false,
color_scheme_updates: bool = false,
in_band_resize: bool = false,
cursor: struct {
row: usize = 0,
col: usize = 0,
@ -151,6 +152,10 @@ pub fn resetState(self: *Vaxis, tty: AnyWriter) !void {
try tty.writeAll(ctlseqs.color_scheme_reset);
self.state.color_scheme_updates = false;
}
if (self.state.in_band_resize) {
try tty.writeAll(ctlseqs.in_band_resize_reset);
self.state.in_band_resize = false;
}
}
/// resize allocates a slice of cells equal to the number of cells
@ -244,6 +249,7 @@ pub fn queryTerminalSend(_: Vaxis, tty: AnyWriter) !void {
try tty.writeAll(ctlseqs.decrqm_sgr_pixels ++
ctlseqs.decrqm_unicode ++
ctlseqs.decrqm_color_scheme ++
ctlseqs.in_band_resize_set ++
ctlseqs.xtversion ++
ctlseqs.csi_u_query ++
ctlseqs.kitty_graphics_query ++

View file

@ -20,6 +20,10 @@ pub const mouse_set = "\x1b[?1002;1003;1004;1006h";
pub const mouse_set_pixels = "\x1b[?1002;1003;1004;1016h";
pub const mouse_reset = "\x1b[?1002;1003;1004;1006;1016l";
// in-band window size reports
pub const in_band_resize_set = "\x1b[?2048h";
pub const in_band_resize_reset = "\x1b[?2048l";
// sync
pub const sync_set = "\x1b[?2026h";
pub const sync_reset = "\x1b[?2026l";