From 0cc906c5463b818bda7ee4ecc611dba2eaf03742 Mon Sep 17 00:00:00 2001 From: drendog Date: Sat, 25 Oct 2025 22:40:33 +0200 Subject: [PATCH] refactor: extract surface dimensions and scaling mode --- src/windowing/mod.rs | 1 + src/windowing/state/mod.rs | 141 ++++++++++++++++------------ src/windowing/surface_dimensions.rs | 39 ++++++++ 3 files changed, 122 insertions(+), 59 deletions(-) create mode 100644 src/windowing/surface_dimensions.rs diff --git a/src/windowing/mod.rs b/src/windowing/mod.rs index 4e3d4aa..2e46a02 100644 --- a/src/windowing/mod.rs +++ b/src/windowing/mod.rs @@ -4,6 +4,7 @@ mod globals; mod macros; mod state; mod surface; +mod surface_dimensions; mod system; pub use system::WindowingSystem; diff --git a/src/windowing/state/mod.rs b/src/windowing/state/mod.rs index ecaf337..ad6ee9b 100644 --- a/src/windowing/state/mod.rs +++ b/src/windowing/state/mod.rs @@ -9,10 +9,18 @@ use wayland_protocols::wp::fractional_scale::v1::client::wp_fractional_scale_v1: use wayland_protocols::wp::viewporter::client::wp_viewport::WpViewport; use crate::rendering::femtovg_window::FemtoVGWindow; use crate::errors::{LayerShikaError, Result}; +use crate::windowing::surface_dimensions::SurfaceDimensions; pub mod builder; pub mod dispatches; +#[derive(Debug)] +enum ScalingMode { + FractionalWithViewport, + FractionalOnly, + Integer, +} + pub struct WindowState { component_instance: ComponentInstance, surface: Rc, @@ -77,78 +85,93 @@ impl WindowState { }) } + const fn determine_scaling_mode(&self) -> ScalingMode { + if self.fractional_scale.is_some() && self.viewport.is_some() { + ScalingMode::FractionalWithViewport + } else if self.fractional_scale.is_some() { + ScalingMode::FractionalOnly + } else { + ScalingMode::Integer + } + } + #[allow(clippy::cast_precision_loss)] + fn configure_slint_window(&self, dimensions: &SurfaceDimensions, mode: &ScalingMode) { + match mode { + ScalingMode::FractionalWithViewport => { + self.window + .set_size(slint::WindowSize::Logical(slint::LogicalSize::new( + dimensions.logical_width as f32, + dimensions.logical_height as f32, + ))); + self.window.set_scale_factor(self.scale_factor); + } + ScalingMode::FractionalOnly => { + self.window + .set_size(slint::WindowSize::Logical(slint::LogicalSize::new( + dimensions.logical_width as f32, + dimensions.logical_height as f32, + ))); + self.window.set_scale_factor(dimensions.buffer_scale as f32); + } + ScalingMode::Integer => { + self.window + .set_size(slint::WindowSize::Physical(dimensions.physical_size())); + self.window.set_scale_factor(self.scale_factor); + } + } + } + #[allow(clippy::cast_possible_wrap)] + fn configure_wayland_surface(&self, dimensions: &SurfaceDimensions, mode: &ScalingMode) { + match mode { + ScalingMode::FractionalWithViewport => { + self.surface.set_buffer_scale(1); + if let Some(viewport) = &self.viewport { + viewport.set_destination( + dimensions.logical_width as i32, + dimensions.logical_height as i32, + ); + } + } + ScalingMode::FractionalOnly | ScalingMode::Integer => { + self.surface.set_buffer_scale(dimensions.buffer_scale); + } + } + + self.layer_surface + .set_size(dimensions.logical_width, dimensions.logical_height); + self.layer_surface.set_exclusive_zone(self.exclusive_zone); + self.surface.commit(); + } + pub fn update_size(&mut self, width: u32, height: u32) { if width == 0 || height == 0 { info!("Skipping update_size with zero dimension: {width}x{height}"); return; } - #[allow(clippy::cast_possible_truncation)] - #[allow(clippy::cast_sign_loss)] - #[allow(clippy::cast_precision_loss)] - let physical_width = (width as f32 * self.scale_factor).round() as u32; - #[allow(clippy::cast_possible_truncation)] - #[allow(clippy::cast_sign_loss)] - #[allow(clippy::cast_precision_loss)] - let physical_height = (height as f32 * self.scale_factor).round() as u32; - - let new_physical_size = PhysicalSize::new(physical_width, physical_height); - let new_logical_size = PhysicalSize::new(width, height); + let dimensions = SurfaceDimensions::calculate(width, height, self.scale_factor); + let scaling_mode = self.determine_scaling_mode(); info!( - "Updating window size: buffer {}x{}, physical {}x{}, scale {}, has_viewport: {}", - width, - height, - physical_width, - physical_height, + "Updating window size: logical {}x{}, physical {}x{}, scale {}, buffer_scale {}, mode {:?}", + dimensions.logical_width, + dimensions.logical_height, + dimensions.physical_width, + dimensions.physical_height, self.scale_factor, - self.viewport.is_some() + dimensions.buffer_scale, + scaling_mode ); - if self.fractional_scale.is_some() && self.viewport.is_some() { - self.surface.set_buffer_scale(1); - self.window - .set_size(slint::WindowSize::Logical(slint::LogicalSize::new( - width as f32, - height as f32, - ))); - self.window.set_scale_factor(self.scale_factor); - - if let Some(viewport) = &self.viewport { - viewport.set_destination(width as i32, height as i32); - } - } else if self.fractional_scale.is_some() { - #[allow(clippy::cast_possible_truncation)] - let buffer_scale = self.scale_factor.round() as i32; - self.surface.set_buffer_scale(buffer_scale); - - self.window - .set_size(slint::WindowSize::Logical(slint::LogicalSize::new( - width as f32, - height as f32, - ))); - #[allow(clippy::cast_precision_loss)] - self.window.set_scale_factor(buffer_scale as f32); - } else { - #[allow(clippy::cast_possible_truncation)] - let buffer_scale = self.scale_factor.round() as i32; - self.surface.set_buffer_scale(buffer_scale); - - self.window - .set_size(slint::WindowSize::Physical(new_physical_size)); - self.window.set_scale_factor(self.scale_factor); - } + self.configure_slint_window(&dimensions, &scaling_mode); + self.configure_wayland_surface(&dimensions, &scaling_mode); info!("Window physical size: {:?}", self.window.size()); - self.layer_surface.set_size(width, height); - self.layer_surface.set_exclusive_zone(self.exclusive_zone); - self.surface.commit(); - - self.size = new_physical_size; - self.logical_size = new_logical_size; + self.size = dimensions.physical_size(); + self.logical_size = dimensions.logical_size(); self.window.request_redraw(); } @@ -159,8 +182,8 @@ impl WindowState { } else { let scale_factor = self.scale_factor; LogicalPosition::new( - physical_x as f32 / scale_factor, - physical_y as f32 / scale_factor, + (physical_x / f64::from(scale_factor)) as f32, + (physical_y / f64::from(scale_factor)) as f32, ) }; self.current_pointer_position = logical_position; @@ -202,8 +225,8 @@ impl WindowState { &self.component_instance } + #[allow(clippy::cast_precision_loss)] pub fn update_scale_factor(&mut self, scale_120ths: u32) { - #[allow(clippy::cast_precision_loss)] let new_scale_factor = scale_120ths as f32 / 120.0; info!( "Updating scale factor from {} to {} ({}x)", diff --git a/src/windowing/surface_dimensions.rs b/src/windowing/surface_dimensions.rs new file mode 100644 index 0000000..b4862e8 --- /dev/null +++ b/src/windowing/surface_dimensions.rs @@ -0,0 +1,39 @@ +use slint::PhysicalSize; + +#[derive(Debug, Clone, Copy)] +pub struct SurfaceDimensions { + pub logical_width: u32, + pub logical_height: u32, + pub physical_width: u32, + pub physical_height: u32, + pub buffer_scale: i32, +} + +impl SurfaceDimensions { + #[allow( + clippy::cast_possible_truncation, + clippy::cast_sign_loss, + clippy::cast_precision_loss + )] + pub fn calculate(logical_width: u32, logical_height: u32, scale_factor: f32) -> Self { + let physical_width = (logical_width as f32 * scale_factor).round() as u32; + let physical_height = (logical_height as f32 * scale_factor).round() as u32; + let buffer_scale = scale_factor.round() as i32; + + Self { + logical_width, + logical_height, + physical_width, + physical_height, + buffer_scale, + } + } + + pub const fn logical_size(&self) -> PhysicalSize { + PhysicalSize::new(self.logical_width, self.logical_height) + } + + pub const fn physical_size(&self) -> PhysicalSize { + PhysicalSize::new(self.physical_width, self.physical_height) + } +}