From 32a4d0f0aaa390dba88a6891df6869b0d04ea42d Mon Sep 17 00:00:00 2001 From: Sophie Herold Date: Tue, 23 Dec 2025 23:04:56 +0100 Subject: [PATCH] image/zoom: Allow 50% zoom via menu for 16px images Zoom out for 16px or smaller images is usually blocked. But allow it for zoom menu as we allow 50% via zoom menu in other situations where it is blocked otherwise. Also, this is probably much less complex implementation wise. Closes #544 --- news.d/50.alpha/changed-limit-zoom-out | 1 + src/widgets/image.rs | 3 +++ src/widgets/image/zoom.rs | 21 +++++++++++++-------- 3 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 news.d/50.alpha/changed-limit-zoom-out diff --git a/news.d/50.alpha/changed-limit-zoom-out b/news.d/50.alpha/changed-limit-zoom-out new file mode 100644 index 0000000..06ea5a8 --- /dev/null +++ b/news.d/50.alpha/changed-limit-zoom-out @@ -0,0 +1 @@ +Don't allow endless zoom out diff --git a/src/widgets/image.rs b/src/widgets/image.rs index bdbf661..c18deb2 100644 --- a/src/widgets/image.rs +++ b/src/widgets/image.rs @@ -130,6 +130,9 @@ const SMALL_OCCUPY_SCREEN: f64 = 0.8; /// this value, unless the image itself is smaller than this. const SMALLEST_RENDERED_PIXEL_SIZE: f64 = 16.0; +/// Smallest zoom level reachable via entries in the zoom menu +const LOWEST_MENU_ZOOM_LEVEL: f64 = 0.5; + #[derive(Default, Debug, Clone, Copy, glib::Variant, glib::Enum, PartialEq, Eq)] #[enum_type(name = "LpFitMode")] pub enum FitMode { diff --git a/src/widgets/image/zoom.rs b/src/widgets/image/zoom.rs index 65b9164..fefd238 100644 --- a/src/widgets/image/zoom.rs +++ b/src/widgets/image/zoom.rs @@ -99,20 +99,25 @@ impl imp::LpImage { pub(super) fn min_zoom(&self) -> f64 { let (width, height) = self.untransformed_dimensions(); - // If the image is smaller than the smallest rendered pixel size, - // block zooming out entirely - if (width as f64) < SMALLEST_RENDERED_PIXEL_SIZE + let zoom_level = if (width as f64) < SMALLEST_RENDERED_PIXEL_SIZE || (height as f64) < SMALLEST_RENDERED_PIXEL_SIZE { + // If the image is smaller than the smallest rendered pixel size, + // block zooming out entirely 1.0 - } - // Prevent the rendered size from going below SMALLEST_RENDERED_PIXEL_SIZE - // Original size * zoom factor = rendered size - // <=> Zoom factor = rendered size / original size - else if width < height { + } else if width < height { + // Prevent the rendered size from going below SMALLEST_RENDERED_PIXEL_SIZE SMALLEST_RENDERED_PIXEL_SIZE / (width as f64) } else { SMALLEST_RENDERED_PIXEL_SIZE / (height as f64) + }; + + if matches!(self.obj().fit_mode(), FitMode::ExactVolatile) { + // Allow zoom menu to allways function. We are allowing this since disabling the + // zoom menu entries would probably be more complicated. + f64::min(zoom_level, LOWEST_MENU_ZOOM_LEVEL) + } else { + zoom_level } }