mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 00:36:07 +03:00
terminal: cursor shape parsing, hook up to apprt callback
This commit is contained in:
@ -525,6 +525,11 @@ pub fn handleMessage(self: *Surface, msg: Message) !void {
|
|||||||
try self.rt_surface.setTitle(slice);
|
try self.rt_surface.setTitle(slice);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.set_cursor_shape => |shape| {
|
||||||
|
log.debug("changing cursor shape: {}", .{shape});
|
||||||
|
try self.rt_surface.setCursorShape(shape);
|
||||||
|
},
|
||||||
|
|
||||||
.cell_size => |size| try self.setCellSize(size),
|
.cell_size => |size| try self.setCellSize(size),
|
||||||
|
|
||||||
.clipboard_read => |kind| try self.clipboardRead(kind),
|
.clipboard_read => |kind| try self.clipboardRead(kind),
|
||||||
|
@ -15,6 +15,7 @@ const objc = @import("objc");
|
|||||||
const input = @import("../input.zig");
|
const input = @import("../input.zig");
|
||||||
const internal_os = @import("../os/main.zig");
|
const internal_os = @import("../os/main.zig");
|
||||||
const renderer = @import("../renderer.zig");
|
const renderer = @import("../renderer.zig");
|
||||||
|
const terminal = @import("../terminal/main.zig");
|
||||||
const Renderer = renderer.Renderer;
|
const Renderer = renderer.Renderer;
|
||||||
const apprt = @import("../apprt.zig");
|
const apprt = @import("../apprt.zig");
|
||||||
const CoreApp = @import("../App.zig");
|
const CoreApp = @import("../App.zig");
|
||||||
@ -508,6 +509,12 @@ pub const Surface = struct {
|
|||||||
self.window.setTitle(slice.ptr);
|
self.window.setTitle(slice.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the shape of the cursor.
|
||||||
|
pub fn setCursorShape(self: *Surface, shape: terminal.CursorShape) !void {
|
||||||
|
_ = self;
|
||||||
|
_ = shape;
|
||||||
|
}
|
||||||
|
|
||||||
/// Read the clipboard. The windowing system is responsible for allocating
|
/// Read the clipboard. The windowing system is responsible for allocating
|
||||||
/// a buffer as necessary. This should be a stable pointer until the next
|
/// a buffer as necessary. This should be a stable pointer until the next
|
||||||
/// time getClipboardString is called.
|
/// time getClipboardString is called.
|
||||||
|
@ -2,6 +2,7 @@ const App = @import("../App.zig");
|
|||||||
const Surface = @import("../Surface.zig");
|
const Surface = @import("../Surface.zig");
|
||||||
const renderer = @import("../renderer.zig");
|
const renderer = @import("../renderer.zig");
|
||||||
const termio = @import("../termio.zig");
|
const termio = @import("../termio.zig");
|
||||||
|
const terminal = @import("../terminal/main.zig");
|
||||||
const Config = @import("../config.zig").Config;
|
const Config = @import("../config.zig").Config;
|
||||||
|
|
||||||
/// The message types that can be sent to a single surface.
|
/// The message types that can be sent to a single surface.
|
||||||
@ -16,6 +17,9 @@ pub const Message = union(enum) {
|
|||||||
/// of any length
|
/// of any length
|
||||||
set_title: [256]u8,
|
set_title: [256]u8,
|
||||||
|
|
||||||
|
/// Set the cursor shape.
|
||||||
|
set_cursor_shape: terminal.CursorShape,
|
||||||
|
|
||||||
/// Change the cell size.
|
/// Change the cell size.
|
||||||
cell_size: renderer.CellSize,
|
cell_size: renderer.CellSize,
|
||||||
|
|
||||||
|
113
src/terminal/cursor_shape.zig
Normal file
113
src/terminal/cursor_shape.zig
Normal 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").?);
|
||||||
|
}
|
@ -15,6 +15,7 @@ pub const parse_table = @import("parse_table.zig");
|
|||||||
pub const Charset = charsets.Charset;
|
pub const Charset = charsets.Charset;
|
||||||
pub const CharsetSlot = charsets.Slots;
|
pub const CharsetSlot = charsets.Slots;
|
||||||
pub const CharsetActiveSlot = charsets.ActiveSlot;
|
pub const CharsetActiveSlot = charsets.ActiveSlot;
|
||||||
|
pub const CursorShape = @import("cursor_shape.zig").CursorShape;
|
||||||
pub const Terminal = @import("Terminal.zig");
|
pub const Terminal = @import("Terminal.zig");
|
||||||
pub const Parser = @import("Parser.zig");
|
pub const Parser = @import("Parser.zig");
|
||||||
pub const Selection = @import("Selection.zig");
|
pub const Selection = @import("Selection.zig");
|
||||||
|
@ -9,6 +9,7 @@ const modes = @import("modes.zig");
|
|||||||
const osc = @import("osc.zig");
|
const osc = @import("osc.zig");
|
||||||
const sgr = @import("sgr.zig");
|
const sgr = @import("sgr.zig");
|
||||||
const trace = @import("tracy").trace;
|
const trace = @import("tracy").trace;
|
||||||
|
const CursorShape = @import("cursor_shape.zig").CursorShape;
|
||||||
|
|
||||||
const log = std.log.scoped(.stream);
|
const log = std.log.scoped(.stream);
|
||||||
|
|
||||||
@ -849,6 +850,17 @@ pub fn Stream(comptime Handler: type) type {
|
|||||||
} else log.warn("unimplemented OSC callback: {}", .{cmd});
|
} 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"))
|
else => if (@hasDecl(T, "oscUnimplemented"))
|
||||||
try self.handler.oscUnimplemented(cmd)
|
try self.handler.oscUnimplemented(cmd)
|
||||||
else
|
else
|
||||||
|
@ -1682,6 +1682,15 @@ const StreamHandler = struct {
|
|||||||
}, .{ .forever = {} });
|
}, .{ .forever = {} });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn setCursorShape(
|
||||||
|
self: *StreamHandler,
|
||||||
|
shape: terminal.CursorShape,
|
||||||
|
) !void {
|
||||||
|
_ = self.ev.surface_mailbox.push(.{
|
||||||
|
.set_cursor_shape = shape,
|
||||||
|
}, .{ .forever = {} });
|
||||||
|
}
|
||||||
|
|
||||||
pub fn clipboardContents(self: *StreamHandler, kind: u8, data: []const u8) !void {
|
pub fn clipboardContents(self: *StreamHandler, kind: u8, data: []const u8) !void {
|
||||||
// Note: we ignore the "kind" field and always use the standard clipboard.
|
// Note: we ignore the "kind" field and always use the standard clipboard.
|
||||||
// iTerm also appears to do this but other terminals seem to only allow
|
// iTerm also appears to do this but other terminals seem to only allow
|
||||||
|
Reference in New Issue
Block a user