mirror of
https://codeberg.org/waydeer/layer-shika.git
synced 2026-01-22 07:05:56 +00:00
fix: ceil integer scale for better text rendering on fractional scaling
This commit is contained in:
parent
c430938bf1
commit
3eea09b2f6
4 changed files with 121 additions and 22 deletions
|
|
@ -10,6 +10,46 @@ pub enum RenderState {
|
||||||
Dirty,
|
Dirty,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct FractionalScaleConfig {
|
||||||
|
pub render_scale: f32,
|
||||||
|
pub render_physical_size: PhysicalSize,
|
||||||
|
pub logical_width: f32,
|
||||||
|
pub logical_height: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FractionalScaleConfig {
|
||||||
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
|
#[allow(clippy::cast_sign_loss)]
|
||||||
|
#[must_use]
|
||||||
|
pub fn new(logical_width: f32, logical_height: f32, scale_factor: f32) -> Self {
|
||||||
|
let render_scale = Self::render_scale(scale_factor);
|
||||||
|
Self {
|
||||||
|
render_scale,
|
||||||
|
render_physical_size: PhysicalSize::new(
|
||||||
|
(logical_width * render_scale) as u32,
|
||||||
|
(logical_height * render_scale) as u32,
|
||||||
|
),
|
||||||
|
logical_width,
|
||||||
|
logical_height,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn render_scale(scale_factor: f32) -> f32 {
|
||||||
|
scale_factor.ceil()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn apply_to<W: RenderableWindow + ?Sized>(&self, window: &W) {
|
||||||
|
window.set_scale_factor(self.render_scale);
|
||||||
|
window.set_size_with_exact_logical(
|
||||||
|
self.render_physical_size,
|
||||||
|
self.logical_width,
|
||||||
|
self.logical_height,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait RenderableWindow: WindowAdapter {
|
pub trait RenderableWindow: WindowAdapter {
|
||||||
fn render_frame_if_dirty(&self) -> Result<()>;
|
fn render_frame_if_dirty(&self) -> Result<()>;
|
||||||
fn set_scale_factor(&self, scale_factor: f32);
|
fn set_scale_factor(&self, scale_factor: f32);
|
||||||
|
|
@ -31,4 +71,16 @@ pub trait RenderableWindow: WindowAdapter {
|
||||||
size: size.to_logical(self.scale_factor()),
|
size: size.to_logical(self.scale_factor()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_size_with_exact_logical(
|
||||||
|
&self,
|
||||||
|
physical: slint::PhysicalSize,
|
||||||
|
logical_width: f32,
|
||||||
|
logical_height: f32,
|
||||||
|
) {
|
||||||
|
self.size_cell().set(physical);
|
||||||
|
self.window().dispatch_event(WindowEvent::Resized {
|
||||||
|
size: slint::LogicalSize::new(logical_width, logical_height),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use super::callbacks::{LockCallbackContext, LockCallbackExt, LockPropertyOperationExt};
|
use super::callbacks::{LockCallbackContext, LockCallbackExt, LockPropertyOperationExt};
|
||||||
use crate::errors::Result;
|
use crate::errors::Result;
|
||||||
use crate::rendering::femtovg::main_window::FemtoVGWindow;
|
use crate::rendering::femtovg::main_window::FemtoVGWindow;
|
||||||
use crate::rendering::femtovg::renderable_window::RenderableWindow;
|
use crate::rendering::femtovg::renderable_window::{FractionalScaleConfig, RenderableWindow};
|
||||||
use crate::rendering::slint_integration::platform::CustomSlintPlatform;
|
use crate::rendering::slint_integration::platform::CustomSlintPlatform;
|
||||||
use crate::wayland::session_lock::lock_surface::LockSurface;
|
use crate::wayland::session_lock::lock_surface::LockSurface;
|
||||||
use crate::wayland::surfaces::component_state::ComponentState;
|
use crate::wayland::surfaces::component_state::ComponentState;
|
||||||
|
|
@ -308,7 +308,22 @@ impl ActiveLockSurface {
|
||||||
scale_factor: f32,
|
scale_factor: f32,
|
||||||
) {
|
) {
|
||||||
match mode {
|
match mode {
|
||||||
LockScalingMode::FractionalWithViewport | LockScalingMode::FractionalOnly => {
|
LockScalingMode::FractionalWithViewport => {
|
||||||
|
let config = FractionalScaleConfig::new(
|
||||||
|
dimensions.logical_width() as f32,
|
||||||
|
dimensions.logical_height() as f32,
|
||||||
|
scale_factor,
|
||||||
|
);
|
||||||
|
info!(
|
||||||
|
"Lock FractionalWithViewport: render scale {} (from {}), physical {}x{}",
|
||||||
|
config.render_scale,
|
||||||
|
scale_factor,
|
||||||
|
config.render_physical_size.width,
|
||||||
|
config.render_physical_size.height
|
||||||
|
);
|
||||||
|
config.apply_to(self.window.as_ref());
|
||||||
|
}
|
||||||
|
LockScalingMode::FractionalOnly => {
|
||||||
RenderableWindow::set_scale_factor(self.window.as_ref(), scale_factor);
|
RenderableWindow::set_scale_factor(self.window.as_ref(), scale_factor);
|
||||||
self.window.set_size(WindowSize::Logical(LogicalSize::new(
|
self.window.set_size(WindowSize::Logical(LogicalSize::new(
|
||||||
dimensions.logical_width() as f32,
|
dimensions.logical_width() as f32,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::errors::{LayerShikaError, Result};
|
use crate::errors::{LayerShikaError, Result};
|
||||||
use crate::rendering::egl::context_factory::RenderContextFactory;
|
use crate::rendering::egl::context_factory::RenderContextFactory;
|
||||||
use crate::rendering::femtovg::{popup_window::PopupWindow, renderable_window::RenderableWindow};
|
use crate::rendering::femtovg::popup_window::PopupWindow;
|
||||||
|
use crate::rendering::femtovg::renderable_window::{FractionalScaleConfig, RenderableWindow};
|
||||||
use crate::wayland::surfaces::display_metrics::{DisplayMetrics, SharedDisplayMetrics};
|
use crate::wayland::surfaces::display_metrics::{DisplayMetrics, SharedDisplayMetrics};
|
||||||
use layer_shika_domain::dimensions::LogicalSize as DomainLogicalSize;
|
use layer_shika_domain::dimensions::LogicalSize as DomainLogicalSize;
|
||||||
use layer_shika_domain::surface_dimensions::SurfaceDimensions;
|
use layer_shika_domain::surface_dimensions::SurfaceDimensions;
|
||||||
|
|
@ -9,7 +10,7 @@ use layer_shika_domain::value_objects::popup_behavior::ConstraintAdjustment;
|
||||||
use layer_shika_domain::value_objects::popup_config::PopupConfig;
|
use layer_shika_domain::value_objects::popup_config::PopupConfig;
|
||||||
use layer_shika_domain::value_objects::popup_position::PopupPosition;
|
use layer_shika_domain::value_objects::popup_position::PopupPosition;
|
||||||
use log::info;
|
use log::info;
|
||||||
use slint::{platform::femtovg_renderer::FemtoVGRenderer, PhysicalSize, WindowSize};
|
use slint::{platform::femtovg_renderer::FemtoVGRenderer, PhysicalSize};
|
||||||
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 std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, VecDeque};
|
||||||
|
|
@ -200,8 +201,9 @@ impl PopupManager {
|
||||||
pub fn update_scale_factor(&self, scale_factor: f32) {
|
pub fn update_scale_factor(&self, scale_factor: f32) {
|
||||||
self.scale_factor.set(scale_factor);
|
self.scale_factor.set(scale_factor);
|
||||||
|
|
||||||
|
let render_scale = FractionalScaleConfig::render_scale(scale_factor);
|
||||||
for popup in self.state.borrow().popups.values() {
|
for popup in self.state.borrow().popups.values() {
|
||||||
popup.window.set_scale_factor(scale_factor);
|
popup.window.set_scale_factor(render_scale);
|
||||||
}
|
}
|
||||||
self.mark_all_popups_dirty();
|
self.mark_all_popups_dirty();
|
||||||
}
|
}
|
||||||
|
|
@ -322,11 +324,16 @@ impl PopupManager {
|
||||||
|
|
||||||
let popup_window = PopupWindow::new_with_callback(renderer, on_close);
|
let popup_window = PopupWindow::new_with_callback(renderer, on_close);
|
||||||
popup_window.set_popup_id(popup_id.to_handle());
|
popup_window.set_popup_id(popup_id.to_handle());
|
||||||
popup_window.set_scale_factor(scale_factor);
|
|
||||||
popup_window.set_size(WindowSize::Logical(slint::LogicalSize::new(
|
let config = FractionalScaleConfig::new(params.width, params.height, scale_factor);
|
||||||
params.width,
|
info!(
|
||||||
params.height,
|
"Popup using render scale {} (from {}), render_physical {}x{}",
|
||||||
)));
|
config.render_scale,
|
||||||
|
scale_factor,
|
||||||
|
config.render_physical_size.width,
|
||||||
|
config.render_physical_size.height
|
||||||
|
);
|
||||||
|
config.apply_to(popup_window.as_ref());
|
||||||
|
|
||||||
let mut state = self.state.borrow_mut();
|
let mut state = self.state.borrow_mut();
|
||||||
state.popups.insert(
|
state.popups.insert(
|
||||||
|
|
@ -489,7 +496,6 @@ impl PopupManager {
|
||||||
ActiveWindow::None
|
ActiveWindow::None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::cast_precision_loss)]
|
|
||||||
pub fn update_scale_for_fractional_scale_object(
|
pub fn update_scale_for_fractional_scale_object(
|
||||||
&self,
|
&self,
|
||||||
fractional_scale_proxy: &WpFractionalScaleV1,
|
fractional_scale_proxy: &WpFractionalScaleV1,
|
||||||
|
|
@ -500,8 +506,12 @@ impl PopupManager {
|
||||||
if let Some(popup_key) = self.find_popup_key_by_fractional_scale_id(&fractional_scale_id) {
|
if let Some(popup_key) = self.find_popup_key_by_fractional_scale_id(&fractional_scale_id) {
|
||||||
if let Some(popup_surface) = self.get_popup_window(popup_key) {
|
if let Some(popup_surface) = self.get_popup_window(popup_key) {
|
||||||
let new_scale_factor = DisplayMetrics::scale_factor_from_120ths(scale_120ths);
|
let new_scale_factor = DisplayMetrics::scale_factor_from_120ths(scale_120ths);
|
||||||
info!("Updating popup scale factor to {new_scale_factor} ({scale_120ths}x)");
|
let render_scale = FractionalScaleConfig::render_scale(new_scale_factor);
|
||||||
popup_surface.set_scale_factor(new_scale_factor);
|
info!(
|
||||||
|
"Updating popup scale factor to {} (render scale {}, from {}x)",
|
||||||
|
new_scale_factor, render_scale, scale_120ths
|
||||||
|
);
|
||||||
|
popup_surface.set_scale_factor(render_scale);
|
||||||
popup_surface.request_redraw();
|
popup_surface.request_redraw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::errors::Result;
|
use crate::errors::Result;
|
||||||
use crate::rendering::femtovg::renderable_window::RenderableWindow;
|
use crate::rendering::femtovg::renderable_window::{FractionalScaleConfig, RenderableWindow};
|
||||||
use crate::wayland::managed_proxies::{
|
use crate::wayland::managed_proxies::{
|
||||||
ManagedWlSurface, ManagedZwlrLayerSurfaceV1, ManagedWpFractionalScaleV1, ManagedWpViewport,
|
ManagedWlSurface, ManagedZwlrLayerSurfaceV1, ManagedWpFractionalScaleV1, ManagedWpViewport,
|
||||||
};
|
};
|
||||||
|
|
@ -92,12 +92,19 @@ impl<W: RenderableWindow> SurfaceRenderer<W> {
|
||||||
) {
|
) {
|
||||||
match mode {
|
match mode {
|
||||||
ScalingMode::FractionalWithViewport => {
|
ScalingMode::FractionalWithViewport => {
|
||||||
self.window.set_scale_factor(scale_factor);
|
let config = FractionalScaleConfig::new(
|
||||||
self.window
|
dimensions.logical_width() as f32,
|
||||||
.set_size(slint::WindowSize::Logical(slint::LogicalSize::new(
|
dimensions.logical_height() as f32,
|
||||||
dimensions.logical_width() as f32,
|
scale_factor,
|
||||||
dimensions.logical_height() as f32,
|
);
|
||||||
)));
|
info!(
|
||||||
|
"FractionalWithViewport: render scale {} (from {}), physical {}x{}",
|
||||||
|
config.render_scale,
|
||||||
|
scale_factor,
|
||||||
|
config.render_physical_size.width,
|
||||||
|
config.render_physical_size.height
|
||||||
|
);
|
||||||
|
config.apply_to(self.window.as_ref());
|
||||||
}
|
}
|
||||||
ScalingMode::FractionalOnly => {
|
ScalingMode::FractionalOnly => {
|
||||||
self.window
|
self.window
|
||||||
|
|
@ -154,15 +161,30 @@ impl<W: RenderableWindow> SurfaceRenderer<W> {
|
||||||
self.apply_surface_dimensions(dimensions, scale_factor);
|
self.apply_surface_dimensions(dimensions, scale_factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::cast_precision_loss)]
|
||||||
pub fn apply_surface_dimensions(&mut self, dimensions: SurfaceDimensions, scale_factor: f32) {
|
pub fn apply_surface_dimensions(&mut self, dimensions: SurfaceDimensions, scale_factor: f32) {
|
||||||
let scaling_mode = self.determine_scaling_mode();
|
let scaling_mode = self.determine_scaling_mode();
|
||||||
|
|
||||||
|
let render_physical_size = match scaling_mode {
|
||||||
|
ScalingMode::FractionalWithViewport => {
|
||||||
|
FractionalScaleConfig::new(
|
||||||
|
dimensions.logical_width() as f32,
|
||||||
|
dimensions.logical_height() as f32,
|
||||||
|
scale_factor,
|
||||||
|
)
|
||||||
|
.render_physical_size
|
||||||
|
}
|
||||||
|
_ => dimensions.to_slint_physical_size(),
|
||||||
|
};
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
"Updating window size: logical {}x{}, physical {}x{}, scale {}, buffer_scale {}, mode {:?}",
|
"Updating window size: logical {}x{}, physical {}x{}, render_physical {}x{}, scale {}, buffer_scale {}, mode {:?}",
|
||||||
dimensions.logical_width(),
|
dimensions.logical_width(),
|
||||||
dimensions.logical_height(),
|
dimensions.logical_height(),
|
||||||
dimensions.physical_width(),
|
dimensions.physical_width(),
|
||||||
dimensions.physical_height(),
|
dimensions.physical_height(),
|
||||||
|
render_physical_size.width,
|
||||||
|
render_physical_size.height,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
dimensions.buffer_scale(),
|
dimensions.buffer_scale(),
|
||||||
scaling_mode
|
scaling_mode
|
||||||
|
|
@ -173,7 +195,7 @@ impl<W: RenderableWindow> SurfaceRenderer<W> {
|
||||||
|
|
||||||
info!("Window physical size: {:?}", self.window.size());
|
info!("Window physical size: {:?}", self.window.size());
|
||||||
|
|
||||||
self.size = dimensions.to_slint_physical_size();
|
self.size = render_physical_size;
|
||||||
self.logical_size = dimensions.to_slint_logical_size();
|
self.logical_size = dimensions.to_slint_logical_size();
|
||||||
RenderableWindow::request_redraw(self.window.as_ref());
|
RenderableWindow::request_redraw(self.window.as_ref());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue