Always set Window.default-font-size

Permit the style metrics to provide a `default-font-size` and bind that
to the `Window` if set. If not provided, then the backend can set a
`default-font-size`. By ensuring that the value is non-zero at run-time,
we can later introduce a rem unit that can act as factor relative to
this non-zero font size.
This commit is contained in:
Simon Hausmann 2022-11-02 15:20:22 +01:00 committed by Simon Hausmann
parent a95504ad4f
commit 39121994ca
12 changed files with 87 additions and 3 deletions

View file

@ -35,6 +35,7 @@ pub struct NativeStyleMetrics {
pub text_cursor_width: Property<LogicalLength>,
pub window_background: Property<Color>,
pub default_text_color: Property<Color>,
pub default_font_size: Property<LogicalLength>,
pub textedit_background: Property<Color>,
pub textedit_text_color: Property<Color>,
pub textedit_background_disabled: Property<Color>,
@ -65,6 +66,7 @@ impl NativeStyleMetrics {
text_cursor_width: Default::default(),
window_background: Default::default(),
default_text_color: Default::default(),
default_font_size: Default::default(),
textedit_background: Default::default(),
textedit_text_color: Default::default(),
textedit_background_disabled: Default::default(),
@ -122,6 +124,10 @@ impl NativeStyleMetrics {
return qApp->palette().color(QPalette::WindowText).rgba();
});
self.default_text_color.set(Color::from_argb_encoded(default_text_color));
let default_font_size = cpp!(unsafe[] -> i32 as "int" {
return QFontInfo(qApp->font()).pixelSize();
});
self.default_font_size.set(LogicalLength::new(default_font_size as f32));
let textedit_text_color = cpp!(unsafe[] -> u32 as "QRgb" {
return qApp->palette().color(QPalette::Text).rgba();
});

View file

@ -22,7 +22,7 @@ use i_slint_core::lengths::{
LogicalLength, LogicalPoint, LogicalRect, LogicalSize, LogicalVector, PhysicalPx, ScaleFactor,
};
use i_slint_core::window::{WindowAdapter, WindowAdapterSealed, WindowInner};
use i_slint_core::{ImageInner, PathData, Property, SharedString};
use i_slint_core::{Coord, ImageInner, PathData, Property, SharedString};
use items::{ImageFit, TextHorizontalAlignment, TextVerticalAlignment};
use std::cell::RefCell;
@ -1612,6 +1612,19 @@ impl WindowAdapterSealed for QtWindow {
self.tree_structure_changed.replace(true);
}
fn register_root_component(&self, window_item: Pin<&i_slint_core::items::WindowItem>) {
let default_font_size_prop =
i_slint_core::items::WindowItem::FIELD_OFFSETS.default_font_size.apply_pin(window_item);
if default_font_size_prop.get().get() <= 0 as Coord {
let default_font_size = cpp!(unsafe[] -> i32 as "int" {
return QFontInfo(qApp->font()).pixelSize();
});
// Ideally this would be a binding that's updated as a FontChange event is received. This is relevant
// for the case of using the Qt backend with a non-native style.
default_font_size_prop.set(LogicalLength::new(default_font_size as f32));
}
}
fn create_popup(&self, geometry: LogicalRect) -> Option<Rc<dyn WindowAdapter>> {
let popup_window = QtWindow::new();

View file

@ -263,6 +263,14 @@ impl<Renderer: WinitCompatibleRenderer + 'static> WindowAdapterSealed for GLWind
}
}
fn register_root_component(&self, window_item: Pin<&i_slint_core::items::WindowItem>) {
let default_font_size_prop =
i_slint_core::items::WindowItem::FIELD_OFFSETS.default_font_size.apply_pin(window_item);
if default_font_size_prop.get().get() <= 0 as Coord {
default_font_size_prop.set(Renderer::default_font_size());
}
}
fn request_window_properties_update(&self) {
self.call_with_event_loop(|self_| {
self_.with_window_handle(&mut |window| {

View file

@ -21,6 +21,7 @@ pub(crate) mod event_loop;
mod renderer {
use std::rc::Weak;
use i_slint_core::lengths::LogicalLength;
use i_slint_core::window::WindowAdapter;
#[cfg(any(feature = "renderer-winit-femtovg", enable_skia_renderer))]
@ -39,6 +40,8 @@ mod renderer {
fn release_canvas(&self, canvas: Self::Canvas);
fn render(&self, canvas: &Self::Canvas, window: &dyn WindowAdapter);
fn default_font_size() -> LogicalLength;
}
pub(crate) trait WinitCompatibleCanvas {

View file

@ -225,6 +225,10 @@ impl super::WinitCompatibleRenderer for FemtoVGRenderer {
canvas.opengl_context.swap_buffers();
canvas.opengl_context.make_not_current();
}
fn default_font_size() -> LogicalLength {
self::fonts::DEFAULT_FONT_SIZE
}
}
impl Renderer for FemtoVGRenderer {

View file

@ -159,6 +159,10 @@ impl super::WinitCompatibleRenderer for SkiaRenderer {
}
});
}
fn default_font_size() -> LogicalLength {
self::textlayout::DEFAULT_FONT_SIZE
}
}
impl i_slint_core::renderer::Renderer for SkiaRenderer {

View file

@ -5,6 +5,7 @@
use super::WinitCompatibleCanvas;
use i_slint_core::graphics::Rgb8Pixel;
use i_slint_core::lengths::LogicalLength;
pub use i_slint_core::software_renderer::SoftwareRenderer;
use i_slint_core::window::WindowAdapter;
use std::cell::RefCell;
@ -99,6 +100,10 @@ impl<const BUFFER_COUNT: usize> super::WinitCompatibleRenderer for SoftwareRende
canvas.opengl_context.swap_buffers();
canvas.opengl_context.make_not_current();
}
fn default_font_size() -> LogicalLength {
i_slint_core::software_renderer::SoftwareRenderer::<BUFFER_COUNT>::default_font_size()
}
}
pub(crate) struct SwCanvas {

View file

@ -157,7 +157,7 @@ WindowItem := _ {
input property <string> title: "Slint Window";
input property <bool> no-frame;
input property <string> default-font-family;
input property <length> default-font-size;
input output property <length> default-font-size; // <=> StyleMetrics.default-font-size set in apply_default_properties_from_style
input property <int> default-font-weight;
input property <image> icon;
}
@ -613,6 +613,7 @@ export global NativeStyleMetrics := {
output property <length> text-cursor-width;
output property <color> window-background;
output property <color> default-text-color;
output property <length> default-font-size;
output property <color> textedit-background;
output property <color> textedit-text-color;
output property <color> textedit-background-disabled;

View file

@ -58,6 +58,25 @@ pub fn apply_default_properties_from_style(
.into(),
to: Type::Brush,
});
if !matches!(
style_metrics
.root_element
.borrow()
.lookup_property("default-font-size")
.property_type,
Type::Invalid,
) {
elem.set_binding_if_not_set("default-font-size".into(), || {
Expression::Cast {
from: Expression::PropertyReference(NamedReference::new(
&style_metrics.root_element,
"default-font-size",
))
.into(),
to: Type::LogicalLength,
}
});
}
}
_ => {}

View file

@ -252,6 +252,11 @@ impl<const MAX_BUFFER_AGE: usize> SoftwareRenderer<MAX_BUFFER_AGE> {
);
}
}
#[doc(hidden)]
pub fn default_font_size() -> LogicalLength {
self::fonts::DEFAULT_FONT_SIZE
}
}
#[doc(hidden)]
@ -1351,6 +1356,13 @@ impl<const MAX_BUFFER_AGE: usize> crate::window::WindowAdapterSealed
fn renderer(&self) -> &dyn Renderer {
&self.renderer
}
fn register_root_component(&self, window_item: Pin<&crate::items::WindowItem>) {
let default_font_size_prop =
crate::items::WindowItem::FIELD_OFFSETS.default_font_size.apply_pin(window_item);
if default_font_size_prop.get().get() <= 0 as Coord {
default_font_size_prop.set(SoftwareRenderer::<MAX_BUFFER_AGE>::default_font_size());
}
}
}
impl<const MAX_BUFFER_AGE: usize> WindowAdapter for MinimalSoftwareWindow<MAX_BUFFER_AGE> {

View file

@ -69,7 +69,7 @@ impl FontMetrics for BitmapGlyphs {
}
}
const DEFAULT_FONT_SIZE: LogicalLength = LogicalLength::new(12 as Coord);
pub(super) const DEFAULT_FONT_SIZE: LogicalLength = LogicalLength::new(12 as Coord);
// A font that is resolved to a specific pixel size.
pub struct PixelFont {

View file

@ -65,6 +65,9 @@ pub trait WindowAdapterSealed {
/// This function is called by the generated code when a component and therefore its tree of items are created.
fn register_component(&self) {}
/// This function is called when the root component is set/changed.
fn register_root_component(&self, _window_item: Pin<&crate::items::WindowItem>) {}
/// This function is called by the generated code when a component and therefore its tree of items are destroyed. The
/// implementation typically uses this to free the underlying graphics resources cached via [`crate::graphics::RenderingCache`].
fn unregister_component<'a>(
@ -271,6 +274,12 @@ impl WindowInner {
self.component.replace(ComponentRc::downgrade(component));
self.window_properties_tracker.set_dirty(); // component changed, layout constraints for sure must be re-calculated
let window_adapter = self.window_adapter();
{
let component = ComponentRc::borrow_pin(&component);
let root_item = component.as_ref().get_item_ref(0);
let window_item = ItemRef::downcast_pin::<crate::items::WindowItem>(root_item).unwrap();
window_adapter.register_root_component(window_item);
}
window_adapter.request_window_properties_update();
window_adapter.request_redraw();
}