Refactor IPC a bit

This commit is contained in:
Jonathan Kelley 2024-01-04 20:27:04 -08:00
parent 4adc912189
commit b5a125b963
No known key found for this signature in database
GPG key ID: 1FBB50F7EB0A08BE
7 changed files with 74 additions and 77 deletions

View file

@ -1,10 +1,11 @@
use crate::{
cfg::{Config, WindowCloseBehaviour},
desktop_context::{EventData, UserWindowEvent, WindowEventHandlers},
desktop_context::WindowEventHandlers,
edits::WebviewQueue,
element::DesktopElement,
file_upload::FileDialogRequest,
ipc::IpcMessage,
ipc::{EventData, UserWindowEvent},
query::QueryResult,
shortcut::{GlobalHotKeyEvent, ShortcutRegistry},
webview::WebviewInstance,
@ -12,7 +13,6 @@ use crate::{
use crossbeam_channel::Receiver;
use dioxus_core::{Component, ElementId, VirtualDom};
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 tao::{
event::Event,
@ -33,6 +33,10 @@ pub(crate) struct App<P> {
pub(crate) webviews: HashMap<WindowId, WebviewInstance>,
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,
}
@ -249,10 +253,7 @@ impl<P: 'static> App<P> {
dioxus_hot_reload::HotReloadMsg::UpdateTemplate(template) => {
for webview in self.webviews.values_mut() {
webview.dom.replace_template(template);
}
for id in self.webviews.keys().copied().collect::<Vec<_>>() {
self.poll_vdom(id);
webview.poll_vdom();
}
}
dioxus_hot_reload::HotReloadMsg::Shutdown => {
@ -300,24 +301,7 @@ impl<P: 'static> App<P> {
return;
};
let mut cx = std::task::Context::from_waker(&view.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 = 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());
}
view.poll_vdom();
}
}

View file

@ -1,19 +1,21 @@
use crate::shortcut::{HotKey, ShortcutId, ShortcutRegistry, ShortcutRegistryError};
use crate::AssetHandler;
use crate::Config;
use crate::{app::SharedContext, ipc::IpcMessage};
use crate::{assets::AssetFuture, edits::WebviewQueue};
use crate::{assets::AssetHandlerRegistry, edits::EditQueue};
use crate::{query::QueryEngine, webview::WebviewInstance};
use dioxus_core::Mutations;
use dioxus_core::VirtualDom;
use crate::{
app::SharedContext,
assets::{AssetFuture, AssetHandlerRegistry},
edits::EditQueue,
ipc::{EventData, UserWindowEvent},
query::QueryEngine,
shortcut::{HotKey, ShortcutId, ShortcutRegistryError},
webview::WebviewInstance,
AssetHandler, Config,
};
use dioxus_core::{Mutations, VirtualDom};
use dioxus_interpreter_js::binary_protocol::Channel;
use rustc_hash::FxHashMap;
use slab::Slab;
use std::{cell::RefCell, fmt::Debug, rc::Rc, rc::Weak, sync::atomic::AtomicU16};
use tao::{
event::Event,
event_loop::{EventLoopProxy, EventLoopWindowTarget},
event_loop::EventLoopWindowTarget,
window::{Fullscreen as WryFullscreen, Window, WindowId},
};
use wry::WebView;
@ -52,21 +54,13 @@ pub struct DesktopService {
/// The tao window itself
pub window: Window,
/// The receiver for queries about the current window
pub(super) query: QueryEngine,
pub(crate) shared: SharedContext,
// pub(crate) event_handlers: WindowEventHandlers,
// pub(super) pending_windows: WebviewQueue,
// pub(crate) shortcut_manager: ShortcutRegistry,
// pub(crate) event_loop: EventLoopWindowTarget<UserWindowEvent>,
/// The receiver for queries about the current window
pub(super) query: QueryEngine,
pub(crate) edit_queue: EditQueue,
pub(crate) templates: RefCell<FxHashMap<String, u16>>,
pub(crate) max_template_count: AtomicU16,
pub(crate) channel: RefCell<Channel>,
pub(crate) asset_handlers: AssetHandlerRegistry,
@ -153,22 +147,17 @@ impl DesktopService {
/// onmousedown: move |_| { desktop.drag_window(); }
/// ```
pub fn drag(&self) {
let window = &self.window;
// if the drag_window has any errors, we don't do anything
if window.fullscreen().is_none() {
window.drag_window().unwrap();
if self.window.fullscreen().is_none() {
_ = self.window.drag_window();
}
}
/// Toggle whether the window is maximized or not
pub fn toggle_maximized(&self) {
let window = &self.window;
window.set_maximized(!window.is_maximized())
self.window.set_maximized(!self.window.is_maximized())
}
/// close window
/// Close this window
pub fn close(&self) {
let _ = self
.shared
@ -176,7 +165,7 @@ impl DesktopService {
.send_event(UserWindowEvent(EventData::CloseWindow, self.id()));
}
/// close window
/// Close a particular window, given its ID
pub fn close_window(&self, id: WindowId) {
let _ = self
.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")]
fn is_main_thread() -> bool {
use objc::runtime::{Class, BOOL, NO};

View file

@ -1,7 +1,9 @@
use std::rc::Rc;
use crate::{assets::*, shortcut::IntoAccelerator, ShortcutHandle, ShortcutRegistryError};
use crate::{desktop_context::UserWindowEvent, window, DesktopContext, WryEventHandler};
use crate::{
assets::*, ipc::UserWindowEvent, shortcut::IntoAccelerator, window, DesktopContext,
ShortcutHandle, ShortcutRegistryError, WryEventHandler,
};
use dioxus_core::ScopeState;
use tao::{event::Event, event_loop::EventLoopWindowTarget};

View file

@ -1,4 +1,22 @@
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
///

View file

@ -1,7 +1,6 @@
use crate::{
app::App,
desktop_context::{EventData, UserWindowEvent},
ipc::IpcMethod,
ipc::{EventData, IpcMethod, UserWindowEvent},
Config,
};
use dioxus_core::*;

View file

@ -1,4 +1,4 @@
use crate::desktop_context::{EventData, UserWindowEvent};
use crate::ipc::{EventData, UserWindowEvent};
use futures_util::task::ArcWake;
use std::sync::Arc;
use tao::{event_loop::EventLoopProxy, window::WindowId};

View file

@ -1,14 +1,15 @@
use crate::{
app::SharedContext,
assets::AssetHandlerRegistry,
desktop_context::{EventData, UserWindowEvent},
edits::EditQueue,
eval::DesktopEvalProvider,
ipc::{EventData, UserWindowEvent},
protocol::{self},
waker::tao_waker,
Config, DesktopContext, DesktopService,
};
use dioxus_core::VirtualDom;
use futures_util::{pin_mut, FutureExt};
use std::{rc::Rc, task::Waker};
use wry::{WebContext, WebViewBuilder};
@ -160,4 +161,25 @@ impl WebviewInstance {
_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());
}
}
}