libghostty: add option to set default cursor style
Adds an option to `libghostty-vt` to configure the default cursor style that should be displayed when an app sends a DECSCUSR reset sequence (`CSI 0 q`).pull/12900/head
parent
6246c288ae
commit
2444e4d557
|
|
@ -232,6 +232,26 @@ typedef enum GHOSTTY_ENUM_TYPED {
|
|||
GHOSTTY_TERMINAL_SCREEN_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
|
||||
} GhosttyTerminalScreen;
|
||||
|
||||
/**
|
||||
* Visual style of the terminal cursor.
|
||||
*
|
||||
* @ingroup terminal
|
||||
*/
|
||||
typedef enum GHOSTTY_ENUM_TYPED {
|
||||
/** Bar cursor (DECSCUSR 5, 6). */
|
||||
GHOSTTY_TERMINAL_CURSOR_STYLE_BAR = 0,
|
||||
|
||||
/** Block cursor (DECSCUSR 1, 2). */
|
||||
GHOSTTY_TERMINAL_CURSOR_STYLE_BLOCK = 1,
|
||||
|
||||
/** Underline cursor (DECSCUSR 3, 4). */
|
||||
GHOSTTY_TERMINAL_CURSOR_STYLE_UNDERLINE = 2,
|
||||
|
||||
/** Hollow block cursor. */
|
||||
GHOSTTY_TERMINAL_CURSOR_STYLE_BLOCK_HOLLOW = 3,
|
||||
GHOSTTY_TERMINAL_CURSOR_STYLE_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
|
||||
} GhosttyTerminalCursorStyle;
|
||||
|
||||
/**
|
||||
* Scrollbar state for the terminal viewport.
|
||||
*
|
||||
|
|
@ -608,6 +628,15 @@ typedef enum GHOSTTY_ENUM_TYPED {
|
|||
* Input type: GhosttySelection*
|
||||
*/
|
||||
GHOSTTY_TERMINAL_OPT_SELECTION = 21,
|
||||
|
||||
/**
|
||||
* Set the default cursor style used by DECSCUSR reset (CSI 0 q).
|
||||
*
|
||||
* A NULL value pointer resets to the built-in default block cursor.
|
||||
*
|
||||
* Input type: GhosttyTerminalCursorStyle*
|
||||
*/
|
||||
GHOSTTY_TERMINAL_OPT_DEFAULT_CURSOR_STYLE = 22,
|
||||
GHOSTTY_TERMINAL_OPT_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
|
||||
} GhosttyTerminalOption;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ const lib = @import("../lib.zig");
|
|||
const CAllocator = lib.alloc.Allocator;
|
||||
pub const ZigTerminal = @import("../Terminal.zig");
|
||||
const Stream = @import("../stream_terminal.zig").Stream;
|
||||
const Screen = @import("../Screen.zig");
|
||||
const ScreenSet = @import("../ScreenSet.zig");
|
||||
const PageList = @import("../PageList.zig");
|
||||
const apc = @import("../apc.zig");
|
||||
|
|
@ -326,6 +327,7 @@ pub const Option = enum(c_int) {
|
|||
apc_max_bytes = 19,
|
||||
apc_max_bytes_kitty = 20,
|
||||
selection = 21,
|
||||
default_cursor_style = 22,
|
||||
|
||||
/// Input type expected for setting the option.
|
||||
pub fn InType(comptime self: Option) type {
|
||||
|
|
@ -349,6 +351,7 @@ pub const Option = enum(c_int) {
|
|||
=> ?*const bool,
|
||||
.apc_max_bytes, .apc_max_bytes_kitty => ?*const usize,
|
||||
.selection => ?*const selection_c.CSelection,
|
||||
.default_cursor_style => ?*const TerminalCursorStyle,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
@ -464,10 +467,36 @@ fn setTyped(
|
|||
wrapper.terminal.screens.active.clearSelection();
|
||||
}
|
||||
},
|
||||
.default_cursor_style => {
|
||||
const style = (if (value) |ptr| ptr.* else TerminalCursorStyle.block).toZig() orelse return .invalid_value;
|
||||
wrapper.stream.handler.default_cursor_style = style;
|
||||
if (wrapper.stream.handler.default_cursor) {
|
||||
wrapper.terminal.screens.active.cursor.cursor_style = style;
|
||||
}
|
||||
},
|
||||
}
|
||||
return .success;
|
||||
}
|
||||
|
||||
/// C: GhosttyTerminalCursorStyle
|
||||
pub const TerminalCursorStyle = enum(c_int) {
|
||||
bar = 0,
|
||||
block = 1,
|
||||
underline = 2,
|
||||
block_hollow = 3,
|
||||
_,
|
||||
|
||||
fn toZig(self: TerminalCursorStyle) ?Screen.CursorStyle {
|
||||
return switch (self) {
|
||||
.bar => .bar,
|
||||
.block => .block,
|
||||
.underline => .underline,
|
||||
.block_hollow => .block_hollow,
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// C: GhosttyDeviceAttributes
|
||||
pub const DeviceAttributes = Effects.CDeviceAttributes;
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,10 @@ pub const Handler = struct {
|
|||
/// the kitty graphics protocol.
|
||||
apc_handler: apc.Handler = .{},
|
||||
|
||||
/// Default cursor style used by DECSCUSR reset (CSI 0 q).
|
||||
default_cursor: bool = true,
|
||||
default_cursor_style: Screen.CursorStyle = .block,
|
||||
|
||||
pub const Effects = struct {
|
||||
/// Called when the terminal needs to write data back to the pty,
|
||||
/// e.g. in response to a DECRQM query. The data is only valid
|
||||
|
|
@ -152,12 +156,18 @@ pub const Handler = struct {
|
|||
self.terminal.screens.active.cursor.x + 1,
|
||||
),
|
||||
.cursor_style => {
|
||||
self.default_cursor = false;
|
||||
|
||||
const blink = switch (value) {
|
||||
.default, .steady_block, .steady_bar, .steady_underline => false,
|
||||
.blinking_block, .blinking_bar, .blinking_underline => true,
|
||||
};
|
||||
const style: Screen.CursorStyle = switch (value) {
|
||||
.default, .blinking_block, .steady_block => .block,
|
||||
.default => style: {
|
||||
self.default_cursor = true;
|
||||
break :style self.default_cursor_style;
|
||||
},
|
||||
.blinking_block, .steady_block => .block,
|
||||
.blinking_bar, .steady_bar => .bar,
|
||||
.blinking_underline, .steady_underline => .underline,
|
||||
};
|
||||
|
|
@ -228,7 +238,11 @@ pub const Handler = struct {
|
|||
},
|
||||
.active_status_display => self.terminal.status_display = value,
|
||||
.decaln => try self.terminal.decaln(),
|
||||
.full_reset => self.terminal.fullReset(),
|
||||
.full_reset => {
|
||||
self.terminal.fullReset();
|
||||
self.default_cursor = true;
|
||||
self.terminal.screens.active.cursor.cursor_style = self.default_cursor_style;
|
||||
},
|
||||
.start_hyperlink => try self.terminal.screens.active.startHyperlink(value.uri, value.id),
|
||||
.end_hyperlink => self.terminal.screens.active.endHyperlink(),
|
||||
.semantic_prompt => try self.terminal.semanticPrompt(value),
|
||||
|
|
|
|||
Loading…
Reference in New Issue