Handle resize
A backend’s display can resize out from under you: a user resizes their terminal (crossterm) or
drags a window’s edge (software/gl/wgpu). retroglyph surfaces this as an ordinary event rather
than something you poll for, and one call resizes the grid to match.
Reacting to Event::Resize
Drain events every tick, same as any other input, and look for
Event::Resize.
It carries the new size in cells, already converted from whatever the backend measured (a real
terminal’s reported columns/rows, or a window’s physical pixel size divided by the font’s cell
size):
fn handle_events<B: Backend>(term: &mut Terminal<B>) -> bool {
let mut requested_size = None;
let mut quit = false;
for event in term.drain_events() {
match event {
Event::Key(key) if key.is_down() => {
if matches!(key.code, KeyCode::Char('q') | KeyCode::Escape) {
quit = true;
}
}
Event::Close => quit = true,
Event::Resize(width, height) => requested_size = Some((width, height)),
_ => {}
}
}
if let Some((width, height)) = requested_size {
term.resize(width, height);
}
!quit
}
Apply it with
Terminal::resize,
not Backend::resize directly: Terminal::resize resizes the grid and calls the backend’s own
resize to keep
Backend::size
in sync. Calling Backend::resize on its own only updates what the backend reports; it does not
touch the grid, so your next draw call would still be working against the old dimensions.
Draw at term.area(), not a hardcoded size
The part that actually needs a resize handler to matter: never assume a fixed grid size. Read
Terminal::area
fresh every frame and lay out relative to it, so whatever size the resize handler applies is
immediately reflected in the next draw:
let area = term.area();
if area.width() == 0 || area.height() == 0 {
return;
}
Redraw the whole area on resize, not just what changed
Terminal::present only sends a backend the cells that changed since the last frame, and
Terminal::resize preserves overlapping content across the resize rather than clearing it. That
combination means a cell your draw code never explicitly touches keeps showing whatever was there
before, indefinitely, on any backend that doesn’t clear its own surface on resize. Shrinking a
window and then growing it back leaves stale glyphs sitting in what’s now the middle of the frame if
your draw code only paints an outline.
The fix isn’t a Terminal method: it’s that a resize-aware draw function fills its entire current
area every frame (background first, then whatever’s drawn on top), so every cell’s on-screen content
is explained by that frame’s own draw call. See examples/examples/14_resize.rs for a complete
example built around exactly this rule, runnable as:
cargo run --example 14_resize --features crossterm
cargo run --example 14_resize --features software
See also
- Choose a backend, if you’re deciding between a terminal and a windowed backend up front.