Map of Core Types and Traits
Note: This chapter is a machine-translated English version of the original Japanese chapter 型・トレイト関係図. Some phrasing may read unnaturally.
This chapter is meant to work as a reference index for the current codebase. The focus is on where frequently used types live, which crate owns them, and what they contain.
Three things to keep in mind first
- the communication boundary lives in the
protocolcrate throughClientMessage/ServerMessage - the rendering boundary lives in the
terminalcrate throughGrid - the UI-state boundary lives in the
clientcrate throughPaneStore
If you keep just those three in mind first, the rest of the types become much easier to place.
yatamux-protocol
This crate contains only the types that travel over the wire.
WorkspaceId(u32)
SurfaceId(u32)
PaneId(u32)
TermSize { cols, rows }
SplitDirection { Horizontal | Vertical }
PaneInfo {
id,
surface,
title,
cols,
rows,
}
CursorInfo {
col,
row,
visible,
}
PaneCapture {
title,
cols,
rows,
lines_requested,
scrollback_len,
cursor,
visible_text,
scrollback_tail,
}
ClientMessage
CreateWorkspace { name }
CreateSurface { workspace }
CreatePane { surface, split_from, direction, size, working_dir }
Input { pane, data }
Resize { pane, size }
ClosePane { pane }
RequestScreen { pane }
Detach
ListPanes
CapturePane { pane, lines, plain_text }
ServerMessage
WorkspaceCreated { id, name }
SurfaceCreated { id, workspace }
PaneCreated { id, surface, split_from?, direction? }
Output { pane, data: Arc<[u8]> }
TitleChanged { pane, title }
Notification { pane, body }
ClipboardWrite { pane, data }
PaneClosed { pane }
CommandFinished { pane, exit_code? }
Error { message }
PanesListed { panes }
PaneContent { pane, content, capture? }
yatamux-terminal
This is the core of terminal emulation.
CjkWidthConfig
TerminalSink
grid: Arc<Mutex<Grid>>
parser: vte::Parser
fn feed(&mut self, data) -> Option<Vec<u8>>
Grid
cols / rows
cells
cursor: CursorPos
dirty
saved_main
scroll_top / scroll_bottom
scrollback
width_config
CursorPos { col, row }
Cell
content: CellContent
style: CellStyle
CellContent
Grapheme { text, width }
Continuation
Empty
CellStyle
fg, bg, bold, italic, underline, reverse, dim ...
PTY-related types
PtySession
fn spawn(size, shell, output_tx, working_dir)
fn write(&mut self, data)
fn resize(&mut self, size)
fn take_child()
fn clone_child_killer()
VT-related types
VtProcessor<'a>
grid: &'a mut Grid
current_style
title
notification
clipboard_data
command_finished
bell
→ impl vte::Perform
The notable part here is that the terminal crate extracts notifications and clipboard events too, not just visible characters.
yatamux-server
This crate manages the session hierarchy and the PTY lifecycle.
Server
workspaces: HashMap<WorkspaceId, Workspace>
surfaces: HashMap<SurfaceId, Surface>
panes: HashMap<PaneId, Pane>
next_*_id
width_config: CjkWidthConfig
client_tx: Sender<ServerMessage>
pane_output_rx / tx
pane_event_rx / tx
Session model
Workspace
id
name: Arc<str>
surfaces: Vec<SurfaceId>
active_surface
Surface
id
workspace
pane_tree: Option<PaneTree>
active_pane
PaneTree
Leaf(PaneId)
Split { direction, ratio, first, second }
Pane types
Pane
id
grid: Arc<tokio::sync::Mutex<Grid>>
cmd_tx: Sender<PtyCmd>
title: Arc<std::sync::Mutex<Arc<str>>>
size: Arc<std::sync::Mutex<TermSize>>
child_killer
PtyCmd
Input(Vec<u8>)
Resize(TermSize)
PaneEvent
Notification(String)
Bell
ProcessExited
CommandFinished(Option<i32>)
Pane is an internal server-side type. It does not appear in the protocol crate.
yatamux-client
This crate owns the UI and rendering logic.
Layout-related types
LayoutNode
Leaf(PaneId)
Split { direction, ratio, first, second }
PaneRect { x, y, w, h }
Direction { Left, Right, Up, Down }
LayoutPreview
node: LayoutNode
commands: Vec<Option<String>>
LauncherState
entries: Vec<(String, Option<LayoutPreview>)>
selected
ThemeLauncherState
entries: Vec<String>
selected
PaneStore
PaneStore
grids: HashMap<PaneId, Arc<Mutex<Grid>>>
layout: LayoutNode
active: PaneId
pending_clipboard: Option<Vec<u8>>
pending_toasts: VecDeque<Toast>
scroll_offset: usize
floating: Option<PaneId>
floating_visible: bool
pre_float_active: Option<PaneId>
should_quit: bool
launcher: Option<LauncherState>
copy_mode: Option<CopyState>
normal_selection: Option<(usize, usize, usize, usize)>
save_prompt: Option<String>
theme_launcher: Option<ThemeLauncherState>
pane_commands: HashMap<PaneId, String>
UI helper types
CopyState
cursor: (usize, usize)
anchor: Option<(usize, usize)>
Toast
pane_id
message
elapsed_ms
Session persistence
LayoutNodeDef
Leaf { id }
Split { direction, ratio, first, second }
LayoutSnapshot
root: LayoutNodeDef
active: PaneId
LayoutNode is the runtime structure used for drawing, while LayoutNodeDef is the mirrored type used for serialization.
Win32-side runtime state
ClientState
panes: Arc<Mutex<PaneStore>>
ime: ImeHandler
msg_tx
split_tx
float_tx
layout_tx
active_toasts
content_rect
app_focused
native_notif_queue
mode: Cell<ClientMode>
theme: Cell<WinTheme>
ClientMode
Normal
Pane
Copy
Root crate (src/)
The top-level orchestration types live here.
AppConfig
hooks: HooksConfig
appearance: AppearanceConfig
HooksConfig
on_pane_created
on_pane_closed
AppearanceConfig
font_family
font_size
background
foreground
cursor
selection_bg
status_bar_bg
Startup and bridge
BootstrapHandles
client_tx
server_rx
ipc_out_tx
surf_id
pane_id
BridgeEvent
PaneOutput
PaneCreated
PaneClosed
UserNotification
CommandFinished
The most important ownership relation
The server-side Grid and client-side Grid are separate instances.
On the client side, TerminalSink keeps the display up to date by reapplying raw PTY data.
That is easy to confuse with earlier explanations from the period when the design looked closer to a monolith, so it is worth calling out explicitly.
A practical reading order for the types
When reading the implementation, the following order tends to work well:
- check the message types in
protocol - look at the entry path in
server::handle_client_message() - inspect
pane.rsand theterminalcrate for PTY and Grid updates - inspect
app/bridge.rsfor how the GUI side is updated - inspect
client::windowfor drawing and input handling
Following that order makes the workspace split much easier to navigate.