wip: more work on priority
This commit is contained in:
1 parent
05e960b6b0
commit
cef116aa3a
14 files changed
+279
-379
No files matched your search
+8
-154
@@ -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"
|
||||
|
||||
Reference in new issue
Block a user