Rust: Allocate the window adapter lazily

This will be needed for embedding - to avoid creating two window
adapters - and it will be needed for the API to allow creating a
component from an existing window.
This commit is contained in:
Simon Hausmann 2023-06-06 15:32:59 +02:00 committed by Simon Hausmann
parent 2a7b20b794
commit 01b00d26eb
21 changed files with 115 additions and 62 deletions

View file

@ -190,7 +190,7 @@ impl NativeButton {
}
impl Item for NativeButton {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(

View file

@ -22,7 +22,7 @@ pub struct NativeCheckBox {
}
impl Item for NativeCheckBox {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(

View file

@ -21,7 +21,7 @@ pub struct NativeComboBox {
}
impl Item for NativeComboBox {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(
@ -151,7 +151,7 @@ pub struct NativeComboBoxPopup {
}
impl Item for NativeComboBoxPopup {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(

View file

@ -62,7 +62,7 @@ fn minimum_group_box_size(title: qttypes::QString) -> qttypes::QSize {
}
impl Item for NativeGroupBox {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {
fn init(self: Pin<&Self>) {
let shared_data = Rc::pin(GroupBoxData::default());
Property::link_two_way(

View file

@ -25,7 +25,7 @@ pub struct NativeLineEdit {
}
impl Item for NativeLineEdit {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {
fn init(self: Pin<&Self>) {
let paddings = Rc::pin(Property::default());
paddings.as_ref().set_binding(move || {

View file

@ -21,7 +21,7 @@ pub struct NativeStandardListViewItem {
}
impl Item for NativeStandardListViewItem {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(

View file

@ -21,7 +21,7 @@ pub struct NativeProgressIndicator {
}
impl Item for NativeProgressIndicator {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(

View file

@ -30,7 +30,7 @@ pub struct NativeScrollView {
}
impl Item for NativeScrollView {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {
fn init(self: Pin<&Self>) {
let paddings = Rc::pin(Property::default());
paddings.as_ref().set_binding(move || {

View file

@ -57,7 +57,7 @@ void initQSliderOptions(QStyleOptionSlider &option, bool pressed, bool enabled,
}}
impl Item for NativeSlider {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(

View file

@ -54,7 +54,7 @@ option.frame = true;
}}
impl Item for NativeSpinBox {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(

View file

@ -22,7 +22,7 @@ pub struct NativeSwitch {
}
impl Item for NativeSwitch {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(

View file

@ -20,7 +20,7 @@ pub struct NativeTableHeaderSection {
}
impl Item for NativeTableHeaderSection {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(

View file

@ -35,7 +35,7 @@ pub struct NativeTabWidget {
}
impl Item for NativeTabWidget {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {
fn init(self: Pin<&Self>) {
#[derive(Default, Clone)]
#[repr(C)]
struct TabWidgetMetrics {
@ -345,7 +345,7 @@ pub struct NativeTab {
}
impl Item for NativeTab {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(

View file

@ -327,8 +327,16 @@ fn generate_public_component(llr: &llr::PublicComponent) -> TokenStream {
let inner_component_id = inner_component_id(&llr.item_tree.root);
let global_container_id = format_ident!("Globals_{}", public_component_id);
let component =
generate_item_tree(&llr.item_tree, llr, None, quote!(globals: #global_container_id), None);
let component = generate_item_tree(
&llr.item_tree,
llr,
None,
quote!(
globals: #global_container_id,
window_adapter_: slint::private_unstable_api::re_exports::OnceCell<slint::private_unstable_api::re_exports::Rc<dyn slint::private_unstable_api::re_exports::WindowAdapter>>,
),
None,
);
let ctx = EvaluationContext {
public_component: llr,
@ -393,15 +401,15 @@ fn generate_public_component(llr: &llr::PublicComponent) -> TokenStream {
}
fn show(&self) -> core::result::Result<(), slint::PlatformError> {
self.window().show()
self.0.window_adapter_ref()?.window().show()
}
fn hide(&self) -> core::result::Result<(), slint::PlatformError> {
self.window().hide()
self.0.window_adapter_ref()?.window().hide()
}
fn window(&self) -> &slint::Window {
vtable::VRc::as_pin_ref(&self.0).get_ref().window_adapter.get().unwrap().window()
self.0.window_adapter_ref().unwrap().window()
}
fn global<'a, T: slint::Global<'a, Self>>(&'a self) -> T {
@ -989,8 +997,6 @@ fn generate_sub_component(
#(#repeated_element_names : slint::private_unstable_api::re_exports::Repeater<#repeated_element_components>,)*
self_weak : slint::private_unstable_api::re_exports::OnceCell<slint::private_unstable_api::re_exports::VWeakMapped<slint::private_unstable_api::re_exports::ComponentVTable, #inner_component_id>>,
#(parent : #parent_component_type,)*
// FIXME: Do we really need a window all the time?
window_adapter: slint::private_unstable_api::re_exports::OnceCell<slint::private_unstable_api::re_exports::Rc<dyn slint::private_unstable_api::re_exports::WindowAdapter>>,
root : slint::private_unstable_api::re_exports::OnceCell<slint::private_unstable_api::re_exports::VWeak<slint::private_unstable_api::re_exports::ComponentVTable, #root_component_id>>,
tree_index: ::core::cell::Cell<u32>,
tree_index_of_first_child: ::core::cell::Cell<u32>,
@ -1006,7 +1012,6 @@ fn generate_sub_component(
let _self = self_rc.as_pin_ref();
_self.self_weak.set(VRcMapped::downgrade(&self_rc));
_self.root.set(VRc::downgrade(root));
_self.window_adapter.set(root.window_adapter.get().unwrap().clone());
_self.tree_index.set(tree_index);
_self.tree_index_of_first_child.set(tree_index_of_first_child);
#(#init)*
@ -1277,12 +1282,28 @@ fn generate_item_tree(
quote!(&self_rc)
};
let (create_window_adapter, init_window, new_result, new_end) = if let Some(parent_ctx) =
parent_ctx
{
let (window_adapter_functions, new_result, new_end) = if let Some(parent_ctx) = parent_ctx {
(
None,
None,
quote!(
#[allow(unused)]
fn window_adapter(
&self,
) -> Rc<dyn slint::private_unstable_api::re_exports::WindowAdapter>
{
self.root.get().unwrap().upgrade().unwrap().window_adapter()
}
#[allow(unused)]
fn maybe_window_adapter(
&self,
) -> Option<Rc<dyn slint::private_unstable_api::re_exports::WindowAdapter>>
{
self.root
.get()
.and_then(|root_weak| root_weak.upgrade())
.and_then(|root| root.maybe_window_adapter())
}
),
quote!(vtable::VRc<slint::private_unstable_api::re_exports::ComponentVTable, Self>),
if parent_ctx.repeater_index.is_some() {
// Repeaters run their user_init() code from RepeatedComponent::init() after update() initialized model_data/index.
@ -1296,13 +1317,41 @@ fn generate_item_tree(
)
} else {
(
Some(
quote!(let window_adapter = slint::private_unstable_api::create_window_adapter()?;),
quote!(
#[allow(unused)]
fn window_adapter(
&self,
) -> Rc<dyn slint::private_unstable_api::re_exports::WindowAdapter>
{
self.window_adapter_ref().unwrap().clone()
}
fn window_adapter_ref(
&self,
) -> Result<
&Rc<dyn slint::private_unstable_api::re_exports::WindowAdapter>,
slint::PlatformError,
> {
self.window_adapter_.get_or_try_init(|| {
let adapter = slint::private_unstable_api::create_window_adapter()?;
let self_rc =
VRcMapped::origin(&self.self_weak.get().unwrap().upgrade().unwrap());
slint::private_unstable_api::re_exports::WindowInner::from_pub(
adapter.window(),
)
.set_component(&self_rc);
core::result::Result::Ok(adapter)
})
}
#[allow(unused)]
fn maybe_window_adapter(
&self,
) -> Option<Rc<dyn slint::private_unstable_api::re_exports::WindowAdapter>>
{
self.window_adapter_.get().cloned()
}
),
Some(quote! {
_self.window_adapter.set(window_adapter);
slint::private_unstable_api::re_exports::WindowInner::from_pub(_self.window_adapter.get().unwrap().window()).set_component(&VRc::into_dyn(self_rc.clone()));
}),
quote!(
core::result::Result<
vtable::VRc<slint::private_unstable_api::re_exports::ComponentVTable, Self>,
@ -1384,13 +1433,11 @@ fn generate_item_tree(
impl #inner_component_id {
pub fn new(#(parent: #parent_component_type)*) -> #new_result {
#![allow(unused)]
#create_window_adapter // We must create the window first to initialize the backend before using the style
let mut _self = Self::default();
#(_self.parent = parent.clone() as #parent_component_type;)*
let self_rc = VRc::new(_self);
let _self = self_rc.as_pin_ref();
#init_window
slint::private_unstable_api::re_exports::register_component(_self, Self::item_array(), #root_token.window_adapter.get().unwrap());
slint::private_unstable_api::re_exports::register_component(_self, Self::item_array(), (*#root_token).maybe_window_adapter());
Self::init(slint::private_unstable_api::re_exports::VRc::map(self_rc.clone(), |x| x), #root_token, 0, 1);
#new_end
}
@ -1407,6 +1454,8 @@ fn generate_item_tree(
> = slint::private_unstable_api::re_exports::OnceBox::new();
&*ITEM_ARRAY.get_or_init(|| Box::new([#(#item_array),*]))
}
#window_adapter_functions
}
impl slint::private_unstable_api::re_exports::PinnedDrop for #inner_component_id {
@ -1414,7 +1463,9 @@ fn generate_item_tree(
use slint::private_unstable_api::re_exports::*;
ComponentVTable_static!(static VT for self::#inner_component_id);
new_vref!(let vref : VRef<ComponentVTable> for Component = self.as_ref().get_ref());
slint::private_unstable_api::re_exports::unregister_component(self.as_ref(), vref, Self::item_array(), self.window_adapter.get().unwrap());
if let Some(wa) = self.maybe_window_adapter() {
slint::private_unstable_api::re_exports::unregister_component(self.as_ref(), vref, Self::item_array(), &wa);
}
}
}
@ -1788,7 +1839,7 @@ fn follow_sub_component_path<'a>(
fn access_window_adapter_field(ctx: &EvaluationContext) -> TokenStream {
let root = &ctx.generator_state;
quote!(#root.window_adapter.get().unwrap())
quote!((&#root.window_adapter()))
}
/// Given a property reference to a native item (eg, the property name is empty)

View file

@ -126,10 +126,12 @@ pub type ComponentWeak = vtable::VWeak<ComponentVTable, Dyn>;
pub fn register_component<Base>(
base: core::pin::Pin<&Base>,
item_array: &[vtable::VOffset<Base, ItemVTable, vtable::AllowPin>],
window_adapter: &Rc<dyn WindowAdapter>,
window_adapter: Option<Rc<dyn WindowAdapter>>,
) {
item_array.iter().for_each(|item| item.apply_pin(base).as_ref().init(window_adapter));
window_adapter.register_component();
item_array.iter().for_each(|item| item.apply_pin(base).as_ref().init());
if let Some(adapter) = window_adapter {
adapter.register_component();
}
}
/// Free the backend graphics resources allocated by the component's items.
@ -166,7 +168,7 @@ pub(crate) mod ffi {
super::register_component(
core::pin::Pin::new_unchecked(&*(component.as_ptr() as *const u8)),
item_array.as_slice(),
window_adapter,
Some(window_adapter.clone()),
)
}

View file

@ -107,7 +107,7 @@ pub struct ItemVTable {
/// This function is called by the run-time after the memory for the item
/// has been allocated and initialized. It will be called before any user specified
/// bindings are set.
pub init: extern "C" fn(core::pin::Pin<VRef<ItemVTable>>, window_adapter: &WindowAdapterRc),
pub init: extern "C" fn(core::pin::Pin<VRef<ItemVTable>>),
/// Returns the geometry of this item (relative to its parent item)
pub geometry: extern "C" fn(core::pin::Pin<VRef<ItemVTable>>) -> LogicalRect,
@ -183,7 +183,7 @@ pub struct Empty {
}
impl Item for Empty {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(
@ -271,7 +271,7 @@ pub struct Rectangle {
}
impl Item for Rectangle {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(
@ -363,7 +363,7 @@ pub struct BorderRectangle {
}
impl Item for BorderRectangle {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(
@ -470,7 +470,7 @@ pub struct TouchArea {
}
impl Item for TouchArea {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(
@ -644,7 +644,7 @@ pub struct FocusScope {
}
impl Item for FocusScope {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(
@ -765,7 +765,7 @@ pub struct Clip {
}
impl Item for Clip {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(
@ -862,7 +862,7 @@ pub struct Opacity {
}
impl Item for Opacity {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(
@ -978,7 +978,7 @@ pub struct Layer {
}
impl Item for Layer {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(
@ -1068,7 +1068,7 @@ pub struct Rotate {
}
impl Item for Rotate {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(
@ -1193,7 +1193,7 @@ pub struct WindowItem {
}
impl Item for WindowItem {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(
@ -1314,7 +1314,7 @@ pub struct BoxShadow {
}
impl Item for BoxShadow {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(

View file

@ -57,7 +57,7 @@ pub struct Flickable {
}
impl Item for Flickable {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(

View file

@ -42,7 +42,7 @@ pub struct ImageItem {
}
impl Item for ImageItem {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(
@ -144,7 +144,7 @@ pub struct ClippedImage {
}
impl Item for ClippedImage {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(

View file

@ -53,7 +53,7 @@ pub struct Path {
}
impl Item for Path {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(

View file

@ -58,7 +58,7 @@ pub struct Text {
}
impl Item for Text {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
fn geometry(self: Pin<&Self>) -> LogicalRect {
LogicalRect::new(
@ -254,7 +254,7 @@ pub struct TextInput {
}
impl Item for TextInput {
fn init(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
fn init(self: Pin<&Self>) {}
// FIXME: width / height. or maybe it doesn't matter? (
fn geometry(self: Pin<&Self>) -> LogicalRect {

View file

@ -1244,7 +1244,7 @@ pub fn instantiate(
i_slint_core::component::register_component(
instance_ref.instance,
instance_ref.component_type.item_array.as_slice(),
eval::window_adapter_ref(instance_ref).unwrap(),
eval::window_adapter_ref(instance_ref).cloned(),
);
}