mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-03 18:29:09 +00:00
Add window_adapter
to ComponentVTable
Make it duplicate as `maybe_window_adapter` with a boolean `do_create` parameter.
This commit is contained in:
parent
de96455dda
commit
a362b7a1ae
7 changed files with 148 additions and 58 deletions
|
@ -1292,6 +1292,21 @@ fn generate_item_tree(
|
|||
}),
|
||||
));
|
||||
|
||||
target_struct.members.push((
|
||||
Access::Private,
|
||||
Declaration::Function(Function {
|
||||
name: "window_adapter".into(),
|
||||
signature:
|
||||
"([[maybe_unused]] slint::private_api::ComponentRef component, [[maybe_unused]] bool do_create, [[maybe_unused]] slint::cbindgen_private::Option<slint::private_api::WindowAdapterRc>* result) -> void"
|
||||
.into(),
|
||||
is_static: true,
|
||||
statements: Some(vec![format!(
|
||||
"/* TODO: implement this! */",
|
||||
)]),
|
||||
..Default::default()
|
||||
}),
|
||||
));
|
||||
|
||||
target_struct.members.push((
|
||||
Access::Public,
|
||||
Declaration::Var(Var {
|
||||
|
@ -1307,7 +1322,7 @@ fn generate_item_tree(
|
|||
init: Some(format!(
|
||||
"{{ visit_children, get_item_ref, get_subtree_range, get_subtree_component, \
|
||||
get_item_tree, parent_node, embed_component, subtree_index, layout_info, \
|
||||
accessible_role, accessible_string_property, \
|
||||
accessible_role, accessible_string_property, window_adapter, \
|
||||
slint::private_api::drop_in_place<{}>, slint::private_api::dealloc }}",
|
||||
item_tree_class_name
|
||||
)),
|
||||
|
|
|
@ -1256,16 +1256,16 @@ fn generate_item_tree(
|
|||
(
|
||||
quote!(
|
||||
#[allow(unused)]
|
||||
fn window_adapter(&self) -> Rc<dyn sp::WindowAdapter> {
|
||||
self.root.get().unwrap().upgrade().unwrap().window_adapter()
|
||||
fn window_adapter_impl(&self) -> Rc<dyn sp::WindowAdapter> {
|
||||
self.root.get().unwrap().upgrade().unwrap().window_adapter_impl()
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn maybe_window_adapter(&self) -> Option<Rc<dyn sp::WindowAdapter>> {
|
||||
fn maybe_window_adapter_impl(&self) -> Option<Rc<dyn sp::WindowAdapter>> {
|
||||
self.root
|
||||
.get()
|
||||
.and_then(|root_weak| root_weak.upgrade())
|
||||
.and_then(|root| root.maybe_window_adapter())
|
||||
.and_then(|root| root.maybe_window_adapter_impl())
|
||||
}
|
||||
),
|
||||
quote!(vtable::VRc<sp::ComponentVTable, Self>),
|
||||
|
@ -1283,7 +1283,7 @@ fn generate_item_tree(
|
|||
(
|
||||
quote!(
|
||||
#[allow(unused)]
|
||||
fn window_adapter(&self) -> Rc<dyn sp::WindowAdapter> {
|
||||
fn window_adapter_impl(&self) -> Rc<dyn sp::WindowAdapter> {
|
||||
Rc::clone(self.window_adapter_ref().unwrap())
|
||||
}
|
||||
|
||||
|
@ -1300,7 +1300,7 @@ fn generate_item_tree(
|
|||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn maybe_window_adapter(&self) -> Option<Rc<dyn sp::WindowAdapter>> {
|
||||
fn maybe_window_adapter_impl(&self) -> Option<Rc<dyn sp::WindowAdapter>> {
|
||||
self.window_adapter_.get().cloned()
|
||||
}
|
||||
),
|
||||
|
@ -1392,7 +1392,7 @@ fn generate_item_tree(
|
|||
#(_self.parent = parent.clone() as #parent_component_type;)*
|
||||
let self_rc = VRc::new(_self);
|
||||
let self_dyn_rc = vtable::VRc::into_dyn(self_rc.clone());
|
||||
sp::register_component(&self_dyn_rc, (*#root_token).maybe_window_adapter());
|
||||
sp::register_component(&self_dyn_rc, (*#root_token).maybe_window_adapter_impl());
|
||||
Self::init(sp::VRc::map(self_rc.clone(), |x| x), #root_token, 0, 1);
|
||||
#new_end
|
||||
}
|
||||
|
@ -1418,7 +1418,7 @@ 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());
|
||||
if let Some(wa) = self.maybe_window_adapter() {
|
||||
if let Some(wa) = self.maybe_window_adapter_impl() {
|
||||
sp::unregister_component(self.as_ref(), vref, Self::item_array(), &wa);
|
||||
}
|
||||
}
|
||||
|
@ -1493,6 +1493,18 @@ fn generate_item_tree(
|
|||
) {
|
||||
*result = self.accessible_string_property(index, what);
|
||||
}
|
||||
|
||||
fn window_adapter(
|
||||
self: ::core::pin::Pin<&Self>,
|
||||
do_create: bool,
|
||||
result: &mut Option<Rc<dyn WindowAdapter>>,
|
||||
) {
|
||||
if do_create {
|
||||
*result = Some(self.window_adapter_impl());
|
||||
} else {
|
||||
*result = self.maybe_window_adapter_impl();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1798,7 +1810,7 @@ fn follow_sub_component_path<'a>(
|
|||
|
||||
fn access_window_adapter_field(ctx: &EvaluationContext) -> TokenStream {
|
||||
let root = &ctx.generator_state;
|
||||
quote!((&#root.window_adapter()))
|
||||
quote!((&#root.window_adapter_impl()))
|
||||
}
|
||||
|
||||
/// Given a property reference to a native item (eg, the property name is empty)
|
||||
|
|
|
@ -12,9 +12,8 @@ use crate::item_tree::{
|
|||
use crate::items::{AccessibleRole, ItemRc, ItemVTable};
|
||||
use crate::layout::{LayoutInfo, Orientation};
|
||||
use crate::slice::Slice;
|
||||
use crate::window::WindowAdapter;
|
||||
use crate::window::WindowAdapterRc;
|
||||
use crate::SharedString;
|
||||
use alloc::rc::Rc;
|
||||
use vtable::*;
|
||||
|
||||
#[repr(C)]
|
||||
|
@ -111,6 +110,13 @@ pub struct ComponentVTable {
|
|||
result: &mut SharedString,
|
||||
),
|
||||
|
||||
/// Returns a Window, creating a fresh one if `do_create` is true.
|
||||
pub window_adapter: extern "C" fn(
|
||||
core::pin::Pin<VRef<ComponentVTable>>,
|
||||
do_create: bool,
|
||||
result: &mut Option<WindowAdapterRc>,
|
||||
),
|
||||
|
||||
/// in-place destructor (for VRc)
|
||||
pub drop_in_place: unsafe fn(VRefMut<ComponentVTable>) -> vtable::Layout,
|
||||
/// dealloc function (for VRc)
|
||||
|
@ -133,10 +139,7 @@ pub type ComponentRc = vtable::VRc<ComponentVTable, Dyn>;
|
|||
pub type ComponentWeak = vtable::VWeak<ComponentVTable, Dyn>;
|
||||
|
||||
/// Call init() on the ItemVTable for each item of the component.
|
||||
pub fn register_component(
|
||||
component_rc: &ComponentRc,
|
||||
window_adapter: Option<Rc<dyn WindowAdapter>>,
|
||||
) {
|
||||
pub fn register_component(component_rc: &ComponentRc, window_adapter: Option<WindowAdapterRc>) {
|
||||
let c = vtable::VRc::borrow_pin(component_rc);
|
||||
let item_tree = c.as_ref().get_item_tree();
|
||||
item_tree.iter().enumerate().for_each(|(tree_index, node)| {
|
||||
|
@ -155,7 +158,7 @@ pub fn unregister_component<Base>(
|
|||
base: core::pin::Pin<&Base>,
|
||||
component: ComponentRef,
|
||||
item_array: &[vtable::VOffset<Base, ItemVTable, vtable::AllowPin>],
|
||||
window_adapter: &Rc<dyn WindowAdapter>,
|
||||
window_adapter: &WindowAdapterRc,
|
||||
) {
|
||||
window_adapter.renderer().free_graphics_resources(
|
||||
component,
|
||||
|
@ -170,7 +173,7 @@ pub fn unregister_component<Base>(
|
|||
pub(crate) mod ffi {
|
||||
#![allow(unsafe_code)]
|
||||
|
||||
use crate::window::WindowAdapter;
|
||||
use crate::window::WindowAdapterRc;
|
||||
|
||||
use super::*;
|
||||
|
||||
|
@ -180,7 +183,7 @@ pub(crate) mod ffi {
|
|||
component_rc: &ComponentRc,
|
||||
window_handle: *const crate::window::ffi::WindowAdapterRcOpaque,
|
||||
) {
|
||||
let window_adapter = (window_handle as *const Rc<dyn WindowAdapter>).as_ref().cloned();
|
||||
let window_adapter = (window_handle as *const WindowAdapterRc).as_ref().cloned();
|
||||
super::register_component(component_rc, window_adapter)
|
||||
}
|
||||
|
||||
|
@ -191,7 +194,7 @@ pub(crate) mod ffi {
|
|||
item_array: Slice<vtable::VOffset<u8, ItemVTable, vtable::AllowPin>>,
|
||||
window_handle: *const crate::window::ffi::WindowAdapterRcOpaque,
|
||||
) {
|
||||
let window_adapter = &*(window_handle as *const Rc<dyn WindowAdapter>);
|
||||
let window_adapter = &*(window_handle as *const WindowAdapterRc);
|
||||
super::unregister_component(
|
||||
core::pin::Pin::new_unchecked(&*(component.as_ptr() as *const u8)),
|
||||
core::pin::Pin::into_inner(component),
|
||||
|
|
|
@ -850,10 +850,13 @@ mod tests {
|
|||
use crate::items::AccessibleRole;
|
||||
use crate::layout::{LayoutInfo, Orientation};
|
||||
use crate::slice::Slice;
|
||||
use crate::window::WindowAdapter;
|
||||
use crate::SharedString;
|
||||
|
||||
use vtable::VRc;
|
||||
|
||||
use alloc::rc::Rc;
|
||||
|
||||
struct TestComponent {
|
||||
parent_component: Option<ComponentRc>,
|
||||
item_tree: Vec<ItemTreeNode>,
|
||||
|
@ -931,6 +934,14 @@ mod tests {
|
|||
_: &mut SharedString,
|
||||
) {
|
||||
}
|
||||
|
||||
fn window_adapter(
|
||||
self: Pin<&Self>,
|
||||
_do_create: bool,
|
||||
_result: &mut Option<Rc<dyn WindowAdapter>>,
|
||||
) {
|
||||
unimplemented!("Not needed for this test")
|
||||
}
|
||||
}
|
||||
|
||||
crate::component::ComponentVTable_static!(static TEST_COMPONENT_VT for TestComponent);
|
||||
|
|
|
@ -1097,11 +1097,11 @@ impl ComponentHandle for ComponentInstance {
|
|||
}
|
||||
|
||||
fn show(&self) -> Result<(), PlatformError> {
|
||||
self.inner.window_adapter()?.window().show()
|
||||
self.inner.window_adapter_ref()?.window().show()
|
||||
}
|
||||
|
||||
fn hide(&self) -> Result<(), PlatformError> {
|
||||
self.inner.window_adapter()?.window().hide()
|
||||
self.inner.window_adapter_ref()?.window().hide()
|
||||
}
|
||||
|
||||
fn run(&self) -> Result<(), PlatformError> {
|
||||
|
@ -1111,7 +1111,7 @@ impl ComponentHandle for ComponentInstance {
|
|||
}
|
||||
|
||||
fn window(&self) -> &Window {
|
||||
self.inner.window_adapter().unwrap().window()
|
||||
self.inner.window_adapter_ref().unwrap().window()
|
||||
}
|
||||
|
||||
fn global<'a, T: Global<'a, Self>>(&'a self) -> T
|
||||
|
|
|
@ -59,9 +59,12 @@ impl<'id> ComponentBox<'id> {
|
|||
InstanceRef { instance: self.instance.as_pin_ref(), component_type: &self.component_type }
|
||||
}
|
||||
|
||||
pub fn window_adapter(&self) -> Result<&Rc<dyn WindowAdapter>, PlatformError> {
|
||||
pub fn window_adapter_ref(&self) -> Result<&Rc<dyn WindowAdapter>, PlatformError> {
|
||||
let root_weak = vtable::VWeak::into_dyn(self.borrow_instance().root_weak().clone());
|
||||
InstanceRef::get_or_init_window_adapter_ref(
|
||||
&self.component_type,
|
||||
root_weak,
|
||||
true,
|
||||
self.instance.as_pin_ref().get_ref(),
|
||||
)
|
||||
}
|
||||
|
@ -220,6 +223,14 @@ impl Component for ErasedComponentBox {
|
|||
) {
|
||||
self.borrow().as_ref().accessible_string_property(index, what, result)
|
||||
}
|
||||
|
||||
fn window_adapter(
|
||||
self: Pin<&Self>,
|
||||
do_create: bool,
|
||||
result: &mut Option<Rc<dyn WindowAdapter>>,
|
||||
) {
|
||||
self.borrow().as_ref().window_adapter(do_create, result);
|
||||
}
|
||||
}
|
||||
|
||||
i_slint_core::ComponentVTable_static!(static COMPONENT_BOX_VT for ErasedComponentBox);
|
||||
|
@ -229,6 +240,7 @@ impl<'id> Drop for ErasedComponentBox {
|
|||
generativity::make_guard!(guard);
|
||||
let unerase = self.unerase(guard);
|
||||
let instance_ref = unerase.borrow_instance();
|
||||
// Do not walk out of our component here:
|
||||
if let Some(window_adapter) = instance_ref.maybe_window_adapter() {
|
||||
i_slint_core::component::unregister_component(
|
||||
instance_ref.instance,
|
||||
|
@ -1130,6 +1142,7 @@ pub(crate) fn generate_component<'id>(
|
|||
subtree_index,
|
||||
accessible_role,
|
||||
accessible_string_property,
|
||||
window_adapter,
|
||||
drop_in_place,
|
||||
dealloc,
|
||||
};
|
||||
|
@ -1266,17 +1279,17 @@ pub fn instantiate(
|
|||
instance_ref.self_weak().set(self_weak.clone()).ok();
|
||||
let component_type = comp.description();
|
||||
|
||||
let root = root
|
||||
.or_else(|| instance_ref.parent_instance().map(|parent| parent.root_weak().clone()))
|
||||
.unwrap_or_else(|| self_weak.clone());
|
||||
component_type.root_offset.apply(instance_ref.as_ref()).set(root).ok().unwrap();
|
||||
|
||||
if !component_type.original.is_global() {
|
||||
let maybe_window_adapter =
|
||||
if let Some(WindowOptions::UseExistingWindow(adapter)) = window_options.as_ref() {
|
||||
Some(adapter.clone())
|
||||
} else {
|
||||
root.as_ref().and_then(|root| root.upgrade()).and_then(|root| {
|
||||
generativity::make_guard!(guard);
|
||||
let comp = root.unerase(guard);
|
||||
let instance = comp.borrow_instance();
|
||||
instance.maybe_window_adapter()
|
||||
})
|
||||
instance_ref.maybe_window_adapter()
|
||||
};
|
||||
|
||||
let component_rc = vtable::VRc::into_dyn(self_rc.clone());
|
||||
|
@ -1318,11 +1331,6 @@ pub fn instantiate(
|
|||
}
|
||||
}
|
||||
|
||||
let root = root
|
||||
.or_else(|| instance_ref.parent_instance().map(|parent| parent.root_weak().clone()))
|
||||
.unwrap_or_else(|| self_weak.clone());
|
||||
component_type.root_offset.apply(instance_ref.as_ref()).set(root).ok().unwrap();
|
||||
|
||||
match &window_options {
|
||||
Some(WindowOptions::UseExistingWindow(existing_adapter))
|
||||
| Some(WindowOptions::EmbedIntoExistingWindow(existing_adapter)) => {
|
||||
|
@ -1543,12 +1551,8 @@ impl ErasedComponentBox {
|
|||
self.0.borrow()
|
||||
}
|
||||
|
||||
pub fn window_adapter(&self) -> Result<&Rc<dyn WindowAdapter>, PlatformError> {
|
||||
self.0.window_adapter()
|
||||
}
|
||||
|
||||
pub fn maybe_window_adapter(&self) -> Option<Rc<dyn WindowAdapter>> {
|
||||
self.0.borrow_instance().maybe_window_adapter()
|
||||
pub fn window_adapter_ref(&self) -> Result<&Rc<dyn WindowAdapter>, PlatformError> {
|
||||
self.0.window_adapter_ref()
|
||||
}
|
||||
|
||||
pub fn run_setup_code(&self) {
|
||||
|
@ -1776,6 +1780,7 @@ extern "C" fn accessible_role(component: ComponentRefPin, item_index: usize) ->
|
|||
None => AccessibleRole::default(),
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn accessible_string_property(
|
||||
component: ComponentRefPin,
|
||||
item_index: usize,
|
||||
|
@ -1802,6 +1807,20 @@ extern "C" fn accessible_string_property(
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" fn window_adapter(
|
||||
component: ComponentRefPin,
|
||||
do_create: bool,
|
||||
result: &mut Option<Rc<dyn WindowAdapter>>,
|
||||
) {
|
||||
generativity::make_guard!(guard);
|
||||
let instance_ref = unsafe { InstanceRef::from_pin_ref(component, guard) };
|
||||
if do_create {
|
||||
*result = Some(instance_ref.window_adapter());
|
||||
} else {
|
||||
*result = instance_ref.maybe_window_adapter();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn drop_in_place(component: vtable::VRefMut<ComponentVTable>) -> vtable::Layout {
|
||||
let instance_ptr = component.as_ptr() as *mut Instance<'static>;
|
||||
let layout = (*instance_ptr).type_info().layout();
|
||||
|
@ -1860,45 +1879,75 @@ impl<'a, 'id> InstanceRef<'a, 'id> {
|
|||
}
|
||||
|
||||
pub fn window_adapter(&self) -> Rc<dyn WindowAdapter> {
|
||||
let root_weak = vtable::VWeak::into_dyn(self.root_weak().clone());
|
||||
let root = self.root_weak().upgrade().unwrap();
|
||||
generativity::make_guard!(guard);
|
||||
let comp = root.unerase(guard);
|
||||
Self::get_or_init_window_adapter_ref(
|
||||
&comp.component_type,
|
||||
root_weak,
|
||||
true,
|
||||
comp.instance.as_pin_ref().get_ref(),
|
||||
)
|
||||
.unwrap()
|
||||
.clone()
|
||||
}
|
||||
|
||||
// Call this only on root components!
|
||||
pub fn get_or_init_window_adapter_ref<'b, 'id2>(
|
||||
component_type: &'b ComponentDescription<'id2>,
|
||||
root_weak: ComponentWeak,
|
||||
do_create: bool,
|
||||
instance: &'b Instance<'id2>,
|
||||
) -> Result<&'b Rc<dyn WindowAdapter>, PlatformError> {
|
||||
// We are the actual root: Generate and store a window_adapter if necessary
|
||||
component_type.window_adapter_offset.apply(instance).get_or_try_init(|| {
|
||||
let extra_data = component_type.extra_data_offset.apply(instance);
|
||||
let window_adapter = i_slint_backend_selector::with_platform(|_b| {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
return _b.create_window_adapter();
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
i_slint_backend_winit::create_gl_window_with_canvas_id(
|
||||
extra_data.canvas_id.get().map_or("canvas", |s| s.as_str()),
|
||||
)
|
||||
})?;
|
||||
let comp_rc = extra_data.self_weak.get().unwrap().upgrade().unwrap();
|
||||
WindowInner::from_pub(window_adapter.window())
|
||||
.set_component(&vtable::VRc::into_dyn(comp_rc));
|
||||
Ok(window_adapter)
|
||||
let mut parent_node = ItemWeak::default();
|
||||
if let Some(rc) = vtable::VWeak::upgrade(&root_weak) {
|
||||
vtable::VRc::borrow_pin(&rc).as_ref().parent_node(&mut parent_node);
|
||||
}
|
||||
|
||||
if let Some(parent) = parent_node.upgrade() {
|
||||
// We are embedded: Get window adapter from our parent
|
||||
let mut result = None;
|
||||
vtable::VRc::borrow_pin(parent.component())
|
||||
.as_ref()
|
||||
.window_adapter(do_create, &mut result);
|
||||
result.ok_or(PlatformError::NoPlatform)
|
||||
} else if do_create {
|
||||
let window_adapter = // We are the root: Create a window adapter
|
||||
i_slint_backend_selector::with_platform(|_b| {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
return _b.create_window_adapter();
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
i_slint_backend_winit::create_gl_window_with_canvas_id(
|
||||
extra_data.canvas_id.get().map_or("canvas", |s| s.as_str()),
|
||||
)
|
||||
})?;
|
||||
|
||||
let extra_data = component_type.extra_data_offset.apply(instance);
|
||||
let comp_rc = extra_data.self_weak.get().unwrap().upgrade().unwrap();
|
||||
WindowInner::from_pub(window_adapter.window())
|
||||
.set_component(&vtable::VRc::into_dyn(comp_rc));
|
||||
Ok(window_adapter)
|
||||
} else {
|
||||
Err(PlatformError::NoPlatform)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn maybe_window_adapter(&self) -> Option<Rc<dyn WindowAdapter>> {
|
||||
let root_weak = vtable::VWeak::into_dyn(self.root_weak().clone());
|
||||
let root = self.root_weak().upgrade()?;
|
||||
generativity::make_guard!(guard);
|
||||
let comp = root.unerase(guard);
|
||||
let instance = comp.borrow_instance();
|
||||
instance.component_type.window_adapter_offset.apply(instance.as_ref()).get().cloned()
|
||||
Self::get_or_init_window_adapter_ref(
|
||||
&comp.component_type,
|
||||
root_weak,
|
||||
false,
|
||||
comp.instance.as_pin_ref().get_ref(),
|
||||
)
|
||||
.ok()
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub fn access_window<R>(
|
||||
|
|
|
@ -579,7 +579,7 @@ pub unsafe extern "C" fn slint_interpreter_component_instance_window(
|
|||
);
|
||||
core::ptr::write(
|
||||
out as *mut *const Rc<dyn WindowAdapter>,
|
||||
inst.window_adapter().unwrap() as *const _,
|
||||
inst.window_adapter_ref().unwrap() as *const _,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue