1use crate::Config;
2use crate::{
3 app::App,
4 ipc::{IpcMethod, UserWindowEvent},
5};
6use dioxus_core::*;
7use dioxus_document::eval;
8use std::any::Any;
9use tao::event::{Event, StartCause, WindowEvent};
10
11pub fn launch_virtual_dom_blocking(virtual_dom: VirtualDom, mut desktop_config: Config) -> ! {
16 let mut custom_event_handler = desktop_config.custom_event_handler.take();
17 let (event_loop, mut app) = App::new(desktop_config, virtual_dom);
18
19 event_loop.run(move |window_event, event_loop, control_flow| {
20 app.tick(&window_event);
22
23 if let Some(ref mut f) = custom_event_handler {
24 f(&window_event, event_loop)
25 }
26
27 match window_event {
28 Event::NewEvents(StartCause::Init) => app.handle_start_cause_init(),
29 Event::LoopDestroyed => app.handle_loop_destroyed(),
30 Event::WindowEvent {
31 event, window_id, ..
32 } => match event {
33 WindowEvent::CloseRequested => app.handle_close_requested(window_id),
34 WindowEvent::Destroyed { .. } => app.window_destroyed(window_id),
35 WindowEvent::Resized(new_size) => app.resize_window(window_id, new_size),
36 _ => {}
37 },
38
39 Event::UserEvent(event) => match event {
40 UserWindowEvent::Poll(id) => app.poll_vdom(id),
41 UserWindowEvent::NewWindow => app.handle_new_window(),
42 UserWindowEvent::CloseWindow(id) => app.handle_close_requested(id),
43 UserWindowEvent::Shutdown => app.control_flow = tao::event_loop::ControlFlow::Exit,
44
45 #[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
46 UserWindowEvent::GlobalHotKeyEvent(evnt) => app.handle_global_hotkey(evnt),
47
48 #[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
49 UserWindowEvent::MudaMenuEvent(evnt) => app.handle_menu_event(evnt),
50
51 #[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
52 UserWindowEvent::TrayMenuEvent(evnt) => app.handle_tray_menu_event(evnt),
53
54 #[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
55 UserWindowEvent::TrayIconEvent(evnt) => app.handle_tray_icon_event(evnt),
56
57 #[cfg(all(feature = "devtools", debug_assertions))]
58 UserWindowEvent::HotReloadEvent(msg) => app.handle_hot_reload_msg(msg),
59
60 UserWindowEvent::WindowsDragDrop(id) => {
62 if let Some(webview) = app.webviews.get(&id) {
63 webview.dom.in_scope(ScopeId::ROOT, || {
64 eval("window.interpreter.handleWindowsDragDrop();");
65 });
66 }
67 }
68 UserWindowEvent::WindowsDragLeave(id) => {
69 if let Some(webview) = app.webviews.get(&id) {
70 webview.dom.in_scope(ScopeId::ROOT, || {
71 eval("window.interpreter.handleWindowsDragLeave();");
72 });
73 }
74 }
75 UserWindowEvent::WindowsDragOver(id, x_pos, y_pos) => {
76 if let Some(webview) = app.webviews.get(&id) {
77 webview.dom.in_scope(ScopeId::ROOT, || {
78 let e = eval(
79 r#"
80 const xPos = await dioxus.recv();
81 const yPos = await dioxus.recv();
82 window.interpreter.handleWindowsDragOver(xPos, yPos)
83 "#,
84 );
85
86 _ = e.send(x_pos);
87 _ = e.send(y_pos);
88 });
89 }
90 }
91
92 UserWindowEvent::Ipc { id, msg } => match msg.method() {
93 IpcMethod::Initialize => app.handle_initialize_msg(id),
94 IpcMethod::UserEvent => {}
95 IpcMethod::Query => app.handle_query_msg(msg, id),
96 IpcMethod::BrowserOpen => app.handle_browser_open(msg),
97 IpcMethod::Other(_) => {}
98 },
99 },
100 _ => {}
101 }
102
103 *control_flow = app.control_flow;
104 })
105}
106
107pub fn launch_virtual_dom(virtual_dom: VirtualDom, desktop_config: Config) -> ! {
109 #[cfg(feature = "tokio_runtime")]
110 {
111 if let std::result::Result::Ok(handle) = tokio::runtime::Handle::try_current() {
112 assert_ne!(
113 handle.runtime_flavor(),
114 tokio::runtime::RuntimeFlavor::CurrentThread,
115 "The tokio current-thread runtime does not work with dioxus event handling"
116 );
117 launch_virtual_dom_blocking(virtual_dom, desktop_config);
118 } else {
119 tokio::runtime::Builder::new_multi_thread()
120 .enable_all()
121 .build()
122 .unwrap()
123 .block_on(tokio::task::unconstrained(async move {
124 launch_virtual_dom_blocking(virtual_dom, desktop_config)
125 }));
126
127 unreachable!("The desktop launch function will never exit")
128 }
129 }
130
131 #[cfg(not(feature = "tokio_runtime"))]
132 {
133 launch_virtual_dom_blocking(virtual_dom, desktop_config);
134 }
135}
136
137pub fn launch(
139 root: fn() -> Element,
140 contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
141 platform_config: Vec<Box<dyn Any>>,
142) -> ! {
143 let mut virtual_dom = VirtualDom::new(root);
144
145 for context in contexts {
146 virtual_dom.insert_any_root_context(context());
147 }
148
149 let platform_config = *platform_config
150 .into_iter()
151 .find_map(|cfg| cfg.downcast::<Config>().ok())
152 .unwrap_or_default();
153
154 launch_virtual_dom(virtual_dom, platform_config)
155}