layer-shika/crates/adapters/src/wayland/surfaces/display_metrics.rs

127 lines
3.9 KiB
Rust

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> {
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<RefCell<DisplayMetrics>>;