terminal: cursor shape parsing, hook up to apprt callback

This commit is contained in:
Mitchell Hashimoto
2023-09-14 10:12:38 -07:00
parent ab8569b4bd
commit 7734bab8c4
7 changed files with 151 additions and 0 deletions

View File

@@ -0,0 +1,113 @@
const std = @import("std");
/// The possible cursor shapes. Not all app runtimes support these shapes.
/// The shapes are always based on the W3C supported cursor styles so we
/// can have a cross platform list.
pub const CursorShape = enum(c_int) {
default,
context_menu,
help,
pointer,
progress,
wait,
cell,
crosshair,
text,
vertical_text,
alias,
copy,
move,
no_drop,
not_allowed,
grab,
grabbing,
all_scroll,
col_resize,
row_resize,
n_resize,
e_resize,
s_resize,
w_resize,
ne_resize,
nw_resize,
se_resize,
sw_resize,
ew_resize,
ns_resize,
nesw_resize,
nwse_resize,
zoom_in,
zoom_out,
/// Build cursor shape from string or null if its unknown.
pub fn fromString(v: []const u8) ?CursorShape {
return string_map.get(v);
}
};
const string_map = std.ComptimeStringMap(CursorShape, .{
// W3C
.{ "default", .default },
.{ "context-menu", .context_menu },
.{ "help", .help },
.{ "pointer", .pointer },
.{ "progress", .progress },
.{ "wait", .wait },
.{ "cell", .cell },
.{ "crosshair", .crosshair },
.{ "text", .text },
.{ "vertical-text", .vertical_text },
.{ "alias", .alias },
.{ "copy", .copy },
.{ "move", .move },
.{ "no-drop", .no_drop },
.{ "not-allowed", .not_allowed },
.{ "grab", .grab },
.{ "grabbing", .grabbing },
.{ "all-scroll", .all_scroll },
.{ "col-resize", .col_resize },
.{ "row-resize", .row_resize },
.{ "n-resize", .n_resize },
.{ "e-resize", .e_resize },
.{ "s-resize", .s_resize },
.{ "w-resize", .w_resize },
.{ "ne-resize", .ne_resize },
.{ "nw-resize", .nw_resize },
.{ "se-resize", .se_resize },
.{ "sw-resize", .sw_resize },
.{ "ew-resize", .ew_resize },
.{ "ns-resize", .ns_resize },
.{ "nesw-resize", .nesw_resize },
.{ "nwse-resize", .nwse_resize },
.{ "zoom-in", .zoom_in },
.{ "zoom-out", .zoom_out },
// xterm/foot
.{ "left_ptr", .default },
.{ "question_arrow", .help },
.{ "hand", .pointer },
.{ "left_ptr_watch", .progress },
.{ "watch", .wait },
.{ "cross", .crosshair },
.{ "xterm", .text },
.{ "dnd-link", .alias },
.{ "dnd-copy", .copy },
.{ "dnd-move", .move },
.{ "dnd-no-drop", .no_drop },
.{ "crossed_circle", .not_allowed },
.{ "hand1", .grab },
.{ "right_side", .e_resize },
.{ "top_side", .n_resize },
.{ "top_right_corner", .ne_resize },
.{ "top_left_corner", .nw_resize },
.{ "bottom_side", .s_resize },
.{ "bottom_right_corner", .se_resize },
.{ "bottom_left_corner", .sw_resize },
.{ "left_side", .w_resize },
.{ "fleur", .all_scroll },
});
test "cursor shape from string" {
const testing = std.testing;
try testing.expectEqual(CursorShape.default, CursorShape.fromString("default").?);
}

View File

@@ -15,6 +15,7 @@ pub const parse_table = @import("parse_table.zig");
pub const Charset = charsets.Charset;
pub const CharsetSlot = charsets.Slots;
pub const CharsetActiveSlot = charsets.ActiveSlot;
pub const CursorShape = @import("cursor_shape.zig").CursorShape;
pub const Terminal = @import("Terminal.zig");
pub const Parser = @import("Parser.zig");
pub const Selection = @import("Selection.zig");

View File

@@ -9,6 +9,7 @@ const modes = @import("modes.zig");
const osc = @import("osc.zig");
const sgr = @import("sgr.zig");
const trace = @import("tracy").trace;
const CursorShape = @import("cursor_shape.zig").CursorShape;
const log = std.log.scoped(.stream);
@@ -849,6 +850,17 @@ pub fn Stream(comptime Handler: type) type {
} else log.warn("unimplemented OSC callback: {}", .{cmd});
},
.pointer_cursor => |v| {
if (@hasDecl(T, "setCursorShape")) {
const shape = CursorShape.fromString(v.value) orelse {
log.warn("unknown cursor shape: {s}", .{v.value});
return;
};
try self.handler.setCursorShape(shape);
} else log.warn("unimplemented OSC callback: {}", .{cmd});
},
else => if (@hasDecl(T, "oscUnimplemented"))
try self.handler.oscUnimplemented(cmd)
else