use layer_shika_domain::dimensions::{ LogicalSize as DomainLogicalSize, PhysicalSize as DomainPhysicalSize, ScaleFactor as DomainScaleFactor, }; use layer_shika_domain::errors::Result as DomainResult; use layer_shika_domain::surface_dimensions::SurfaceDimensions; use log::info; use slint::PhysicalSize; use std::cell::RefCell; use std::rc::Rc; pub struct DisplayMetrics { surface: SurfaceDimensions, output_size: PhysicalSize, has_fractional_scale: bool, } impl DisplayMetrics { #[must_use] pub fn new(scale_factor: f32, has_fractional_scale: bool) -> Self { let scale = DomainScaleFactor::from_raw(scale_factor); let logical = DomainLogicalSize::from_raw(1.0, 1.0); let surface = SurfaceDimensions::from_logical(logical, scale); Self { surface, output_size: PhysicalSize::new(0, 0), has_fractional_scale, } } #[must_use] pub fn with_output_size(mut self, output_size: PhysicalSize) -> Self { self.output_size = output_size; self.recalculate_surface_size(); self } #[must_use] pub fn scale_factor(&self) -> f32 { self.surface.scale_factor().value() } #[must_use] pub fn scale_factor_typed(&self) -> DomainScaleFactor { self.surface.scale_factor() } #[must_use] pub const fn output_size(&self) -> PhysicalSize { self.output_size } #[must_use] pub fn surface_size(&self) -> PhysicalSize { PhysicalSize::new( self.surface.physical_width(), self.surface.physical_height(), ) } #[must_use] pub const fn surface_dimensions(&self) -> &SurfaceDimensions { &self.surface } #[must_use] pub const fn has_fractional_scale(&self) -> bool { self.has_fractional_scale } pub fn calculate_dimensions( &self, logical_width: u32, logical_height: u32, ) -> DomainResult { SurfaceDimensions::calculate(logical_width, logical_height, self.scale_factor()) } pub fn scale_factor_from_120ths(scale_120ths: u32) -> f32 { DomainScaleFactor::from_120ths(scale_120ths).value() } #[allow(clippy::cast_precision_loss)] pub fn update_scale_factor(&mut self, scale_120ths: u32) -> f32 { let new_scale = DomainScaleFactor::from_120ths(scale_120ths); let new_scale_factor = new_scale.value(); let old_scale_factor = self.scale_factor(); if (old_scale_factor - new_scale_factor).abs() > f32::EPSILON { info!( "DisplayMetrics: Updating scale factor from {} to {} ({}x)", old_scale_factor, new_scale_factor, scale_120ths ); self.surface.update_scale_factor(new_scale); self.recalculate_surface_size(); } new_scale_factor } pub fn update_output_size(&mut self, output_size: PhysicalSize) { if self.output_size != output_size { info!( "DisplayMetrics: Updating output size from {:?} to {:?}", self.output_size, output_size ); self.output_size = output_size; self.recalculate_surface_size(); } } pub fn update_surface_size(&mut self, surface_size: PhysicalSize) { let physical = DomainPhysicalSize::from_raw(surface_size.width, surface_size.height); self.surface = SurfaceDimensions::from_physical(physical, self.surface.scale_factor()); } fn recalculate_surface_size(&mut self) { if self.output_size.width > 0 && self.output_size.height > 0 && self.scale_factor() > 0.0 { let physical = DomainPhysicalSize::from_raw(self.output_size.width, self.output_size.height); self.surface = SurfaceDimensions::from_physical(physical, self.surface.scale_factor()); } } } pub type SharedDisplayMetrics = Rc>;