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