Просмотр исходного кода

wip: more overhaul on virtualevents

Jonathan Kelley 3 лет назад
Родитель
Сommit
41cc429

+ 5 - 5
packages/core/src/diff.rs

@@ -251,7 +251,7 @@ impl<'bump> DiffMachine<'bump> {
     fn create_suspended_node(&mut self, suspended: &'bump VSuspended) {
         let real_id = self.vdom.reserve_node();
         self.mutations.create_placeholder(real_id);
-        suspended.node.set(Some(real_id));
+        suspended.dom_id.set(Some(real_id));
         self.stack.add_child_count(1);
     }
 
@@ -372,7 +372,7 @@ impl<'bump> DiffMachine<'bump> {
             (Component(old), Component(new)) => self.diff_component_nodes(old, new),
             (Fragment(old), Fragment(new)) => self.diff_fragment_nodes(old, new),
             (Anchor(old), Anchor(new)) => new.dom_id.set(old.dom_id.get()),
-            (Suspended(old), Suspended(new)) => new.node.set(old.node.get()),
+            (Suspended(old), Suspended(new)) => new.dom_id.set(old.dom_id.get()),
             (Element(old), Element(new)) => self.diff_element_nodes(old, new),
 
             // Anything else is just a basic replace and create
@@ -952,7 +952,7 @@ impl<'bump> DiffMachine<'bump> {
             match &search_node.take().unwrap() {
                 VNode::Text(t) => break t.dom_id.get(),
                 VNode::Element(t) => break t.dom_id.get(),
-                VNode::Suspended(t) => break t.node.get(),
+                VNode::Suspended(t) => break t.dom_id.get(),
                 VNode::Anchor(t) => break t.dom_id.get(),
 
                 VNode::Fragment(frag) => {
@@ -983,7 +983,7 @@ impl<'bump> DiffMachine<'bump> {
                 }
                 VNode::Text(t) => break t.dom_id.get(),
                 VNode::Element(t) => break t.dom_id.get(),
-                VNode::Suspended(t) => break t.node.get(),
+                VNode::Suspended(t) => break t.dom_id.get(),
                 VNode::Anchor(t) => break t.dom_id.get(),
             }
         }
@@ -1016,7 +1016,7 @@ impl<'bump> DiffMachine<'bump> {
                     });
                 }
                 VNode::Suspended(s) => {
-                    s.node.get().map(|id| {
+                    s.dom_id.get().map(|id| {
                         self.mutations.remove(id.as_u64());
                         self.vdom.collect_garbage(id);
                     });

+ 27 - 33
packages/core/src/events.rs

@@ -3,16 +3,7 @@
 //!
 //! 3rd party renderers are responsible for converting their native events into these virtual event types. Events might
 //! be heavy or need to interact through FFI, so the events themselves are designed to be lazy.
-
-use std::{
-    cell::{Cell, RefCell},
-    rc::Rc,
-};
-
-use crate::{
-    innerlude::{ElementId, ScopeId},
-    VNode,
-};
+use crate::innerlude::{ElementId, ScopeId};
 
 #[derive(Debug)]
 pub struct EventTrigger {
@@ -23,12 +14,15 @@ pub struct EventTrigger {
     pub mounted_dom_id: Option<ElementId>,
 
     /// The type of event
-    pub event: VirtualEvent,
+    pub event: SyntheticEvent,
 
+    /// Is consistency important for this event?
+    /// UI events are the only events where consistency is important.
+    /// All else may be batched.
     pub discrete: bool,
 }
 
-pub enum VirtualEvent {
+pub enum SyntheticEvent {
     KeyboardEvent(on::KeyboardEvent),
     TouchEvent(on::TouchEvent),
     MouseEvent(on::MouseEvent),
@@ -47,24 +41,24 @@ pub enum VirtualEvent {
     // ImageEvent(event_data::ImageEvent),
 }
 
-impl std::fmt::Debug for VirtualEvent {
+impl std::fmt::Debug for SyntheticEvent {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         let name = match self {
-            VirtualEvent::ClipboardEvent(_) => "ClipboardEvent",
-            VirtualEvent::CompositionEvent(_) => "CompositionEvent",
-            VirtualEvent::KeyboardEvent(_) => "KeyboardEvent",
-            VirtualEvent::FocusEvent(_) => "FocusEvent",
-            VirtualEvent::FormEvent(_) => "FormEvent",
-            VirtualEvent::SelectionEvent(_) => "SelectionEvent",
-            VirtualEvent::TouchEvent(_) => "TouchEvent",
-            VirtualEvent::UIEvent(_) => "UIEvent",
-            VirtualEvent::WheelEvent(_) => "WheelEvent",
-            VirtualEvent::MediaEvent(_) => "MediaEvent",
-            VirtualEvent::AnimationEvent(_) => "AnimationEvent",
-            VirtualEvent::TransitionEvent(_) => "TransitionEvent",
-            VirtualEvent::ToggleEvent(_) => "ToggleEvent",
-            VirtualEvent::MouseEvent(_) => "MouseEvent",
-            VirtualEvent::PointerEvent(_) => "PointerEvent",
+            SyntheticEvent::ClipboardEvent(_) => "ClipboardEvent",
+            SyntheticEvent::CompositionEvent(_) => "CompositionEvent",
+            SyntheticEvent::KeyboardEvent(_) => "KeyboardEvent",
+            SyntheticEvent::FocusEvent(_) => "FocusEvent",
+            SyntheticEvent::FormEvent(_) => "FormEvent",
+            SyntheticEvent::SelectionEvent(_) => "SelectionEvent",
+            SyntheticEvent::TouchEvent(_) => "TouchEvent",
+            SyntheticEvent::UIEvent(_) => "UIEvent",
+            SyntheticEvent::WheelEvent(_) => "WheelEvent",
+            SyntheticEvent::MediaEvent(_) => "MediaEvent",
+            SyntheticEvent::AnimationEvent(_) => "AnimationEvent",
+            SyntheticEvent::TransitionEvent(_) => "TransitionEvent",
+            SyntheticEvent::ToggleEvent(_) => "ToggleEvent",
+            SyntheticEvent::MouseEvent(_) => "MouseEvent",
+            SyntheticEvent::PointerEvent(_) => "PointerEvent",
         };
 
         f.debug_struct("VirtualEvent").field("type", &name).finish()
@@ -90,7 +84,7 @@ pub mod on {
     };
     use std::cell::Cell;
 
-    use super::VirtualEvent;
+    use super::SyntheticEvent;
 
     macro_rules! event_directory {
         ( $(
@@ -126,12 +120,12 @@ pub mod on {
                     {
                         let bump = &c.bump();
 
-                        let cb: &mut dyn FnMut(VirtualEvent) = bump.alloc(move |evt: VirtualEvent| match evt {
-                            VirtualEvent::$wrapper(event) => callback(event),
-                            _ => unreachable!("Downcasted VirtualEvent to wrong event type - this is an internal bug!")
+                        let cb: &mut dyn FnMut(SyntheticEvent) = bump.alloc(move |evt: SyntheticEvent| match evt {
+                            SyntheticEvent::$wrapper(event) => callback(event),
+                            _ => unreachable!("Downcasted SyntheticEvent to wrong event type - this is an internal bug!")
                         });
 
-                        let callback: BumpBox<dyn FnMut(VirtualEvent) + 'a> = unsafe { BumpBox::from_raw(cb) };
+                        let callback: BumpBox<dyn FnMut(SyntheticEvent) + 'a> = unsafe { BumpBox::from_raw(cb) };
 
                         let event_name = stringify!($name);
                         let shortname: &'static str = &event_name[2..];

+ 54 - 57
packages/core/src/hooks.rs

@@ -126,14 +126,7 @@ where
             let handle = cx.submit_task(Box::pin(task_fut.then(move |output| async move {
                 *slot.as_ref().borrow_mut() = Some(output);
                 updater(update_id);
-                EventTrigger {
-                    event: VirtualEvent::AsyncEvent {
-                        should_rerender: false,
-                    },
-                    scope: originator,
-                    priority: EventPriority::Low,
-                    mounted_dom_id: None,
-                }
+                originator
             })));
 
             TaskHook {
@@ -172,71 +165,75 @@ where
     Out: 'static,
     Cb: for<'a> Fn(SuspendedContext<'a>, &Out) -> DomTree<'a> + 'static,
 {
+    /*
+    General strategy:
+    - Create a slot for the future to dump its output into
+    - Create a new future feeding off the user's future that feeds the output into that slot
+    - Submit that future as a task
+    - Take the task handle id and attach that to our suspended node
+    - when the hook runs, check if the value exists
+    - if it does, then we can render the node directly
+    - if it doesn't, then we render a suspended node along with with the callback and task id
+    */
     cx.use_hook(
         move |hook_idx| {
             let value = Rc::new(RefCell::new(None));
-
-            let dom_node_id = Rc::new(empty_cell());
-            let domnode = dom_node_id.clone();
-
             let slot = value.clone();
 
-            let callback: SuspendedCallback = Box::new(move |ctx: SuspendedContext| {
-                let v: std::cell::Ref<Option<Box<dyn Any>>> = slot.as_ref().borrow();
-                match v.as_ref() {
-                    Some(a) => {
-                        let v: &dyn Any = a.as_ref();
-                        let real_val = v.downcast_ref::<Out>().unwrap();
-                        user_callback(ctx, real_val)
-                    }
-                    None => {
-                        //
-                        Some(VNode::Suspended(VSuspended {
-                            node: domnode.clone(),
-                        }))
-                    }
-                }
-            });
-
             let originator = cx.scope.our_arena_idx.clone();
-            let task_fut = task_initializer();
-            let domnode = dom_node_id.clone();
 
-            let slot = value.clone();
-            cx.submit_task(Box::pin(task_fut.then(move |output| async move {
-                // When the new value arrives, set the hooks internal slot
-                // Dioxus will call the user's callback to generate new nodes outside of the diffing system
-                *slot.borrow_mut() = Some(Box::new(output) as Box<dyn Any>);
-                EventTrigger {
-                    event: VirtualEvent::SuspenseEvent { hook_idx, domnode },
-                    scope: originator,
-                    priority: EventPriority::Low,
-                    mounted_dom_id: None,
-                }
-            })));
+            let handle = cx.submit_task(Box::pin(task_initializer().then(
+                move |output| async move {
+                    *slot.borrow_mut() = Some(Box::new(output) as Box<dyn Any>);
+                    originator
+                },
+            )));
 
-            SuspenseHook {
-                value,
-                callback,
-                dom_node_id,
-            }
+            SuspenseHook { handle, value }
         },
-        move |hook| {
-            let cx = Context {
-                scope: &cx.scope,
-                props: &(),
-            };
-            let csx = SuspendedContext { inner: cx };
-            (&hook.callback)(csx)
+        move |hook| match hook.value.borrow().as_ref() {
+            Some(value) => {
+                let out = value.downcast_ref::<Out>().unwrap();
+                let sus = SuspendedContext {
+                    inner: Context {
+                        props: &(),
+                        scope: cx.scope,
+                    },
+                };
+                user_callback(sus, out)
+            }
+            None => {
+                let value = hook.value.clone();
+
+                cx.render(LazyNodes::new(|f| {
+                    let bump = f.bump();
+                    let g: &dyn FnOnce(SuspendedContext<'src>) -> DomTree<'src> =
+                        bump.alloc(|sus| {
+                            let out = value
+                                .borrow()
+                                .as_ref()
+                                .unwrap()
+                                .as_ref()
+                                .downcast_ref::<Out>()
+                                .unwrap();
+                            user_callback(sus, out)
+                        });
+
+                    VNode::Suspended(bump.alloc(VSuspended {
+                        dom_id: empty_cell(),
+                        task_id: hook.handle.our_id,
+                        callback: RefCell::new(Some(g)),
+                    }))
+                }))
+            }
         },
         |_| {},
     )
 }
 
 pub(crate) struct SuspenseHook {
+    pub handle: TaskHandle,
     pub value: Rc<RefCell<Option<Box<dyn Any>>>>,
-    pub callback: SuspendedCallback,
-    pub dom_node_id: Rc<Cell<Option<ElementId>>>,
 }
 type SuspendedCallback = Box<dyn for<'a> Fn(SuspendedContext<'a>) -> DomTree<'a>>;
 pub struct SuspendedContext<'a> {

+ 1 - 1
packages/core/src/lib.rs

@@ -13,7 +13,7 @@
 pub use crate::innerlude::{
     format_args_f, html, rsx, Context, DiffInstruction, DioxusElement, DomEdit, DomTree, ElementId,
     EventPriority, EventTrigger, LazyNodes, MountType, Mutations, NodeFactory, Properties, ScopeId,
-    SuspendedContext, VNode, VirtualDom, VirtualEvent, FC,
+    SuspendedContext, SyntheticEvent, VNode, VirtualDom, FC,
 };
 
 pub mod prelude {

+ 8 - 11
packages/core/src/nodes.rs

@@ -4,8 +4,9 @@
 //!
 //! These VNodes should be *very* cheap and *very* fast to construct - building a full tree should be insanely quick.
 use crate::{
-    events::VirtualEvent,
+    events::SyntheticEvent,
     innerlude::{empty_cell, Context, DomTree, ElementId, Properties, Scope, ScopeId, FC},
+    SuspendedContext,
 };
 use bumpalo::{boxed::Box as BumpBox, Bump};
 use std::{
@@ -30,7 +31,7 @@ pub enum VNode<'src> {
 
     Component(&'src VComponent<'src>),
 
-    Suspended(VSuspended),
+    Suspended(&'src VSuspended<'src>),
 
     Anchor(VAnchor),
 }
@@ -127,7 +128,7 @@ pub struct Listener<'bump> {
 
     pub mounted_node: Cell<Option<ElementId>>,
 
-    pub(crate) callback: RefCell<Option<BumpBox<'bump, dyn FnMut(VirtualEvent) + 'bump>>>,
+    pub(crate) callback: RefCell<Option<BumpBox<'bump, dyn FnMut(SyntheticEvent) + 'bump>>>,
 }
 
 impl Listener<'_> {
@@ -168,8 +169,10 @@ pub struct VComponent<'src> {
     pub(crate) user_fc: *const (),
 }
 
-pub struct VSuspended {
-    pub node: Rc<Cell<Option<ElementId>>>,
+pub struct VSuspended<'a> {
+    pub dom_id: Cell<Option<ElementId>>,
+    pub task_id: u64,
+    pub callback: RefCell<Option<&'a dyn FnOnce(SuspendedContext<'a>) -> DomTree<'a>>>,
 }
 
 /// This struct provides an ergonomic API to quickly build VNodes.
@@ -301,12 +304,6 @@ impl<'a> NodeFactory<'a> {
         }))
     }
 
-    pub fn suspended() -> VNode<'static> {
-        VNode::Suspended(VSuspended {
-            node: Rc::new(empty_cell()),
-        })
-    }
-
     pub fn attr(
         &self,
         name: &'static str,

+ 20 - 30
packages/core/src/scheduler.rs

@@ -34,7 +34,7 @@ pub struct EventChannel {
 
 pub enum SchedulerMsg {
     Immediate(ScopeId),
-    UiEvent(),
+    UiEvent(EventTrigger),
     SubmitTask(u64),
     ToggleTask(u64),
     PauseTask(u64),
@@ -232,16 +232,6 @@ impl Scheduler {
         id
     }
 
-    pub fn make_trigger_key(&self, trigger: &EventTrigger) -> EventKey {
-        let height = self.get_scope(trigger.scope).map(|f| f.height).unwrap();
-
-        EventKey {
-            height,
-            originator: trigger.scope,
-            priority: trigger.priority,
-        }
-    }
-
     pub fn clean_up_garbage(&mut self) {
         let mut scopes_to_kill = Vec::new();
         let mut garbage_list = Vec::new();
@@ -330,11 +320,11 @@ impl Scheduler {
     pub fn consume_pending_events(&mut self) -> Result<()> {
         while let Some(trigger) = self.pending_events.pop_back() {
             match &trigger.event {
-                VirtualEvent::AsyncEvent { .. } => {}
+                SyntheticEvent::AsyncEvent { .. } => {}
 
                 // This suspense system works, but it's not the most elegant solution.
                 // TODO: Replace this system
-                VirtualEvent::SuspenseEvent { hook_idx, domnode } => {
+                SyntheticEvent::SuspenseEvent { hook_idx, domnode } => {
                     todo!("suspense needs to be converted into its own channel");
 
                     // // Safety: this handler is the only thing that can mutate shared items at this moment in tim
@@ -369,21 +359,21 @@ impl Scheduler {
                     // }
                 }
 
-                VirtualEvent::ClipboardEvent(_)
-                | VirtualEvent::CompositionEvent(_)
-                | VirtualEvent::KeyboardEvent(_)
-                | VirtualEvent::FocusEvent(_)
-                | VirtualEvent::FormEvent(_)
-                | VirtualEvent::SelectionEvent(_)
-                | VirtualEvent::TouchEvent(_)
-                | VirtualEvent::UIEvent(_)
-                | VirtualEvent::WheelEvent(_)
-                | VirtualEvent::MediaEvent(_)
-                | VirtualEvent::AnimationEvent(_)
-                | VirtualEvent::TransitionEvent(_)
-                | VirtualEvent::ToggleEvent(_)
-                | VirtualEvent::MouseEvent(_)
-                | VirtualEvent::PointerEvent(_) => {
+                SyntheticEvent::ClipboardEvent(_)
+                | SyntheticEvent::CompositionEvent(_)
+                | SyntheticEvent::KeyboardEvent(_)
+                | SyntheticEvent::FocusEvent(_)
+                | SyntheticEvent::FormEvent(_)
+                | SyntheticEvent::SelectionEvent(_)
+                | SyntheticEvent::TouchEvent(_)
+                | SyntheticEvent::UIEvent(_)
+                | SyntheticEvent::WheelEvent(_)
+                | SyntheticEvent::MediaEvent(_)
+                | SyntheticEvent::AnimationEvent(_)
+                | SyntheticEvent::TransitionEvent(_)
+                | SyntheticEvent::ToggleEvent(_)
+                | SyntheticEvent::MouseEvent(_)
+                | SyntheticEvent::PointerEvent(_) => {
                     if let Some(scope) = self.get_scope_mut(trigger.scope) {
                         if let Some(element) = trigger.mounted_dom_id {
                             scope.call_listener(trigger.event, element)?;
@@ -528,8 +518,8 @@ impl Scheduler {
 }
 
 pub struct TaskHandle {
-    channel: EventChannel,
-    our_id: u64,
+    pub channel: EventChannel,
+    pub our_id: u64,
 }
 
 impl TaskHandle {

+ 11 - 3
packages/core/src/scope.rs

@@ -40,6 +40,8 @@ pub struct Scope {
     pub(crate) listeners: RefCell<Vec<*const Listener<'static>>>,
     pub(crate) borrowed_props: RefCell<Vec<*const VComponent<'static>>>,
 
+    pub(crate) suspended_nodes: RefCell<HashMap<u64, *const VNode<'static>>>,
+
     // State
     pub(crate) hooks: HookList,
     pub(crate) shared_contexts: RefCell<HashMap<TypeId, Rc<dyn Any>>>,
@@ -52,8 +54,9 @@ pub struct Scope {
 // The type of closure that wraps calling components
 pub type WrappedCaller = dyn for<'b> Fn(&'b Scope) -> DomTree<'b>;
 
-// The type of task that gets sent to the task scheduler
-pub type FiberTask = Pin<Box<dyn Future<Output = EventTrigger>>>;
+/// The type of task that gets sent to the task scheduler
+/// Submitting a fiber task returns a handle to that task, which can be used to wake up suspended nodes
+pub type FiberTask = Pin<Box<dyn Future<Output = ScopeId>>>;
 
 impl Scope {
     // we are being created in the scope of an existing component (where the creator_node lifetime comes into play)
@@ -91,6 +94,7 @@ impl Scope {
             height,
             frames: ActiveFrame::new(),
             hooks: Default::default(),
+            suspended_nodes: Default::default(),
             shared_contexts: Default::default(),
             listeners: Default::default(),
             borrowed_props: Default::default(),
@@ -194,7 +198,11 @@ impl Scope {
     // A safe wrapper around calling listeners
     //
     //
-    pub(crate) fn call_listener(&mut self, event: VirtualEvent, element: ElementId) -> Result<()> {
+    pub(crate) fn call_listener(
+        &mut self,
+        event: SyntheticEvent,
+        element: ElementId,
+    ) -> Result<()> {
         let listners = self.listeners.borrow_mut();
 
         let raw_listener = listners.iter().find(|lis| {

+ 18 - 20
packages/core/src/virtual_dom.rs

@@ -100,24 +100,31 @@ impl VirtualDom {
     ///
     /// Note: the VirtualDOM is not progressed, you must either "run_with_deadline" or use "rebuild" to progress it.
     pub fn new_with_props<P: Properties + 'static>(root: FC<P>, root_props: P) -> Self {
-        let components = Scheduler::new();
+        let scheduler = Scheduler::new();
 
-        let root_props: Pin<Box<dyn Any>> = Box::pin(root_props);
-        let props_ptr = root_props.as_ref().downcast_ref::<P>().unwrap() as *const P;
+        let _root_props: Pin<Box<dyn Any>> = Box::pin(root_props);
+        let _root_prop_type = TypeId::of::<P>();
 
-        let update_sender = components.immediate_sender.clone();
+        let props_ptr = _root_props.as_ref().downcast_ref::<P>().unwrap() as *const P;
 
-        let base_scope = components.insert_scope_with_key(move |myidx| {
+        let base_scope = scheduler.insert_scope_with_key(|myidx| {
             let caller = NodeFactory::create_component_caller(root, props_ptr as *const _);
             let name = type_name_of(root);
-            Scope::new(caller, myidx, None, 0, ScopeChildren(&[]), update_sender)
+            Scope::new(
+                caller,
+                myidx,
+                None,
+                0,
+                ScopeChildren(&[]),
+                scheduler.channel.clone(),
+            )
         });
 
         Self {
             base_scope,
-            _root_props: root_props,
-            scheduler: components,
-            _root_prop_type: TypeId::of::<P>(),
+            _root_props,
+            scheduler,
+            _root_prop_type,
         }
     }
 
@@ -218,15 +225,6 @@ impl VirtualDom {
         //     .expect("this future will always resolve immediately")
     }
 
-    /// Runs the virtualdom with no time limit.
-    ///
-    /// If there are pending tasks, they will be progressed before returning. This is useful when rendering an application
-    /// that has suspended nodes or suspended tasks. Be warned - any async tasks running forever will prevent this method
-    /// from completing. Consider using `run` and specifing a deadline.
-    pub async fn run_unbounded<'s>(&'s mut self) -> Mutations<'s> {
-        self.run_with_deadline(async {}).await.unwrap()
-    }
-
     /// Run the virtualdom with a deadline.
     ///
     /// This method will progress async tasks until the deadline is reached. If tasks are completed before the deadline,
@@ -327,8 +325,8 @@ impl VirtualDom {
         }
     }
 
-    pub fn get_event_sender(&self) -> futures_channel::mpsc::UnboundedSender<EventTrigger> {
-        self.scheduler.ui_event_sender.clone()
+    pub fn get_event_sender(&self) -> futures_channel::mpsc::UnboundedSender<SchedulerMsg> {
+        self.scheduler.channel.sender.clone()
     }
 
     pub fn has_work(&self) -> bool {

+ 2 - 2
packages/desktop/src/events.rs

@@ -6,7 +6,7 @@ use std::rc::Rc;
 use dioxus_core::{
     events::{
         on::{MouseEvent, MouseEventInner},
-        VirtualEvent,
+        SyntheticEvent,
     },
     ElementId, EventPriority, EventTrigger, ScopeId,
 };
@@ -21,7 +21,7 @@ pub fn trigger_from_serialized(val: serde_json::Value) -> EventTrigger {
     let mut data: Vec<ImEvent> = serde_json::from_value(val).unwrap();
     let data = data.drain(..).next().unwrap();
 
-    let event = VirtualEvent::MouseEvent(MouseEvent(Rc::new(WebviewMouseEvent)));
+    let event = SyntheticEvent::MouseEvent(MouseEvent(Rc::new(WebviewMouseEvent)));
     let scope = ScopeId(data.scope as usize);
     let mounted_dom_id = Some(ElementId(data.mounted_dom_id as usize));
     let priority = EventPriority::High;

+ 19 - 19
packages/web/src/dom.rs

@@ -1,7 +1,7 @@
 use std::{collections::HashMap, fmt::Debug, rc::Rc, sync::Arc};
 
 use dioxus_core::{
-    events::{on::GenericEventInner, EventTrigger, VirtualEvent},
+    events::{on::GenericEventInner, EventTrigger, SyntheticEvent},
     mutations::NodeRefMutation,
     DomEdit, ElementId, ScopeId,
 };
@@ -436,82 +436,82 @@ impl Stack {
     }
 }
 
-fn virtual_event_from_websys_event(event: web_sys::Event) -> VirtualEvent {
+fn virtual_event_from_websys_event(event: web_sys::Event) -> SyntheticEvent {
     use crate::events::*;
     use dioxus_core::events::on::*;
     match event.type_().as_str() {
         "copy" | "cut" | "paste" => {
-            VirtualEvent::ClipboardEvent(ClipboardEvent(Rc::new(WebsysClipboardEvent(event))))
+            SyntheticEvent::ClipboardEvent(ClipboardEvent(Rc::new(WebsysClipboardEvent(event))))
         }
         "compositionend" | "compositionstart" | "compositionupdate" => {
             let evt: web_sys::CompositionEvent = event.clone().dyn_into().unwrap();
-            VirtualEvent::CompositionEvent(CompositionEvent(Rc::new(WebsysCompositionEvent(evt))))
+            SyntheticEvent::CompositionEvent(CompositionEvent(Rc::new(WebsysCompositionEvent(evt))))
         }
         "keydown" | "keypress" | "keyup" => {
             let evt: web_sys::KeyboardEvent = event.dyn_into().unwrap();
-            VirtualEvent::KeyboardEvent(KeyboardEvent(Rc::new(WebsysKeyboardEvent(evt))))
+            SyntheticEvent::KeyboardEvent(KeyboardEvent(Rc::new(WebsysKeyboardEvent(evt))))
         }
         "focus" | "blur" => {
             let evt: web_sys::FocusEvent = event.dyn_into().unwrap();
-            VirtualEvent::FocusEvent(FocusEvent(Rc::new(WebsysFocusEvent(evt))))
+            SyntheticEvent::FocusEvent(FocusEvent(Rc::new(WebsysFocusEvent(evt))))
         }
         "change" => {
             let evt = event.dyn_into().unwrap();
-            VirtualEvent::UIEvent(UIEvent(Rc::new(WebsysGenericUiEvent(evt))))
+            SyntheticEvent::UIEvent(UIEvent(Rc::new(WebsysGenericUiEvent(evt))))
         }
         "input" | "invalid" | "reset" | "submit" => {
             let evt: web_sys::InputEvent = event.clone().dyn_into().unwrap();
-            VirtualEvent::FormEvent(FormEvent(Rc::new(WebsysFormEvent(evt))))
+            SyntheticEvent::FormEvent(FormEvent(Rc::new(WebsysFormEvent(evt))))
         }
         "click" | "contextmenu" | "doubleclick" | "drag" | "dragend" | "dragenter" | "dragexit"
         | "dragleave" | "dragover" | "dragstart" | "drop" | "mousedown" | "mouseenter"
         | "mouseleave" | "mousemove" | "mouseout" | "mouseover" | "mouseup" => {
             let evt: web_sys::MouseEvent = event.clone().dyn_into().unwrap();
-            VirtualEvent::MouseEvent(MouseEvent(Rc::new(WebsysMouseEvent(evt))))
+            SyntheticEvent::MouseEvent(MouseEvent(Rc::new(WebsysMouseEvent(evt))))
         }
         "pointerdown" | "pointermove" | "pointerup" | "pointercancel" | "gotpointercapture"
         | "lostpointercapture" | "pointerenter" | "pointerleave" | "pointerover" | "pointerout" => {
             let evt: web_sys::PointerEvent = event.clone().dyn_into().unwrap();
-            VirtualEvent::PointerEvent(PointerEvent(Rc::new(WebsysPointerEvent(evt))))
+            SyntheticEvent::PointerEvent(PointerEvent(Rc::new(WebsysPointerEvent(evt))))
         }
         "select" => {
             let evt: web_sys::UiEvent = event.clone().dyn_into().unwrap();
-            VirtualEvent::SelectionEvent(SelectionEvent(Rc::new(WebsysGenericUiEvent(evt))))
+            SyntheticEvent::SelectionEvent(SelectionEvent(Rc::new(WebsysGenericUiEvent(evt))))
         }
         "touchcancel" | "touchend" | "touchmove" | "touchstart" => {
             let evt: web_sys::TouchEvent = event.clone().dyn_into().unwrap();
-            VirtualEvent::TouchEvent(TouchEvent(Rc::new(WebsysTouchEvent(evt))))
+            SyntheticEvent::TouchEvent(TouchEvent(Rc::new(WebsysTouchEvent(evt))))
         }
         "scroll" => {
             let evt: web_sys::UiEvent = event.clone().dyn_into().unwrap();
-            VirtualEvent::UIEvent(UIEvent(Rc::new(WebsysGenericUiEvent(evt))))
+            SyntheticEvent::UIEvent(UIEvent(Rc::new(WebsysGenericUiEvent(evt))))
         }
         "wheel" => {
             let evt: web_sys::WheelEvent = event.clone().dyn_into().unwrap();
-            VirtualEvent::WheelEvent(WheelEvent(Rc::new(WebsysWheelEvent(evt))))
+            SyntheticEvent::WheelEvent(WheelEvent(Rc::new(WebsysWheelEvent(evt))))
         }
         "animationstart" | "animationend" | "animationiteration" => {
             let evt: web_sys::AnimationEvent = event.clone().dyn_into().unwrap();
-            VirtualEvent::AnimationEvent(AnimationEvent(Rc::new(WebsysAnimationEvent(evt))))
+            SyntheticEvent::AnimationEvent(AnimationEvent(Rc::new(WebsysAnimationEvent(evt))))
         }
         "transitionend" => {
             let evt: web_sys::TransitionEvent = event.clone().dyn_into().unwrap();
-            VirtualEvent::TransitionEvent(TransitionEvent(Rc::new(WebsysTransitionEvent(evt))))
+            SyntheticEvent::TransitionEvent(TransitionEvent(Rc::new(WebsysTransitionEvent(evt))))
         }
         "abort" | "canplay" | "canplaythrough" | "durationchange" | "emptied" | "encrypted"
         | "ended" | "error" | "loadeddata" | "loadedmetadata" | "loadstart" | "pause" | "play"
         | "playing" | "progress" | "ratechange" | "seeked" | "seeking" | "stalled" | "suspend"
         | "timeupdate" | "volumechange" | "waiting" => {
             let evt: web_sys::UiEvent = event.clone().dyn_into().unwrap();
-            VirtualEvent::MediaEvent(MediaEvent(Rc::new(WebsysMediaEvent(evt))))
+            SyntheticEvent::MediaEvent(MediaEvent(Rc::new(WebsysMediaEvent(evt))))
         }
         "toggle" => {
             let evt: web_sys::UiEvent = event.clone().dyn_into().unwrap();
-            VirtualEvent::ToggleEvent(ToggleEvent(Rc::new(WebsysToggleEvent(evt))))
+            SyntheticEvent::ToggleEvent(ToggleEvent(Rc::new(WebsysToggleEvent(evt))))
         }
         _ => {
             let evt: web_sys::UiEvent = event.clone().dyn_into().unwrap();
-            VirtualEvent::UIEvent(UIEvent(Rc::new(WebsysGenericUiEvent(evt))))
+            SyntheticEvent::UIEvent(UIEvent(Rc::new(WebsysGenericUiEvent(evt))))
         }
     }
 }