tlc: revert to blocking-read event loop — fix terminal resize on Redox

The poll-based event loop (rustix::event::poll with 200ms timeout) broke
terminal size detection on Redox. When tui.size() returned (0,0) via
unwrap_or_default() after a failed dup(1,"winsize"), the size-change
check would clear the screen and render nothing.

Ratatui's draw() already calls autoresize() on every frame, which queries
backend.size() and resizes buffers automatically. The manual size check
and poll-based wake-up were redundant and harmful.

Reverted to the original blocking-read approach that worked on Redox:
  stdin.lock().events_and_raw().next()  →  process key  →  render()
Resize is detected on the next keypress via ratatui's built-in autoresize.
This commit is contained in:
2026-06-19 19:06:02 +03:00
parent 612732dc39
commit 4edc3ddd5b
+7 -33
View File
@@ -13,7 +13,6 @@ use std::io::Write;
use std::time::Duration;
use anyhow::Result;
use rustix::event::{poll, PollFd, PollFlags, Timespec};
use termion::event::{Event as TermEvent, Key as TermKey};
use termion::input::TermReadEventsAndRaw;
@@ -54,25 +53,13 @@ impl Application {
// Initial paint.
render(&mut tui, &mut fm)?;
let mut last_size = tui.size();
// Stdin fd for poll — obtained without locking so the subshell
// can still read from stdin when we drop into CTRL+O.
let stdin = std::io::stdin();
let poll_timeout =
Timespec::try_from(Duration::from_millis(200)).unwrap_or_default();
// Main event loop — MC-style resize detection via poll timeout.
// poll() wakes every 200ms even without key input, letting us
// detect terminal resize without requiring a keypress.
// Main event loop — blocking stdin, raw mode is active.
//
// Ratatui's `draw()` calls `autoresize()` on every frame, which
// queries `backend.size()` and resizes buffers if the terminal
// dimensions changed. This means resize is detected automatically
// on the next keypress after a resize — no SIGWINCH or poll needed.
loop {
let cur_size = tui.size();
if cur_size != last_size {
last_size = cur_size;
let _ = tui.terminal_mut().clear();
render(&mut tui, &mut fm)?;
}
// Handle pending external execution (subshell or command line)
// before reading the next key. This runs every iteration
// regardless of which code path set the flag.
@@ -81,20 +68,7 @@ impl Application {
render(&mut tui, &mut fm)?;
}
// Poll stdin with 200ms timeout. On timeout (no key), loop
// back and re-check terminal size. On data, read the key.
let mut poll_fds = [PollFd::new(&stdin, PollFlags::IN)];
match poll(&mut poll_fds, Some(&poll_timeout)) {
Ok(0) => continue,
Ok(_) => {
if !poll_fds[0].revents().contains(PollFlags::IN) {
continue;
}
}
Err(_) => continue,
}
// Data available on stdin — read the key event.
let stdin = std::io::stdin();
let mut events = stdin.lock().events_and_raw();
let (event, raw) = match events.next() {
Some(Ok(pair)) => pair,