vaxis: add support for color scheme updates
This commit is contained in:
parent
0fa082033e
commit
93ac8e00f8
7 changed files with 89 additions and 4 deletions
|
@ -30,7 +30,7 @@ Vaxis uses zig `0.12.0`.
|
||||||
| System Notifications (OSC 777) | ✅ | ✅ | ❌ |
|
| System Notifications (OSC 777) | ✅ | ✅ | ❌ |
|
||||||
| Synchronized Output (DEC 2026) | ✅ | ✅ | ✅ |
|
| Synchronized Output (DEC 2026) | ✅ | ✅ | ✅ |
|
||||||
| Unicode Core (DEC 2027) | ✅ | ✅ | ❌ |
|
| Unicode Core (DEC 2027) | ✅ | ✅ | ❌ |
|
||||||
| Color Mode Updates (DEC 2031) | ✅ | planned | ❌ |
|
| Color Mode Updates (DEC 2031) | ✅ | ✅ | ❌ |
|
||||||
| Images (full/space) | ✅ | planned | ✅ |
|
| Images (full/space) | ✅ | planned | ✅ |
|
||||||
| Images (half block) | ✅ | planned | ✅ |
|
| Images (half block) | ✅ | planned | ✅ |
|
||||||
| Images (quadrant) | ✅ | planned | ✅ |
|
| Images (quadrant) | ✅ | planned | ✅ |
|
||||||
|
|
|
@ -118,6 +118,11 @@ pub const Color = union(enum) {
|
||||||
value: [3]u8,
|
value: [3]u8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Scheme = enum {
|
||||||
|
dark,
|
||||||
|
light,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn eql(a: Color, b: Color) bool {
|
pub fn eql(a: Color, b: Color) bool {
|
||||||
switch (a) {
|
switch (a) {
|
||||||
.default => return b == .default,
|
.default => return b == .default,
|
||||||
|
|
|
@ -341,6 +341,47 @@ pub fn parse(self: *Parser, input: []const u8, paste_allocator: ?std.mem.Allocat
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'n' => {
|
||||||
|
switch (seq.params[0]) {
|
||||||
|
5 => {
|
||||||
|
// "Ok" response
|
||||||
|
return .{
|
||||||
|
.event = null,
|
||||||
|
.n = i + 1,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
997 => {
|
||||||
|
switch (seq.params[1]) {
|
||||||
|
1 => {
|
||||||
|
return .{
|
||||||
|
.event = .{ .color_scheme = .dark },
|
||||||
|
.n = i + 1,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
2 => {
|
||||||
|
return .{
|
||||||
|
.event = .{ .color_scheme = .dark },
|
||||||
|
.n = i + 1,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
|
||||||
|
return .{
|
||||||
|
.event = null,
|
||||||
|
.n = i + 1,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
|
||||||
|
return .{
|
||||||
|
.event = null,
|
||||||
|
.n = i + 1,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
'u' => blk: {
|
'u' => blk: {
|
||||||
if (seq.private_indicator) |priv| {
|
if (seq.private_indicator) |priv| {
|
||||||
// response to our kitty query
|
// response to our kitty query
|
||||||
|
@ -417,7 +458,12 @@ pub fn parse(self: *Parser, input: []const u8, paste_allocator: ?std.mem.Allocat
|
||||||
else => return .{ .event = .cap_unicode, .n = i + 1 },
|
else => return .{ .event = .cap_unicode, .n = i + 1 },
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
2031 => {},
|
2031 => {
|
||||||
|
switch (seq.params[1]) {
|
||||||
|
0, 4 => return .{ .event = null, .n = i + 1 },
|
||||||
|
else => return .{ .event = .cap_color_scheme_updates, .n = i + 1 },
|
||||||
|
}
|
||||||
|
},
|
||||||
else => {
|
else => {
|
||||||
log.warn("unhandled DECRPM: CSI {s}", .{input[start + 1 .. i + 1]});
|
log.warn("unhandled DECRPM: CSI {s}", .{input[start + 1 .. i + 1]});
|
||||||
return .{ .event = null, .n = i + 1 };
|
return .{ .event = null, .n = i + 1 };
|
||||||
|
|
13
src/Tty.zig
13
src/Tty.zig
|
@ -32,6 +32,7 @@ state: struct {
|
||||||
bracketed_paste: bool = false,
|
bracketed_paste: bool = false,
|
||||||
mouse: bool = false,
|
mouse: bool = false,
|
||||||
pixel_mouse: bool = false,
|
pixel_mouse: bool = false,
|
||||||
|
color_scheme_updates: bool = false,
|
||||||
cursor: struct {
|
cursor: struct {
|
||||||
row: usize = 0,
|
row: usize = 0,
|
||||||
col: usize = 0,
|
col: usize = 0,
|
||||||
|
@ -67,6 +68,9 @@ pub fn deinit(self: *Tty) void {
|
||||||
if (self.state.alt_screen) {
|
if (self.state.alt_screen) {
|
||||||
_ = self.write(ctlseqs.rmcup) catch {};
|
_ = self.write(ctlseqs.rmcup) catch {};
|
||||||
}
|
}
|
||||||
|
if (self.state.color_scheme_updates) {
|
||||||
|
_ = self.write(ctlseqs.color_scheme_reset) catch {};
|
||||||
|
}
|
||||||
// always show the cursor on exit
|
// always show the cursor on exit
|
||||||
_ = self.write(ctlseqs.show_cursor) catch {};
|
_ = self.write(ctlseqs.show_cursor) catch {};
|
||||||
self.flush() catch {};
|
self.flush() catch {};
|
||||||
|
@ -224,6 +228,11 @@ pub fn run(
|
||||||
loop.postEvent(.{ .color_report = report });
|
loop.postEvent(.{ .color_report = report });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.color_scheme => |scheme| {
|
||||||
|
if (@hasField(Event, "color_scheme")) {
|
||||||
|
loop.postEvent(.{ .color_scheme = scheme });
|
||||||
|
}
|
||||||
|
},
|
||||||
.cap_kitty_keyboard => {
|
.cap_kitty_keyboard => {
|
||||||
log.info("kitty keyboard capability detected", .{});
|
log.info("kitty keyboard capability detected", .{});
|
||||||
loop.vaxis.caps.kitty_keyboard = true;
|
loop.vaxis.caps.kitty_keyboard = true;
|
||||||
|
@ -247,6 +256,10 @@ pub fn run(
|
||||||
log.info("pixel mouse capability detected", .{});
|
log.info("pixel mouse capability detected", .{});
|
||||||
loop.vaxis.caps.sgr_pixels = true;
|
loop.vaxis.caps.sgr_pixels = true;
|
||||||
},
|
},
|
||||||
|
.cap_color_scheme_updates => {
|
||||||
|
log.info("color_scheme_updates capability detected", .{});
|
||||||
|
loop.vaxis.caps.color_scheme_updates = true;
|
||||||
|
},
|
||||||
.cap_da1 => {
|
.cap_da1 => {
|
||||||
std.Thread.Futex.wake(&loop.vaxis.query_futex, 10);
|
std.Thread.Futex.wake(&loop.vaxis.query_futex, 10);
|
||||||
},
|
},
|
||||||
|
|
|
@ -32,6 +32,7 @@ pub const Capabilities = struct {
|
||||||
rgb: bool = false,
|
rgb: bool = false,
|
||||||
unicode: gwidth.Method = .wcwidth,
|
unicode: gwidth.Method = .wcwidth,
|
||||||
sgr_pixels: bool = false,
|
sgr_pixels: bool = false,
|
||||||
|
color_scheme_updates: bool = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Options = struct {
|
pub const Options = struct {
|
||||||
|
@ -202,7 +203,7 @@ pub fn queryTerminalSend(self: *Vaxis) !void {
|
||||||
// _ = try tty.write(ctlseqs.decrqm_sync);
|
// _ = try tty.write(ctlseqs.decrqm_sync);
|
||||||
_ = try tty.write(ctlseqs.decrqm_sgr_pixels);
|
_ = try tty.write(ctlseqs.decrqm_sgr_pixels);
|
||||||
_ = try tty.write(ctlseqs.decrqm_unicode);
|
_ = try tty.write(ctlseqs.decrqm_unicode);
|
||||||
_ = try tty.write(ctlseqs.decrqm_color_theme);
|
_ = try tty.write(ctlseqs.decrqm_color_scheme);
|
||||||
// TODO: XTVERSION has a DCS response. uncomment when we can parse
|
// TODO: XTVERSION has a DCS response. uncomment when we can parse
|
||||||
// that
|
// that
|
||||||
// _ = try tty.write(ctlseqs.xtversion);
|
// _ = try tty.write(ctlseqs.xtversion);
|
||||||
|
@ -872,3 +873,16 @@ pub fn queryColor(self: Vaxis, kind: Cell.Color.Kind) !void {
|
||||||
}
|
}
|
||||||
try tty.flush();
|
try tty.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Subscribe to color theme updates. A `color_scheme: Color.Scheme` tag must
|
||||||
|
/// exist on your Event type to receive the response. This is a queried
|
||||||
|
/// capability. Support can be detected by checking the value of
|
||||||
|
/// vaxis.caps.color_scheme_updates. The initial scheme will be reported when
|
||||||
|
/// subscribing.
|
||||||
|
pub fn subscribeToColorSchemeUpdates(self: Vaxis) !void {
|
||||||
|
var tty = self.tty orelse return;
|
||||||
|
_ = try tty.write(ctlseqs.color_scheme_request);
|
||||||
|
_ = try tty.write(ctlseqs.color_scheme_set);
|
||||||
|
try tty.flush();
|
||||||
|
tty.state.color_scheme_updates = true;
|
||||||
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ pub const decrqm_focus = "\x1b[?1004$p";
|
||||||
pub const decrqm_sgr_pixels = "\x1b[?1016$p";
|
pub const decrqm_sgr_pixels = "\x1b[?1016$p";
|
||||||
pub const decrqm_sync = "\x1b[?2026$p";
|
pub const decrqm_sync = "\x1b[?2026$p";
|
||||||
pub const decrqm_unicode = "\x1b[?2027$p";
|
pub const decrqm_unicode = "\x1b[?2027$p";
|
||||||
pub const decrqm_color_theme = "\x1b[?2031$p";
|
pub const decrqm_color_scheme = "\x1b[?2031$p";
|
||||||
pub const csi_u_query = "\x1b[?u";
|
pub const csi_u_query = "\x1b[?u";
|
||||||
pub const kitty_graphics_query = "\x1b_Gi=1,a=q\x1b\\";
|
pub const kitty_graphics_query = "\x1b_Gi=1,a=q\x1b\\";
|
||||||
pub const sixel_geometry_query = "\x1b[?2;1;0S";
|
pub const sixel_geometry_query = "\x1b[?2;1;0S";
|
||||||
|
@ -29,6 +29,11 @@ pub const unicode_reset = "\x1b[?2027l";
|
||||||
pub const bp_set = "\x1b[?2004h";
|
pub const bp_set = "\x1b[?2004h";
|
||||||
pub const bp_reset = "\x1b[?2004l";
|
pub const bp_reset = "\x1b[?2004l";
|
||||||
|
|
||||||
|
// color scheme updates
|
||||||
|
pub const color_scheme_request = "\x1b[?996n";
|
||||||
|
pub const color_scheme_set = "\x1b[?2031h";
|
||||||
|
pub const color_scheme_reset = "\x1b[?2031l";
|
||||||
|
|
||||||
// Key encoding
|
// Key encoding
|
||||||
pub const csi_u_push = "\x1b[>{d}u";
|
pub const csi_u_push = "\x1b[>{d}u";
|
||||||
pub const csi_u_pop = "\x1b[<u";
|
pub const csi_u_pop = "\x1b[<u";
|
||||||
|
|
|
@ -13,6 +13,7 @@ pub const Event = union(enum) {
|
||||||
paste_end, // bracketed paste end
|
paste_end, // bracketed paste end
|
||||||
paste: []const u8, // osc 52 paste, caller must free
|
paste: []const u8, // osc 52 paste, caller must free
|
||||||
color_report: Color.Report, // osc 4, 10, 11, 12 response
|
color_report: Color.Report, // osc 4, 10, 11, 12 response
|
||||||
|
color_scheme: Color.Scheme,
|
||||||
|
|
||||||
// these are delivered as discovered terminal capabilities
|
// these are delivered as discovered terminal capabilities
|
||||||
cap_kitty_keyboard,
|
cap_kitty_keyboard,
|
||||||
|
@ -21,4 +22,5 @@ pub const Event = union(enum) {
|
||||||
cap_sgr_pixels,
|
cap_sgr_pixels,
|
||||||
cap_unicode,
|
cap_unicode,
|
||||||
cap_da1,
|
cap_da1,
|
||||||
|
cap_color_scheme_updates,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue