Ports the remainder of ZIG/src/termio: Options, backend, message, mailbox, Termio, Thread, Exec and stream_handler. Threading model (replacing libxev): the IO thread owns Termio and runs a single poll(2) loop over the mailbox eventfd, a stop eventfd, the child pidfd and pty POLLOUT, driving Ghostty's timers (25 ms resize coalescing, 1 s synchronized-output, 15 ms selection scroll, 200 ms termios polling). A separate pty read thread locks the shared renderer state and feeds the terminal. Renderer and surface interaction go through RendererMailbox/SurfaceMailbox traits. The stream handler answers all queries (DA, DSR, XTVERSION, DECRQM, OSC color queries, XTGETTCAP, DECRQSS, ...) and forwards titles, pwd, OSC 52, notifications, progress and bell as surface messages. Zig unlocks the renderer mutex when a mailbox is full; here overflow goes to an ordered outbox flushed after the locks drop. IO1's local stand-ins are replaced with the real config types. Open: RendererState lives in termio for now (renderer State.zig is being ported); kitty graphics replies and tmux viewer are not hooked up; wait-after-command lives in Surface (core); Flatpak stop path needs a ghostty-os change. Test Plan: - cargo test -p ghostty-termio (102 unit + 21 end-to-end tests on a real pty, incl. backpressure, DA1 replies, resize coalescing, exits)
38 lines
1.5 KiB
Rust
38 lines
1.5 KiB
Rust
//! The outward-facing mailboxes termio needs from the rest of the program.
|
|
//!
|
|
//! In Zig these are concrete types (`apprt.surface.Mailbox`,
|
|
//! `renderer.Thread.Mailbox`). The renderer thread is not ported yet and the
|
|
//! surface mailbox is generic over the core's surface handle and app
|
|
//! mailbox, so termio only depends on these two small traits.
|
|
|
|
use ghostty_apprt::surface::{AppMailbox, Mailbox as ApprtMailbox, Message as SurfaceMessage};
|
|
use ghostty_datastruct::blocking_queue::Timeout;
|
|
use ghostty_renderer::message::Message as RendererMessage;
|
|
|
|
/// The mailbox for sending messages to the surface
|
|
/// (`apprt.surface.Mailbox`).
|
|
///
|
|
/// `push` returns the queue size after the push; zero means the push failed
|
|
/// (only possible with [`Timeout::Instant`] on a full queue).
|
|
pub trait SurfaceMailbox: Send + Sync {
|
|
fn push(&self, msg: SurfaceMessage, timeout: Timeout) -> usize;
|
|
}
|
|
|
|
impl<S, A> SurfaceMailbox for ApprtMailbox<S, A>
|
|
where
|
|
S: Clone + Send + Sync,
|
|
A: AppMailbox<S> + Send + Sync,
|
|
{
|
|
fn push(&self, msg: SurfaceMessage, timeout: Timeout) -> usize {
|
|
ApprtMailbox::push(self, msg, timeout)
|
|
}
|
|
}
|
|
|
|
/// The mailbox for sending messages to the renderer thread
|
|
/// (`renderer.Thread.Mailbox`). The renderer thread also has a wakeup handle
|
|
/// (see [`crate::Options::renderer_wakeup`]) which termio signals to hint
|
|
/// that a redraw should happen.
|
|
pub trait RendererMailbox: Send + Sync {
|
|
fn push(&self, msg: RendererMessage, timeout: Timeout) -> usize;
|
|
}
|