Refactor IPC a bit

This commit is contained in:
Jonathan Kelley committed 2024-01-04 20:27:04 -08:00
1 parent 4adc912189
commit b5a125b963
7 files changed
+74 -77

No files matched your search

+8 -24
View File
@@ -1,10 +1,11 @@
use crate::{ use crate::{
cfg::{Config, WindowCloseBehaviour}, cfg::{Config, WindowCloseBehaviour},
desktop_context::{EventData, UserWindowEvent, WindowEventHandlers}, desktop_context::WindowEventHandlers,
edits::WebviewQueue, edits::WebviewQueue,
element::DesktopElement, element::DesktopElement,
file_upload::FileDialogRequest, file_upload::FileDialogRequest,
ipc::IpcMessage, ipc::IpcMessage,
ipc::{EventData, UserWindowEvent},
query::QueryResult, query::QueryResult,
shortcut::{GlobalHotKeyEvent, ShortcutRegistry}, shortcut::{GlobalHotKeyEvent, ShortcutRegistry},
webview::WebviewInstance, webview::WebviewInstance,
@@ -12,7 +13,6 @@ use crate::{
use crossbeam_channel::Receiver; use crossbeam_channel::Receiver;
use dioxus_core::{Component, ElementId, VirtualDom}; use dioxus_core::{Component, ElementId, VirtualDom};
use dioxus_html::{native_bind::NativeFileEngine, FormData, HtmlEvent, MountedData}; use dioxus_html::{native_bind::NativeFileEngine, FormData, HtmlEvent, MountedData};
use futures_util::{pin_mut, FutureExt};
use std::{cell::Cell, collections::HashMap, rc::Rc, sync::Arc}; use std::{cell::Cell, collections::HashMap, rc::Rc, sync::Arc};
use tao::{ use tao::{
event::Event, event::Event,
@@ -33,6 +33,10 @@ pub(crate) struct App<P> {
pub(crate) webviews: HashMap<WindowId, WebviewInstance>, pub(crate) webviews: HashMap<WindowId, WebviewInstance>,
pub(crate) window_behavior: WindowCloseBehaviour, pub(crate) window_behavior: WindowCloseBehaviour,
/// This bit of state is shared between all the windows, providing a way for us to communicate with
/// running instances.
///
/// Todo: everything in this struct is wrapped in Rc<>, but we really only need the one top-level refcell
pub(crate) shared: SharedContext, pub(crate) shared: SharedContext,
} }
@@ -249,10 +253,7 @@ impl<P: 'static> App<P> {
dioxus_hot_reload::HotReloadMsg::UpdateTemplate(template) => { dioxus_hot_reload::HotReloadMsg::UpdateTemplate(template) => {
for webview in self.webviews.values_mut() { for webview in self.webviews.values_mut() {
webview.dom.replace_template(template); webview.dom.replace_template(template);
} webview.poll_vdom();
for id in self.webviews.keys().copied().collect::<Vec<_>>() {
self.poll_vdom(id);
} }
} }
dioxus_hot_reload::HotReloadMsg::Shutdown => { dioxus_hot_reload::HotReloadMsg::Shutdown => {
@@ -300,24 +301,7 @@ impl<P: 'static> App<P> {
return; return;
}; };
let mut cx = std::task::Context::from_waker(&view.waker); view.poll_vdom();
// Continously poll the virtualdom until it's pending
// Wait for work will return Ready when it has edits to be sent to the webview
// It will return Pending when it needs to be polled again - nothing is ready
loop {
{
let fut = view.dom.wait_for_work();
pin_mut!(fut);
match fut.poll_unpin(&mut cx) {
std::task::Poll::Ready(_) => {}
std::task::Poll::Pending => return,
}
}
view.desktop_context.send_edits(view.dom.render_immediate());
}
} }
} }
+19 -47
View File
@@ -1,19 +1,21 @@
use crate::shortcut::{HotKey, ShortcutId, ShortcutRegistry, ShortcutRegistryError}; use crate::{
use crate::AssetHandler; app::SharedContext,
use crate::Config; assets::{AssetFuture, AssetHandlerRegistry},
use crate::{app::SharedContext, ipc::IpcMessage}; edits::EditQueue,
use crate::{assets::AssetFuture, edits::WebviewQueue}; ipc::{EventData, UserWindowEvent},
use crate::{assets::AssetHandlerRegistry, edits::EditQueue}; query::QueryEngine,
use crate::{query::QueryEngine, webview::WebviewInstance}; shortcut::{HotKey, ShortcutId, ShortcutRegistryError},
use dioxus_core::Mutations; webview::WebviewInstance,
use dioxus_core::VirtualDom; AssetHandler, Config,
};
use dioxus_core::{Mutations, VirtualDom};
use dioxus_interpreter_js::binary_protocol::Channel; use dioxus_interpreter_js::binary_protocol::Channel;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use slab::Slab; use slab::Slab;
use std::{cell::RefCell, fmt::Debug, rc::Rc, rc::Weak, sync::atomic::AtomicU16}; use std::{cell::RefCell, fmt::Debug, rc::Rc, rc::Weak, sync::atomic::AtomicU16};
use tao::{ use tao::{
event::Event, event::Event,
event_loop::{EventLoopProxy, EventLoopWindowTarget}, event_loop::EventLoopWindowTarget,
window::{Fullscreen as WryFullscreen, Window, WindowId}, window::{Fullscreen as WryFullscreen, Window, WindowId},
}; };
use wry::WebView; use wry::WebView;
@@ -52,21 +54,13 @@ pub struct DesktopService {
/// The tao window itself /// The tao window itself
pub window: Window, pub window: Window,
/// The receiver for queries about the current window
pub(super) query: QueryEngine,
pub(crate) shared: SharedContext, pub(crate) shared: SharedContext,
// pub(crate) event_handlers: WindowEventHandlers, /// The receiver for queries about the current window
// pub(super) pending_windows: WebviewQueue, pub(super) query: QueryEngine,
// pub(crate) shortcut_manager: ShortcutRegistry,
// pub(crate) event_loop: EventLoopWindowTarget<UserWindowEvent>,
pub(crate) edit_queue: EditQueue, pub(crate) edit_queue: EditQueue,
pub(crate) templates: RefCell<FxHashMap<String, u16>>, pub(crate) templates: RefCell<FxHashMap<String, u16>>,
pub(crate) max_template_count: AtomicU16, pub(crate) max_template_count: AtomicU16,
pub(crate) channel: RefCell<Channel>, pub(crate) channel: RefCell<Channel>,
pub(crate) asset_handlers: AssetHandlerRegistry, pub(crate) asset_handlers: AssetHandlerRegistry,
@@ -153,22 +147,17 @@ impl DesktopService {
/// onmousedown: move |_| { desktop.drag_window(); } /// onmousedown: move |_| { desktop.drag_window(); }
/// ``` /// ```
pub fn drag(&self) { pub fn drag(&self) {
let window = &self.window; if self.window.fullscreen().is_none() {
_ = self.window.drag_window();
// if the drag_window has any errors, we don't do anything
if window.fullscreen().is_none() {
window.drag_window().unwrap();
} }
} }
/// Toggle whether the window is maximized or not /// Toggle whether the window is maximized or not
pub fn toggle_maximized(&self) { pub fn toggle_maximized(&self) {
let window = &self.window; self.window.set_maximized(!self.window.is_maximized())
window.set_maximized(!window.is_maximized())
} }
/// close window /// Close this window
pub fn close(&self) { pub fn close(&self) {
let _ = self let _ = self
.shared .shared
@@ -176,7 +165,7 @@ impl DesktopService {
.send_event(UserWindowEvent(EventData::CloseWindow, self.id())); .send_event(UserWindowEvent(EventData::CloseWindow, self.id()));
} }
/// close window /// Close a particular window, given its ID
pub fn close_window(&self, id: WindowId) { pub fn close_window(&self, id: WindowId) {
let _ = self let _ = self
.shared .shared
@@ -304,23 +293,6 @@ impl DesktopService {
} }
} }
#[derive(Debug, Clone)]
pub struct UserWindowEvent(pub EventData, pub WindowId);
#[derive(Debug, Clone)]
pub enum EventData {
Poll,
Ipc(IpcMessage),
#[cfg(all(feature = "hot-reload", debug_assertions))]
HotReloadEvent(dioxus_hot_reload::HotReloadMsg),
NewWindow,
CloseWindow,
}
#[cfg(target_os = "ios")] #[cfg(target_os = "ios")]
fn is_main_thread() -> bool { fn is_main_thread() -> bool {
use objc::runtime::{Class, BOOL, NO}; use objc::runtime::{Class, BOOL, NO};
+4 -2
View File
@@ -1,7 +1,9 @@
use std::rc::Rc; use std::rc::Rc;
use crate::{assets::*, shortcut::IntoAccelerator, ShortcutHandle, ShortcutRegistryError}; use crate::{
use crate::{desktop_context::UserWindowEvent, window, DesktopContext, WryEventHandler}; assets::*, ipc::UserWindowEvent, shortcut::IntoAccelerator, window, DesktopContext,
ShortcutHandle, ShortcutRegistryError, WryEventHandler,
};
use dioxus_core::ScopeState; use dioxus_core::ScopeState;
use tao::{event::Event, event_loop::EventLoopWindowTarget}; use tao::{event::Event, event_loop::EventLoopWindowTarget};
+18
View File
@@ -1,4 +1,22 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tao::window::WindowId;
#[derive(Debug, Clone)]
pub struct UserWindowEvent(pub EventData, pub WindowId);
#[derive(Debug, Clone)]
pub enum EventData {
Poll,
Ipc(IpcMessage),
#[cfg(all(feature = "hot-reload", debug_assertions))]
HotReloadEvent(dioxus_hot_reload::HotReloadMsg),
NewWindow,
CloseWindow,
}
/// A message struct that manages the communication between the webview and the eventloop code /// A message struct that manages the communication between the webview and the eventloop code
/// ///
+1 -2
View File
@@ -1,7 +1,6 @@
use crate::{ use crate::{
app::App, app::App,
desktop_context::{EventData, UserWindowEvent}, ipc::{EventData, IpcMethod, UserWindowEvent},
ipc::IpcMethod,
Config, Config,
}; };
use dioxus_core::*; use dioxus_core::*;
+1 -1
View File
@@ -1,4 +1,4 @@
use crate::desktop_context::{EventData, UserWindowEvent}; use crate::ipc::{EventData, UserWindowEvent};
use futures_util::task::ArcWake; use futures_util::task::ArcWake;
use std::sync::Arc; use std::sync::Arc;
use tao::{event_loop::EventLoopProxy, window::WindowId}; use tao::{event_loop::EventLoopProxy, window::WindowId};
+23 -1
View File
@@ -1,14 +1,15 @@
use crate::{ use crate::{
app::SharedContext, app::SharedContext,
assets::AssetHandlerRegistry, assets::AssetHandlerRegistry,
desktop_context::{EventData, UserWindowEvent},
edits::EditQueue, edits::EditQueue,
eval::DesktopEvalProvider, eval::DesktopEvalProvider,
ipc::{EventData, UserWindowEvent},
protocol::{self}, protocol::{self},
waker::tao_waker, waker::tao_waker,
Config, DesktopContext, DesktopService, Config, DesktopContext, DesktopService,
}; };
use dioxus_core::VirtualDom; use dioxus_core::VirtualDom;
use futures_util::{pin_mut, FutureExt};
use std::{rc::Rc, task::Waker}; use std::{rc::Rc, task::Waker};
use wry::{WebContext, WebViewBuilder}; use wry::{WebContext, WebViewBuilder};
@@ -160,4 +161,25 @@ impl WebviewInstance {
_web_context: web_context, _web_context: web_context,
} }
} }
pub fn poll_vdom(&mut self) {
let mut cx = std::task::Context::from_waker(&self.waker);
// Continously poll the virtualdom until it's pending
// Wait for work will return Ready when it has edits to be sent to the webview
// It will return Pending when it needs to be polled again - nothing is ready
loop {
{
let fut = self.dom.wait_for_work();
pin_mut!(fut);
match fut.poll_unpin(&mut cx) {
std::task::Poll::Ready(_) => {}
std::task::Poll::Pending => return,
}
}
self.desktop_context.send_edits(self.dom.render_immediate());
}
}
} }