mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-23 08:42:20 +00:00
Clean up wasm-interpreter / winit interface
Use the window attributes hook instead of a private function in the winit backend.
This commit is contained in:
parent
ca0c75bfe1
commit
4e65998016
5 changed files with 62 additions and 46 deletions
|
@ -24,6 +24,8 @@ slint-interpreter = { workspace = true, features = [
|
||||||
"compat-1-2",
|
"compat-1-2",
|
||||||
"internal",
|
"internal",
|
||||||
] }
|
] }
|
||||||
|
i-slint-backend-winit = { workspace = true }
|
||||||
|
i-slint-core = { workspace = true }
|
||||||
send_wrapper = { workspace = true }
|
send_wrapper = { workspace = true }
|
||||||
|
|
||||||
vtable = { workspace = true }
|
vtable = { workspace = true }
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
//! This wasm library can be loaded from JS to load and display the content of .slint files
|
//! This wasm library can be loaded from JS to load and display the content of .slint files
|
||||||
#![cfg(target_arch = "wasm32")]
|
#![cfg(target_arch = "wasm32")]
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::rc::Rc;
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
use slint_interpreter::ComponentHandle;
|
use slint_interpreter::ComponentHandle;
|
||||||
|
@ -155,7 +157,10 @@ impl WrappedCompiledComp {
|
||||||
/// where the result is gonna be rendered
|
/// where the result is gonna be rendered
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn run(&self, canvas_id: String) {
|
pub fn run(&self, canvas_id: String) {
|
||||||
let component = self.0.create_with_canvas_id(&canvas_id).unwrap();
|
NEXT_CANVAS_ID.with(|next_id| {
|
||||||
|
*next_id.borrow_mut() = Some(canvas_id);
|
||||||
|
});
|
||||||
|
let component = self.0.create().unwrap();
|
||||||
component.show().unwrap();
|
component.show().unwrap();
|
||||||
slint_interpreter::spawn_event_loop().unwrap();
|
slint_interpreter::spawn_event_loop().unwrap();
|
||||||
}
|
}
|
||||||
|
@ -172,8 +177,11 @@ impl WrappedCompiledComp {
|
||||||
let canvas_id = canvas_id.clone();
|
let canvas_id = canvas_id.clone();
|
||||||
let resolve = send_wrapper::SendWrapper::new(resolve);
|
let resolve = send_wrapper::SendWrapper::new(resolve);
|
||||||
if let Err(e) = slint_interpreter::invoke_from_event_loop(move || {
|
if let Err(e) = slint_interpreter::invoke_from_event_loop(move || {
|
||||||
|
NEXT_CANVAS_ID.with(|next_id| {
|
||||||
|
*next_id.borrow_mut() = Some(canvas_id);
|
||||||
|
});
|
||||||
let instance =
|
let instance =
|
||||||
WrappedInstance(comp.take().create_with_canvas_id(&canvas_id).unwrap());
|
WrappedInstance(comp.take().create().unwrap());
|
||||||
resolve.take().call1(&JsValue::UNDEFINED, &JsValue::from(instance)).unwrap_throw();
|
resolve.take().call1(&JsValue::UNDEFINED, &JsValue::from(instance)).unwrap_throw();
|
||||||
}) {
|
}) {
|
||||||
reject
|
reject
|
||||||
|
@ -314,3 +322,53 @@ pub fn run_event_loop() -> Result<(), JsValue> {
|
||||||
slint_interpreter::spawn_event_loop().map_err(|e| -> JsValue { format!("{e}").into() })?;
|
slint_interpreter::spawn_event_loop().map_err(|e| -> JsValue { format!("{e}").into() })?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
thread_local!(
|
||||||
|
static NEXT_CANVAS_ID: Rc<RefCell<Option<String>>> = Default::default();
|
||||||
|
);
|
||||||
|
|
||||||
|
#[wasm_bindgen(start)]
|
||||||
|
pub fn init() -> Result<(), JsValue> {
|
||||||
|
let backend = i_slint_backend_winit::Backend::builder()
|
||||||
|
.with_window_attributes_hook(|mut attrs| {
|
||||||
|
NEXT_CANVAS_ID.with(|next_id| {
|
||||||
|
if let Some(canvas_id) = next_id.borrow_mut().take() {
|
||||||
|
use i_slint_backend_winit::winit::platform::web::WindowAttributesExtWebSys;
|
||||||
|
|
||||||
|
use wasm_bindgen::JsCast;
|
||||||
|
|
||||||
|
let html_canvas = web_sys::window()
|
||||||
|
.expect("wasm-interpreter: Could not retrieve DOM window")
|
||||||
|
.document()
|
||||||
|
.expect("wasm-interpreter: Could not retrieve DOM document")
|
||||||
|
.get_element_by_id(&canvas_id)
|
||||||
|
.expect( {
|
||||||
|
&format!(
|
||||||
|
"wasm-interpreter: Could not retrieve existing HTML Canvas element '{}'",
|
||||||
|
canvas_id
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.dyn_into::<web_sys::HtmlCanvasElement>()
|
||||||
|
.expect(
|
||||||
|
&format!(
|
||||||
|
"winit backend: Specified DOM element '{}' is not a HTML Canvas",
|
||||||
|
canvas_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
attrs = attrs
|
||||||
|
.with_canvas(Some(html_canvas))
|
||||||
|
// Don't activate the window by default, as that will cause the page to scroll,
|
||||||
|
// ignoring any existing anchors.
|
||||||
|
.with_active(false);
|
||||||
|
attrs
|
||||||
|
} else {
|
||||||
|
attrs
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
i_slint_core::platform::set_platform(Box::new(backend))
|
||||||
|
.map_err(|e| -> JsValue { format!("{e}").into() })?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
@ -85,20 +85,6 @@ mod xdg_color_scheme;
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
pub(crate) mod wasm_input_helper;
|
pub(crate) mod wasm_input_helper;
|
||||||
|
|
||||||
/// Create an open GL renderer for the HTML canvas element with the given `canvas_id`
|
|
||||||
#[cfg(all(target_arch = "wasm32", feature = "renderer-femtovg"))]
|
|
||||||
pub fn create_gl_window_with_canvas_id(
|
|
||||||
canvas_id: &str,
|
|
||||||
) -> Result<Rc<dyn WindowAdapter>, PlatformError> {
|
|
||||||
let attrs = WinitWindowAdapter::window_attributes(canvas_id)?;
|
|
||||||
let adapter = WinitWindowAdapter::new(
|
|
||||||
renderer::femtovg::GlutinFemtoVGRenderer::new_suspended(),
|
|
||||||
attrs,
|
|
||||||
None,
|
|
||||||
)?;
|
|
||||||
Ok(adapter)
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(feature = "renderer-femtovg")] {
|
if #[cfg(feature = "renderer-femtovg")] {
|
||||||
const DEFAULT_RENDERER_NAME: &str = "FemtoVG";
|
const DEFAULT_RENDERER_NAME: &str = "FemtoVG";
|
||||||
|
|
|
@ -983,22 +983,6 @@ impl ComponentDefinition {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Instantiate the component for wasm using the given canvas id
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
pub fn create_with_canvas_id(
|
|
||||||
&self,
|
|
||||||
canvas_id: &str,
|
|
||||||
) -> Result<ComponentInstance, PlatformError> {
|
|
||||||
generativity::make_guard!(guard);
|
|
||||||
Ok(ComponentInstance {
|
|
||||||
inner: self
|
|
||||||
.inner
|
|
||||||
.unerase(guard)
|
|
||||||
.clone()
|
|
||||||
.create(WindowOptions::CreateWithCanvasId(canvas_id.into()))?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Instantiate the component using an existing window.
|
/// Instantiate the component using an existing window.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[cfg(feature = "internal")]
|
#[cfg(feature = "internal")]
|
||||||
|
|
|
@ -289,8 +289,6 @@ pub(crate) struct ComponentExtraData {
|
||||||
pub(crate) globals: OnceCell<crate::global_component::GlobalStorage>,
|
pub(crate) globals: OnceCell<crate::global_component::GlobalStorage>,
|
||||||
pub(crate) self_weak: OnceCell<ErasedItemTreeBoxWeak>,
|
pub(crate) self_weak: OnceCell<ErasedItemTreeBoxWeak>,
|
||||||
pub(crate) embedding_position: OnceCell<(ItemTreeWeak, u32)>,
|
pub(crate) embedding_position: OnceCell<(ItemTreeWeak, u32)>,
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
pub(crate) canvas_id: OnceCell<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ErasedRepeaterWithinComponent<'id>(RepeaterWithinItemTree<'id, 'static>);
|
struct ErasedRepeaterWithinComponent<'id>(RepeaterWithinItemTree<'id, 'static>);
|
||||||
|
@ -460,8 +458,6 @@ pub enum WindowOptions {
|
||||||
#[default]
|
#[default]
|
||||||
CreateNewWindow,
|
CreateNewWindow,
|
||||||
UseExistingWindow(WindowAdapterRc),
|
UseExistingWindow(WindowAdapterRc),
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
CreateWithCanvasId(String),
|
|
||||||
Embed {
|
Embed {
|
||||||
parent_item_tree: ItemTreeWeak,
|
parent_item_tree: ItemTreeWeak,
|
||||||
parent_item_tree_index: u32,
|
parent_item_tree_index: u32,
|
||||||
|
@ -1513,11 +1509,6 @@ pub fn instantiate(
|
||||||
}
|
}
|
||||||
let extra_data = description.extra_data_offset.apply(instance_ref.as_ref());
|
let extra_data = description.extra_data_offset.apply(instance_ref.as_ref());
|
||||||
extra_data.globals.set(globals).ok().unwrap();
|
extra_data.globals.set(globals).ok().unwrap();
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
if let Some(WindowOptions::CreateWithCanvasId(canvas_id)) = window_options {
|
|
||||||
extra_data.canvas_id.set(canvas_id.clone()).unwrap();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(WindowOptions::Embed { parent_item_tree, parent_item_tree_index }) = window_options
|
if let Some(WindowOptions::Embed { parent_item_tree, parent_item_tree_index }) = window_options
|
||||||
|
@ -2301,12 +2292,7 @@ impl<'a, 'id> InstanceRef<'a, 'id> {
|
||||||
let extra_data = description.extra_data_offset.apply(instance);
|
let extra_data = description.extra_data_offset.apply(instance);
|
||||||
let window_adapter = // We are the root: Create a window adapter
|
let window_adapter = // We are the root: Create a window adapter
|
||||||
i_slint_backend_selector::with_platform(|_b| {
|
i_slint_backend_selector::with_platform(|_b| {
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
return _b.create_window_adapter();
|
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();
|
let comp_rc = extra_data.self_weak.get().unwrap().upgrade().unwrap();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue