mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
implement cursor reset when data comes in pty
This commit is contained in:
@ -367,6 +367,7 @@ pub fn create(alloc: Allocator, loop: libuv.Loop, config: *const Config) !*Windo
|
||||
.config = config,
|
||||
.renderer_state = &self.renderer_state,
|
||||
.renderer_wakeup = render_thread.wakeup,
|
||||
.renderer_mailbox = render_thread.mailbox,
|
||||
});
|
||||
errdefer io.deinit();
|
||||
|
||||
|
@ -300,8 +300,8 @@ pub fn setFocus(self: *Metal, focus: bool) !void {
|
||||
}
|
||||
|
||||
/// Called to toggle the blink state of the cursor
|
||||
pub fn blinkCursor(self: *Metal) void {
|
||||
self.cursor_visible = !self.cursor_visible;
|
||||
pub fn blinkCursor(self: *Metal, reset: bool) void {
|
||||
self.cursor_visible = reset or !self.cursor_visible;
|
||||
}
|
||||
|
||||
/// The primary render callback that is completely thread-safe.
|
||||
|
@ -442,8 +442,8 @@ pub fn setFocus(self: *OpenGL, focus: bool) !void {
|
||||
}
|
||||
|
||||
/// Called to toggle the blink state of the cursor
|
||||
pub fn blinkCursor(self: *OpenGL) void {
|
||||
self.cursor_visible = !self.cursor_visible;
|
||||
pub fn blinkCursor(self: *OpenGL, reset: bool) void {
|
||||
self.cursor_visible = reset or !self.cursor_visible;
|
||||
}
|
||||
|
||||
/// The primary render callback that is completely thread-safe.
|
||||
|
@ -15,7 +15,7 @@ const log = std.log.scoped(.renderer_thread);
|
||||
/// The type used for sending messages to the IO thread. For now this is
|
||||
/// hardcoded with a capacity. We can make this a comptime parameter in
|
||||
/// the future if we want it configurable.
|
||||
const Mailbox = BlockingQueue(renderer.Message, 64);
|
||||
pub const Mailbox = BlockingQueue(renderer.Message, 64);
|
||||
|
||||
/// The main event loop for the application. The user data of this loop
|
||||
/// is always the allocator used to create the loop. This is a convenience
|
||||
@ -227,14 +227,22 @@ fn drainMailbox(self: *Thread) !void {
|
||||
// If we're focused, we immediately show the cursor again
|
||||
// and then restart the timer.
|
||||
if (!try self.cursor_h.isActive()) {
|
||||
self.renderer.blinkCursor(true);
|
||||
try self.cursor_h.start(
|
||||
cursorTimerCallback,
|
||||
0,
|
||||
self.cursor_h.getRepeat(),
|
||||
self.cursor_h.getRepeat(),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
.reset_cursor_blink => {
|
||||
self.renderer.blinkCursor(true);
|
||||
if (try self.cursor_h.isActive()) {
|
||||
_ = try self.cursor_h.again();
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -278,7 +286,7 @@ fn cursorTimerCallback(h: *libuv.Timer) void {
|
||||
return;
|
||||
};
|
||||
|
||||
t.renderer.blinkCursor();
|
||||
t.renderer.blinkCursor(false);
|
||||
t.wakeup.send() catch {};
|
||||
}
|
||||
|
||||
|
@ -8,4 +8,8 @@ pub const Message = union(enum) {
|
||||
/// rendering within. This is only sent when a change is detected so
|
||||
/// the renderer is expected to handle all of these.
|
||||
focus: bool,
|
||||
|
||||
/// Reset the cursor blink by immediately showing the cursor then
|
||||
/// restarting the timer.
|
||||
reset_cursor_blink: void,
|
||||
};
|
||||
|
@ -40,6 +40,9 @@ renderer_state: *renderer.State,
|
||||
/// a repaint should happen.
|
||||
renderer_wakeup: libuv.Async,
|
||||
|
||||
/// The mailbox for notifying the renderer of things.
|
||||
renderer_mailbox: *renderer.Thread.Mailbox,
|
||||
|
||||
/// The cached grid size whenever a resize is called.
|
||||
grid_size: renderer.GridSize,
|
||||
|
||||
@ -103,6 +106,7 @@ pub fn init(alloc: Allocator, opts: termio.Options) !Exec {
|
||||
.terminal_stream = undefined,
|
||||
.renderer_state = opts.renderer_state,
|
||||
.renderer_wakeup = opts.renderer_wakeup,
|
||||
.renderer_mailbox = opts.renderer_mailbox,
|
||||
.grid_size = opts.grid_size,
|
||||
.data = null,
|
||||
};
|
||||
@ -141,6 +145,7 @@ pub fn threadEnter(self: *Exec, loop: libuv.Loop) !ThreadData {
|
||||
.read_arena = std.heap.ArenaAllocator.init(alloc),
|
||||
.renderer_state = self.renderer_state,
|
||||
.renderer_wakeup = self.renderer_wakeup,
|
||||
.renderer_mailbox = self.renderer_mailbox,
|
||||
.data_stream = stream,
|
||||
.terminal_stream = .{
|
||||
.handler = .{
|
||||
@ -238,6 +243,9 @@ const EventData = struct {
|
||||
/// a repaint should happen.
|
||||
renderer_wakeup: libuv.Async,
|
||||
|
||||
/// The mailbox for notifying the renderer of things.
|
||||
renderer_mailbox: *renderer.Thread.Mailbox,
|
||||
|
||||
/// The data stream is the main IO for the pty.
|
||||
data_stream: libuv.Tty,
|
||||
|
||||
@ -334,18 +342,16 @@ fn ttyRead(t: *libuv.Tty, n: isize, buf: []const u8) void {
|
||||
return;
|
||||
};
|
||||
|
||||
// Whenever a character is typed, we ensure the cursor is in the
|
||||
// non-blink state so it is rendered if visible.
|
||||
_ = ev.renderer_mailbox.push(.{
|
||||
.reset_cursor_blink = {},
|
||||
}, .{ .forever = {} });
|
||||
|
||||
// We are modifying terminal state from here on out
|
||||
ev.renderer_state.mutex.lock();
|
||||
defer ev.renderer_state.mutex.unlock();
|
||||
|
||||
// Whenever a character is typed, we ensure the cursor is in the
|
||||
// non-blink state so it is rendered if visible.
|
||||
//ev.renderer_state.cursor.blink = false;
|
||||
// TODO
|
||||
// if (win.terminal_cursor.timer.isActive() catch false) {
|
||||
// _ = win.terminal_cursor.timer.again() catch null;
|
||||
// }
|
||||
|
||||
// Schedule a render
|
||||
ev.queueRender() catch unreachable;
|
||||
|
||||
|
@ -22,3 +22,6 @@ renderer_state: *renderer.State,
|
||||
/// A handle to wake up the renderer. This hints to the renderer that that
|
||||
/// a repaint should happen.
|
||||
renderer_wakeup: libuv.Async,
|
||||
|
||||
/// The mailbox for renderer messages.
|
||||
renderer_mailbox: *renderer.Thread.Mailbox,
|
||||
|
Reference in New Issue
Block a user