Support default-font-* properties in Live-Preview

... by changing the resolution for the `WindowItem` to traverse the
item tree from the current item, instead of going to the window.

This doesn't quite fix #4298 because `rem` resolution is still missing.
That requires the built-in default font size function to be fixed as
well, which is non-trivial.

cc #4298
This commit is contained in:
Simon Hausmann 2024-12-03 14:37:55 +01:00 committed by Simon Hausmann
parent 7c02bbd833
commit eb825f2e95
32 changed files with 189 additions and 86 deletions

View file

@ -170,6 +170,16 @@ inline float layout_cache_access(const SharedVector<float> &cache, int offset, i
size_t idx = size_t(cache[offset]) + repeater_index * 2; size_t idx = size_t(cache[offset]) + repeater_index * 2;
return idx < cache.size() ? cache[idx] : 0; return idx < cache.size() ? cache[idx] : 0;
} }
template<typename VT, typename ItemType>
inline cbindgen_private::LayoutInfo
item_layout_info(VT *itemvtable, ItemType *item_ptr, cbindgen_private::Orientation orientation,
WindowAdapterRc *window_adapter, const ItemTreeRc &component_rc,
uint32_t item_index)
{
cbindgen_private::ItemRc item_rc { component_rc, item_index };
return itemvtable->layout_info({ itemvtable, item_ptr }, orientation, window_adapter, &item_rc);
}
} // namespace private_api } // namespace private_api
namespace private_api { namespace private_api {

View file

@ -448,7 +448,7 @@ extern "system" fn Java_SlintAndroidJavaHelper_moveCursorHandle(
let adaptor = adaptor.clone() as Rc<dyn WindowAdapter>; let adaptor = adaptor.clone() as Rc<dyn WindowAdapter>;
let size = text_input let size = text_input
.as_pin_ref() .as_pin_ref()
.font_request(&adaptor) .font_request(&focus_item)
.pixel_size .pixel_size
.unwrap_or_default() .unwrap_or_default()
.get(); .get();
@ -457,7 +457,11 @@ extern "system" fn Java_SlintAndroidJavaHelper_moveCursorHandle(
pos_x as f32 / scale_factor, pos_x as f32 / scale_factor,
pos_y as f32 / scale_factor - size / 2., pos_y as f32 / scale_factor - size / 2.,
) - focus_item.map_to_window(focus_item.geometry().origin).to_vector(); ) - focus_item.map_to_window(focus_item.geometry().origin).to_vector();
let text_pos = text_input.as_pin_ref().byte_offset_for_position(pos, &adaptor); let text_pos = text_input.as_pin_ref().byte_offset_for_position(
pos,
&adaptor,
&focus_item,
);
let cur_pos = if id == 0 { let cur_pos = if id == 0 {
text_input.anchor_position_byte_offset.set(text_pos as i32); text_input.anchor_position_byte_offset.set(text_pos as i32);

View file

@ -202,6 +202,7 @@ impl Item for NativeButton {
self: Pin<&Self>, self: Pin<&Self>,
orientation: Orientation, orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
let standard_button_kind = self.actual_standard_button_kind(); let standard_button_kind = self.actual_standard_button_kind();
let mut text: qttypes::QString = self.actual_text(standard_button_kind); let mut text: qttypes::QString = self.actual_text(standard_button_kind);

View file

@ -35,6 +35,7 @@ impl Item for NativeCheckBox {
self: Pin<&Self>, self: Pin<&Self>,
orientation: Orientation, orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
let text: qttypes::QString = self.text().as_str().into(); let text: qttypes::QString = self.text().as_str().into();
let widget: NonNull<()> = SlintTypeErasedWidgetPtr::qwidget_ptr(&self.widget_ptr); let widget: NonNull<()> = SlintTypeErasedWidgetPtr::qwidget_ptr(&self.widget_ptr);

View file

@ -32,6 +32,7 @@ impl Item for NativeComboBox {
self: Pin<&Self>, self: Pin<&Self>,
orientation: Orientation, orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
let widget: NonNull<()> = SlintTypeErasedWidgetPtr::qwidget_ptr(&self.widget_ptr); let widget: NonNull<()> = SlintTypeErasedWidgetPtr::qwidget_ptr(&self.widget_ptr);
let size = cpp!(unsafe [widget as "QWidget*"] -> qttypes::QSize as "QSize" { let size = cpp!(unsafe [widget as "QWidget*"] -> qttypes::QSize as "QSize" {
@ -185,6 +186,7 @@ impl Item for NativeComboBoxPopup {
self: Pin<&Self>, self: Pin<&Self>,
_orientation: Orientation, _orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
Default::default() Default::default()
} }

View file

@ -146,6 +146,7 @@ impl Item for NativeGroupBox {
self: Pin<&Self>, self: Pin<&Self>,
orientation: Orientation, orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
let text: qttypes::QString = self.title().as_str().into(); let text: qttypes::QString = self.title().as_str().into();

View file

@ -76,6 +76,7 @@ impl Item for NativeLineEdit {
self: Pin<&Self>, self: Pin<&Self>,
orientation: Orientation, orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
let min = match orientation { let min = match orientation {
Orientation::Horizontal => self.native_padding_left() + self.native_padding_right(), Orientation::Horizontal => self.native_padding_left() + self.native_padding_right(),

View file

@ -37,6 +37,7 @@ impl Item for NativeStandardListViewItem {
self: Pin<&Self>, self: Pin<&Self>,
orientation: Orientation, orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
let index: i32 = self.index(); let index: i32 = self.index();
let item = self.item(); let item = self.item();

View file

@ -30,6 +30,7 @@ impl Item for NativeProgressIndicator {
self: Pin<&Self>, self: Pin<&Self>,
orientation: Orientation, orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
let indeterminate = self.indeterminate(); let indeterminate = self.indeterminate();
let progress = let progress =

View file

@ -93,6 +93,7 @@ impl Item for NativeScrollView {
self: Pin<&Self>, self: Pin<&Self>,
orientation: Orientation, orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
let min = match orientation { let min = match orientation {
Orientation::Horizontal => self.native_padding_left() + self.native_padding_right(), Orientation::Horizontal => self.native_padding_left() + self.native_padding_right(),

View file

@ -78,6 +78,7 @@ impl Item for NativeSlider {
self: Pin<&Self>, self: Pin<&Self>,
orientation: Orientation, orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
let enabled = self.enabled(); let enabled = self.enabled();
// Slint slider supports floating point ranges, while Qt uses integer. To support (0..1) ranges // Slint slider supports floating point ranges, while Qt uses integer. To support (0..1) ranges

View file

@ -73,6 +73,7 @@ impl Item for NativeSpinBox {
self: Pin<&Self>, self: Pin<&Self>,
orientation: Orientation, orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
//let value: i32 = self.value(); //let value: i32 = self.value();
let data = self.data(); let data = self.data();

View file

@ -29,6 +29,7 @@ impl Item for NativeTableHeaderSection {
self: Pin<&Self>, self: Pin<&Self>,
orientation: Orientation, orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
let index: i32 = self.index(); let index: i32 = self.index();
let item = self.item(); let item = self.item();

View file

@ -178,6 +178,7 @@ impl Item for NativeTabWidget {
self: Pin<&Self>, self: Pin<&Self>,
orientation: Orientation, orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
let (content_size, tabbar_size) = match orientation { let (content_size, tabbar_size) = match orientation {
Orientation::Horizontal => ( Orientation::Horizontal => (
@ -368,6 +369,7 @@ impl Item for NativeTab {
self: Pin<&Self>, self: Pin<&Self>,
orientation: Orientation, orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
let text: qttypes::QString = self.title().as_str().into(); let text: qttypes::QString = self.title().as_str().into();
let icon: qttypes::QPixmap = let icon: qttypes::QPixmap =

View file

@ -695,14 +695,14 @@ impl ItemRenderer for QtItemRenderer<'_> {
fn draw_text( fn draw_text(
&mut self, &mut self,
text: Pin<&dyn RenderText>, text: Pin<&dyn RenderText>,
_: &ItemRc, self_rc: &ItemRc,
size: LogicalSize, size: LogicalSize,
_: &CachedRenderingData, _: &CachedRenderingData,
) { ) {
let rect: qttypes::QRectF = check_geometry!(size); let rect: qttypes::QRectF = check_geometry!(size);
let fill_brush: qttypes::QBrush = into_qbrush(text.color(), rect.width, rect.height); let fill_brush: qttypes::QBrush = into_qbrush(text.color(), rect.width, rect.height);
let mut string: qttypes::QString = text.text().as_str().into(); let mut string: qttypes::QString = text.text().as_str().into();
let font: QFont = get_font(text.font_request(WindowInner::from_pub(self.window))); let font: QFont = get_font(text.font_request(self_rc));
let (horizontal_alignment, vertical_alignment) = text.alignment(); let (horizontal_alignment, vertical_alignment) = text.alignment();
let alignment = match horizontal_alignment { let alignment = match horizontal_alignment {
TextHorizontalAlignment::Left => key_generated::Qt_AlignmentFlag_AlignLeft, TextHorizontalAlignment::Left => key_generated::Qt_AlignmentFlag_AlignLeft,
@ -872,14 +872,13 @@ impl ItemRenderer for QtItemRenderer<'_> {
fn draw_text_input( fn draw_text_input(
&mut self, &mut self,
text_input: Pin<&items::TextInput>, text_input: Pin<&items::TextInput>,
_: &ItemRc, self_rc: &ItemRc,
size: LogicalSize, size: LogicalSize,
) { ) {
let rect: qttypes::QRectF = check_geometry!(size); let rect: qttypes::QRectF = check_geometry!(size);
let fill_brush: qttypes::QBrush = into_qbrush(text_input.color(), rect.width, rect.height); let fill_brush: qttypes::QBrush = into_qbrush(text_input.color(), rect.width, rect.height);
let font: QFont = let font: QFont = get_font(text_input.font_request(self_rc));
get_font(text_input.font_request(&WindowInner::from_pub(self.window).window_adapter()));
let flags = match text_input.horizontal_alignment() { let flags = match text_input.horizontal_alignment() {
TextHorizontalAlignment::Left => key_generated::Qt_AlignmentFlag_AlignLeft, TextHorizontalAlignment::Left => key_generated::Qt_AlignmentFlag_AlignLeft,
TextHorizontalAlignment::Center => key_generated::Qt_AlignmentFlag_AlignHCenter, TextHorizontalAlignment::Center => key_generated::Qt_AlignmentFlag_AlignHCenter,

View file

@ -3916,13 +3916,15 @@ fn compile_builtin_function_call(
BuiltinFunction::ImplicitLayoutInfo(orient) => { BuiltinFunction::ImplicitLayoutInfo(orient) => {
if let [llr::Expression::PropertyReference(pr)] = arguments { if let [llr::Expression::PropertyReference(pr)] = arguments {
let native = native_prop_info(pr, ctx).0; let native = native_prop_info(pr, ctx).0;
let item_rc = access_item_rc(pr, ctx);
format!( format!(
"{vt}->layout_info({{{vt}, const_cast<slint::cbindgen_private::{ty}*>(&{i})}}, {o}, &{window})", "slint::private_api::item_layout_info({vt}, const_cast<slint::cbindgen_private::{ty}*>(&{i}), {o}, &{window}, {item_rc})",
vt = native.cpp_vtable_getter, vt = native.cpp_vtable_getter,
ty = native.class_name, ty = native.class_name,
o = to_cpp_orientation(orient), o = to_cpp_orientation(orient),
i = access_member(pr, ctx), i = access_member(pr, ctx),
window = access_window_field(ctx) window = access_window_field(ctx),
item_rc = item_rc
) )
} else { } else {
panic!("internal error: invalid args to ImplicitLayoutInfo {arguments:?}") panic!("internal error: invalid args to ImplicitLayoutInfo {arguments:?}")

View file

@ -2909,10 +2909,11 @@ fn compile_builtin_function_call(
BuiltinFunction::ItemFontMetrics => { BuiltinFunction::ItemFontMetrics => {
if let [Expression::PropertyReference(pr)] = arguments { if let [Expression::PropertyReference(pr)] = arguments {
let item = access_member(pr, ctx); let item = access_member(pr, ctx);
let item_rc = access_item_rc(pr, ctx);
let window_adapter_tokens = access_window_adapter_field(ctx); let window_adapter_tokens = access_window_adapter_field(ctx);
item.then(|item| { item.then(|item| {
quote!( quote!(
#item.font_metrics(#window_adapter_tokens) #item.font_metrics(#window_adapter_tokens, #item_rc)
) )
}) })
} else { } else {
@ -2924,8 +2925,9 @@ fn compile_builtin_function_call(
let item = access_member(pr, ctx); let item = access_member(pr, ctx);
let window_adapter_tokens = access_window_adapter_field(ctx); let window_adapter_tokens = access_window_adapter_field(ctx);
item.then(|item| { item.then(|item| {
let item_rc = access_item_rc(pr, ctx);
quote!( quote!(
sp::Item::layout_info(#item, #orient, #window_adapter_tokens) sp::Item::layout_info(#item, #orient, #window_adapter_tokens, &#item_rc)
) )
}) })
} else { } else {

View file

@ -315,7 +315,7 @@ pub trait RenderImage {
pub trait RenderText { pub trait RenderText {
fn target_size(self: Pin<&Self>) -> LogicalSize; fn target_size(self: Pin<&Self>) -> LogicalSize;
fn text(self: Pin<&Self>) -> SharedString; fn text(self: Pin<&Self>) -> SharedString;
fn font_request(self: Pin<&Self>, window: &WindowInner) -> FontRequest; fn font_request(self: Pin<&Self>, self_rc: &ItemRc) -> FontRequest;
fn color(self: Pin<&Self>) -> Brush; fn color(self: Pin<&Self>) -> Brush;
fn alignment(self: Pin<&Self>) -> (TextHorizontalAlignment, TextVerticalAlignment); fn alignment(self: Pin<&Self>) -> (TextHorizontalAlignment, TextVerticalAlignment);
fn wrap(self: Pin<&Self>) -> TextWrap; fn wrap(self: Pin<&Self>) -> TextWrap;
@ -325,12 +325,13 @@ pub trait RenderText {
fn text_bounding_rect( fn text_bounding_rect(
self: Pin<&Self>, self: Pin<&Self>,
self_rc: &ItemRc,
window_adapter: &Rc<dyn WindowAdapter>, window_adapter: &Rc<dyn WindowAdapter>,
mut geometry: euclid::Rect<f32, crate::lengths::LogicalPx>, mut geometry: euclid::Rect<f32, crate::lengths::LogicalPx>,
) -> euclid::Rect<f32, crate::lengths::LogicalPx> { ) -> euclid::Rect<f32, crate::lengths::LogicalPx> {
let window_inner = WindowInner::from_pub(window_adapter.window()); let window_inner = WindowInner::from_pub(window_adapter.window());
let text_string = self.text(); let text_string = self.text();
let font_request = self.font_request(window_inner); let font_request = self.font_request(self_rc);
let scale_factor = crate::lengths::ScaleFactor::new(window_inner.scale_factor()); let scale_factor = crate::lengths::ScaleFactor::new(window_inner.scale_factor());
let max_width = geometry.size.width_length(); let max_width = geometry.size.width_length();
geometry.size = geometry.size.max( geometry.size = geometry.size.max(

View file

@ -745,6 +745,14 @@ impl ItemRc {
result result
} }
pub fn window_item(&self) -> Option<VRcMapped<ItemTreeVTable, crate::items::WindowItem>> {
let root_item_in_local_item_tree = ItemRc::new(self.item_tree.clone(), 0);
root_item_in_local_item_tree.downcast::<crate::items::WindowItem>().or_else(|| {
root_item_in_local_item_tree.parent_item().and_then(|parent| parent.window_item())
})
}
/// Visit the children of this element and call the visitor to each of them, until the visitor returns [`ControlFlow::Break`]. /// Visit the children of this element and call the visitor to each of them, until the visitor returns [`ControlFlow::Break`].
/// When the visitor breaks, the function returns the value. If it doesn't break, the function returns None. /// When the visitor breaks, the function returns the value. If it doesn't break, the function returns None.
fn visit_descendants_impl<R>( fn visit_descendants_impl<R>(

View file

@ -26,7 +26,7 @@ use crate::input::{
KeyEventType, MouseEvent, KeyEventType, MouseEvent,
}; };
use crate::item_rendering::{CachedRenderingData, RenderBorderRectangle, RenderRectangle}; use crate::item_rendering::{CachedRenderingData, RenderBorderRectangle, RenderRectangle};
pub use crate::item_tree::ItemRc; pub use crate::item_tree::{ItemRc, ItemTreeVTable};
use crate::layout::LayoutInfo; use crate::layout::LayoutInfo;
use crate::lengths::{ use crate::lengths::{
LogicalBorderRadius, LogicalLength, LogicalRect, LogicalSize, LogicalVector, PointLengths, LogicalBorderRadius, LogicalLength, LogicalRect, LogicalSize, LogicalVector, PointLengths,
@ -130,6 +130,7 @@ pub struct ItemVTable {
core::pin::Pin<VRef<ItemVTable>>, core::pin::Pin<VRef<ItemVTable>>,
orientation: Orientation, orientation: Orientation,
window_adapter: &WindowAdapterRc, window_adapter: &WindowAdapterRc,
self_rc: &ItemRc,
) -> LayoutInfo, ) -> LayoutInfo,
/// Event handler for mouse and touch event. This function is called before being called on children. /// Event handler for mouse and touch event. This function is called before being called on children.
@ -201,6 +202,7 @@ impl Item for Empty {
self: Pin<&Self>, self: Pin<&Self>,
_orientation: Orientation, _orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() } LayoutInfo { stretch: 1., ..LayoutInfo::default() }
} }
@ -292,6 +294,7 @@ impl Item for Rectangle {
self: Pin<&Self>, self: Pin<&Self>,
_orientation: Orientation, _orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() } LayoutInfo { stretch: 1., ..LayoutInfo::default() }
} }
@ -392,6 +395,7 @@ impl Item for BasicBorderRectangle {
self: Pin<&Self>, self: Pin<&Self>,
_orientation: Orientation, _orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() } LayoutInfo { stretch: 1., ..LayoutInfo::default() }
} }
@ -505,6 +509,7 @@ impl Item for BorderRectangle {
self: Pin<&Self>, self: Pin<&Self>,
_orientation: Orientation, _orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() } LayoutInfo { stretch: 1., ..LayoutInfo::default() }
} }
@ -633,6 +638,7 @@ impl Item for Clip {
self: Pin<&Self>, self: Pin<&Self>,
_orientation: Orientation, _orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() } LayoutInfo { stretch: 1., ..LayoutInfo::default() }
} }
@ -744,6 +750,7 @@ impl Item for Opacity {
self: Pin<&Self>, self: Pin<&Self>,
_orientation: Orientation, _orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() } LayoutInfo { stretch: 1., ..LayoutInfo::default() }
} }
@ -861,6 +868,7 @@ impl Item for Layer {
self: Pin<&Self>, self: Pin<&Self>,
_orientation: Orientation, _orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() } LayoutInfo { stretch: 1., ..LayoutInfo::default() }
} }
@ -953,6 +961,7 @@ impl Item for Rotate {
self: Pin<&Self>, self: Pin<&Self>,
_orientation: Orientation, _orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() } LayoutInfo { stretch: 1., ..LayoutInfo::default() }
} }
@ -1097,6 +1106,7 @@ impl Item for WindowItem {
self: Pin<&Self>, self: Pin<&Self>,
_orientation: Orientation, _orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
LayoutInfo::default() LayoutInfo::default()
} }
@ -1227,6 +1237,7 @@ impl Item for ContextMenu {
self: Pin<&Self>, self: Pin<&Self>,
_orientation: Orientation, _orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
LayoutInfo::default() LayoutInfo::default()
} }
@ -1404,6 +1415,7 @@ impl Item for BoxShadow {
self: Pin<&Self>, self: Pin<&Self>,
_orientation: Orientation, _orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() } LayoutInfo { stretch: 1., ..LayoutInfo::default() }
} }

View file

@ -167,6 +167,7 @@ impl Item for ComponentContainer {
self: Pin<&Self>, self: Pin<&Self>,
orientation: Orientation, orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
self.ensure_updated(); self.ensure_updated();
if let Some(rc) = self.item_tree.borrow().clone() { if let Some(rc) = self.item_tree.borrow().clone() {

View file

@ -65,6 +65,7 @@ impl Item for Flickable {
self: Pin<&Self>, self: Pin<&Self>,
_orientation: Orientation, _orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() } LayoutInfo { stretch: 1., ..LayoutInfo::default() }
} }

View file

@ -49,6 +49,7 @@ impl Item for ImageItem {
self: Pin<&Self>, self: Pin<&Self>,
orientation: Orientation, orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
let natural_size = self.source().size(); let natural_size = self.source().size();
LayoutInfo { LayoutInfo {
@ -195,6 +196,7 @@ impl Item for ClippedImage {
self: Pin<&Self>, self: Pin<&Self>,
orientation: Orientation, orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
LayoutInfo { LayoutInfo {
preferred: match orientation { preferred: match orientation {

View file

@ -60,6 +60,7 @@ impl Item for TouchArea {
self: Pin<&Self>, self: Pin<&Self>,
_orientation: Orientation, _orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() } LayoutInfo { stretch: 1., ..LayoutInfo::default() }
} }
@ -272,6 +273,7 @@ impl Item for FocusScope {
self: Pin<&Self>, self: Pin<&Self>,
_orientation: Orientation, _orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() } LayoutInfo { stretch: 1., ..LayoutInfo::default() }
} }
@ -408,6 +410,7 @@ impl Item for SwipeGestureHandler {
self: Pin<&Self>, self: Pin<&Self>,
_orientation: Orientation, _orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() } LayoutInfo { stretch: 1., ..LayoutInfo::default() }
} }

View file

@ -58,6 +58,7 @@ impl Item for Path {
self: Pin<&Self>, self: Pin<&Self>,
_orientation: Orientation, _orientation: Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() } LayoutInfo { stretch: 1., ..LayoutInfo::default() }
} }

View file

@ -70,9 +70,11 @@ impl Item for ComplexText {
self: Pin<&Self>, self: Pin<&Self>,
orientation: Orientation, orientation: Orientation,
window_adapter: &Rc<dyn WindowAdapter>, window_adapter: &Rc<dyn WindowAdapter>,
self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
text_layout_info( text_layout_info(
self, self,
&self_rc,
window_adapter, window_adapter,
orientation, orientation,
Self::FIELD_OFFSETS.width.apply_pin(self), Self::FIELD_OFFSETS.width.apply_pin(self),
@ -128,10 +130,10 @@ impl Item for ComplexText {
fn bounding_rect( fn bounding_rect(
self: core::pin::Pin<&Self>, self: core::pin::Pin<&Self>,
window_adapter: &Rc<dyn WindowAdapter>, window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc, self_rc: &ItemRc,
geometry: LogicalRect, geometry: LogicalRect,
) -> LogicalRect { ) -> LogicalRect {
self.text_bounding_rect(window_adapter, geometry.cast()).cast() self.text_bounding_rect(self_rc, window_adapter, geometry.cast()).cast()
} }
fn clips_children(self: core::pin::Pin<&Self>) -> bool { fn clips_children(self: core::pin::Pin<&Self>) -> bool {
@ -155,8 +157,8 @@ impl RenderText for ComplexText {
self.text() self.text()
} }
fn font_request(self: Pin<&Self>, window: &WindowInner) -> FontRequest { fn font_request(self: Pin<&Self>, self_rc: &ItemRc) -> FontRequest {
let window_item = window.window_item(); let window_item = self_rc.window_item();
FontRequest { FontRequest {
family: { family: {
@ -216,10 +218,14 @@ impl RenderText for ComplexText {
} }
impl ComplexText { impl ComplexText {
pub fn font_metrics(self: Pin<&Self>, window_adapter: &Rc<dyn WindowAdapter>) -> FontMetrics { pub fn font_metrics(
self: Pin<&Self>,
window_adapter: &Rc<dyn WindowAdapter>,
self_rc: &ItemRc,
) -> FontMetrics {
let window_inner = WindowInner::from_pub(window_adapter.window()); let window_inner = WindowInner::from_pub(window_adapter.window());
let scale_factor = ScaleFactor::new(window_inner.scale_factor()); let scale_factor = ScaleFactor::new(window_inner.scale_factor());
let font_request = self.font_request(window_inner); let font_request = self.font_request(self_rc);
window_adapter.renderer().font_metrics(font_request, scale_factor) window_adapter.renderer().font_metrics(font_request, scale_factor)
} }
} }
@ -248,9 +254,11 @@ impl Item for SimpleText {
self: Pin<&Self>, self: Pin<&Self>,
orientation: Orientation, orientation: Orientation,
window_adapter: &Rc<dyn WindowAdapter>, window_adapter: &Rc<dyn WindowAdapter>,
self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
text_layout_info( text_layout_info(
self, self,
&self_rc,
window_adapter, window_adapter,
orientation, orientation,
Self::FIELD_OFFSETS.width.apply_pin(self), Self::FIELD_OFFSETS.width.apply_pin(self),
@ -306,10 +314,10 @@ impl Item for SimpleText {
fn bounding_rect( fn bounding_rect(
self: core::pin::Pin<&Self>, self: core::pin::Pin<&Self>,
window_adapter: &Rc<dyn WindowAdapter>, window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc, self_rc: &ItemRc,
geometry: LogicalRect, geometry: LogicalRect,
) -> LogicalRect { ) -> LogicalRect {
self.text_bounding_rect(window_adapter, geometry.cast()).cast() self.text_bounding_rect(self_rc, window_adapter, geometry.cast()).cast()
} }
fn clips_children(self: core::pin::Pin<&Self>) -> bool { fn clips_children(self: core::pin::Pin<&Self>) -> bool {
@ -333,8 +341,8 @@ impl RenderText for SimpleText {
self.text() self.text()
} }
fn font_request(self: Pin<&Self>, window: &WindowInner) -> FontRequest { fn font_request(self: Pin<&Self>, self_rc: &ItemRc) -> FontRequest {
let window_item = window.window_item(); let window_item = self_rc.window_item();
FontRequest { FontRequest {
family: window_item.as_ref().and_then(|item| item.as_pin_ref().font_family()), family: window_item.as_ref().and_then(|item| item.as_pin_ref().font_family()),
@ -387,23 +395,28 @@ impl RenderText for SimpleText {
} }
impl SimpleText { impl SimpleText {
pub fn font_metrics(self: Pin<&Self>, window_adapter: &Rc<dyn WindowAdapter>) -> FontMetrics { pub fn font_metrics(
self: Pin<&Self>,
window_adapter: &Rc<dyn WindowAdapter>,
self_rc: &ItemRc,
) -> FontMetrics {
let window_inner = WindowInner::from_pub(window_adapter.window()); let window_inner = WindowInner::from_pub(window_adapter.window());
let scale_factor = ScaleFactor::new(window_inner.scale_factor()); let scale_factor = ScaleFactor::new(window_inner.scale_factor());
let font_request = self.font_request(window_inner); let font_request = self.font_request(self_rc);
window_adapter.renderer().font_metrics(font_request, scale_factor) window_adapter.renderer().font_metrics(font_request, scale_factor)
} }
} }
fn text_layout_info( fn text_layout_info(
text: Pin<&dyn RenderText>, text: Pin<&dyn RenderText>,
self_rc: &ItemRc,
window_adapter: &Rc<dyn WindowAdapter>, window_adapter: &Rc<dyn WindowAdapter>,
orientation: Orientation, orientation: Orientation,
width: Pin<&Property<LogicalLength>>, width: Pin<&Property<LogicalLength>>,
) -> LayoutInfo { ) -> LayoutInfo {
let window_inner = WindowInner::from_pub(window_adapter.window()); let window_inner = WindowInner::from_pub(window_adapter.window());
let text_string = text.text(); let text_string = text.text();
let font_request = text.font_request(window_inner); let font_request = text.font_request(self_rc);
let scale_factor = ScaleFactor::new(window_inner.scale_factor()); let scale_factor = ScaleFactor::new(window_inner.scale_factor());
let implicit_size = |max_width, text_wrap| { let implicit_size = |max_width, text_wrap| {
window_adapter.renderer().text_size( window_adapter.renderer().text_size(
@ -545,11 +558,12 @@ impl Item for TextInput {
self: Pin<&Self>, self: Pin<&Self>,
orientation: Orientation, orientation: Orientation,
window_adapter: &Rc<dyn WindowAdapter>, window_adapter: &Rc<dyn WindowAdapter>,
self_rc: &ItemRc,
) -> LayoutInfo { ) -> LayoutInfo {
let text = self.text(); let text = self.text();
let implicit_size = |max_width, text_wrap| { let implicit_size = |max_width, text_wrap| {
window_adapter.renderer().text_size( window_adapter.renderer().text_size(
self.font_request(window_adapter), self.font_request(&self_rc),
{ {
if text.is_empty() { if text.is_empty() {
"*" "*"
@ -615,7 +629,8 @@ impl Item for TextInput {
} }
match event { match event {
MouseEvent::Pressed { position, button: PointerEventButton::Left, click_count } => { MouseEvent::Pressed { position, button: PointerEventButton::Left, click_count } => {
let clicked_offset = self.byte_offset_for_position(position, window_adapter) as i32; let clicked_offset =
self.byte_offset_for_position(position, window_adapter, self_rc) as i32;
self.as_ref().pressed.set((click_count % 3) + 1); self.as_ref().pressed.set((click_count % 3) + 1);
if !window_adapter.window().0.modifiers.get().shift() { if !window_adapter.window().0.modifiers.get().shift() {
@ -651,7 +666,8 @@ impl Item for TextInput {
self.ensure_focus_and_ime(window_adapter, self_rc); self.ensure_focus_and_ime(window_adapter, self_rc);
} }
MouseEvent::Released { position, button: PointerEventButton::Middle, .. } => { MouseEvent::Released { position, button: PointerEventButton::Middle, .. } => {
let clicked_offset = self.byte_offset_for_position(position, window_adapter) as i32; let clicked_offset =
self.byte_offset_for_position(position, window_adapter, self_rc) as i32;
self.as_ref().anchor_position_byte_offset.set(clicked_offset); self.as_ref().anchor_position_byte_offset.set(clicked_offset);
self.set_cursor_position( self.set_cursor_position(
clicked_offset, clicked_offset,
@ -676,7 +692,7 @@ impl Item for TextInput {
let pressed = self.as_ref().pressed.get(); let pressed = self.as_ref().pressed.get();
if pressed > 0 { if pressed > 0 {
let clicked_offset = let clicked_offset =
self.byte_offset_for_position(position, window_adapter) as i32; self.byte_offset_for_position(position, window_adapter, self_rc) as i32;
self.set_cursor_position( self.set_cursor_position(
clicked_offset, clicked_offset,
true, true,
@ -987,12 +1003,12 @@ impl Item for TextInput {
fn bounding_rect( fn bounding_rect(
self: core::pin::Pin<&Self>, self: core::pin::Pin<&Self>,
window_adapter: &Rc<dyn WindowAdapter>, window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc, self_rc: &ItemRc,
mut geometry: LogicalRect, mut geometry: LogicalRect,
) -> LogicalRect { ) -> LogicalRect {
let window_inner = WindowInner::from_pub(window_adapter.window()); let window_inner = WindowInner::from_pub(window_adapter.window());
let text_string = self.text(); let text_string = self.text();
let font_request = self.font_request(window_adapter); let font_request = self.font_request(self_rc);
let scale_factor = crate::lengths::ScaleFactor::new(window_inner.scale_factor()); let scale_factor = crate::lengths::ScaleFactor::new(window_inner.scale_factor());
let max_width = geometry.size.width_length(); let max_width = geometry.size.width_length();
geometry.size = geometry.size.max(window_adapter.renderer().text_size( geometry.size = geometry.size.max(window_adapter.renderer().text_size(
@ -1208,7 +1224,7 @@ impl TextInput {
let font_height = window_adapter let font_height = window_adapter
.renderer() .renderer()
.text_size( .text_size(
self.font_request(window_adapter), self.font_request(self_rc),
" ", " ",
None, None,
ScaleFactor::new(window_adapter.window().scale_factor()), ScaleFactor::new(window_adapter.window().scale_factor()),
@ -1240,22 +1256,24 @@ impl TextInput {
TextCursorDirection::NextLine => { TextCursorDirection::NextLine => {
reset_preferred_x_pos = false; reset_preferred_x_pos = false;
let cursor_rect = self.cursor_rect_for_byte_offset(last_cursor_pos, window_adapter); let cursor_rect =
self.cursor_rect_for_byte_offset(last_cursor_pos, window_adapter, self_rc);
let mut cursor_xy_pos = cursor_rect.center(); let mut cursor_xy_pos = cursor_rect.center();
cursor_xy_pos.y += font_height; cursor_xy_pos.y += font_height;
cursor_xy_pos.x = self.preferred_x_pos.get(); cursor_xy_pos.x = self.preferred_x_pos.get();
self.byte_offset_for_position(cursor_xy_pos, window_adapter) self.byte_offset_for_position(cursor_xy_pos, window_adapter, self_rc)
} }
TextCursorDirection::PreviousLine => { TextCursorDirection::PreviousLine => {
reset_preferred_x_pos = false; reset_preferred_x_pos = false;
let cursor_rect = self.cursor_rect_for_byte_offset(last_cursor_pos, window_adapter); let cursor_rect =
self.cursor_rect_for_byte_offset(last_cursor_pos, window_adapter, self_rc);
let mut cursor_xy_pos = cursor_rect.center(); let mut cursor_xy_pos = cursor_rect.center();
cursor_xy_pos.y -= font_height; cursor_xy_pos.y -= font_height;
cursor_xy_pos.x = self.preferred_x_pos.get(); cursor_xy_pos.x = self.preferred_x_pos.get();
self.byte_offset_for_position(cursor_xy_pos, window_adapter) self.byte_offset_for_position(cursor_xy_pos, window_adapter, self_rc)
} }
TextCursorDirection::PreviousCharacter => { TextCursorDirection::PreviousCharacter => {
let mut i = last_cursor_pos; let mut i = last_cursor_pos;
@ -1272,18 +1290,20 @@ impl TextInput {
prev_word_boundary(&text, last_cursor_pos.saturating_sub(1)) prev_word_boundary(&text, last_cursor_pos.saturating_sub(1))
} }
TextCursorDirection::StartOfLine => { TextCursorDirection::StartOfLine => {
let cursor_rect = self.cursor_rect_for_byte_offset(last_cursor_pos, window_adapter); let cursor_rect =
self.cursor_rect_for_byte_offset(last_cursor_pos, window_adapter, self_rc);
let mut cursor_xy_pos = cursor_rect.center(); let mut cursor_xy_pos = cursor_rect.center();
cursor_xy_pos.x = 0 as Coord; cursor_xy_pos.x = 0 as Coord;
self.byte_offset_for_position(cursor_xy_pos, window_adapter) self.byte_offset_for_position(cursor_xy_pos, window_adapter, self_rc)
} }
TextCursorDirection::EndOfLine => { TextCursorDirection::EndOfLine => {
let cursor_rect = self.cursor_rect_for_byte_offset(last_cursor_pos, window_adapter); let cursor_rect =
self.cursor_rect_for_byte_offset(last_cursor_pos, window_adapter, self_rc);
let mut cursor_xy_pos = cursor_rect.center(); let mut cursor_xy_pos = cursor_rect.center();
cursor_xy_pos.x = Coord::MAX; cursor_xy_pos.x = Coord::MAX;
self.byte_offset_for_position(cursor_xy_pos, window_adapter) self.byte_offset_for_position(cursor_xy_pos, window_adapter, self_rc)
} }
TextCursorDirection::StartOfParagraph => { TextCursorDirection::StartOfParagraph => {
prev_paragraph_boundary(&text, last_cursor_pos.saturating_sub(1)) prev_paragraph_boundary(&text, last_cursor_pos.saturating_sub(1))
@ -1299,11 +1319,12 @@ impl TextInput {
return false; return false;
} }
reset_preferred_x_pos = false; reset_preferred_x_pos = false;
let cursor_rect = self.cursor_rect_for_byte_offset(last_cursor_pos, window_adapter); let cursor_rect =
self.cursor_rect_for_byte_offset(last_cursor_pos, window_adapter, self_rc);
let mut cursor_xy_pos = cursor_rect.center(); let mut cursor_xy_pos = cursor_rect.center();
cursor_xy_pos.y -= offset; cursor_xy_pos.y -= offset;
cursor_xy_pos.x = self.preferred_x_pos.get(); cursor_xy_pos.x = self.preferred_x_pos.get();
self.byte_offset_for_position(cursor_xy_pos, window_adapter) self.byte_offset_for_position(cursor_xy_pos, window_adapter, self_rc)
} }
TextCursorDirection::PageDown => { TextCursorDirection::PageDown => {
let offset = self.page_height().get() - font_height; let offset = self.page_height().get() - font_height;
@ -1311,11 +1332,12 @@ impl TextInput {
return false; return false;
} }
reset_preferred_x_pos = false; reset_preferred_x_pos = false;
let cursor_rect = self.cursor_rect_for_byte_offset(last_cursor_pos, window_adapter); let cursor_rect =
self.cursor_rect_for_byte_offset(last_cursor_pos, window_adapter, self_rc);
let mut cursor_xy_pos = cursor_rect.center(); let mut cursor_xy_pos = cursor_rect.center();
cursor_xy_pos.y += offset; cursor_xy_pos.y += offset;
cursor_xy_pos.x = self.preferred_x_pos.get(); cursor_xy_pos.x = self.preferred_x_pos.get();
self.byte_offset_for_position(cursor_xy_pos, window_adapter) self.byte_offset_for_position(cursor_xy_pos, window_adapter, self_rc)
} }
}; };
@ -1350,8 +1372,9 @@ impl TextInput {
) { ) {
self.cursor_position_byte_offset.set(new_position); self.cursor_position_byte_offset.set(new_position);
if new_position >= 0 { if new_position >= 0 {
let pos = let pos = self
self.cursor_rect_for_byte_offset(new_position as usize, window_adapter).origin; .cursor_rect_for_byte_offset(new_position as usize, window_adapter, self_rc)
.origin;
if reset_preferred_x_pos { if reset_preferred_x_pos {
self.preferred_x_pos.set(pos.x); self.preferred_x_pos.set(pos.x);
} }
@ -1460,14 +1483,15 @@ impl TextInput {
WindowInner::from_pub(window_adapter.window()).last_ime_text.replace(text.clone()); WindowInner::from_pub(window_adapter.window()).last_ime_text.replace(text.clone());
let cursor_position = self.cursor_position(&text); let cursor_position = self.cursor_position(&text);
let anchor_position = self.anchor_position(&text); let anchor_position = self.anchor_position(&text);
let cursor_relative = self.cursor_rect_for_byte_offset(cursor_position, window_adapter); let cursor_relative =
self.cursor_rect_for_byte_offset(cursor_position, window_adapter, self_rc);
let geometry = self_rc.geometry(); let geometry = self_rc.geometry();
let origin = self_rc.map_to_window(geometry.origin).to_vector(); let origin = self_rc.map_to_window(geometry.origin).to_vector();
let cursor_rect_origin = let cursor_rect_origin =
crate::api::LogicalPosition::from_euclid(cursor_relative.origin + origin); crate::api::LogicalPosition::from_euclid(cursor_relative.origin + origin);
let cursor_rect_size = crate::api::LogicalSize::from_euclid(cursor_relative.size); let cursor_rect_size = crate::api::LogicalSize::from_euclid(cursor_relative.size);
let anchor_point = crate::api::LogicalPosition::from_euclid( let anchor_point = crate::api::LogicalPosition::from_euclid(
self.cursor_rect_for_byte_offset(anchor_position, window_adapter).origin self.cursor_rect_for_byte_offset(anchor_position, window_adapter, self_rc).origin
+ origin + origin
+ cursor_relative.size, + cursor_relative.size,
); );
@ -1679,8 +1703,8 @@ impl TextInput {
} }
} }
pub fn font_request(self: Pin<&Self>, window_adapter: &Rc<dyn WindowAdapter>) -> FontRequest { pub fn font_request(self: Pin<&Self>, self_rc: &ItemRc) -> FontRequest {
let window_item = WindowInner::from_pub(window_adapter.window()).window_item(); let window_item = self_rc.window_item();
FontRequest { FontRequest {
family: { family: {
@ -1781,11 +1805,12 @@ impl TextInput {
self: Pin<&Self>, self: Pin<&Self>,
byte_offset: usize, byte_offset: usize,
window_adapter: &Rc<dyn WindowAdapter>, window_adapter: &Rc<dyn WindowAdapter>,
self_rc: &ItemRc,
) -> LogicalRect { ) -> LogicalRect {
window_adapter.renderer().text_input_cursor_rect_for_byte_offset( window_adapter.renderer().text_input_cursor_rect_for_byte_offset(
self, self,
byte_offset, byte_offset,
self.font_request(window_adapter), self.font_request(self_rc),
ScaleFactor::new(window_adapter.window().scale_factor()), ScaleFactor::new(window_adapter.window().scale_factor()),
) )
} }
@ -1794,11 +1819,12 @@ impl TextInput {
self: Pin<&Self>, self: Pin<&Self>,
pos: LogicalPoint, pos: LogicalPoint,
window_adapter: &Rc<dyn WindowAdapter>, window_adapter: &Rc<dyn WindowAdapter>,
self_rc: &ItemRc,
) -> usize { ) -> usize {
window_adapter.renderer().text_input_byte_offset_for_position( window_adapter.renderer().text_input_byte_offset_for_position(
self, self,
pos, pos,
self.font_request(window_adapter), self.font_request(self_rc),
ScaleFactor::new(window_adapter.window().scale_factor()), ScaleFactor::new(window_adapter.window().scale_factor()),
) )
} }
@ -1948,10 +1974,14 @@ impl TextInput {
self.undo_items.set(undo_items); self.undo_items.set(undo_items);
} }
pub fn font_metrics(self: Pin<&Self>, window_adapter: &Rc<dyn WindowAdapter>) -> FontMetrics { pub fn font_metrics(
self: Pin<&Self>,
window_adapter: &Rc<dyn WindowAdapter>,
self_rc: &ItemRc,
) -> FontMetrics {
let window_inner = WindowInner::from_pub(window_adapter.window()); let window_inner = WindowInner::from_pub(window_adapter.window());
let scale_factor = ScaleFactor::new(window_inner.scale_factor()); let scale_factor = ScaleFactor::new(window_inner.scale_factor());
let font_request = self.font_request(window_adapter); let font_request = self.font_request(self_rc);
window_adapter.renderer().font_metrics(font_request, scale_factor) window_adapter.renderer().font_metrics(font_request, scale_factor)
} }
@ -2096,13 +2126,14 @@ pub unsafe extern "C" fn slint_textinput_paste(
pub fn slint_text_item_fontmetrics( pub fn slint_text_item_fontmetrics(
window_adapter: &Rc<dyn WindowAdapter>, window_adapter: &Rc<dyn WindowAdapter>,
item_ref: Pin<ItemRef<'_>>, item_ref: Pin<ItemRef<'_>>,
self_rc: &ItemRc,
) -> FontMetrics { ) -> FontMetrics {
if let Some(simple_text) = ItemRef::downcast_pin::<SimpleText>(item_ref) { if let Some(simple_text) = ItemRef::downcast_pin::<SimpleText>(item_ref) {
simple_text.font_metrics(window_adapter) simple_text.font_metrics(window_adapter, self_rc)
} else if let Some(complex_text) = ItemRef::downcast_pin::<ComplexText>(item_ref) { } else if let Some(complex_text) = ItemRef::downcast_pin::<ComplexText>(item_ref) {
complex_text.font_metrics(window_adapter) complex_text.font_metrics(window_adapter, self_rc)
} else if let Some(text_input) = ItemRef::downcast_pin::<TextInput>(item_ref) { } else if let Some(text_input) = ItemRef::downcast_pin::<TextInput>(item_ref) {
text_input.font_metrics(window_adapter) text_input.font_metrics(window_adapter, self_rc)
} else { } else {
Default::default() Default::default()
} }
@ -2118,5 +2149,5 @@ pub unsafe extern "C" fn slint_cpp_text_item_fontmetrics(
let window_adapter = &*(window_adapter as *const Rc<dyn WindowAdapter>); let window_adapter = &*(window_adapter as *const Rc<dyn WindowAdapter>);
let self_rc = ItemRc::new(self_component.clone(), self_index); let self_rc = ItemRc::new(self_component.clone(), self_index);
let self_ref = self_rc.borrow(); let self_ref = self_rc.borrow();
slint_text_item_fontmetrics(window_adapter, self_ref) slint_text_item_fontmetrics(window_adapter, self_ref, &self_rc)
} }

View file

@ -154,6 +154,7 @@ impl crate::items::Item for MenuItem {
self: Pin<&Self>, self: Pin<&Self>,
_orientation: crate::items::Orientation, _orientation: crate::items::Orientation,
_window_adapter: &Rc<dyn WindowAdapter>, _window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
) -> crate::layout::LayoutInfo { ) -> crate::layout::LayoutInfo {
Default::default() Default::default()
} }

View file

@ -2104,7 +2104,7 @@ impl<T: ProcessScene> crate::item_rendering::ItemRenderer for SceneBuilder<'_, T
fn draw_text( fn draw_text(
&mut self, &mut self,
text: Pin<&dyn crate::item_rendering::RenderText>, text: Pin<&dyn crate::item_rendering::RenderText>,
_: &ItemRc, self_rc: &ItemRc,
size: LogicalSize, size: LogicalSize,
_cache: &CachedRenderingData, _cache: &CachedRenderingData,
) { ) {
@ -2117,7 +2117,7 @@ impl<T: ProcessScene> crate::item_rendering::ItemRenderer for SceneBuilder<'_, T
return; return;
} }
let font_request = text.font_request(self.window); let font_request = text.font_request(self_rc);
let color = self.alpha_color(text.color().color()); let color = self.alpha_color(text.color().color());
let max_size = (geom.size.cast() * self.scale_factor).cast(); let max_size = (geom.size.cast() * self.scale_factor).cast();
@ -2179,7 +2179,7 @@ impl<T: ProcessScene> crate::item_rendering::ItemRenderer for SceneBuilder<'_, T
fn draw_text_input( fn draw_text_input(
&mut self, &mut self,
text_input: Pin<&crate::items::TextInput>, text_input: Pin<&crate::items::TextInput>,
_: &ItemRc, self_rc: &ItemRc,
size: LogicalSize, size: LogicalSize,
) { ) {
let geom = LogicalRect::from(size); let geom = LogicalRect::from(size);
@ -2187,7 +2187,7 @@ impl<T: ProcessScene> crate::item_rendering::ItemRenderer for SceneBuilder<'_, T
return; return;
} }
let font_request = text_input.font_request(&self.window.window_adapter()); let font_request = text_input.font_request(self_rc);
let max_size = (geom.size.cast() * self.scale_factor).cast(); let max_size = (geom.size.cast() * self.scale_factor).cast();
// Clip glyphs not only against the global clip but also against the Text's geometry to avoid drawing outside // Clip glyphs not only against the global clip but also against the Text's geometry to avoid drawing outside

View file

@ -19,6 +19,7 @@ use i_slint_compiler::langtype::Type;
use i_slint_compiler::namedreference::NamedReference; use i_slint_compiler::namedreference::NamedReference;
use i_slint_compiler::object_tree::ElementRc; use i_slint_compiler::object_tree::ElementRc;
use i_slint_core as corelib; use i_slint_core as corelib;
use i_slint_core::items::ItemRc;
use smol_str::SmolStr; use smol_str::SmolStr;
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
@ -845,9 +846,17 @@ fn call_builtin_function(
let item_info = &description.items[elem.borrow().id.as_str()]; let item_info = &description.items[elem.borrow().id.as_str()];
let item_ref = let item_ref =
unsafe { item_info.item_from_item_tree(enclosing_component.as_ptr()) }; unsafe { item_info.item_from_item_tree(enclosing_component.as_ptr()) };
let item_comp = enclosing_component.self_weak().get().unwrap().upgrade().unwrap();
let item_rc = corelib::items::ItemRc::new(
vtable::VRc::into_dyn(item_comp),
item_info.item_index(),
);
let window_adapter = component.window_adapter(); let window_adapter = component.window_adapter();
let metrics = let metrics = i_slint_core::items::slint_text_item_fontmetrics(
i_slint_core::items::slint_text_item_fontmetrics(&window_adapter, item_ref); &window_adapter,
item_ref,
&item_rc,
);
metrics.into() metrics.into()
} else { } else {
panic!("internal error: argument to set-selection-offsetsAll must be an element") panic!("internal error: argument to set-selection-offsetsAll must be an element")
@ -1225,11 +1234,15 @@ fn call_builtin_function(
let item_info = &description.items[item.borrow().id.as_str()]; let item_info = &description.items[item.borrow().id.as_str()];
let item_ref = let item_ref =
unsafe { item_info.item_from_item_tree(enclosing_component.as_ptr()) }; unsafe { item_info.item_from_item_tree(enclosing_component.as_ptr()) };
let item_comp = enclosing_component.self_weak().get().unwrap().upgrade().unwrap();
let window_adapter = component.window_adapter(); let window_adapter = component.window_adapter();
item_ref item_ref
.as_ref() .as_ref()
.layout_info(crate::eval_layout::to_runtime(orient), &window_adapter) .layout_info(
crate::eval_layout::to_runtime(orient),
&window_adapter,
&ItemRc::new(vtable::VRc::into_dyn(item_comp), item_info.item_index()),
)
.into() .into()
} else { } else {
panic!("internal error: incorrect arguments to ImplicitLayoutInfo {arguments:?}"); panic!("internal error: incorrect arguments to ImplicitLayoutInfo {arguments:?}");

View file

@ -9,7 +9,7 @@ use i_slint_compiler::langtype::Type;
use i_slint_compiler::layout::{Layout, LayoutConstraints, LayoutGeometry, Orientation}; use i_slint_compiler::layout::{Layout, LayoutConstraints, LayoutGeometry, Orientation};
use i_slint_compiler::namedreference::NamedReference; use i_slint_compiler::namedreference::NamedReference;
use i_slint_compiler::object_tree::ElementRc; use i_slint_compiler::object_tree::ElementRc;
use i_slint_core::items::DialogButtonRole; use i_slint_core::items::{DialogButtonRole, ItemRc};
use i_slint_core::layout::{self as core_layout}; use i_slint_core::layout::{self as core_layout};
use i_slint_core::model::RepeatedItemTree; use i_slint_core::model::RepeatedItemTree;
use i_slint_core::slice::Slice; use i_slint_core::slice::Slice;
@ -310,10 +310,14 @@ pub(crate) fn get_layout_info(
.items .items
.get(elem.id.as_str()) .get(elem.id.as_str())
.unwrap_or_else(|| panic!("Internal error: Item {} not found", elem.id)); .unwrap_or_else(|| panic!("Internal error: Item {} not found", elem.id));
let item_comp = component.self_weak().get().unwrap().upgrade().unwrap();
unsafe { unsafe {
item.item_from_item_tree(component.as_ptr()) item.item_from_item_tree(component.as_ptr()).as_ref().layout_info(
.as_ref() to_runtime(orientation),
.layout_info(to_runtime(orientation), window_adapter) window_adapter,
&ItemRc::new(vtable::VRc::into_dyn(item_comp), item.item_index()),
)
} }
} }
} }

View file

@ -23,7 +23,6 @@ use i_slint_core::lengths::{
LogicalBorderRadius, LogicalLength, LogicalPoint, LogicalRect, LogicalSize, LogicalVector, LogicalBorderRadius, LogicalLength, LogicalPoint, LogicalRect, LogicalSize, LogicalVector,
RectLengths, ScaleFactor, SizeLengths, RectLengths, ScaleFactor, SizeLengths,
}; };
use i_slint_core::window::WindowInner;
use i_slint_core::{Brush, Color, ImageInner, SharedString}; use i_slint_core::{Brush, Color, ImageInner, SharedString};
use super::images::{Texture, TextureCacheKey}; use super::images::{Texture, TextureCacheKey};
@ -310,7 +309,7 @@ impl ItemRenderer for GLItemRenderer<'_> {
fn draw_text( fn draw_text(
&mut self, &mut self,
text: Pin<&dyn RenderText>, text: Pin<&dyn RenderText>,
_: &ItemRc, self_rc: &ItemRc,
size: LogicalSize, size: LogicalSize,
_cache: &CachedRenderingData, _cache: &CachedRenderingData,
) { ) {
@ -328,11 +327,7 @@ impl ItemRenderer for GLItemRenderer<'_> {
let string = text.text(); let string = text.text();
let string = string.as_str(); let string = string.as_str();
let font = fonts::FONT_CACHE.with(|cache| { let font = fonts::FONT_CACHE.with(|cache| {
cache.borrow_mut().font( cache.borrow_mut().font(text.font_request(self_rc), self.scale_factor, &text.text())
text.font_request(WindowInner::from_pub(self.window)),
self.scale_factor,
&text.text(),
)
}); });
let text_path = rect_to_path((size * self.scale_factor).into()); let text_path = rect_to_path((size * self.scale_factor).into());
@ -396,7 +391,7 @@ impl ItemRenderer for GLItemRenderer<'_> {
fn draw_text_input( fn draw_text_input(
&mut self, &mut self,
text_input: Pin<&items::TextInput>, text_input: Pin<&items::TextInput>,
_: &ItemRc, self_rc: &ItemRc,
size: LogicalSize, size: LogicalSize,
) { ) {
let width = size.width_length() * self.scale_factor; let width = size.width_length() * self.scale_factor;
@ -411,7 +406,7 @@ impl ItemRenderer for GLItemRenderer<'_> {
let font = fonts::FONT_CACHE.with(|cache| { let font = fonts::FONT_CACHE.with(|cache| {
cache.borrow_mut().font( cache.borrow_mut().font(
text_input.font_request(&WindowInner::from_pub(self.window).window_adapter()), text_input.font_request(self_rc),
self.scale_factor, self.scale_factor,
&text_input.text(), &text_input.text(),
) )

View file

@ -498,7 +498,7 @@ impl ItemRenderer for SkiaItemRenderer<'_> {
fn draw_text( fn draw_text(
&mut self, &mut self,
text: Pin<&dyn RenderText>, text: Pin<&dyn RenderText>,
_self_rc: &i_slint_core::items::ItemRc, self_rc: &i_slint_core::items::ItemRc,
size: LogicalSize, size: LogicalSize,
_cache: &CachedRenderingData, _cache: &CachedRenderingData,
) { ) {
@ -511,7 +511,7 @@ impl ItemRenderer for SkiaItemRenderer<'_> {
let string = text.text(); let string = text.text();
let string = string.as_str(); let string = string.as_str();
let font_request = text.font_request(WindowInner::from_pub(self.window)); let font_request = text.font_request(self_rc);
let paint = match self.brush_to_paint(text.color(), max_width, max_height) { let paint = match self.brush_to_paint(text.color(), max_width, max_height) {
Some(paint) => paint, Some(paint) => paint,
@ -597,7 +597,7 @@ impl ItemRenderer for SkiaItemRenderer<'_> {
fn draw_text_input( fn draw_text_input(
&mut self, &mut self,
text_input: Pin<&i_slint_core::items::TextInput>, text_input: Pin<&i_slint_core::items::TextInput>,
_self_rc: &i_slint_core::items::ItemRc, self_rc: &i_slint_core::items::ItemRc,
size: LogicalSize, size: LogicalSize,
) { ) {
let max_width = size.width_length() * self.scale_factor; let max_width = size.width_length() * self.scale_factor;
@ -607,8 +607,7 @@ impl ItemRenderer for SkiaItemRenderer<'_> {
return; return;
} }
let font_request = let font_request = text_input.font_request(self_rc);
text_input.font_request(&WindowInner::from_pub(self.window).window_adapter());
let visual_representation = text_input.visual_representation(None); let visual_representation = text_input.visual_representation(None);
let paint = let paint =