From 8fb79dfe8c08083b056ac164681323bd7aa9bc79 Mon Sep 17 00:00:00 2001 From: Kitsu Date: Mon, 13 Apr 2026 23:13:58 -0300 Subject: [PATCH 1/2] Fix back text overflow --- src/draw/input_text.rs | 2 +- src/draw/list_view.rs | 2 +- src/lib.rs | 36 +++++++++++++++++++++----- src/window.rs | 30 ++++++---------------- tests/fixtures/long_input.png | Bin 0 -> 26833 bytes tests/fixtures/long_name.png | Bin 0 -> 39893 bytes tests/regression/main.rs | 21 ++++++++++++++- tests/regression/snap.rs | 47 ++++++++++++++++++++++++++-------- 8 files changed, 96 insertions(+), 42 deletions(-) create mode 100644 tests/fixtures/long_input.png create mode 100644 tests/fixtures/long_name.png diff --git a/src/draw/input_text.rs b/src/draw/input_text.rs index 65c6c8f..3ee734e 100644 --- a/src/draw/input_text.rs +++ b/src/draw/input_text.rs @@ -96,7 +96,7 @@ impl<'a> Drawable for InputText<'a> { let pos = Point::new(rect_point.x + padding.left, rect_point.y + padding.top); let end_pos = Point::new( - dt.width() as f32 - self.params.padding.right - self.params.margin.right, + point.x + space.width - self.params.padding.right - self.params.margin.right, pos.y, ); diff --git a/src/draw/list_view.rs b/src/draw/list_view.rs index 39415e4..9bc5dfb 100644 --- a/src/draw/list_view.rs +++ b/src/draw/list_view.rs @@ -163,7 +163,7 @@ where } let pos = Point::new(x_offset + icon_size_f32 + icon_spacing, y_offset); - let end_pos = Point::new(dt.width() as f32 - self.params.margin.right, y_offset); + let end_pos = Point::new(point.x + space.width - margin.right, y_offset); let color = if i == selected_item { self.params.selected_font_color diff --git a/src/lib.rs b/src/lib.rs index 1ed0488..24b5d19 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,22 +24,43 @@ macro_rules! prog_name { }; } +pub struct Viewport { + buf_size: (i32, i32), + content_offset: (f32, f32), + content_size: (f32, f32), +} + +impl Viewport { + pub fn full(width: i32, height: i32) -> Self { + Self { + buf_size: (width, height), + content_offset: (0.0, 0.0), + content_size: (width as f32, height as f32), + } + } + + pub fn inset(mut self, offset: (f32, f32), content: (f32, f32)) -> Self { + self.content_offset = offset; + self.content_size = content; + self + } +} + pub fn render_to_buffer( config: &config::Config, state: &mut state::State, scale: u16, - width: i32, - height: i32, buffer: &mut [u32], + viewport: Viewport, ) { use draw::Drawable; - let mut dt = DrawTarget::from_backing(width, height, buffer); + let mut dt = DrawTarget::from_backing(viewport.buf_size.0, viewport.buf_size.1, buffer); let mut space_left = draw::Space { - width: width as f32, - height: height as f32, + width: viewport.content_size.0, + height: viewport.content_size.1, }; - let mut point = draw::Point::new(0., 0.); + let mut point = draw::Point::new(viewport.content_offset.0, viewport.content_offset.1); let (mut drawables, dyn_space) = draw::make_drawables(config, state, scale); if let Some(dyn_space) = dyn_space { @@ -47,6 +68,9 @@ pub fn render_to_buffer( } while let Some(d) = drawables.borrowed_next() { let occupied = d.draw(&mut dt, scale, space_left, point); + debug_assert!( + occupied.width <= space_left.width && occupied.height <= space_left.height + ); point.y += occupied.height; space_left.height -= occupied.height; } diff --git a/src/window.rs b/src/window.rs index e1f48fc..a171cec 100644 --- a/src/window.rs +++ b/src/window.rs @@ -273,8 +273,7 @@ impl Window { } }; - use crate::draw::*; - let mut dt = { + let canvas = { #[allow(clippy::needless_lifetimes)] fn transmute_slice<'a>(a: &'a mut [u8]) -> &'a mut [u32] { assert_eq!(a.as_ptr().align_offset(std::mem::align_of::()), 0); @@ -289,30 +288,17 @@ impl Window { &mut *std::ptr::slice_from_raw_parts_mut(a.as_mut_ptr().cast(), a.len() / 4) } } - let canvas = transmute_slice(canvas); - DrawTarget::from_backing(width, height, canvas) + transmute_slice(canvas) }; - let mut space_left = Space { - width: content_w as f32, - height: content_h as f32, - }; - let mut point = Point::new(scaled_offset_x, scaled_offset_y); - - let (mut drawables, dyn_space) = - crate::draw::make_drawables(&self.config, &mut self.state, self.scale); - if let Some(dyn_space) = dyn_space { - space_left.height = space_left.height.min(dyn_space.height); - } - while let Some(d) = drawables.borrowed_next() { - let occupied = d.draw(&mut dt, self.scale, space_left, point); - debug_assert!( - occupied.width <= space_left.width && occupied.height <= space_left.height + let mut viewport = crate::Viewport::full(width, height); + if overlay { + viewport = viewport.inset( + (scaled_offset_x, scaled_offset_y), + (content_w as f32, content_h as f32), ); - - point.y += occupied.height; - space_left.height -= occupied.height; } + crate::render_to_buffer(&self.config, &mut self.state, self.scale, canvas, viewport); self.surface.damage_buffer(0, 0, width, height); self.surface.frame(qh, self.surface.clone()); diff --git a/tests/fixtures/long_input.png b/tests/fixtures/long_input.png new file mode 100644 index 0000000000000000000000000000000000000000..d27b0034ca5a1a6e4b630fab00948e557b8a6763 GIT binary patch literal 26833 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 z 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%0AINzVXm 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 Vec { + items.iter().map(|s| s.to_string()).collect() +} + pub fn test_entries() -> Vec { - [ + to_entries(&[ "Firefox", "Chromium", "Terminal", @@ -18,10 +22,16 @@ pub fn test_entries() -> Vec { "Calculator", "Text Editor", "Music Player", - ] - .iter() - .map(|s| s.to_string()) - .collect() + ]) +} + +pub fn test_entries_with_long_name() -> Vec { + to_entries(&[ + "Very Long Application Name That Definitely Does Not Fit In The Window", + "Firefox", + "Chromium", + "Terminal", + ]) } fn unpremultiply_to_rgba(buffer: &[u32]) -> Vec { @@ -85,6 +95,15 @@ fn load_png_rgba(path: &str) -> (u32, u32, Vec) { } pub fn run_regression(name: &str, entries: Vec, actions: &[Action]) { + run_regression_with_padding(name, entries, actions, (0, 0)); +} + +pub fn run_regression_with_padding( + name: &str, + entries: Vec, + actions: &[Action], + padding: (u32, u32), +) { let config = Config::default(); let mode = Mode::dialog_from_lines(entries); @@ -99,14 +118,20 @@ pub fn run_regression(name: &str, entries: Vec, actions: &[Action]) { let params: Params = config.param(); let scale = params.scale.unwrap_or(1); - let w = (params.width * u32::from(scale)) as i32; - let h = (params.height * u32::from(scale)) as i32; - let mut buffer = vec![0u32; (w * h) as usize]; - yofi::render_to_buffer(&config, &mut state, scale, w, h, &mut buffer); + let content_w = params.width * u32::from(scale); + let content_h = params.height * u32::from(scale); + let buf_w = (content_w + 2 * padding.0) as i32; + let buf_h = (content_h + 2 * padding.1) as i32; + + let mut buffer = vec![0u32; (buf_w * buf_h) as usize]; + let viewport = yofi::Viewport::full(buf_w, buf_h).inset( + (padding.0 as f32, padding.1 as f32), + (content_w as f32, content_h as f32), + ); + yofi::render_to_buffer(&config, &mut state, scale, &mut buffer, viewport); let actual_rgba = unpremultiply_to_rgba(&buffer); - let w = w as u32; - let h = h as u32; + let (w, h) = (buf_w as u32, buf_h as u32); let fixture = format!("tests/fixtures/{name}.png"); let new_file = format!("tests/fixtures/{name}.new.png"); From 67cb69d4a1a2db747ee1189033c27faa1f2ac855 Mon Sep 17 00:00:00 2001 From: Kitsu Date: Tue, 14 Apr 2026 08:11:57 -0300 Subject: [PATCH 2/2] fix fmt --- src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 24b5d19..2d89134 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -68,9 +68,7 @@ pub fn render_to_buffer( } while let Some(d) = drawables.borrowed_next() { let occupied = d.draw(&mut dt, scale, space_left, point); - debug_assert!( - occupied.width <= space_left.width && occupied.height <= space_left.height - ); + debug_assert!(occupied.width <= space_left.width && occupied.height <= space_left.height); point.y += occupied.height; space_left.height -= occupied.height; }