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,
|
.config = config,
|
||||||
.renderer_state = &self.renderer_state,
|
.renderer_state = &self.renderer_state,
|
||||||
.renderer_wakeup = render_thread.wakeup,
|
.renderer_wakeup = render_thread.wakeup,
|
||||||
|
.renderer_mailbox = render_thread.mailbox,
|
||||||
});
|
});
|
||||||
errdefer io.deinit();
|
errdefer io.deinit();
|
||||||
|
|
||||||
|
@ -300,8 +300,8 @@ pub fn setFocus(self: *Metal, focus: bool) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Called to toggle the blink state of the cursor
|
/// Called to toggle the blink state of the cursor
|
||||||
pub fn blinkCursor(self: *Metal) void {
|
pub fn blinkCursor(self: *Metal, reset: bool) void {
|
||||||
self.cursor_visible = !self.cursor_visible;
|
self.cursor_visible = reset or !self.cursor_visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The primary render callback that is completely thread-safe.
|
/// 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
|
/// Called to toggle the blink state of the cursor
|
||||||
pub fn blinkCursor(self: *OpenGL) void {
|
pub fn blinkCursor(self: *OpenGL, reset: bool) void {
|
||||||
self.cursor_visible = !self.cursor_visible;
|
self.cursor_visible = reset or !self.cursor_visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The primary render callback that is completely thread-safe.
|
/// 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
|
/// 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
|
/// hardcoded with a capacity. We can make this a comptime parameter in
|
||||||
/// the future if we want it configurable.
|
/// 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
|
/// 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
|
/// 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
|
// If we're focused, we immediately show the cursor again
|
||||||
// and then restart the timer.
|
// and then restart the timer.
|
||||||
if (!try self.cursor_h.isActive()) {
|
if (!try self.cursor_h.isActive()) {
|
||||||
|
self.renderer.blinkCursor(true);
|
||||||
try self.cursor_h.start(
|
try self.cursor_h.start(
|
||||||
cursorTimerCallback,
|
cursorTimerCallback,
|
||||||
0,
|
self.cursor_h.getRepeat(),
|
||||||
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;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
t.renderer.blinkCursor();
|
t.renderer.blinkCursor(false);
|
||||||
t.wakeup.send() catch {};
|
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
|
/// rendering within. This is only sent when a change is detected so
|
||||||
/// the renderer is expected to handle all of these.
|
/// the renderer is expected to handle all of these.
|
||||||
focus: bool,
|
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.
|
/// a repaint should happen.
|
||||||
renderer_wakeup: libuv.Async,
|
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.
|
/// The cached grid size whenever a resize is called.
|
||||||
grid_size: renderer.GridSize,
|
grid_size: renderer.GridSize,
|
||||||
|
|
||||||
@ -103,6 +106,7 @@ pub fn init(alloc: Allocator, opts: termio.Options) !Exec {
|
|||||||
.terminal_stream = undefined,
|
.terminal_stream = undefined,
|
||||||
.renderer_state = opts.renderer_state,
|
.renderer_state = opts.renderer_state,
|
||||||
.renderer_wakeup = opts.renderer_wakeup,
|
.renderer_wakeup = opts.renderer_wakeup,
|
||||||
|
.renderer_mailbox = opts.renderer_mailbox,
|
||||||
.grid_size = opts.grid_size,
|
.grid_size = opts.grid_size,
|
||||||
.data = null,
|
.data = null,
|
||||||
};
|
};
|
||||||
@ -141,6 +145,7 @@ pub fn threadEnter(self: *Exec, loop: libuv.Loop) !ThreadData {
|
|||||||
.read_arena = std.heap.ArenaAllocator.init(alloc),
|
.read_arena = std.heap.ArenaAllocator.init(alloc),
|
||||||
.renderer_state = self.renderer_state,
|
.renderer_state = self.renderer_state,
|
||||||
.renderer_wakeup = self.renderer_wakeup,
|
.renderer_wakeup = self.renderer_wakeup,
|
||||||
|
.renderer_mailbox = self.renderer_mailbox,
|
||||||
.data_stream = stream,
|
.data_stream = stream,
|
||||||
.terminal_stream = .{
|
.terminal_stream = .{
|
||||||
.handler = .{
|
.handler = .{
|
||||||
@ -238,6 +243,9 @@ const EventData = struct {
|
|||||||
/// a repaint should happen.
|
/// a repaint should happen.
|
||||||
renderer_wakeup: libuv.Async,
|
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.
|
/// The data stream is the main IO for the pty.
|
||||||
data_stream: libuv.Tty,
|
data_stream: libuv.Tty,
|
||||||
|
|
||||||
@ -334,18 +342,16 @@ fn ttyRead(t: *libuv.Tty, n: isize, buf: []const u8) void {
|
|||||||
return;
|
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
|
// We are modifying terminal state from here on out
|
||||||
ev.renderer_state.mutex.lock();
|
ev.renderer_state.mutex.lock();
|
||||||
defer ev.renderer_state.mutex.unlock();
|
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
|
// Schedule a render
|
||||||
ev.queueRender() catch unreachable;
|
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 handle to wake up the renderer. This hints to the renderer that that
|
||||||
/// a repaint should happen.
|
/// a repaint should happen.
|
||||||
renderer_wakeup: libuv.Async,
|
renderer_wakeup: libuv.Async,
|
||||||
|
|
||||||
|
/// The mailbox for renderer messages.
|
||||||
|
renderer_mailbox: *renderer.Thread.Mailbox,
|
||||||
|
Reference in New Issue
Block a user