, props: P, builder: impl FnOnce(&mut DesktopConfig) -> &mut DesktopConfig, ) { let mut cfg = DesktopConfig::default().with_default_icon(); builder(&mut cfg); let event_loop = EventLoop::with_user_event(); let mut desktop = DesktopController::new_on_tokio(root, props, event_loop.create_proxy()); let proxy = event_loop.create_proxy(); event_loop.run(move |window_event, event_loop, control_flow| { *control_flow = ControlFlow::Wait; match window_event { Event::NewEvents(StartCause::Init) => { let builder = cfg.window.clone(); let window = builder.build(event_loop).unwrap(); let window_id = window.id(); let (is_ready, sender) = (desktop.is_ready.clone(), desktop.sender.clone()); let proxy = proxy.clone(); let file_handler = cfg.file_drop_handler.take(); let custom_head = cfg.custom_head.clone(); let resource_dir = cfg.resource_dir.clone(); let index_file = cfg.custom_index.clone(); let mut webview = WebViewBuilder::new(window) .unwrap() .with_transparent(cfg.window.window.transparent) .with_url("dioxus://index.html/") .unwrap() .with_ipc_handler(move |_window: &Window, payload: String| { parse_ipc_message(&payload) .map(|message| match message.method() { "user_event" => { let event = trigger_from_serialized(message.params()); log::trace!("User event: {:?}", event); sender.unbounded_send(SchedulerMsg::Event(event)).unwrap(); } "initialize" => { is_ready.store(true, std::sync::atomic::Ordering::Relaxed); let _ = proxy.send_event(UserWindowEvent::Update); } "browser_open" => { let data = message.params(); log::trace!("Open browser: {:?}", data); if let Some(temp) = data.as_object() { if temp.contains_key("href") { let url = temp.get("href").unwrap().as_str().unwrap(); if let Err(e) = webbrowser::open(url) { log::error!("Open Browser error: {:?}", e); } } } } _ => (), }) .unwrap_or_else(|| { log::warn!("invalid IPC message received"); }); }) .with_custom_protocol(String::from("dioxus"), move |r| { protocol::desktop_handler( r, resource_dir.clone(), custom_head.clone(), index_file.clone(), ) }) .with_file_drop_handler(move |window, evet| { file_handler .as_ref() .map(|handler| handler(window, evet)) .unwrap_or_default() }); for (name, handler) in cfg.protocols.drain(..) { webview = webview.with_custom_protocol(name, handler) } if cfg.disable_context_menu { // in release mode, we don't want to show the dev tool or reload menus webview = webview.with_initialization_script( r#" if (document.addEventListener) { document.addEventListener('contextmenu', function(e) { e.preventDefault(); }, false); } else { document.attachEvent('oncontextmenu', function() { window.event.returnValue = false; }); } "#, ) } else { // in debug, we are okay with the reload menu showing and dev tool webview = webview.with_devtools(true); } desktop.webviews.insert(window_id, webview.build().unwrap()); } Event::WindowEvent { event, window_id, .. } => match event { WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, WindowEvent::Destroyed { .. } => desktop.close_window(window_id, control_flow), WindowEvent::Resized(_) | WindowEvent::Moved(_) => { if let Some(view) = desktop.webviews.get_mut(&window_id) { let _ = view.resize(); } } _ => {} }, Event::UserEvent(user_event) => { desktop_context::handler(user_event, &mut desktop, control_flow) } Event::MainEventsCleared => {} Event::Resumed => {} Event::Suspended => {} Event::LoopDestroyed => {} Event::RedrawRequested(_id) => {} _ => {} } }) }