vaxis: enable da1 parsing, use futex timeout to return from query

Now that DA1 parsing is done, block the queryTerminal function until the
DA1 response is received, or a 1 second timeout elapses. With this
functionality, move certain events into Vaxis's realm of handling: IE
enabling kitty keyboard, unicode mode, etc

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
This commit is contained in:
Tim Culverhouse 2024-01-23 21:30:09 -06:00
parent a2dc97c039
commit 04f6117cfe
7 changed files with 47 additions and 17 deletions

View file

@ -61,8 +61,6 @@ pub fn main() !void {
.winsize => |ws| {
try vx.resize(alloc, ws);
},
.cap_rgb => continue,
.cap_kitty_keyboard => try vx.enableKittyKeyboard(.{}),
else => {},
}
@ -98,7 +96,5 @@ const Event = union(enum) {
key_press: vaxis.Key,
winsize: vaxis.Winsize,
focus_in,
cap_rgb,
cap_kitty_keyboard,
foo: u8,
};

View file

@ -357,6 +357,17 @@ pub fn parse(self: *Parser, input: []const u8) !Result {
log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
return .{ .event = null, .n = i + 1 };
},
'c' => { // DA1 response
const priv = seq.private_indicator orelse {
log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
return .{ .event = null, .n = i + 1 };
};
if (priv != '?') {
log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
return .{ .event = null, .n = i + 1 };
}
return .{ .event = .cap_da1, .n = i + 1 };
},
else => {
log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
return .{

View file

@ -178,19 +178,16 @@ pub fn run(
}
},
.cap_kitty_keyboard => {
if (@hasField(EventType, "cap_kitty_keyboard")) {
vx.postEvent(.cap_kitty_keyboard);
}
vx.caps.kitty_keyboard = true;
},
.cap_rgb => {
if (@hasField(EventType, "cap_rgb")) {
vx.postEvent(.cap_rgb);
}
vx.caps.rgb = true;
},
.cap_unicode => {
if (@hasField(EventType, "cap_unicode")) {
vx.postEvent(.cap_unicode);
}
vx.caps.unicode = true;
},
.cap_da1 => {
std.Thread.Futex.wake(&vx.query_futex, 10);
},
}
}

View file

@ -14,6 +14,9 @@ pub const sixel_geometry_query = "\x1b[?2;1;0S";
pub const sync_set = "\x1b[?2026h";
pub const sync_reset = "\x1b[?2026l";
pub const unicode_set = "\x1b[?2027h";
pub const unicode_reset = "\x1b[?2027l";
// Key encoding
pub const csi_u_push = "\x1b[>{d}u";
pub const csi_u_pop = "\x1b[<u";

View file

@ -1,7 +1,6 @@
pub const Key = @import("Key.zig");
/// The events that Vaxis emits. This can be used as the generic EventType if
/// there are no internal events
/// The events that Vaxis emits internally
pub const Event = union(enum) {
key_press: Key,
focus_in,
@ -13,4 +12,5 @@ pub const Event = union(enum) {
cap_kitty_keyboard,
cap_rgb,
cap_unicode,
cap_da1,
};

View file

@ -7,7 +7,6 @@ pub const Style = cell.Style;
pub const Key = @import("Key.zig");
pub const Winsize = @import("Tty.zig").Winsize;
pub const Event = @import("event.zig").Event;
pub const widgets = @import("widgets/main.zig");

View file

@ -1,4 +1,5 @@
const std = @import("std");
const atomic = std.atomic;
const Queue = @import("queue.zig").Queue;
const ctlseqs = @import("ctlseqs.zig");
@ -30,6 +31,12 @@ pub fn Vaxis(comptime T: type) type {
pub const EventType = T;
pub const Capabilities = struct {
kitty_keyboard: bool = false,
rgb: bool = false,
unicode: bool = false,
};
/// the event queue for Vaxis
//
// TODO: is 512 ok?
@ -49,9 +56,15 @@ pub fn Vaxis(comptime T: type) type {
/// if we have entered kitty keyboard
kitty_keyboard: bool = false,
caps: Capabilities = .{},
/// if we should redraw the entire screen on the next render
refresh: bool = false,
/// blocks the main thread until a DA1 query has been received, or the
/// futex times out
query_futex: atomic.Value(u32) = atomic.Value(u32).init(0),
// statistics
renders: usize = 0,
render_dur: i128 = 0,
@ -201,6 +214,17 @@ pub fn Vaxis(comptime T: type) type {
_ = try tty.write(ctlseqs.primary_device_attrs);
try tty.flush();
// 1 second timeout
std.Thread.Futex.timedWait(&self.query_futex, 0, 1 * std.time.ns_per_s) catch {};
// enable detected features
if (self.caps.kitty_keyboard) {
try self.enableKittyKeyboard(.{});
}
if (self.caps.unicode) {
_ = try tty.write(ctlseqs.unicode_set);
}
}
// the next render call will refresh the entire screen
@ -429,7 +453,7 @@ pub fn Vaxis(comptime T: type) type {
}
}
pub fn enableKittyKeyboard(self: *Self, flags: Key.KittyFlags) !void {
fn enableKittyKeyboard(self: *Self, flags: Key.KittyFlags) !void {
self.kitty_keyboard = true;
const flag_int: u5 = @bitCast(flags);
try std.fmt.format(