Files
dioxus/packages/desktop/src/launch.rs
T
1e8693a0e8 wgpu windows (fixed) (#3257)
* Working triangle rendering with wgpu in examples. Resize needs work in order to not reinitialize everything but only the bits needed. Naming of variables and resources are wonky and not the greatest.

* The child window wasn't being resized along with the parent. This works. the abstractions in place should be passed the bounds rect down into the desktopservice to resize as opposed to in the app impl instead of how they are rn.

---------

Co-authored-by: Vineeth Yeevani <vineethyeevani@Vineeths-MacBook-Air.local>
Co-authored-by: Vineeth Yeevani <vineeth.yeevani@gmail.com>
2024-11-26 18:44:53 +01:00

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(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)
}