wip: more work on priority

This commit is contained in:
Jonathan Kelley committed 2021-08-25 15:54:33 -04:00
1 parent 05e960b6b0
commit cef116aa3a
14 files changed
+279 -379

No files matched your search

+8 -154
View File
@@ -17,169 +17,34 @@ use crate::{
#[derive(Debug)]
pub struct EventTrigger {
/// The originator of the event trigger
pub originator: ScopeId,
pub scope: ScopeId,
/// The optional real node associated with the trigger
pub real_node_id: Option<ElementId>,
pub mounted_dom_id: Option<ElementId>,
/// The type of event
pub event: VirtualEvent,
/// The priority of the event
pub priority: EventPriority,
}
#[derive(PartialEq, Eq, Clone, Copy)]
pub struct EventKey {
/// The originator of the event trigger
pub originator: ScopeId,
/// The priority of the event
pub priority: EventPriority,
/// The height of the scope (used for ordering)
pub height: u32,
// TODO: add the time that the event was queued
}
impl PartialOrd for EventKey {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
todo!()
}
}
impl Ord for EventKey {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
todo!()
}
}
/// Priority of Event Triggers.
///
/// Internally, Dioxus will abort work that's taking too long if new, more important, work arrives. Unlike React, Dioxus
/// won't be afraid to pause work or flush changes to the RealDOM. This is called "cooperative scheduling". Some Renderers
/// implement this form of scheduling internally, however Dioxus will perform its own scheduling as well.
///
/// The ultimate goal of the scheduler is to manage latency of changes, prioritizing "flashier" changes over "subtler" changes.
///
/// React has a 5-tier priority system. However, they break things into "Continuous" and "Discrete" priority. For now,
/// we keep it simple, and just use a 3-tier priority system.
///
/// - NoPriority = 0
/// - LowPriority = 1
/// - NormalPriority = 2
/// - UserBlocking = 3
/// - HighPriority = 4
/// - ImmediatePriority = 5
///
/// We still have a concept of discrete vs continuous though - discrete events won't be batched, but continuous events will.
/// This means that multiple "scroll" events will be processed in a single frame, but multiple "click" events will be
/// flushed before proceeding. Multiple discrete events is highly unlikely, though.
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord)]
pub enum EventPriority {
/// "High Priority" work will not interrupt other high priority work, but will interrupt medium and low priority work.
///
/// This is typically reserved for things like user interaction.
///
/// React calls these "discrete" events, but with an extra category of "user-blocking".
High = 2,
/// "Medium priority" work is generated by page events not triggered by the user. These types of events are less important
/// than "High Priority" events and will take presedence over low priority events.
///
/// This is typically reserved for VirtualEvents that are not related to keyboard or mouse input.
///
/// React calls these "continuous" events (e.g. mouse move, mouse wheel, touch move, etc).
Medium = 1,
/// "Low Priority" work will always be pre-empted unless the work is significantly delayed, in which case it will be
/// advanced to the front of the work queue until completed.
///
/// The primary user of Low Priority work is the asynchronous work system (suspense).
///
/// This is considered "idle" work or "background" work.
Low = 0,
}
impl EventTrigger {
pub fn new(
event: VirtualEvent,
scope: ScopeId,
mounted_dom_id: Option<ElementId>,
priority: EventPriority,
) -> Self {
Self {
priority,
originator: scope,
real_node_id: mounted_dom_id,
event,
}
}
pub discrete: bool,
}
pub enum VirtualEvent {
// Whenever a task is ready (complete) Dioxus produces this "AsyncEvent"
//
// Async events don't necessarily propagate into a scope being ran. It's up to the event itself
// to force an update for itself.
//
// Most async events should have a low priority.
//
// This type exists for the task/concurrency system to signal that a task is ready.
// However, this does not necessarily signal that a scope must be re-ran, so the hook implementation must cause its
// own re-run.
AsyncEvent {
should_rerender: bool,
},
// Suspense events are a type of async event generated when suspended nodes are ready to be processed.
//
// they have the lowest priority
SuspenseEvent {
hook_idx: usize,
domnode: Rc<Cell<Option<ElementId>>>,
},
// image event has conflicting method types
// ImageEvent(event_data::ImageEvent),
// Real events
KeyboardEvent(on::KeyboardEvent),
TouchEvent(on::TouchEvent),
MouseEvent(on::MouseEvent),
ClipboardEvent(on::ClipboardEvent),
CompositionEvent(on::CompositionEvent),
KeyboardEvent(on::KeyboardEvent),
FocusEvent(on::FocusEvent),
FormEvent(on::FormEvent),
SelectionEvent(on::SelectionEvent),
TouchEvent(on::TouchEvent),
UIEvent(on::UIEvent),
WheelEvent(on::WheelEvent),
MediaEvent(on::MediaEvent),
AnimationEvent(on::AnimationEvent),
TransitionEvent(on::TransitionEvent),
ToggleEvent(on::ToggleEvent),
MouseEvent(on::MouseEvent),
PointerEvent(on::PointerEvent),
}
impl VirtualEvent {
pub fn is_input_event(&self) -> bool {
match self {
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(_) => true,
VirtualEvent::AsyncEvent { .. } | VirtualEvent::SuspenseEvent { .. } => false,
}
}
// ImageEvent(event_data::ImageEvent),
}
impl std::fmt::Debug for VirtualEvent {
@@ -200,8 +65,6 @@ impl std::fmt::Debug for VirtualEvent {
VirtualEvent::ToggleEvent(_) => "ToggleEvent",
VirtualEvent::MouseEvent(_) => "MouseEvent",
VirtualEvent::PointerEvent(_) => "PointerEvent",
VirtualEvent::AsyncEvent { .. } => "AsyncEvent",
VirtualEvent::SuspenseEvent { .. } => "SuspenseEvent",
};
f.debug_struct("VirtualEvent").field("type", &name).finish()
@@ -215,8 +78,7 @@ pub mod on {
//! Synthetic events are immutable and wrapped in Arc. It is the intention for Dioxus renderers to re-use the underyling
//! Arc allocation through "get_mut"
//!
//!
//!
//! React recently dropped support for re-using event allocation and just passes the real event along.
#![allow(unused)]
use bumpalo::boxed::Box as BumpBox;
@@ -285,14 +147,6 @@ pub mod on {
}
// The Dioxus Synthetic event system
//
//
//
//
//
//
//
//
event_directory! {
ClipboardEventInner(ClipboardEvent): [
/// Called when "copy"