refactor: extract surface dimensions and scaling mode

This commit is contained in:
drendog 2025-10-25 22:40:33 +02:00
parent f5338750e6
commit 0cc906c546
Signed by: dwenya
GPG key ID: 8DD77074645332D0
3 changed files with 122 additions and 59 deletions

View file

@ -4,6 +4,7 @@ mod globals;
mod macros; mod macros;
mod state; mod state;
mod surface; mod surface;
mod surface_dimensions;
mod system; mod system;
pub use system::WindowingSystem; pub use system::WindowingSystem;

View file

@ -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 wayland_protocols::wp::viewporter::client::wp_viewport::WpViewport;
use crate::rendering::femtovg_window::FemtoVGWindow; use crate::rendering::femtovg_window::FemtoVGWindow;
use crate::errors::{LayerShikaError, Result}; use crate::errors::{LayerShikaError, Result};
use crate::windowing::surface_dimensions::SurfaceDimensions;
pub mod builder; pub mod builder;
pub mod dispatches; pub mod dispatches;
#[derive(Debug)]
enum ScalingMode {
FractionalWithViewport,
FractionalOnly,
Integer,
}
pub struct WindowState { pub struct WindowState {
component_instance: ComponentInstance, component_instance: ComponentInstance,
surface: Rc<WlSurface>, surface: Rc<WlSurface>,
@ -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)] #[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)] #[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) { pub fn update_size(&mut self, width: u32, height: u32) {
if width == 0 || height == 0 { if width == 0 || height == 0 {
info!("Skipping update_size with zero dimension: {width}x{height}"); info!("Skipping update_size with zero dimension: {width}x{height}");
return; return;
} }
#[allow(clippy::cast_possible_truncation)] let dimensions = SurfaceDimensions::calculate(width, height, self.scale_factor);
#[allow(clippy::cast_sign_loss)] let scaling_mode = self.determine_scaling_mode();
#[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);
info!( info!(
"Updating window size: buffer {}x{}, physical {}x{}, scale {}, has_viewport: {}", "Updating window size: logical {}x{}, physical {}x{}, scale {}, buffer_scale {}, mode {:?}",
width, dimensions.logical_width,
height, dimensions.logical_height,
physical_width, dimensions.physical_width,
physical_height, dimensions.physical_height,
self.scale_factor, self.scale_factor,
self.viewport.is_some() dimensions.buffer_scale,
scaling_mode
); );
if self.fractional_scale.is_some() && self.viewport.is_some() { self.configure_slint_window(&dimensions, &scaling_mode);
self.surface.set_buffer_scale(1); self.configure_wayland_surface(&dimensions, &scaling_mode);
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);
}
info!("Window physical size: {:?}", self.window.size()); info!("Window physical size: {:?}", self.window.size());
self.layer_surface.set_size(width, height); self.size = dimensions.physical_size();
self.layer_surface.set_exclusive_zone(self.exclusive_zone); self.logical_size = dimensions.logical_size();
self.surface.commit();
self.size = new_physical_size;
self.logical_size = new_logical_size;
self.window.request_redraw(); self.window.request_redraw();
} }
@ -159,8 +182,8 @@ impl WindowState {
} else { } else {
let scale_factor = self.scale_factor; let scale_factor = self.scale_factor;
LogicalPosition::new( LogicalPosition::new(
physical_x as f32 / scale_factor, (physical_x / f64::from(scale_factor)) as f32,
physical_y as f32 / scale_factor, (physical_y / f64::from(scale_factor)) as f32,
) )
}; };
self.current_pointer_position = logical_position; self.current_pointer_position = logical_position;
@ -202,8 +225,8 @@ impl WindowState {
&self.component_instance &self.component_instance
} }
pub fn update_scale_factor(&mut self, scale_120ths: u32) {
#[allow(clippy::cast_precision_loss)] #[allow(clippy::cast_precision_loss)]
pub fn update_scale_factor(&mut self, scale_120ths: u32) {
let new_scale_factor = scale_120ths as f32 / 120.0; let new_scale_factor = scale_120ths as f32 / 120.0;
info!( info!(
"Updating scale factor from {} to {} ({}x)", "Updating scale factor from {} to {} ({}x)",

View file

@ -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)
}
}