wip: move desktop to main thread and use tokio main
This commit is contained in:
1 parent
6a4979b574
commit
ff697d41e3
4 files changed
+218
-141
No files matched your search
+3
-2
@@ -4,8 +4,9 @@
|
|||||||
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
#[tokio::main]
|
||||||
dioxus_desktop::launch(app);
|
async fn main() {
|
||||||
|
dioxus_desktop::launch(app).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
|
|||||||
+106
-106
@@ -21,7 +21,7 @@ use wry::{
|
|||||||
pub(super) struct DesktopController {
|
pub(super) struct DesktopController {
|
||||||
pub(super) webviews: HashMap<WindowId, WebView>,
|
pub(super) webviews: HashMap<WindowId, WebView>,
|
||||||
pub(super) eval_sender: tokio::sync::mpsc::UnboundedSender<Value>,
|
pub(super) eval_sender: tokio::sync::mpsc::UnboundedSender<Value>,
|
||||||
pub(super) pending_edits: Arc<Mutex<Vec<String>>>,
|
|
||||||
pub(super) quit_app_on_close: bool,
|
pub(super) quit_app_on_close: bool,
|
||||||
pub(super) is_ready: Arc<AtomicBool>,
|
pub(super) is_ready: Arc<AtomicBool>,
|
||||||
pub(super) proxy: EventLoopProxy<UserWindowEvent>,
|
pub(super) proxy: EventLoopProxy<UserWindowEvent>,
|
||||||
@@ -35,97 +35,6 @@ pub(super) struct DesktopController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DesktopController {
|
impl DesktopController {
|
||||||
// Launch the virtualdom on its own thread managed by tokio
|
|
||||||
// returns the desktop state
|
|
||||||
pub(super) fn new_on_tokio<P: Send + 'static>(
|
|
||||||
root: Component<P>,
|
|
||||||
props: P,
|
|
||||||
proxy: EventLoopProxy<UserWindowEvent>,
|
|
||||||
) -> Self {
|
|
||||||
let edit_queue = Arc::new(Mutex::new(Vec::new()));
|
|
||||||
let (event_tx, mut event_rx) = unbounded();
|
|
||||||
let (templates_tx, mut templates_rx) = unbounded();
|
|
||||||
let proxy2 = proxy.clone();
|
|
||||||
|
|
||||||
let pending_edits = edit_queue.clone();
|
|
||||||
let desktop_context_proxy = proxy.clone();
|
|
||||||
let (eval_sender, eval_reciever) = tokio::sync::mpsc::unbounded_channel::<Value>();
|
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
|
||||||
// We create the runtime as multithreaded, so you can still "tokio::spawn" onto multiple threads
|
|
||||||
// I'd personally not require tokio to be built-in to Dioxus-Desktop, but the DX is worse without it
|
|
||||||
|
|
||||||
let runtime = tokio::runtime::Builder::new_multi_thread()
|
|
||||||
.enable_all()
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
runtime.block_on(async move {
|
|
||||||
let mut dom = VirtualDom::new_with_props(root, props)
|
|
||||||
.with_root_context(DesktopContext::new(desktop_context_proxy, eval_reciever));
|
|
||||||
{
|
|
||||||
let edits = dom.rebuild();
|
|
||||||
let mut queue = edit_queue.lock().unwrap();
|
|
||||||
queue.push(serde_json::to_string(&edits).unwrap());
|
|
||||||
proxy.send_event(UserWindowEvent::EditsReady).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
loop {
|
|
||||||
tokio::select! {
|
|
||||||
template = {
|
|
||||||
#[allow(unused)]
|
|
||||||
fn maybe_future<'a>(templates_rx: &'a mut UnboundedReceiver<Template<'static>>) -> impl Future<Output = dioxus_core::Template<'static>> + 'a {
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
return templates_rx.select_next_some();
|
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
return std::future::pending();
|
|
||||||
}
|
|
||||||
maybe_future(&mut templates_rx)
|
|
||||||
} => {
|
|
||||||
dom.replace_template(template);
|
|
||||||
}
|
|
||||||
_ = dom.wait_for_work() => {}
|
|
||||||
Some(json_value) = event_rx.next() => {
|
|
||||||
if let Ok(value) = serde_json::from_value::<HtmlEvent>(json_value) {
|
|
||||||
let HtmlEvent {
|
|
||||||
name,
|
|
||||||
element,
|
|
||||||
bubbles,
|
|
||||||
data
|
|
||||||
} = value;
|
|
||||||
dom.handle_event(&name, data.into_any(), element, bubbles);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let muts = dom
|
|
||||||
.render_with_deadline(tokio::time::sleep(Duration::from_millis(16)))
|
|
||||||
.await;
|
|
||||||
|
|
||||||
edit_queue
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.push(serde_json::to_string(&muts).unwrap());
|
|
||||||
let _ = proxy.send_event(UserWindowEvent::EditsReady);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
Self {
|
|
||||||
pending_edits,
|
|
||||||
eval_sender,
|
|
||||||
webviews: HashMap::new(),
|
|
||||||
is_ready: Arc::new(AtomicBool::new(false)),
|
|
||||||
quit_app_on_close: true,
|
|
||||||
proxy: proxy2,
|
|
||||||
event_tx,
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
templates_tx,
|
|
||||||
#[cfg(target_os = "ios")]
|
|
||||||
views: vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn close_window(&mut self, window_id: WindowId, control_flow: &mut ControlFlow) {
|
pub(super) fn close_window(&mut self, window_id: WindowId, control_flow: &mut ControlFlow) {
|
||||||
self.webviews.remove(&window_id);
|
self.webviews.remove(&window_id);
|
||||||
|
|
||||||
@@ -134,21 +43,112 @@ impl DesktopController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn try_load_ready_webviews(&mut self) {
|
// pub(super) fn try_load_ready_webviews(&mut self) {
|
||||||
if self.is_ready.load(std::sync::atomic::Ordering::Relaxed) {
|
// if self.is_ready.load(std::sync::atomic::Ordering::Relaxed) {
|
||||||
let mut new_queue = Vec::new();
|
// let mut new_queue = Vec::new();
|
||||||
|
|
||||||
{
|
// {
|
||||||
let mut queue = self.pending_edits.lock().unwrap();
|
// let mut queue = self.pending_edits.lock().unwrap();
|
||||||
std::mem::swap(&mut new_queue, &mut *queue);
|
// std::mem::swap(&mut new_queue, &mut *queue);
|
||||||
}
|
// }
|
||||||
|
|
||||||
let (_id, view) = self.webviews.iter_mut().next().unwrap();
|
// let (_id, view) = self.webviews.iter_mut().next().unwrap();
|
||||||
|
|
||||||
for edit in new_queue.drain(..) {
|
// for edit in new_queue.drain(..) {
|
||||||
view.evaluate_script(&format!("window.interpreter.handleEdits({})", edit))
|
// view.evaluate_script(&format!("window.interpreter.handleEdits({})", edit))
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// // Launch the virtualdom on its own thread managed by tokio
|
||||||
|
// // returns the desktop state
|
||||||
|
// pub(super) fn new_on_tokio<P: Send + 'static>(
|
||||||
|
// root: Component<P>,
|
||||||
|
// props: P,
|
||||||
|
// proxy: EventLoopProxy<UserWindowEvent>,
|
||||||
|
// ) -> Self {
|
||||||
|
// let edit_queue = Arc::new(Mutex::new(Vec::new()));
|
||||||
|
// let (event_tx, mut event_rx) = unbounded();
|
||||||
|
// let (templates_tx, mut templates_rx) = unbounded();
|
||||||
|
// let proxy2 = proxy.clone();
|
||||||
|
|
||||||
|
// let pending_edits = edit_queue.clone();
|
||||||
|
// let desktop_context_proxy = proxy.clone();
|
||||||
|
// let (eval_sender, eval_reciever) = tokio::sync::mpsc::unbounded_channel::<Value>();
|
||||||
|
|
||||||
|
// std::thread::spawn(move || {
|
||||||
|
// // We create the runtime as multithreaded, so you can still "tokio::spawn" onto multiple threads
|
||||||
|
// // I'd personally not require tokio to be built-in to Dioxus-Desktop, but the DX is worse without it
|
||||||
|
|
||||||
|
// let runtime = tokio::runtime::Builder::new_multi_thread()
|
||||||
|
// .enable_all()
|
||||||
|
// .build()
|
||||||
|
// .unwrap();
|
||||||
|
|
||||||
|
// runtime.block_on(async move {
|
||||||
|
// let mut dom = VirtualDom::new_with_props(root, props)
|
||||||
|
// .with_root_context(DesktopContext::new(desktop_context_proxy, eval_reciever));
|
||||||
|
// {
|
||||||
|
// let edits = dom.rebuild();
|
||||||
|
// let mut queue = edit_queue.lock().unwrap();
|
||||||
|
// queue.push(serde_json::to_string(&edits).unwrap());
|
||||||
|
// proxy.send_event(UserWindowEvent::EditsReady).unwrap();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// loop {
|
||||||
|
// tokio::select! {
|
||||||
|
// template = {
|
||||||
|
// #[allow(unused)]
|
||||||
|
// fn maybe_future<'a>(templates_rx: &'a mut UnboundedReceiver<Template<'static>>) -> impl Future<Output = dioxus_core::Template<'static>> + 'a {
|
||||||
|
// #[cfg(debug_assertions)]
|
||||||
|
// return templates_rx.select_next_some();
|
||||||
|
// #[cfg(not(debug_assertions))]
|
||||||
|
// return std::future::pending();
|
||||||
|
// }
|
||||||
|
// maybe_future(&mut templates_rx)
|
||||||
|
// } => {
|
||||||
|
// dom.replace_template(template);
|
||||||
|
// }
|
||||||
|
// _ = dom.wait_for_work() => {}
|
||||||
|
// Some(json_value) = event_rx.next() => {
|
||||||
|
// if let Ok(value) = serde_json::from_value::<HtmlEvent>(json_value) {
|
||||||
|
// let HtmlEvent {
|
||||||
|
// name,
|
||||||
|
// element,
|
||||||
|
// bubbles,
|
||||||
|
// data
|
||||||
|
// } = value;
|
||||||
|
// dom.handle_event(&name, data.into_any(), element, bubbles);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let muts = dom
|
||||||
|
// .render_with_deadline(tokio::time::sleep(Duration::from_millis(16)))
|
||||||
|
// .await;
|
||||||
|
|
||||||
|
// edit_queue
|
||||||
|
// .lock()
|
||||||
|
// .unwrap()
|
||||||
|
// .push(serde_json::to_string(&muts).unwrap());
|
||||||
|
// let _ = proxy.send_event(UserWindowEvent::EditsReady);
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// });
|
||||||
|
|
||||||
|
// Self {
|
||||||
|
// pending_edits,
|
||||||
|
// eval_sender,
|
||||||
|
// webviews: HashMap::new(),
|
||||||
|
// is_ready: Arc::new(AtomicBool::new(false)),
|
||||||
|
// quit_app_on_close: true,
|
||||||
|
// proxy: proxy2,
|
||||||
|
// event_tx,
|
||||||
|
// #[cfg(debug_assertions)]
|
||||||
|
// templates_tx,
|
||||||
|
// #[cfg(target_os = "ios")]
|
||||||
|
// views: vec![],
|
||||||
|
// }
|
||||||
|
// }
|
||||||
@@ -175,6 +175,8 @@ pub enum UserWindowEvent {
|
|||||||
EditsReady,
|
EditsReady,
|
||||||
Initialize,
|
Initialize,
|
||||||
|
|
||||||
|
Poll,
|
||||||
|
|
||||||
CloseWindow,
|
CloseWindow,
|
||||||
DragWindow,
|
DragWindow,
|
||||||
FocusWindow,
|
FocusWindow,
|
||||||
@@ -226,7 +228,9 @@ impl DesktopController {
|
|||||||
let window = webview.window();
|
let window = webview.window();
|
||||||
|
|
||||||
match user_event {
|
match user_event {
|
||||||
Initialize | EditsReady => self.try_load_ready_webviews(),
|
Initialize | EditsReady => {
|
||||||
|
// self.try_load_ready_webviews();
|
||||||
|
}
|
||||||
CloseWindow => *control_flow = ControlFlow::Exit,
|
CloseWindow => *control_flow = ControlFlow::Exit,
|
||||||
DragWindow => {
|
DragWindow => {
|
||||||
// if the drag_window has any errors, we don't do anything
|
// if the drag_window has any errors, we don't do anything
|
||||||
@@ -268,6 +272,10 @@ impl DesktopController {
|
|||||||
SetZoomLevel(scale_factor) => webview.zoom(scale_factor),
|
SetZoomLevel(scale_factor) => webview.zoom(scale_factor),
|
||||||
SetInnerSize(logical_size) => window.set_inner_size(logical_size),
|
SetInnerSize(logical_size) => window.set_inner_size(logical_size),
|
||||||
|
|
||||||
|
Poll => {
|
||||||
|
// todo
|
||||||
|
}
|
||||||
|
|
||||||
Print => {
|
Print => {
|
||||||
if let Err(e) = webview.print() {
|
if let Err(e) = webview.print() {
|
||||||
// we can't panic this error.
|
// we can't panic this error.
|
||||||
|
|||||||
+100
-32
@@ -13,12 +13,20 @@ mod protocol;
|
|||||||
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
||||||
mod hot_reload;
|
mod hot_reload;
|
||||||
|
|
||||||
|
use futures_util::task::ArcWake;
|
||||||
|
use serde_json::Value;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::task::Waker;
|
||||||
|
|
||||||
use desktop_context::UserWindowEvent;
|
use desktop_context::UserWindowEvent;
|
||||||
pub use desktop_context::{use_eval, use_window, DesktopContext, EvalResult};
|
pub use desktop_context::{use_eval, use_window, DesktopContext, EvalResult};
|
||||||
use futures_channel::mpsc::UnboundedSender;
|
use futures_channel::mpsc::UnboundedSender;
|
||||||
|
use futures_util::future::poll_fn;
|
||||||
|
use futures_util::{pin_mut, FutureExt};
|
||||||
pub use wry;
|
pub use wry;
|
||||||
pub use wry::application as tao;
|
pub use wry::application as tao;
|
||||||
|
|
||||||
@@ -33,6 +41,8 @@ use tao::{
|
|||||||
event_loop::{ControlFlow, EventLoop},
|
event_loop::{ControlFlow, EventLoop},
|
||||||
window::Window,
|
window::Window,
|
||||||
};
|
};
|
||||||
|
use wry::application::event_loop::EventLoopProxy;
|
||||||
|
use wry::application::platform::run_return::EventLoopExtRunReturn;
|
||||||
use wry::webview::WebViewBuilder;
|
use wry::webview::WebViewBuilder;
|
||||||
|
|
||||||
/// Launch the WebView and run the event loop.
|
/// Launch the WebView and run the event loop.
|
||||||
@@ -52,8 +62,8 @@ use wry::webview::WebViewBuilder;
|
|||||||
/// })
|
/// })
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn launch(root: Component) {
|
pub async fn launch(root: Component) {
|
||||||
launch_with_props(root, (), Config::default())
|
launch_with_props(root, (), Config::default()).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Launch the WebView and run the event loop, with configuration.
|
/// Launch the WebView and run the event loop, with configuration.
|
||||||
@@ -75,12 +85,14 @@ pub fn launch(root: Component) {
|
|||||||
/// })
|
/// })
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn launch_cfg(root: Component, config_builder: Config) {
|
pub async fn launch_cfg(root: Component, config_builder: Config) {
|
||||||
launch_with_props(root, (), config_builder)
|
launch_with_props(root, (), config_builder).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Launch the WebView and run the event loop, with configuration and root props.
|
/// Launch the WebView and run the event loop, with configuration and root props.
|
||||||
///
|
///
|
||||||
|
/// THIS WILL BLOCK THE CURRENT THREAD
|
||||||
|
///
|
||||||
/// This function will start a multithreaded Tokio runtime as well the WebView event loop.
|
/// This function will start a multithreaded Tokio runtime as well the WebView event loop.
|
||||||
///
|
///
|
||||||
/// You can configure the WebView window with a configuration closure
|
/// You can configure the WebView window with a configuration closure
|
||||||
@@ -102,28 +114,92 @@ 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) {
|
pub async fn launch_with_props<P: 'static + Send>(root: Component<P>, props: P, mut cfg: Config) {
|
||||||
let event_loop = EventLoop::with_user_event();
|
let mut event_loop = EventLoop::with_user_event();
|
||||||
let mut desktop = DesktopController::new_on_tokio(root, props, event_loop.create_proxy());
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
let is_ready = Arc::new(AtomicBool::new(false));
|
||||||
hot_reload::init(desktop.templates_tx.clone());
|
let (eval_sender, eval_reciever) = tokio::sync::mpsc::unbounded_channel();
|
||||||
|
|
||||||
|
let mut dom = VirtualDom::new_with_props(root, props).with_root_context(DesktopContext::new(
|
||||||
|
event_loop.create_proxy(),
|
||||||
|
eval_reciever,
|
||||||
|
));
|
||||||
|
|
||||||
|
let proxy = event_loop.create_proxy();
|
||||||
|
|
||||||
|
let waker = futures_util::task::waker(Arc::new(DomHandle {
|
||||||
|
proxy: proxy.clone(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
let mut events = Rc::new(RefCell::new(vec![]));
|
||||||
|
let mut webviews = HashMap::new();
|
||||||
|
|
||||||
event_loop.run(move |window_event, event_loop, control_flow| {
|
event_loop.run(move |window_event, event_loop, control_flow| {
|
||||||
*control_flow = ControlFlow::Wait;
|
*control_flow = ControlFlow::Wait;
|
||||||
|
|
||||||
match window_event {
|
match window_event {
|
||||||
Event::NewEvents(StartCause::Init) => desktop.start(&mut cfg, event_loop),
|
Event::NewEvents(StartCause::Init) => {
|
||||||
|
let window = build_webview(
|
||||||
|
&mut cfg,
|
||||||
|
event_loop,
|
||||||
|
is_ready.clone(),
|
||||||
|
proxy.clone(),
|
||||||
|
eval_sender.clone(),
|
||||||
|
events.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
Event::WindowEvent {
|
webviews.insert(window.window().id(), window);
|
||||||
event, window_id, ..
|
|
||||||
} => match event {
|
// desktop.start(&mut cfg, event_loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
Event::WindowEvent { event, .. } => match event {
|
||||||
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
|
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
|
||||||
WindowEvent::Destroyed { .. } => desktop.close_window(window_id, control_flow),
|
WindowEvent::Destroyed { .. } => {
|
||||||
|
// desktop.close_window(window_id, control_flow);
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
|
|
||||||
Event::UserEvent(user_event) => desktop.handle_event(user_event, control_flow),
|
Event::UserEvent(user_event) => {
|
||||||
|
println!("user event: {:?}", user_event);
|
||||||
|
|
||||||
|
match user_event {
|
||||||
|
UserWindowEvent::Poll => {
|
||||||
|
let mut cx = std::task::Context::from_waker(&waker);
|
||||||
|
|
||||||
|
let render = {
|
||||||
|
let fut = dom.wait_for_work();
|
||||||
|
pin_mut!(fut);
|
||||||
|
matches!(fut.poll_unpin(&mut cx), std::task::Poll::Ready(_))
|
||||||
|
};
|
||||||
|
|
||||||
|
if render {
|
||||||
|
let edits = dom.render_immediate();
|
||||||
|
|
||||||
|
// apply the edits
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UserWindowEvent::EditsReady => {
|
||||||
|
let edits = dom.rebuild();
|
||||||
|
|
||||||
|
let (_id, view) = webviews.iter_mut().next().unwrap();
|
||||||
|
|
||||||
|
let serialized = serde_json::to_string(&edits).unwrap();
|
||||||
|
|
||||||
|
view.evaluate_script(&format!(
|
||||||
|
"window.interpreter.handleEdits({})",
|
||||||
|
serialized
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
other => {
|
||||||
|
// desktop.handle_event(user_event, control_flow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Event::MainEventsCleared => {}
|
Event::MainEventsCleared => {}
|
||||||
Event::Resumed => {}
|
Event::Resumed => {}
|
||||||
Event::Suspended => {}
|
Event::Suspended => {}
|
||||||
@@ -134,22 +210,13 @@ pub fn launch_with_props<P: 'static + Send>(root: Component<P>, props: P, mut cf
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DesktopController {
|
struct DomHandle {
|
||||||
fn start(
|
proxy: EventLoopProxy<UserWindowEvent>,
|
||||||
&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);
|
impl ArcWake for DomHandle {
|
||||||
|
fn wake_by_ref(arc_self: &Arc<Self>) {
|
||||||
|
arc_self.proxy.send_event(UserWindowEvent::Poll).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +226,7 @@ fn build_webview(
|
|||||||
is_ready: Arc<AtomicBool>,
|
is_ready: Arc<AtomicBool>,
|
||||||
proxy: tao::event_loop::EventLoopProxy<UserWindowEvent>,
|
proxy: tao::event_loop::EventLoopProxy<UserWindowEvent>,
|
||||||
eval_sender: tokio::sync::mpsc::UnboundedSender<serde_json::Value>,
|
eval_sender: tokio::sync::mpsc::UnboundedSender<serde_json::Value>,
|
||||||
event_tx: UnboundedSender<serde_json::Value>,
|
event_tx: Rc<RefCell<Vec<Value>>>,
|
||||||
) -> wry::webview::WebView {
|
) -> wry::webview::WebView {
|
||||||
let builder = cfg.window.clone();
|
let builder = cfg.window.clone();
|
||||||
let window = builder.build(event_loop).unwrap();
|
let window = builder.build(event_loop).unwrap();
|
||||||
@@ -201,7 +268,8 @@ fn build_webview(
|
|||||||
eval_sender.send(result).unwrap();
|
eval_sender.send(result).unwrap();
|
||||||
}
|
}
|
||||||
"user_event" => {
|
"user_event" => {
|
||||||
_ = event_tx.unbounded_send(message.params());
|
_ = event_tx.borrow_mut().push(message.params());
|
||||||
|
let _ = proxy.send_event(UserWindowEvent::Poll);
|
||||||
}
|
}
|
||||||
"initialize" => {
|
"initialize" => {
|
||||||
is_ready.store(true, std::sync::atomic::Ordering::Relaxed);
|
is_ready.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
|||||||
Reference in new issue
Block a user