Compare commits

...

4 Commits

Author SHA1 Message Date
Javier Soto
557731d7d6 Fix CI errors 2025-09-02 16:34:59 -07:00
Javier Soto
8ac87edd64 Use proper logging method 2025-09-02 15:28:54 -07:00
Javier Soto
bba09a89e2 Simplify 2025-09-02 14:33:47 -07:00
Javier Soto
8958283edd fix: work-around "The cursor position could not be read within a normal duration" crash
Fixes #2805
2025-09-02 14:28:39 -07:00

View File

@@ -22,6 +22,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
use std::io;
use std::io::ErrorKind;
use ratatui::backend::Backend;
use ratatui::backend::ClearType;
@@ -200,7 +201,14 @@ where
/// Creates a new [`Terminal`] with the given [`Backend`] and [`TerminalOptions`].
pub fn with_options(mut backend: B) -> io::Result<Self> {
let screen_size = backend.size()?;
let cursor_pos = backend.get_cursor_position()?;
let cursor_pos = backend.get_cursor_position().or_else(|error| {
if is_get_cursor_position_timeout_error(&error) {
tracing::warn!("cursor position read timed out during startup: {error}");
Ok(Position { x: 0, y: 0 })
} else {
Err(error)
}
})?;
Ok(Self {
backend,
buffers: [
@@ -406,7 +414,19 @@ where
/// This is the position of the cursor after the last draw call.
#[allow(dead_code)]
pub fn get_cursor_position(&mut self) -> io::Result<Position> {
self.backend.get_cursor_position()
self.backend
.get_cursor_position()
.inspect(|position| {
self.last_known_cursor_pos = *position;
})
.or_else(|error| {
if is_get_cursor_position_timeout_error(&error) {
tracing::warn!("cursor position read timed out: {error}");
Ok(self.last_known_cursor_pos)
} else {
Err(error)
}
})
}
/// Sets the cursor position.
@@ -441,3 +461,10 @@ where
self.backend.size()
}
}
// Crossterm occasionally times out while another task holds the terminal for event polling.
// That error originates here: https://github.com/crossterm-rs/crossterm/blob/6af9116b6a8ba365d8d8e7a806cbce318498b84d/src/cursor/sys/unix.rs#L53
fn is_get_cursor_position_timeout_error(error: &io::Error) -> bool {
error.kind() == ErrorKind::Other
&& error.to_string() == "The cursor position could not be read within a normal duration"
}