123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- use crate::Config;
- use crate::{
- app::App,
- ipc::{IpcMethod, UserWindowEvent},
- };
- use dioxus_core::*;
- use dioxus_document::eval;
- use std::any::Any;
- use tao::event::{Event, StartCause, WindowEvent};
- /// Launch the WebView and run the event loop, with configuration and root props.
- ///
- /// This will block the main thread, and *must* be spawned on the main thread. This function does not assume any runtime
- /// and is equivalent to calling launch_with_props with the tokio feature disabled.
- pub fn launch_virtual_dom_blocking(virtual_dom: VirtualDom, mut desktop_config: Config) -> ! {
- let mut custom_event_handler = desktop_config.custom_event_handler.take();
- let (event_loop, mut app) = App::new(desktop_config, virtual_dom);
- event_loop.run(move |window_event, event_loop, control_flow| {
- // Set the control flow and check if any events need to be handled in the app itself
- app.tick(&window_event);
- if let Some(ref mut f) = custom_event_handler {
- f(&window_event, event_loop)
- }
- match window_event {
- Event::NewEvents(StartCause::Init) => app.handle_start_cause_init(),
- Event::LoopDestroyed => app.handle_loop_destroyed(),
- Event::WindowEvent {
- event, window_id, ..
- } => match event {
- WindowEvent::CloseRequested => app.handle_close_requested(window_id),
- WindowEvent::Destroyed { .. } => app.window_destroyed(window_id),
- WindowEvent::Resized(new_size) => app.resize_window(window_id, new_size),
- _ => {}
- },
- Event::UserEvent(event) => match event {
- UserWindowEvent::Poll(id) => app.poll_vdom(id),
- UserWindowEvent::NewWindow => app.handle_new_window(),
- UserWindowEvent::CloseWindow(id) => app.handle_close_msg(id),
- UserWindowEvent::Shutdown => app.control_flow = tao::event_loop::ControlFlow::Exit,
- #[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
- UserWindowEvent::GlobalHotKeyEvent(evnt) => app.handle_global_hotkey(evnt),
- #[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
- UserWindowEvent::MudaMenuEvent(evnt) => app.handle_menu_event(evnt),
- #[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
- UserWindowEvent::TrayMenuEvent(evnt) => app.handle_tray_menu_event(evnt),
- #[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
- UserWindowEvent::TrayIconEvent(evnt) => app.handle_tray_icon_event(evnt),
- #[cfg(all(feature = "devtools", debug_assertions))]
- UserWindowEvent::HotReloadEvent(msg) => app.handle_hot_reload_msg(msg),
- // Windows-only drag-n-drop fix events. We need to call the interpreter drag-n-drop code.
- UserWindowEvent::WindowsDragDrop(id) => {
- if let Some(webview) = app.webviews.get(&id) {
- webview.dom.in_runtime(|| {
- ScopeId::ROOT.in_runtime(|| {
- eval("window.interpreter.handleWindowsDragDrop();");
- });
- });
- }
- }
- UserWindowEvent::WindowsDragLeave(id) => {
- if let Some(webview) = app.webviews.get(&id) {
- webview.dom.in_runtime(|| {
- ScopeId::ROOT.in_runtime(|| {
- eval("window.interpreter.handleWindowsDragLeave();");
- });
- });
- }
- }
- UserWindowEvent::WindowsDragOver(id, x_pos, y_pos) => {
- if let Some(webview) = app.webviews.get(&id) {
- webview.dom.in_runtime(|| {
- ScopeId::ROOT.in_runtime(|| {
- let e = eval(
- r#"
- const xPos = await dioxus.recv();
- const yPos = await dioxus.recv();
- window.interpreter.handleWindowsDragOver(xPos, yPos)
- "#,
- );
- _ = e.send(x_pos);
- _ = e.send(y_pos);
- });
- });
- }
- }
- UserWindowEvent::Ipc { id, msg } => match msg.method() {
- IpcMethod::Initialize => app.handle_initialize_msg(id),
- IpcMethod::FileDialog => app.handle_file_dialog_msg(msg, id),
- IpcMethod::UserEvent => {}
- IpcMethod::Query => app.handle_query_msg(msg, id),
- IpcMethod::BrowserOpen => app.handle_browser_open(msg),
- IpcMethod::Other(_) => {}
- },
- },
- _ => {}
- }
- *control_flow = app.control_flow;
- })
- }
- /// Launches the WebView and runs the event loop, with configuration and root props.
- pub fn launch_virtual_dom(virtual_dom: VirtualDom, desktop_config: Config) -> ! {
- #[cfg(feature = "tokio_runtime")]
- {
- tokio::runtime::Builder::new_multi_thread()
- .enable_all()
- .build()
- .unwrap()
- .block_on(tokio::task::unconstrained(async move {
- launch_virtual_dom_blocking(virtual_dom, desktop_config)
- }));
- unreachable!("The desktop launch function will never exit")
- }
- #[cfg(not(feature = "tokio_runtime"))]
- {
- launch_virtual_dom_blocking(virtual_dom, desktop_config);
- }
- }
- /// Launches the WebView and runs the event loop, with configuration and root props.
- pub fn launch(
- root: fn() -> Element,
- contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
- platform_config: Vec<Box<dyn Any>>,
- ) -> ! {
- let mut virtual_dom = VirtualDom::new(root);
- for context in contexts {
- virtual_dom.insert_any_root_context(context());
- }
- let platform_config = *platform_config
- .into_iter()
- .find_map(|cfg| cfg.downcast::<Config>().ok())
- .unwrap_or_default();
- launch_virtual_dom(virtual_dom, platform_config)
- }
|