fix: crash on resize (#1683)

Without this, resizing the terminal prints "Error: The cursor position
could not be read within a normal duration" and quits the app.
This commit is contained in:
Jeremy Rose
2025-07-25 14:23:38 -07:00
committed by GitHub
parent 75b4008094
commit c66c99c5b5

View File

@@ -88,39 +88,51 @@ impl App<'_> {
{ {
let app_event_tx = app_event_tx.clone(); let app_event_tx = app_event_tx.clone();
std::thread::spawn(move || { std::thread::spawn(move || {
while let Ok(event) = crossterm::event::read() { loop {
match event { // This timeout is necessary to avoid holding the event lock
crossterm::event::Event::Key(key_event) => { // that crossterm::event::read() acquires. In particular,
app_event_tx.send(AppEvent::KeyEvent(key_event)); // reading the cursor position (crossterm::cursor::position())
} // needs to acquire the event lock, and so will fail if it
crossterm::event::Event::Resize(_, _) => { // can't acquire it within 2 sec. Resizing the terminal
app_event_tx.send(AppEvent::RequestRedraw); // crashes the app if the cursor position can't be read.
} if let Ok(true) = crossterm::event::poll(Duration::from_millis(100)) {
crossterm::event::Event::Mouse(MouseEvent { if let Ok(event) = crossterm::event::read() {
kind: MouseEventKind::ScrollUp, match event {
.. crossterm::event::Event::Key(key_event) => {
}) => { app_event_tx.send(AppEvent::KeyEvent(key_event));
scroll_event_helper.scroll_up(); }
} crossterm::event::Event::Resize(_, _) => {
crossterm::event::Event::Mouse(MouseEvent { app_event_tx.send(AppEvent::RequestRedraw);
kind: MouseEventKind::ScrollDown, }
.. crossterm::event::Event::Mouse(MouseEvent {
}) => { kind: MouseEventKind::ScrollUp,
scroll_event_helper.scroll_down(); ..
} }) => {
crossterm::event::Event::Paste(pasted) => { scroll_event_helper.scroll_up();
// Many terminals convert newlines to \r when }
// pasting, e.g. [iTerm2][]. But [tui-textarea crossterm::event::Event::Mouse(MouseEvent {
// expects \n][tui-textarea]. This seems like a bug kind: MouseEventKind::ScrollDown,
// in tui-textarea IMO, but work around it for now. ..
// [tui-textarea]: https://github.com/rhysd/tui-textarea/blob/4d18622eeac13b309e0ff6a55a46ac6706da68cf/src/textarea.rs#L782-L783 }) => {
// [iTerm2]: https://github.com/gnachman/iTerm2/blob/5d0c0d9f68523cbd0494dad5422998964a2ecd8d/sources/iTermPasteHelper.m#L206-L216 scroll_event_helper.scroll_down();
let pasted = pasted.replace("\r", "\n"); }
app_event_tx.send(AppEvent::Paste(pasted)); crossterm::event::Event::Paste(pasted) => {
} // Many terminals convert newlines to \r when
_ => { // pasting, e.g. [iTerm2][]. But [tui-textarea
// Ignore any other events. // expects \n][tui-textarea]. This seems like a bug
// in tui-textarea IMO, but work around it for now.
// [tui-textarea]: https://github.com/rhysd/tui-textarea/blob/4d18622eeac13b309e0ff6a55a46ac6706da68cf/src/textarea.rs#L782-L783
// [iTerm2]: https://github.com/gnachman/iTerm2/blob/5d0c0d9f68523cbd0494dad5422998964a2ecd8d/sources/iTermPasteHelper.m#L206-L216
let pasted = pasted.replace("\r", "\n");
app_event_tx.send(AppEvent::Paste(pasted));
}
_ => {
// Ignore any other events.
}
}
} }
} else {
// Timeout expired, no `Event` is available
} }
} }
}); });