mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
update cursor on request from shell
This commit is contained in:
13
src/Grid.zig
13
src/Grid.zig
@ -47,10 +47,21 @@ foreground: terminal.color.RGB,
|
||||
|
||||
/// Available cursor styles for drawing. The values represents the mode value
|
||||
/// in the shader.
|
||||
const CursorStyle = enum(u8) {
|
||||
pub const CursorStyle = enum(u8) {
|
||||
box = 3,
|
||||
box_hollow = 4,
|
||||
bar = 5,
|
||||
|
||||
/// Create a cursor style from the terminal style request.
|
||||
pub fn fromTerminal(style: terminal.CursorStyle) ?CursorStyle {
|
||||
return switch (style) {
|
||||
.blinking_block, .steady_block => .box,
|
||||
.blinking_bar, .steady_bar => .bar,
|
||||
.blinking_underline, .steady_underline => null, // TODO
|
||||
.default => .box,
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// The raw structure that maps directly to the buffer sent to the vertex shader.
|
||||
|
@ -36,6 +36,9 @@ alloc: Allocator,
|
||||
/// The glfw window handle.
|
||||
window: glfw.Window,
|
||||
|
||||
/// Whether the window is currently focused
|
||||
focused: bool,
|
||||
|
||||
/// The terminal grid attached to this window.
|
||||
grid: Grid,
|
||||
|
||||
@ -56,6 +59,7 @@ terminal_stream: terminal.Stream(*Window),
|
||||
|
||||
/// Timer that blinks the cursor.
|
||||
cursor_timer: libuv.Timer,
|
||||
cursor_style: terminal.CursorStyle,
|
||||
|
||||
/// Render at least 60fps.
|
||||
render_timer: RenderTimer,
|
||||
@ -199,12 +203,14 @@ pub fn create(alloc: Allocator, loop: libuv.Loop, config: *const Config) !*Windo
|
||||
self.* = .{
|
||||
.alloc = alloc,
|
||||
.window = window,
|
||||
.focused = false,
|
||||
.grid = grid,
|
||||
.pty = pty,
|
||||
.command = cmd,
|
||||
.terminal = term,
|
||||
.terminal_stream = .{ .handler = self },
|
||||
.cursor_timer = timer,
|
||||
.cursor_style = .blinking_block,
|
||||
.render_timer = try RenderTimer.init(loop, self, 16, 96),
|
||||
.pty_stream = stream,
|
||||
.config = config,
|
||||
@ -285,6 +291,25 @@ fn queueWrite(self: *Window, data: []const u8) !void {
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates te style of the cursor.
|
||||
fn updateCursorStyle(self: *Window, style: Grid.CursorStyle, blink: bool) !void {
|
||||
self.grid.cursor_style = style;
|
||||
self.grid.cursor_visible = !blink;
|
||||
|
||||
if (blink) {
|
||||
try self.cursor_timer.start(
|
||||
cursorTimerCallback,
|
||||
0,
|
||||
self.cursor_timer.getRepeat(),
|
||||
);
|
||||
} else {
|
||||
try self.cursor_timer.stop();
|
||||
}
|
||||
|
||||
// Always schedule a render when we change cursors
|
||||
try self.render_timer.schedule();
|
||||
}
|
||||
|
||||
fn sizeCallback(window: glfw.Window, width: i32, height: i32) void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
@ -394,19 +419,25 @@ fn focusCallback(window: glfw.Window, focused: bool) void {
|
||||
|
||||
const win = window.getUserPointer(Window) orelse return;
|
||||
|
||||
// If we aren't changing focus state, do nothing. I don't think this
|
||||
// can happen but it costs very little to check.
|
||||
if (win.focused == focused) return;
|
||||
|
||||
// We have to schedule a render because no matter what we're changing
|
||||
// the cursor.
|
||||
win.render_timer.schedule() catch unreachable;
|
||||
|
||||
// Set our focused state on the window.
|
||||
win.focused = focused;
|
||||
|
||||
if (focused) {
|
||||
win.wakeup = true;
|
||||
win.cursor_timer.start(cursorTimerCallback, 0, win.cursor_timer.getRepeat()) catch unreachable;
|
||||
win.grid.cursor_style = .box;
|
||||
win.grid.cursor_visible = false;
|
||||
win.updateCursorStyle(
|
||||
Grid.CursorStyle.fromTerminal(win.cursor_style) orelse .box,
|
||||
win.cursor_style.blinking(),
|
||||
) catch unreachable;
|
||||
} else {
|
||||
win.grid.cursor_visible = true;
|
||||
win.grid.cursor_style = .box_hollow;
|
||||
win.cursor_timer.stop() catch unreachable;
|
||||
win.updateCursorStyle(.box_hollow, false) catch unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
@ -676,7 +707,17 @@ pub fn setCursorStyle(
|
||||
) !void {
|
||||
_ = self;
|
||||
|
||||
switch (style) {
|
||||
else => log.warn("unimplemented cursor style: {}", .{style}),
|
||||
}
|
||||
// Get the style that we use in the renderer
|
||||
const grid_style = Grid.CursorStyle.fromTerminal(style) orelse {
|
||||
log.warn("unimplemented cursor style: {}", .{style});
|
||||
return;
|
||||
};
|
||||
|
||||
// Set our style
|
||||
self.cursor_style = style;
|
||||
|
||||
// If we're currently focused, we update our style, since our unfocused
|
||||
// cursor is manually managed. If we're not focused, we ignore it because
|
||||
// it'll be updated the next time the window comes into focus.
|
||||
if (self.focused) try self.updateCursorStyle(grid_style, style.blinking());
|
||||
}
|
||||
|
@ -71,4 +71,12 @@ pub const CursorStyle = enum(u16) {
|
||||
|
||||
// Non-exhaustive so that @intToEnum never fails for unsupported modes.
|
||||
_,
|
||||
|
||||
/// True if the cursor should blink.
|
||||
pub fn blinking(self: CursorStyle) bool {
|
||||
return switch (self) {
|
||||
.blinking_block, .blinking_underline, .blinking_bar => true,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
Reference in New Issue
Block a user