Merge branch 'upstream' into return-from-js
This commit is contained in:
commit
bf47f64852
281 files changed
+16169
-19328
No files matched your search
+132
-117
@@ -8,16 +8,20 @@ mod controller;
|
||||
mod desktop_context;
|
||||
mod escape;
|
||||
mod events;
|
||||
#[cfg(any(feature = "hot-reload", debug_assertions))]
|
||||
mod hot_reload;
|
||||
mod protocol;
|
||||
|
||||
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
||||
mod hot_reload;
|
||||
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
|
||||
use desktop_context::UserWindowEvent;
|
||||
pub use desktop_context::{use_eval, use_window, DesktopContext, EvalResult};
|
||||
use futures_channel::mpsc::UnboundedSender;
|
||||
pub use wry;
|
||||
pub use wry::application as tao;
|
||||
|
||||
use crate::events::trigger_from_serialized;
|
||||
pub use cfg::Config;
|
||||
use controller::DesktopController;
|
||||
use dioxus_core::*;
|
||||
@@ -100,107 +104,139 @@ pub fn launch_cfg(root: Component, config_builder: Config) {
|
||||
/// ```
|
||||
pub fn launch_with_props<P: 'static + Send>(root: Component<P>, props: P, mut cfg: Config) {
|
||||
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();
|
||||
|
||||
// We assume that if the icon is None, then the user just didnt set it
|
||||
event_loop.run(move |window_event, event_loop, control_flow| {
|
||||
*control_flow = ControlFlow::Wait;
|
||||
|
||||
match window_event {
|
||||
Event::NewEvents(StartCause::Init) => desktop.start(&mut cfg, event_loop),
|
||||
|
||||
Event::WindowEvent {
|
||||
event, window_id, ..
|
||||
} => match event {
|
||||
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
|
||||
WindowEvent::Destroyed { .. } => desktop.close_window(window_id, control_flow),
|
||||
_ => {}
|
||||
},
|
||||
|
||||
Event::UserEvent(user_event) => desktop.handle_event(user_event, control_flow),
|
||||
Event::MainEventsCleared => {}
|
||||
Event::Resumed => {}
|
||||
Event::Suspended => {}
|
||||
Event::LoopDestroyed => {}
|
||||
Event::RedrawRequested(_id) => {}
|
||||
_ => {}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
impl DesktopController {
|
||||
fn start(
|
||||
&mut self,
|
||||
cfg: &mut Config,
|
||||
event_loop: &tao::event_loop::EventLoopWindowTarget<UserWindowEvent>,
|
||||
) {
|
||||
let webview = build_webview(
|
||||
cfg,
|
||||
event_loop,
|
||||
self.is_ready.clone(),
|
||||
self.proxy.clone(),
|
||||
self.eval_sender.clone(),
|
||||
self.event_tx.clone(),
|
||||
);
|
||||
|
||||
self.webviews.insert(webview.window().id(), webview);
|
||||
}
|
||||
}
|
||||
|
||||
fn build_webview(
|
||||
cfg: &mut Config,
|
||||
event_loop: &tao::event_loop::EventLoopWindowTarget<UserWindowEvent>,
|
||||
is_ready: Arc<AtomicBool>,
|
||||
proxy: tao::event_loop::EventLoopProxy<UserWindowEvent>,
|
||||
eval_sender: tokio::sync::mpsc::UnboundedSender<serde_json::Value>,
|
||||
event_tx: UnboundedSender<serde_json::Value>,
|
||||
) -> wry::webview::WebView {
|
||||
let builder = cfg.window.clone();
|
||||
let window = builder.build(event_loop).unwrap();
|
||||
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();
|
||||
|
||||
// We assume that if the icon is None in cfg, then the user just didnt set it
|
||||
if cfg.window.window.window_icon.is_none() {
|
||||
cfg.window.window.window_icon = Some(
|
||||
window.set_window_icon(Some(
|
||||
tao::window::Icon::from_rgba(
|
||||
include_bytes!("./assets/default_icon.bin").to_vec(),
|
||||
460,
|
||||
460,
|
||||
)
|
||||
.expect("image parse failed"),
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
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, eval_sender) = (
|
||||
desktop.is_ready.clone(),
|
||||
desktop.sender.clone(),
|
||||
desktop.eval_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() {
|
||||
"eval_result" => {
|
||||
let result = message.params();
|
||||
eval_sender.send(result).unwrap();
|
||||
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() {
|
||||
"eval_result" => {
|
||||
let result = message.params();
|
||||
eval_sender.send(result).unwrap();
|
||||
}
|
||||
"user_event" => {
|
||||
_ = event_tx.unbounded_send(message.params());
|
||||
}
|
||||
"initialize" => {
|
||||
is_ready.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
let _ = proxy.send_event(UserWindowEvent::EditsReady);
|
||||
}
|
||||
"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);
|
||||
}
|
||||
"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()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
})
|
||||
.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)
|
||||
}
|
||||
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 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();
|
||||
@@ -211,32 +247,11 @@ pub fn launch_with_props<P: 'static + Send>(root: Component<P>, props: P, mut cf
|
||||
});
|
||||
}
|
||||
"#,
|
||||
)
|
||||
} else {
|
||||
// in debug, we are okay with the reload menu showing and dev tool
|
||||
webview = webview.with_devtools(true);
|
||||
}
|
||||
)
|
||||
} 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),
|
||||
_ => {}
|
||||
},
|
||||
|
||||
Event::UserEvent(user_event) => {
|
||||
desktop_context::handler(user_event, &mut desktop, control_flow)
|
||||
}
|
||||
Event::MainEventsCleared => {}
|
||||
Event::Resumed => {}
|
||||
Event::Suspended => {}
|
||||
Event::LoopDestroyed => {}
|
||||
Event::RedrawRequested(_id) => {}
|
||||
_ => {}
|
||||
}
|
||||
})
|
||||
webview.build().unwrap()
|
||||
}
|
||||
Reference in new issue
Block a user