1#![cfg_attr(docsrs, feature(doc_cfg))]
2
3mod assets;
13mod config;
14mod contexts;
15mod dioxus_application;
16mod dioxus_renderer;
17mod event_handlers;
18mod hooks;
19mod link_handler;
20
21#[cfg(feature = "prelude")]
22pub mod prelude;
23
24#[cfg(all(feature = "net", not(target_arch = "wasm32")))]
25use blitz_traits::net::NetProvider;
26#[doc(inline)]
27pub use dioxus_native_dom::*;
28
29use assets::DioxusNativeNetProvider;
30pub use dioxus_application::{DioxusNativeApplication, DioxusNativeEvent};
31pub use dioxus_renderer::DioxusNativeWindowRenderer;
32
33#[cfg(target_os = "android")]
34#[cfg_attr(docsrs, doc(cfg(target_os = "android")))]
35pub fn set_android_app(app: android_activity::AndroidApp) {
37 blitz_shell::set_android_app(app);
38}
39
40#[cfg(target_os = "android")]
41#[cfg_attr(docsrs, doc(cfg(target_os = "android")))]
42pub fn current_android_app() -> android_activity::AndroidApp {
45 blitz_shell::current_android_app()
46}
47
48#[cfg(target_os = "android")]
49#[cfg_attr(docsrs, doc(cfg(target_os = "android")))]
50pub use android_activity::AndroidApp;
51
52#[cfg(any(feature = "vello", feature = "vello-hybrid"))]
53pub use {
54 dioxus_renderer::{Features, Limits},
55 wgpu_context::DeviceHandle,
56};
57
58pub use blitz_dom::{FontContext, Widget, build_single_font_ctx};
59pub use config::Config;
60pub use event_handlers::WinitEventHandlerId;
61pub use hooks::{use_back_button, use_window_event};
62pub use winit;
63pub use winit::dpi::{LogicalSize, PhysicalSize};
64pub use winit::window::WindowAttributes;
65
66use blitz_shell::{BlitzShellEvent, BlitzShellProxy, WindowConfig, create_default_event_loop};
67use dioxus_core::{ComponentFunction, Element, VirtualDom, consume_context, use_hook};
68use link_handler::DioxusNativeNavigationProvider;
69use std::any::Any;
70use std::sync::Arc;
71use winit::{
72 raw_window_handle::{HasWindowHandle as _, RawWindowHandle},
73 window::Window,
74};
75
76pub fn use_window() -> Arc<dyn Window> {
77 use_hook(consume_context::<Arc<dyn Window>>)
78}
79
80pub fn use_raw_window_handle() -> RawWindowHandle {
81 use_hook(|| {
82 consume_context::<Arc<dyn Window>>()
83 .window_handle()
84 .unwrap()
85 .as_raw()
86 })
87}
88
89pub fn launch(app: fn() -> Element) {
91 launch_cfg(app, vec![], vec![])
92}
93
94pub fn launch_cfg(
95 app: fn() -> Element,
96 contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
97 cfg: Vec<Box<dyn Any>>,
98) {
99 launch_cfg_with_props(app, (), contexts, cfg)
100}
101
102pub fn launch_cfg_with_props<P: Clone + 'static, M: 'static>(
104 app: impl ComponentFunction<P, M>,
105 props: P,
106 contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
107 configs: Vec<Box<dyn Any>>,
108) {
109 macro_rules! try_read_config {
111 ($input:ident, $store:ident, $kind:ty) => {
112 match $input.downcast::<$kind>() {
114 Ok(value) => {
116 $store = Some(*value);
117 continue;
118 }
119 Err(cfg) => cfg,
122 }
123 };
124 }
125
126 #[cfg(any(feature = "vello", feature = "vello-hybrid"))]
128 let (mut features, mut limits) = (None, None);
129 let mut window_attributes = None;
130 let mut config = None;
131 for mut cfg in configs {
132 #[cfg(any(feature = "vello", feature = "vello-hybrid"))]
133 {
134 cfg = try_read_config!(cfg, features, Features);
135 cfg = try_read_config!(cfg, limits, Limits);
136 }
137 cfg = try_read_config!(cfg, window_attributes, WindowAttributes);
138 cfg = try_read_config!(cfg, config, Config);
139 let _ = cfg;
140 }
141
142 let mut config = config.unwrap_or_default();
143 if let Some(window_attributes) = window_attributes {
144 config.window_attributes = window_attributes;
145 }
146 let event_loop = create_default_event_loop();
147 let winit_proxy = event_loop.create_proxy();
148 let (proxy, event_queue) = BlitzShellProxy::new(winit_proxy);
149
150 #[cfg(feature = "net")]
152 #[cfg(not(target_arch = "wasm32"))]
153 let rt = tokio::runtime::Builder::new_multi_thread()
154 .enable_all()
155 .build()
156 .unwrap();
157 #[cfg(feature = "net")]
158 #[cfg(not(target_arch = "wasm32"))]
159 let _guard = rt.enter();
160
161 #[cfg(all(feature = "hot-reload", debug_assertions))]
163 #[cfg(not(target_arch = "wasm32"))]
164 {
165 let proxy = proxy.clone();
166 dioxus_devtools::connect(move |event| {
167 let dxn_event = DioxusNativeEvent::DevserverEvent(event);
168 proxy.send_event(BlitzShellEvent::embedder_event(dxn_event));
169 })
170 }
171
172 let mut vdom = VirtualDom::new_with_props(app, props);
175
176 for context in contexts {
177 vdom.insert_any_root_context(context());
178 }
179
180 #[cfg(all(feature = "net", not(target_arch = "wasm32")))]
181 let net_provider = {
182 let net_waker = Some(Arc::new(proxy.clone()) as _);
183 let inner_net_provider = Arc::new(blitz_net::Provider::new(net_waker));
184 vdom.provide_root_context(Arc::clone(&inner_net_provider));
185
186 Arc::new(DioxusNativeNetProvider::with_inner(
187 proxy.clone(),
188 inner_net_provider as _,
189 )) as Arc<dyn NetProvider>
190 };
191
192 #[cfg(any(not(feature = "net"), target_arch = "wasm32"))]
193 let net_provider = DioxusNativeNetProvider::shared(proxy.clone());
194
195 vdom.provide_root_context(Arc::clone(&net_provider));
196
197 #[cfg(feature = "html")]
198 let html_parser_provider = {
199 let html_parser = Arc::new(blitz_html::HtmlProvider) as _;
200 vdom.provide_root_context(Arc::clone(&html_parser));
201 Some(html_parser)
202 };
203 #[cfg(not(feature = "html"))]
204 let html_parser_provider = None;
205
206 let navigation_provider = Some(Arc::new(DioxusNativeNavigationProvider) as _);
207
208 let doc = DioxusDocument::new(
210 vdom,
211 DocumentConfig {
212 net_provider: Some(net_provider),
213 html_parser_provider,
214 navigation_provider,
215 font_ctx: config.font_ctx,
216 ..Default::default()
217 },
218 );
219 #[cfg(any(feature = "vello", feature = "vello-hybrid"))]
220 let renderer = DioxusNativeWindowRenderer::with_features_and_limits(features, limits);
221 #[cfg(not(any(feature = "vello", feature = "vello-hybrid")))]
222 let renderer = DioxusNativeWindowRenderer::new();
223 let config = WindowConfig::with_attributes(
224 Box::new(doc) as _,
225 renderer.clone(),
226 config.window_attributes,
227 );
228
229 let application = DioxusNativeApplication::new(proxy, event_queue, config);
231
232 event_loop.run_app(application).unwrap();
234}