Explorar o código

Refactor IPC a bit

Jonathan Kelley hai 1 ano
pai
achega
b5a125b963

+ 8 - 24
packages/desktop/src/app.rs

@@ -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();
     }
 }
 

+ 19 - 47
packages/desktop/src/desktop_context.rs

@@ -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};

+ 4 - 2
packages/desktop/src/hooks.rs

@@ -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};
 

+ 18 - 0
packages/desktop/src/ipc.rs

@@ -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
 ///

+ 1 - 2
packages/desktop/src/launch.rs

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

+ 1 - 1
packages/desktop/src/waker.rs

@@ -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};

+ 23 - 1
packages/desktop/src/webview.rs

@@ -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());
+        }
+    }
 }