From 071eaaa6e142384a24ee78649bc7328c7a59c13c Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Tue, 14 Apr 2026 09:36:19 +0200 Subject: [PATCH] scrollback-history-limit (closes #993) --- docs/docs/config.md | 14 ++ docs/src/pages/changelog.mdx | 7 + frontends/rioterm/src/context/mod.rs | 5 + frontends/rioterm/src/screen/mod.rs | 1 + rio-backend/src/config/defaults.rs | 5 + rio-backend/src/config/mod.rs | 41 ++++ rio-backend/src/crosswords/mod.rs | 299 ++++++++++++++++++++------ rio-backend/src/crosswords/search.rs | 20 +- rio-backend/src/crosswords/vi_mode.rs | 1 + rio-backend/src/graphics/kitty/mod.rs | 20 ++ rio-backend/src/selection.rs | 9 +- 11 files changed, 356 insertions(+), 66 deletions(-) diff --git a/docs/docs/config.md b/docs/docs/config.md index 43c34a8b..5151d00c 100644 --- a/docs/docs/config.md +++ b/docs/docs/config.md @@ -1352,6 +1352,20 @@ Default is `true`. enable-scroll-bar = true ``` +## scrollback-history-limit + +Maximum number of scrollback history lines retained per panel. Scrollback lets you scroll up to inspect command output that has moved off-screen. + +- Raising this keeps more history available at the cost of memory proportional to the total number of cells held in the buffer. +- Setting it to `0` disables scrollback entirely. +- The alt-screen grid (used by full-screen TUIs like `vim`, `less`, `htop`) never keeps scrollback regardless of this value. + +Default is `10000`. + +```toml +scrollback-history-limit = 10000 +``` + ## shell You can set `shell.program` to the path of your favorite shell, e.g. `/bin/fish`. diff --git a/docs/src/pages/changelog.mdx b/docs/src/pages/changelog.mdx index dade0e5a..3c65f753 100644 --- a/docs/src/pages/changelog.mdx +++ b/docs/src/pages/changelog.mdx @@ -5,6 +5,13 @@ language: 'en'

Changelog

+## 0.3.9 + +- Add `scrollback-history-limit` config option (default `10000`, set to `0` to disable scrollback). Fixes [#993](https://github.com/raphamorim/rio/issues/993). +- Harden Kitty graphics protocol: reject images exceeding 10000 px per axis or 400 MiB, add per-chunk base64 decoding so clients like `chafa --format=kitty` (which pads every chunk) merge correctly, time out stale chunked uploads after 10 s, combine `i=/I=/p=` response keys, validate `i=`/`I=` mutual exclusion, and require `i=` for `a=q` queries. +- Fix kitty image protocol whenever using transmission. +- Fix color picker not rendering correctly. + ## 0.3.8 - Fix click between panels not working if it's on alternative screen. diff --git a/frontends/rioterm/src/context/mod.rs b/frontends/rioterm/src/context/mod.rs index 792c796c..cc6f7695 100644 --- a/frontends/rioterm/src/context/mod.rs +++ b/frontends/rioterm/src/context/mod.rs @@ -132,6 +132,7 @@ pub struct ContextManagerConfig { pub panel: rio_backend::config::layout::Panel, pub title: rio_backend::config::title::Title, pub keyboard: rio_backend::config::keyboard::Keyboard, + pub scrollback_history_limit: usize, } const DEFAULT_CONTEXT_CAPACITY: usize = 28; @@ -161,6 +162,8 @@ pub fn create_dead_context( event_proxy, window_id, route_id, + // Dead context never sees new input — no scrollback needed. + 0, ); let terminal: Arc>> = Arc::new(FairMutex::new(terminal)); let (sender, _receiver) = corcovado::channel::channel(); @@ -235,6 +238,7 @@ impl ContextManager { event_proxy.clone(), window_id, route_id, + config.scrollback_history_limit, ); terminal.blinking_cursor = cursor_state.1; let terminal: Arc>> = Arc::new(FairMutex::new(terminal)); @@ -1013,6 +1017,7 @@ impl ContextManager { panel: config.panel, title: config.title, keyboard: config.keyboard, + scrollback_history_limit: config.scrollback_history_limit, }; let current = self.current(); diff --git a/frontends/rioterm/src/screen/mod.rs b/frontends/rioterm/src/screen/mod.rs index 34279b99..949385da 100644 --- a/frontends/rioterm/src/screen/mod.rs +++ b/frontends/rioterm/src/screen/mod.rs @@ -200,6 +200,7 @@ impl Screen<'_> { panel: config.panel, title: config.title.clone(), keyboard: config.keyboard, + scrollback_history_limit: config.scrollback_history_limit, }; // Create rich text with initial position accounting for island diff --git a/rio-backend/src/config/defaults.rs b/rio-backend/src/config/defaults.rs index 5cf91a1c..9a2ad9b1 100644 --- a/rio-backend/src/config/defaults.rs +++ b/rio-backend/src/config/defaults.rs @@ -15,6 +15,11 @@ pub fn default_cursor_interval() -> u64 { 800 } +#[inline] +pub fn default_scrollback_history_limit() -> usize { + 10_000 +} + #[inline] pub fn default_title_placeholder() -> Option { Some(String::from("▲")) diff --git a/rio-backend/src/config/mod.rs b/rio-backend/src/config/mod.rs index 836f18e4..ad0794dc 100644 --- a/rio-backend/src/config/mod.rs +++ b/rio-backend/src/config/mod.rs @@ -162,6 +162,11 @@ pub struct Config { pub bell: Bell, #[serde(default = "default_bool_true", rename = "enable-scroll-bar")] pub enable_scroll_bar: bool, + #[serde( + default = "default_scrollback_history_limit", + rename = "scrollback-history-limit" + )] + pub scrollback_history_limit: usize, #[serde(default = "effects::Effects::default")] pub effects: effects::Effects, } @@ -659,6 +664,7 @@ impl Default for Config { hints: Hints::default(), bell: Bell::default(), enable_scroll_bar: true, + scrollback_history_limit: default_scrollback_history_limit(), effects: effects::Effects::default(), } } @@ -1263,6 +1269,41 @@ mod tests { assert_eq!(result.window.colorspace, window::Colorspace::DisplayP3); } + #[test] + fn test_scrollback_history_limit_default() { + let result = create_temporary_config( + "scrollback-default", + r#" + [window] + width = 800 + "#, + ); + assert_eq!(result.scrollback_history_limit, 10_000); + } + + #[test] + fn test_scrollback_history_limit_custom() { + let result = create_temporary_config( + "scrollback-custom", + r#" + scrollback-history-limit = 50000 + "#, + ); + assert_eq!(result.scrollback_history_limit, 50_000); + } + + #[test] + fn test_scrollback_history_limit_zero_disables() { + // A value of 0 disables scrollback. Must round-trip cleanly. + let result = create_temporary_config( + "scrollback-zero", + r#" + scrollback-history-limit = 0 + "#, + ); + assert_eq!(result.scrollback_history_limit, 0); + } + #[test] fn test_window_colorspace_default() { let result = create_temporary_config( diff --git a/rio-backend/src/crosswords/mod.rs b/rio-backend/src/crosswords/mod.rs index 250b8107..7d14fe20 100644 --- a/rio-backend/src/crosswords/mod.rs +++ b/rio-backend/src/crosswords/mod.rs @@ -449,10 +449,11 @@ impl Crosswords { event_proxy: U, window_id: WindowId, route_id: usize, + scrollback_history_limit: usize, ) -> Crosswords { let cols = dimensions.columns(); let rows = dimensions.screen_lines(); - let grid = Grid::new(rows, cols, 10_000); + let grid = Grid::new(rows, cols, scrollback_history_limit); let alt = Grid::new(rows, cols, 0); let scroll_region = Line(0)..Line(rows as i32); @@ -4038,8 +4039,14 @@ mod tests { fn scroll_up() { let size = CrosswordsSize::new(1, 10); let window_id = crate::event::WindowId::from(0); - let mut cw = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut cw = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); for i in 0..10 { cw.grid[Line(i)][Column(0)].set_c(i as u8 as char); } @@ -4073,8 +4080,14 @@ mod tests { let size = CrosswordsSize::new(1, 1); let window_id = crate::event::WindowId::from(0); - let mut cw = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut cw = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); assert_eq!(cw.grid.total_lines(), 1); cw.linefeed(); @@ -4087,8 +4100,14 @@ mod tests { let window_id = crate::event::WindowId::from(0); - let mut cw = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut cw = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); let cursor = cw.cursor(); assert_eq!(cursor.pos.col, 0); assert_eq!(cursor.pos.row, 0); @@ -4113,8 +4132,14 @@ mod tests { let size = CrosswordsSize::new(5, 10); let window_id = crate::event::WindowId::from(0); - let mut cw = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut cw = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); for i in 0..4 { cw.grid[Line(0)][Column(i)].set_c(i as u8 as char); } @@ -4142,8 +4167,14 @@ mod tests { let size = CrosswordsSize::new(40, 5); let window_id = crate::event::WindowId::from(0); - let mut cw = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut cw = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); let mut processor = Processor::::new(); // Plain text, then "click" wrapped in an OSC 8, then plain "." @@ -4190,8 +4221,14 @@ mod tests { let size = CrosswordsSize::new(40, 5); let window_id = crate::event::WindowId::from(0); - let mut cw = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut cw = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); let mut processor = Processor::::new(); let bytes = b"\x1b]8;;https://a.example\x07A\x1b]8;;\x07\ @@ -4221,8 +4258,14 @@ mod tests { let size = CrosswordsSize::new(40, 5); let window_id = crate::event::WindowId::from(0); - let mut cw = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut cw = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); let mut processor = Processor::::new(); // Open a hyperlink, write 'X', close it, then write 'Y'. @@ -4247,8 +4290,14 @@ mod tests { let size = CrosswordsSize::new(40, 5); let window_id = crate::event::WindowId::from(0); - let mut cw = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut cw = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); let mut processor = Processor::::new(); // "AB\nCD" with the whole thing inside one OSC 8 link. @@ -4274,8 +4323,14 @@ mod tests { fn test_damage_tracking_after_control_c() { let size = CrosswordsSize::new(80, 24); let window_id = crate::event::WindowId::from(0); - let mut cw = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut cw = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); // Simulate fzf-like scenario: write some text let test_text = "fzf> search term"; @@ -4343,8 +4398,14 @@ mod tests { fn test_damage_tracking_cursor_movement() { let size = CrosswordsSize::new(80, 24); let window_id = crate::event::WindowId::from(0); - let mut cw = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut cw = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); // Write text on multiple lines cw.input('A'); @@ -4373,8 +4434,14 @@ mod tests { fn test_damage_tracking_clear_operations() { let size = CrosswordsSize::new(80, 24); let window_id = crate::event::WindowId::from(0); - let mut cw = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut cw = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); // Fill some lines with content for line in 0..5 { @@ -4417,8 +4484,14 @@ mod tests { fn test_damage_tracking_prompt_redraw() { let size = CrosswordsSize::new(80, 24); let window_id = crate::event::WindowId::from(0); - let mut cw = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut cw = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); // Simulate a shell prompt scenario let prompt = "$ "; @@ -4466,8 +4539,14 @@ mod tests { let size = CrosswordsSize::new(5, 5); let window_id = crate::event::WindowId::from(0); - let mut term = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut term = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); let grid = &mut term.grid; for i in 0..4 { if i == 1 { @@ -4539,8 +4618,14 @@ mod tests { let size = CrosswordsSize::new(5, 1); let window_id = crate::event::WindowId::from(0); - let mut term = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut term = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); let mut grid: Grid = Grid::new(1, 5, 0); for i in 0..5 { grid[Line(0)][Column(i)].set_c('a'); @@ -4566,8 +4651,14 @@ mod tests { let size = CrosswordsSize::new(5, 5); let window_id = crate::event::WindowId::from(0); - let mut term = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut term = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); let grid = &mut term.grid; for i in 1..4 { grid[Line(i)][Column(0)].set_c('"'); @@ -4651,8 +4742,14 @@ mod tests { let size = CrosswordsSize::new(10, 10); let window_id = WindowId::from(0); - let mut term = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut term = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); // Move cursor to position (1, 5) and type some text term.goto(Line(1), Column(5)); @@ -4728,8 +4825,14 @@ mod tests { let size = CrosswordsSize::new(10, 10); let window_id = WindowId::from(0); - let mut term = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut term = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); // Reset damage to start clean term.reset_damage(); @@ -4796,8 +4899,14 @@ mod tests { fn test_keyboard_mode_push_pop() { let size = CrosswordsSize::new(10, 10); let window_id = WindowId::from(0); - let mut term = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut term = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); // Initial state: stack should be empty with NO_MODE assert_eq!( @@ -4837,8 +4946,14 @@ mod tests { fn test_keyboard_mode_stack_wraparound() { let size = CrosswordsSize::new(10, 10); let window_id = WindowId::from(0); - let mut term = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut term = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); // Fill the stack to maximum depth using Handler trait for i in 0..KEYBOARD_MODE_STACK_MAX_DEPTH { @@ -4862,8 +4977,14 @@ mod tests { fn test_keyboard_mode_pop_excessive() { let size = CrosswordsSize::new(10, 10); let window_id = WindowId::from(0); - let mut term = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut term = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); // Push a few modes using Handler trait Handler::push_keyboard_mode(&mut term, KeyboardModes::DISAMBIGUATE_ESC_CODES); @@ -4884,8 +5005,14 @@ mod tests { fn test_keyboard_mode_set_replace() { let size = CrosswordsSize::new(10, 10); let window_id = WindowId::from(0); - let mut term = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut term = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); // Set initial mode using Handler trait method Handler::set_keyboard_mode( @@ -4914,8 +5041,14 @@ mod tests { fn test_keyboard_mode_set_union() { let size = CrosswordsSize::new(10, 10); let window_id = WindowId::from(0); - let mut term = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut term = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); // Set initial mode using Handler trait method Handler::set_keyboard_mode( @@ -4940,8 +5073,14 @@ mod tests { fn test_keyboard_mode_set_difference() { let size = CrosswordsSize::new(10, 10); let window_id = WindowId::from(0); - let mut term = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut term = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); // Set combined mode using Handler trait method let combined_mode = @@ -4970,7 +5109,8 @@ mod tests { let size = CrosswordsSize::new(10, 10); let window_id = WindowId::from(0); let listener = VoidListener {}; - let mut term = Crosswords::new(size, CursorShape::Block, listener, window_id, 0); + let mut term = + Crosswords::new(size, CursorShape::Block, listener, window_id, 0, 10_000); // Push a mode and test reporting using Handler trait Handler::push_keyboard_mode(&mut term, KeyboardModes::DISAMBIGUATE_ESC_CODES); @@ -4986,8 +5126,14 @@ mod tests { fn test_keyboard_mode_reset() { let size = CrosswordsSize::new(10, 10); let window_id = WindowId::from(0); - let mut term = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut term = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); // Push several modes Handler::push_keyboard_mode(&mut term, KeyboardModes::DISAMBIGUATE_ESC_CODES); @@ -5010,8 +5156,14 @@ mod tests { fn test_keyboard_mode_stack_underflow_protection() { let size = CrosswordsSize::new(10, 10); let window_id = WindowId::from(0); - let mut term = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut term = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); // Start at index 0, try to pop using Handler trait - should wrap correctly assert_eq!(term.keyboard_mode_idx, 0); @@ -5051,7 +5203,8 @@ mod tests { let listener = TestListener { events: events.clone(), }; - let mut term = Crosswords::new(size, CursorShape::Block, listener, window_id, 0); + let mut term = + Crosswords::new(size, CursorShape::Block, listener, window_id, 0, 10_000); // Call report_version using Handler trait Handler::report_version(&mut term); @@ -5087,8 +5240,14 @@ mod tests { fn test_keyboard_mode_syncs_with_mode() { let size = CrosswordsSize::new(10, 10); let window_id = WindowId::from(0); - let mut term = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut term = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); // Initially, no keyboard mode should be set assert!(!term.mode().contains(Mode::DISAMBIGUATE_ESC_CODES)); @@ -5166,8 +5325,14 @@ mod tests { // 20×20 pixel image, 10×10 cell size → 2×2 cells let size = CrosswordsSize::new(20, 10); let window_id = crate::event::WindowId::from(0); - let mut cw = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut cw = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); // Set cell dimensions so insert_graphic can compute layout. cw.graphics.cell_width = 10.0; @@ -5224,8 +5389,14 @@ mod tests { fn cell_graphic_accessor() { let size = CrosswordsSize::new(20, 10); let window_id = crate::event::WindowId::from(0); - let mut cw = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut cw = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); cw.graphics.cell_width = 10.0; cw.graphics.cell_height = 10.0; @@ -5259,8 +5430,14 @@ mod tests { fn delete_all_graphics_frees_extras() { let size = CrosswordsSize::new(20, 10); let window_id = crate::event::WindowId::from(0); - let mut cw = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut cw = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); cw.graphics.cell_width = 10.0; cw.graphics.cell_height = 10.0; diff --git a/rio-backend/src/crosswords/search.rs b/rio-backend/src/crosswords/search.rs index 40031e5b..82c1039e 100644 --- a/rio-backend/src/crosswords/search.rs +++ b/rio-backend/src/crosswords/search.rs @@ -769,8 +769,14 @@ mod tests { // Create terminal with the appropriate dimensions. let window_id = crate::event::WindowId::from(0); let size = CrosswordsSize::new(num_cols, lines.len()); - let mut term = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut term = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); // Fill terminal with content. for (line, text) in lines.iter().enumerate() { @@ -1254,8 +1260,14 @@ mod tests { fn wide_without_spacer() { let window_id = crate::event::WindowId::from(0); let size = CrosswordsSize::new(2, 2); - let mut term = - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0); + let mut term = Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ); term.grid[Line(0)][Column(0)].set_c('x'); term.grid[Line(0)][Column(1)].set_c('字'); term.grid[Line(0)][Column(1)].set_wide(Wide::Wide); diff --git a/rio-backend/src/crosswords/vi_mode.rs b/rio-backend/src/crosswords/vi_mode.rs index fc5a11a1..305efe5b 100644 --- a/rio-backend/src/crosswords/vi_mode.rs +++ b/rio-backend/src/crosswords/vi_mode.rs @@ -419,6 +419,7 @@ mod tests { VoidListener, crate::event::WindowId::from(0), 0, + 10_000, ) } diff --git a/rio-backend/src/graphics/kitty/mod.rs b/rio-backend/src/graphics/kitty/mod.rs index 26f564ba..54c867f7 100644 --- a/rio-backend/src/graphics/kitty/mod.rs +++ b/rio-backend/src/graphics/kitty/mod.rs @@ -132,6 +132,7 @@ fn test_png_transmit_and_display() { event_listener, window_id, 0, + 10_000, ); // Set proper cell dimensions @@ -370,6 +371,7 @@ fn test_cursor_movement_default() { event_listener, window_id, 0, + 10_000, ); let initial_cursor_row = term.grid.cursor.pos.row.0; @@ -444,6 +446,7 @@ fn test_cursor_movement_no_move() { event_listener, window_id, 0, + 10_000, ); // Set proper cell dimensions for testing @@ -547,6 +550,7 @@ fn test_image_row_occupation_exact_fit() { event_listener, window_id, 0, + 10_000, ); // Start at row 0 @@ -616,6 +620,7 @@ fn test_image_row_occupation_single_row() { event_listener, window_id, 0, + 10_000, ); // Set proper cell dimensions for testing @@ -682,6 +687,7 @@ fn test_image_row_occupation_three_rows() { event_listener, window_id, 0, + 10_000, ); let initial_cursor_row = term.grid.cursor.pos.row.0; @@ -749,6 +755,7 @@ fn test_image_row_occupation_from_middle() { event_listener, window_id, 0, + 10_000, ); // Move cursor to row 5 @@ -819,6 +826,7 @@ fn test_delete_all() { event_listener, window_id, 0, + 10_000, ); // Delete all graphics (d=a) @@ -850,6 +858,7 @@ fn test_store_graphic() { event_listener, window_id, 0, + 10_000, ); let pixels = vec![255u8, 0, 0, 255]; // 1x1 red pixel @@ -886,6 +895,7 @@ fn test_place_nonexistent_graphic() { event_listener, window_id, 0, + 10_000, ); let placement = kitty_graphics_protocol::PlacementRequest { @@ -970,6 +980,7 @@ fn test_placed_textures_tracks_inserts() { event_listener, window_id, 0, + 10_000, ); term.graphics.cell_width = 10.0; @@ -2341,6 +2352,7 @@ fn make_test_term() -> Crosswords { TestEventListener, unsafe { WindowId::dummy() }, 0, + 10_000, ) } @@ -3019,6 +3031,7 @@ fn test_resize_widen_unwraps_command_image_follows() { event_listener, window_id, 0, + 10_000, ); term.graphics.cell_width = 10.0; term.graphics.cell_height = 20.0; @@ -3097,6 +3110,7 @@ fn test_resize_narrow_wraps_command_image_follows() { event_listener, window_id, 0, + 10_000, ); term.graphics.cell_width = 10.0; term.graphics.cell_height = 20.0; @@ -3210,6 +3224,7 @@ fn test_debug_widen_visible_layout() { event_listener, window_id, 0, + 10_000, ); term.graphics.cell_width = 10.0; term.graphics.cell_height = 20.0; @@ -3266,6 +3281,7 @@ fn test_debug_narrow_visible_layout() { event_listener, window_id, 0, + 10_000, ); term.graphics.cell_width = 10.0; term.graphics.cell_height = 20.0; @@ -3324,6 +3340,7 @@ fn test_resize_narrow_combined_col_and_row_change() { event_listener, window_id, 0, + 10_000, ); term.graphics.cell_width = 10.0; term.graphics.cell_height = 20.0; @@ -3416,6 +3433,7 @@ fn test_resize_narrow_with_multi_row_image() { event_listener, window_id, 0, + 10_000, ); term.graphics.cell_width = 10.0; term.graphics.cell_height = 20.0; @@ -3522,6 +3540,7 @@ fn test_resize_narrow_with_cursor_at_bottom_of_screen() { event_listener, window_id, 0, + 10_000, ); term.graphics.cell_width = 10.0; term.graphics.cell_height = 20.0; @@ -3629,6 +3648,7 @@ fn test_resize_narrow_with_prompt_after_image() { event_listener, window_id, 0, + 10_000, ); term.graphics.cell_width = 10.0; term.graphics.cell_height = 20.0; diff --git a/rio-backend/src/selection.rs b/rio-backend/src/selection.rs index 0f219118..53642862 100644 --- a/rio-backend/src/selection.rs +++ b/rio-backend/src/selection.rs @@ -450,7 +450,14 @@ mod tests { let size = CrosswordsSize::new(width, height); let window_id = crate::event::WindowId::from(0); - Crosswords::new(size, CursorShape::Block, VoidListener {}, window_id, 0) + Crosswords::new( + size, + CursorShape::Block, + VoidListener {}, + window_id, + 0, + 10_000, + ) } /// Test case of single cell selection. -- 2.51.2