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

@ -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)