154 lines
6.4 KiB
Rust
154 lines
6.4 KiB
Rust
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)
|
|
}
|