mirror of
https://codeberg.org/waydeer/layer-shika.git
synced 2025-10-28 23:04:22 +00:00
refactor: better fractional scaling management
This commit is contained in:
parent
238bd150ad
commit
2cd5df6ee1
6 changed files with 281 additions and 35 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
|
@ -4012,9 +4012,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-protocols-wlr"
|
name = "wayland-protocols-wlr"
|
||||||
version = "0.3.3"
|
version = "0.3.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fd993de54a40a40fbe5601d9f1fbcaef0aebcc5fda447d7dc8f6dcbaae4f8953"
|
checksum = "efd94963ed43cf9938a090ca4f7da58eb55325ec8200c3848963e98dc25b78ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.10.0",
|
"bitflags 2.10.0",
|
||||||
"wayland-backend",
|
"wayland-backend",
|
||||||
|
|
|
||||||
|
|
@ -38,4 +38,4 @@ slint-interpreter = { path = "../slint/internal/interpreter", default-features =
|
||||||
smithay-client-toolkit = "0.20.0"
|
smithay-client-toolkit = "0.20.0"
|
||||||
thiserror = "2.0.17"
|
thiserror = "2.0.17"
|
||||||
wayland-client = "0.31.11"
|
wayland-client = "0.31.11"
|
||||||
wayland-protocols = { version = "0.32.6", features = ["client", "staging"] }
|
wayland-protocols = { version = "0.32.9", features = ["client", "staging"] }
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,13 @@ use wayland_client::{
|
||||||
},
|
},
|
||||||
Connection, EventQueue, Proxy, QueueHandle,
|
Connection, EventQueue, Proxy, QueueHandle,
|
||||||
};
|
};
|
||||||
|
use wayland_protocols::wp::fractional_scale::v1::client::{
|
||||||
|
wp_fractional_scale_manager_v1::WpFractionalScaleManagerV1,
|
||||||
|
wp_fractional_scale_v1::WpFractionalScaleV1,
|
||||||
|
};
|
||||||
|
use wayland_protocols::wp::viewporter::client::{
|
||||||
|
wp_viewport::WpViewport, wp_viewporter::WpViewporter,
|
||||||
|
};
|
||||||
|
|
||||||
pub mod builder;
|
pub mod builder;
|
||||||
mod config;
|
mod config;
|
||||||
|
|
@ -44,14 +51,16 @@ impl WindowingSystem {
|
||||||
Rc::new(Connection::connect_to_env().map_err(LayerShikaError::WaylandConnection)?);
|
Rc::new(Connection::connect_to_env().map_err(LayerShikaError::WaylandConnection)?);
|
||||||
let event_queue = connection.new_event_queue();
|
let event_queue = connection.new_event_queue();
|
||||||
|
|
||||||
let (compositor, output, layer_shell, seat) =
|
let (compositor, output, layer_shell, seat, fractional_scale_manager, viewporter) =
|
||||||
Self::initialize_globals(&connection, &event_queue.handle())
|
Self::initialize_globals(&connection, &event_queue.handle())
|
||||||
.map_err(|e| LayerShikaError::GlobalInitialization(e.to_string()))?;
|
.map_err(|e| LayerShikaError::GlobalInitialization(e.to_string()))?;
|
||||||
|
|
||||||
let (surface, layer_surface) = Self::setup_surface(
|
let (surface, layer_surface, fractional_scale, viewport) = Self::setup_surface(
|
||||||
&compositor,
|
&compositor,
|
||||||
&output,
|
&output,
|
||||||
&layer_shell,
|
&layer_shell,
|
||||||
|
fractional_scale_manager.as_ref(),
|
||||||
|
viewporter.as_ref(),
|
||||||
&event_queue.handle(),
|
&event_queue.handle(),
|
||||||
config,
|
config,
|
||||||
);
|
);
|
||||||
|
|
@ -63,7 +72,7 @@ impl WindowingSystem {
|
||||||
LayerShikaError::WindowConfiguration("Component definition is required".to_string())
|
LayerShikaError::WindowConfiguration("Component definition is required".to_string())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let state = WindowStateBuilder::new()
|
let mut builder = WindowStateBuilder::new()
|
||||||
.with_component_definition(component_definition)
|
.with_component_definition(component_definition)
|
||||||
.with_surface(Rc::clone(&surface))
|
.with_surface(Rc::clone(&surface))
|
||||||
.with_layer_surface(Rc::clone(&layer_surface))
|
.with_layer_surface(Rc::clone(&layer_surface))
|
||||||
|
|
@ -71,7 +80,17 @@ impl WindowingSystem {
|
||||||
.with_scale_factor(config.scale_factor)
|
.with_scale_factor(config.scale_factor)
|
||||||
.with_height(config.height)
|
.with_height(config.height)
|
||||||
.with_exclusive_zone(config.exclusive_zone)
|
.with_exclusive_zone(config.exclusive_zone)
|
||||||
.with_window(window)
|
.with_window(window);
|
||||||
|
|
||||||
|
if let Some(fs) = fractional_scale {
|
||||||
|
builder = builder.with_fractional_scale(fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(vp) = viewport {
|
||||||
|
builder = builder.with_viewport(vp);
|
||||||
|
}
|
||||||
|
|
||||||
|
let state = builder
|
||||||
.build()
|
.build()
|
||||||
.map_err(|e| LayerShikaError::WindowConfiguration(e.to_string()))?;
|
.map_err(|e| LayerShikaError::WindowConfiguration(e.to_string()))?;
|
||||||
|
|
||||||
|
|
@ -89,7 +108,17 @@ impl WindowingSystem {
|
||||||
fn initialize_globals(
|
fn initialize_globals(
|
||||||
connection: &Connection,
|
connection: &Connection,
|
||||||
queue_handle: &QueueHandle<WindowState>,
|
queue_handle: &QueueHandle<WindowState>,
|
||||||
) -> Result<(WlCompositor, WlOutput, ZwlrLayerShellV1, WlSeat), LayerShikaError> {
|
) -> Result<
|
||||||
|
(
|
||||||
|
WlCompositor,
|
||||||
|
WlOutput,
|
||||||
|
ZwlrLayerShellV1,
|
||||||
|
WlSeat,
|
||||||
|
Option<WpFractionalScaleManagerV1>,
|
||||||
|
Option<WpViewporter>,
|
||||||
|
),
|
||||||
|
LayerShikaError,
|
||||||
|
> {
|
||||||
let global_list = registry_queue_init::<WindowState>(connection)
|
let global_list = registry_queue_init::<WindowState>(connection)
|
||||||
.map(|(global_list, _)| global_list)
|
.map(|(global_list, _)| global_list)
|
||||||
.map_err(|e| LayerShikaError::GlobalInitialization(e.to_string()))?;
|
.map_err(|e| LayerShikaError::GlobalInitialization(e.to_string()))?;
|
||||||
|
|
@ -97,22 +126,52 @@ impl WindowingSystem {
|
||||||
let (compositor, output, layer_shell, seat) = bind_globals!(
|
let (compositor, output, layer_shell, seat) = bind_globals!(
|
||||||
&global_list,
|
&global_list,
|
||||||
queue_handle,
|
queue_handle,
|
||||||
(WlCompositor, compositor, 1..=1),
|
(WlCompositor, compositor, 3..=6),
|
||||||
(WlOutput, output, 1..=1),
|
(WlOutput, output, 1..=4),
|
||||||
(ZwlrLayerShellV1, layer_shell, 1..=1),
|
(ZwlrLayerShellV1, layer_shell, 1..=5),
|
||||||
(WlSeat, seat, 1..=1)
|
(WlSeat, seat, 1..=9)
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok((compositor, output, layer_shell, seat))
|
let fractional_scale_manager = global_list
|
||||||
|
.bind::<WpFractionalScaleManagerV1, _, _>(queue_handle, 1..=1, ())
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
let viewporter = global_list
|
||||||
|
.bind::<WpViewporter, _, _>(queue_handle, 1..=1, ())
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
if fractional_scale_manager.is_none() {
|
||||||
|
info!("Fractional scale protocol not available, using integer scaling");
|
||||||
|
}
|
||||||
|
|
||||||
|
if viewporter.is_none() {
|
||||||
|
info!("Viewporter protocol not available");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
compositor,
|
||||||
|
output,
|
||||||
|
layer_shell,
|
||||||
|
seat,
|
||||||
|
fractional_scale_manager,
|
||||||
|
viewporter,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_surface(
|
fn setup_surface(
|
||||||
compositor: &WlCompositor,
|
compositor: &WlCompositor,
|
||||||
output: &WlOutput,
|
output: &WlOutput,
|
||||||
layer_shell: &ZwlrLayerShellV1,
|
layer_shell: &ZwlrLayerShellV1,
|
||||||
|
fractional_scale_manager: Option<&WpFractionalScaleManagerV1>,
|
||||||
|
viewporter: Option<&WpViewporter>,
|
||||||
queue_handle: &QueueHandle<WindowState>,
|
queue_handle: &QueueHandle<WindowState>,
|
||||||
config: &WindowConfig,
|
config: &WindowConfig,
|
||||||
) -> (Rc<WlSurface>, Rc<ZwlrLayerSurfaceV1>) {
|
) -> (
|
||||||
|
Rc<WlSurface>,
|
||||||
|
Rc<ZwlrLayerSurfaceV1>,
|
||||||
|
Option<Rc<WpFractionalScaleV1>>,
|
||||||
|
Option<Rc<WpViewport>>,
|
||||||
|
) {
|
||||||
let surface = Rc::new(compositor.create_surface(queue_handle, ()));
|
let surface = Rc::new(compositor.create_surface(queue_handle, ()));
|
||||||
let layer_surface = Rc::new(layer_shell.get_layer_surface(
|
let layer_surface = Rc::new(layer_shell.get_layer_surface(
|
||||||
&surface,
|
&surface,
|
||||||
|
|
@ -123,9 +182,21 @@ impl WindowingSystem {
|
||||||
(),
|
(),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
let fractional_scale = fractional_scale_manager.map(|manager| {
|
||||||
|
info!("Creating fractional scale object for surface");
|
||||||
|
Rc::new(manager.get_fractional_scale(&surface, queue_handle, ()))
|
||||||
|
});
|
||||||
|
|
||||||
|
let viewport = viewporter.map(|vp| {
|
||||||
|
info!("Creating viewport for surface");
|
||||||
|
Rc::new(vp.get_viewport(&surface, queue_handle, ()))
|
||||||
|
});
|
||||||
|
|
||||||
Self::configure_layer_surface(&layer_surface, &surface, config);
|
Self::configure_layer_surface(&layer_surface, &surface, config);
|
||||||
|
|
||||||
(surface, layer_surface)
|
surface.set_buffer_scale(1);
|
||||||
|
|
||||||
|
(surface, layer_surface, fractional_scale, viewport)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configure_layer_surface(
|
fn configure_layer_surface(
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ use slint::PhysicalSize;
|
||||||
use slint_interpreter::ComponentDefinition;
|
use slint_interpreter::ComponentDefinition;
|
||||||
use smithay_client_toolkit::reexports::protocols_wlr::layer_shell::v1::client::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1;
|
use smithay_client_toolkit::reexports::protocols_wlr::layer_shell::v1::client::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1;
|
||||||
use wayland_client::protocol::{wl_pointer::WlPointer, wl_surface::WlSurface};
|
use wayland_client::protocol::{wl_pointer::WlPointer, wl_surface::WlSurface};
|
||||||
|
use wayland_protocols::wp::fractional_scale::v1::client::wp_fractional_scale_v1::WpFractionalScaleV1;
|
||||||
|
use wayland_protocols::wp::viewporter::client::wp_viewport::WpViewport;
|
||||||
use crate::{errors::LayerShikaError, rendering::{femtovg_window::FemtoVGWindow, slint_platform::CustomSlintPlatform}};
|
use crate::{errors::LayerShikaError, rendering::{femtovg_window::FemtoVGWindow, slint_platform::CustomSlintPlatform}};
|
||||||
|
|
||||||
use super::WindowState;
|
use super::WindowState;
|
||||||
|
|
@ -11,6 +13,8 @@ pub struct WindowStateBuilder {
|
||||||
pub component_definition: Option<ComponentDefinition>,
|
pub component_definition: Option<ComponentDefinition>,
|
||||||
pub surface: Option<Rc<WlSurface>>,
|
pub surface: Option<Rc<WlSurface>>,
|
||||||
pub layer_surface: Option<Rc<ZwlrLayerSurfaceV1>>,
|
pub layer_surface: Option<Rc<ZwlrLayerSurfaceV1>>,
|
||||||
|
pub fractional_scale: Option<Rc<WpFractionalScaleV1>>,
|
||||||
|
pub viewport: Option<Rc<WpViewport>>,
|
||||||
pub size: Option<PhysicalSize>,
|
pub size: Option<PhysicalSize>,
|
||||||
pub output_size: Option<PhysicalSize>,
|
pub output_size: Option<PhysicalSize>,
|
||||||
pub pointer: Option<Rc<WlPointer>>,
|
pub pointer: Option<Rc<WlPointer>>,
|
||||||
|
|
@ -86,6 +90,18 @@ impl WindowStateBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_fractional_scale(mut self, fractional_scale: Rc<WpFractionalScaleV1>) -> Self {
|
||||||
|
self.fractional_scale = Some(fractional_scale);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_viewport(mut self, viewport: Rc<WpViewport>) -> Self {
|
||||||
|
self.viewport = Some(viewport);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build(self) -> Result<WindowState, LayerShikaError> {
|
pub fn build(self) -> Result<WindowState, LayerShikaError> {
|
||||||
let platform = CustomSlintPlatform::new(Rc::clone(
|
let platform = CustomSlintPlatform::new(Rc::clone(
|
||||||
self.window
|
self.window
|
||||||
|
|
@ -106,6 +122,8 @@ impl Default for WindowStateBuilder {
|
||||||
component_definition: None,
|
component_definition: None,
|
||||||
surface: None,
|
surface: None,
|
||||||
layer_surface: None,
|
layer_surface: None,
|
||||||
|
fractional_scale: None,
|
||||||
|
viewport: None,
|
||||||
size: None,
|
size: None,
|
||||||
output_size: None,
|
output_size: None,
|
||||||
pointer: None,
|
pointer: None,
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,20 @@ use wayland_client::{
|
||||||
},
|
},
|
||||||
Connection, Dispatch, Proxy, QueueHandle,
|
Connection, Dispatch, Proxy, QueueHandle,
|
||||||
};
|
};
|
||||||
|
use wayland_protocols::wp::fractional_scale::v1::client::{
|
||||||
|
wp_fractional_scale_manager_v1::WpFractionalScaleManagerV1,
|
||||||
|
wp_fractional_scale_v1::{self, WpFractionalScaleV1},
|
||||||
|
};
|
||||||
|
use wayland_protocols::wp::viewporter::client::{
|
||||||
|
wp_viewport::WpViewport, wp_viewporter::WpViewporter,
|
||||||
|
};
|
||||||
|
|
||||||
use super::WindowState;
|
use super::WindowState;
|
||||||
|
|
||||||
impl Dispatch<ZwlrLayerSurfaceV1, ()> for WindowState {
|
impl Dispatch<ZwlrLayerSurfaceV1, ()> for WindowState {
|
||||||
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
|
#[allow(clippy::cast_sign_loss)]
|
||||||
|
#[allow(clippy::cast_precision_loss)]
|
||||||
fn event(
|
fn event(
|
||||||
state: &mut Self,
|
state: &mut Self,
|
||||||
layer_surface: &ZwlrLayerSurfaceV1,
|
layer_surface: &ZwlrLayerSurfaceV1,
|
||||||
|
|
@ -39,14 +49,49 @@ impl Dispatch<ZwlrLayerSurfaceV1, ()> for WindowState {
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
} => {
|
} => {
|
||||||
info!("Layer surface configured with size: {}x{}", width, height);
|
info!(
|
||||||
|
"Layer surface configured with compositor size: {}x{}",
|
||||||
|
width, height
|
||||||
|
);
|
||||||
layer_surface.ack_configure(serial);
|
layer_surface.ack_configure(serial);
|
||||||
if width > 0 && height > 0 {
|
|
||||||
state.update_size(state.output_size().width, state.height());
|
let output_width = state.output_size().width;
|
||||||
|
let scale_factor = state.scale_factor();
|
||||||
|
|
||||||
|
let target_width = if width == 0 || (width == 1 && output_width > 1) {
|
||||||
|
if scale_factor > 1.0 {
|
||||||
|
(output_width as f32 / scale_factor).round() as u32
|
||||||
|
} else {
|
||||||
|
output_width
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let current_size = state.output_size();
|
width
|
||||||
state.update_size(current_size.width, current_size.height);
|
};
|
||||||
}
|
|
||||||
|
let target_height = if height > 0 {
|
||||||
|
height
|
||||||
|
} else {
|
||||||
|
let h = state.height();
|
||||||
|
if scale_factor > 1.0 {
|
||||||
|
(h as f32 / scale_factor).round() as u32
|
||||||
|
} else {
|
||||||
|
h
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let clamped_width = target_width.min(output_width);
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"Using dimensions: {}x{} (clamped from {}x{}, output: {}x{})",
|
||||||
|
clamped_width,
|
||||||
|
target_height,
|
||||||
|
target_width,
|
||||||
|
target_height,
|
||||||
|
output_width,
|
||||||
|
state.output_size().height
|
||||||
|
);
|
||||||
|
|
||||||
|
state.update_size(clamped_width, target_height);
|
||||||
}
|
}
|
||||||
zwlr_layer_surface_v1::Event::Closed => {
|
zwlr_layer_surface_v1::Event::Closed => {
|
||||||
info!("Layer surface closed");
|
info!("Layer surface closed");
|
||||||
|
|
@ -153,10 +198,31 @@ impl Dispatch<WlPointer, ()> for WindowState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Dispatch<WpFractionalScaleV1, ()> for WindowState {
|
||||||
|
fn event(
|
||||||
|
state: &mut Self,
|
||||||
|
_proxy: &WpFractionalScaleV1,
|
||||||
|
event: wp_fractional_scale_v1::Event,
|
||||||
|
_data: &(),
|
||||||
|
_conn: &Connection,
|
||||||
|
_qhandle: &QueueHandle<Self>,
|
||||||
|
) {
|
||||||
|
if let wp_fractional_scale_v1::Event::PreferredScale { scale } = event {
|
||||||
|
#[allow(clippy::cast_precision_loss)]
|
||||||
|
let scale_float = scale as f32 / 120.0;
|
||||||
|
info!("Fractional scale received: {scale_float} ({scale}x)");
|
||||||
|
state.update_scale_factor(scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl_empty_dispatch!(
|
impl_empty_dispatch!(
|
||||||
(WlRegistry, GlobalListContents),
|
(WlRegistry, GlobalListContents),
|
||||||
(WlCompositor, ()),
|
(WlCompositor, ()),
|
||||||
(WlSurface, ()),
|
(WlSurface, ()),
|
||||||
(ZwlrLayerShellV1, ()),
|
(ZwlrLayerShellV1, ()),
|
||||||
(WlSeat, ())
|
(WlSeat, ()),
|
||||||
|
(WpFractionalScaleManagerV1, ()),
|
||||||
|
(WpViewporter, ()),
|
||||||
|
(WpViewport, ())
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ use slint::{LogicalPosition, PhysicalSize, ComponentHandle};
|
||||||
use slint_interpreter::ComponentInstance;
|
use slint_interpreter::ComponentInstance;
|
||||||
use smithay_client_toolkit::reexports::protocols_wlr::layer_shell::v1::client::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1;
|
use smithay_client_toolkit::reexports::protocols_wlr::layer_shell::v1::client::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1;
|
||||||
use wayland_client::protocol::wl_surface::WlSurface;
|
use wayland_client::protocol::wl_surface::WlSurface;
|
||||||
|
use wayland_protocols::wp::fractional_scale::v1::client::wp_fractional_scale_v1::WpFractionalScaleV1;
|
||||||
|
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;
|
use crate::errors::LayerShikaError;
|
||||||
|
|
||||||
|
|
@ -15,7 +17,10 @@ pub struct WindowState {
|
||||||
component_instance: ComponentInstance,
|
component_instance: ComponentInstance,
|
||||||
surface: Rc<WlSurface>,
|
surface: Rc<WlSurface>,
|
||||||
layer_surface: Rc<ZwlrLayerSurfaceV1>,
|
layer_surface: Rc<ZwlrLayerSurfaceV1>,
|
||||||
|
fractional_scale: Option<Rc<WpFractionalScaleV1>>,
|
||||||
|
viewport: Option<Rc<WpViewport>>,
|
||||||
size: PhysicalSize,
|
size: PhysicalSize,
|
||||||
|
logical_size: PhysicalSize,
|
||||||
output_size: PhysicalSize,
|
output_size: PhysicalSize,
|
||||||
window: Rc<FemtoVGWindow>,
|
window: Rc<FemtoVGWindow>,
|
||||||
current_pointer_position: LogicalPosition,
|
current_pointer_position: LogicalPosition,
|
||||||
|
|
@ -39,7 +44,6 @@ impl WindowState {
|
||||||
.show()
|
.show()
|
||||||
.map_err(|e| LayerShikaError::SlintComponentCreation(e.to_string()))?;
|
.map_err(|e| LayerShikaError::SlintComponentCreation(e.to_string()))?;
|
||||||
|
|
||||||
// Request initial redraw to ensure the first frame is rendered
|
|
||||||
window.request_redraw();
|
window.request_redraw();
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|
@ -50,7 +54,10 @@ impl WindowState {
|
||||||
layer_surface: builder
|
layer_surface: builder
|
||||||
.layer_surface
|
.layer_surface
|
||||||
.ok_or_else(|| LayerShikaError::InvalidInput("Layer surface is required".into()))?,
|
.ok_or_else(|| LayerShikaError::InvalidInput("Layer surface is required".into()))?,
|
||||||
|
fractional_scale: builder.fractional_scale,
|
||||||
|
viewport: builder.viewport,
|
||||||
size: builder.size.unwrap_or_default(),
|
size: builder.size.unwrap_or_default(),
|
||||||
|
logical_size: PhysicalSize::default(),
|
||||||
output_size: builder.output_size.unwrap_or_default(),
|
output_size: builder.output_size.unwrap_or_default(),
|
||||||
window,
|
window,
|
||||||
current_pointer_position: LogicalPosition::default(),
|
current_pointer_position: LogicalPosition::default(),
|
||||||
|
|
@ -61,27 +68,92 @@ impl WindowState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_size(&mut self, width: u32, height: u32) {
|
pub fn update_size(&mut self, width: u32, height: u32) {
|
||||||
let new_size = PhysicalSize::new(width, height);
|
if width == 0 || height == 0 {
|
||||||
info!("Updating window size to {}x{}", width, height);
|
info!(
|
||||||
self.window.set_size(slint::WindowSize::Physical(new_size));
|
"Skipping update_size with zero dimension: {}x{}",
|
||||||
self.window.set_scale_factor(self.scale_factor);
|
width, 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);
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"Updating window size: buffer {}x{}, physical {}x{}, scale {}, has_viewport: {}",
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
physical_width,
|
||||||
|
physical_height,
|
||||||
|
self.scale_factor,
|
||||||
|
self.viewport.is_some()
|
||||||
|
);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("Window physical size: {:?}", self.window.size());
|
||||||
|
|
||||||
info!("Updating layer surface size to {}x{}", width, height);
|
|
||||||
self.layer_surface.set_size(width, height);
|
self.layer_surface.set_size(width, height);
|
||||||
self.layer_surface.set_exclusive_zone(self.exclusive_zone);
|
self.layer_surface.set_exclusive_zone(self.exclusive_zone);
|
||||||
|
|
||||||
self.surface.commit();
|
self.surface.commit();
|
||||||
self.size = new_size;
|
|
||||||
|
self.size = new_physical_size;
|
||||||
|
self.logical_size = new_logical_size;
|
||||||
self.window.request_redraw();
|
self.window.request_redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::cast_possible_truncation)]
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
pub fn set_current_pointer_position(&mut self, physical_x: f64, physical_y: f64) {
|
pub fn set_current_pointer_position(&mut self, physical_x: f64, physical_y: f64) {
|
||||||
let scale_factor = self.scale_factor;
|
let logical_position = if self.fractional_scale.is_some() {
|
||||||
let logical_position = LogicalPosition::new(
|
LogicalPosition::new(physical_x as f32, physical_y as f32)
|
||||||
physical_x as f32 / scale_factor,
|
} else {
|
||||||
physical_y as f32 / scale_factor,
|
let scale_factor = self.scale_factor;
|
||||||
);
|
LogicalPosition::new(
|
||||||
|
physical_x as f32 / scale_factor,
|
||||||
|
physical_y as f32 / scale_factor,
|
||||||
|
)
|
||||||
|
};
|
||||||
self.current_pointer_position = logical_position;
|
self.current_pointer_position = logical_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,4 +192,23 @@ impl WindowState {
|
||||||
pub const fn component_instance(&self) -> &ComponentInstance {
|
pub const fn component_instance(&self) -> &ComponentInstance {
|
||||||
&self.component_instance
|
&self.component_instance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)",
|
||||||
|
self.scale_factor, new_scale_factor, scale_120ths
|
||||||
|
);
|
||||||
|
self.scale_factor = new_scale_factor;
|
||||||
|
|
||||||
|
let current_logical_size = self.logical_size;
|
||||||
|
if current_logical_size.width > 0 && current_logical_size.height > 0 {
|
||||||
|
self.update_size(current_logical_size.width, current_logical_size.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn scale_factor(&self) -> f32 {
|
||||||
|
self.scale_factor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue