mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Move most animation processing to script
This is preparation for sharing this code with layout_2020 and implementing selective off-the-main-thread animations. We still look for nodes not in the flow tree in the layout thread.
This commit is contained in:
parent
aa9f16ce45
commit
3b0619aedd
21 changed files with 444 additions and 371 deletions
|
@ -17,6 +17,9 @@
|
|||
//! a page runs its course and the script thread returns to processing events in the main event
|
||||
//! loop.
|
||||
|
||||
use crate::animations::{
|
||||
AnimationsUpdate, TransitionOrAnimationEvent, TransitionOrAnimationEventType,
|
||||
};
|
||||
use crate::devtools;
|
||||
use crate::document_loader::DocumentLoader;
|
||||
use crate::dom::animationevent::AnimationEvent;
|
||||
|
@ -141,8 +144,8 @@ use script_traits::{
|
|||
LayoutMsg, LoadData, LoadOrigin, MediaSessionActionType, MouseButton, MouseEventType,
|
||||
NewLayoutInfo, Painter, ProgressiveWebMetricType, ScriptMsg, ScriptThreadFactory,
|
||||
ScriptToConstellationChan, StructuredSerializedData, TimerSchedulerMsg, TouchEventType,
|
||||
TouchId, TransitionOrAnimationEvent, TransitionOrAnimationEventType, UntrustedNodeAddress,
|
||||
UpdatePipelineIdReason, WebrenderIpcSender, WheelDelta, WindowSizeData, WindowSizeType,
|
||||
TouchId, UntrustedNodeAddress, UpdatePipelineIdReason, WebrenderIpcSender, WheelDelta,
|
||||
WindowSizeData, WindowSizeType,
|
||||
};
|
||||
use servo_atoms::Atom;
|
||||
use servo_config::opts;
|
||||
|
@ -510,10 +513,8 @@ impl<'a> Iterator for DocumentsIter<'a> {
|
|||
// thread during parsing. For this reason, we don't trace the
|
||||
// incomplete parser contexts during GC.
|
||||
type IncompleteParserContexts = Vec<(PipelineId, ParserContext)>;
|
||||
unsafe_no_jsmanaged_fields!(RefCell<IncompleteParserContexts>);
|
||||
|
||||
unsafe_no_jsmanaged_fields!(TaskQueue<MainThreadScriptMsg>);
|
||||
|
||||
unsafe_no_jsmanaged_fields!(dyn BackgroundHangMonitorRegister);
|
||||
unsafe_no_jsmanaged_fields!(dyn BackgroundHangMonitor);
|
||||
|
||||
|
@ -644,6 +645,9 @@ pub struct ScriptThread {
|
|||
/// of the transition.
|
||||
animating_nodes: DomRefCell<HashMap<PipelineId, Vec<Dom<Node>>>>,
|
||||
|
||||
/// Animations events that are pending to be sent.
|
||||
animation_events: RefCell<Vec<TransitionOrAnimationEvent>>,
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#custom-element-reactions-stack>
|
||||
custom_element_reaction_stack: CustomElementReactionStack,
|
||||
|
||||
|
@ -826,20 +830,35 @@ impl ScriptThread {
|
|||
})
|
||||
}
|
||||
|
||||
pub unsafe fn note_newly_animating_nodes(
|
||||
pipeline_id: PipelineId,
|
||||
nodes: Vec<UntrustedNodeAddress>,
|
||||
) {
|
||||
/// Consume the list of pointer addresses corresponding to DOM nodes that are animating
|
||||
/// and root them in a per-pipeline list of nodes.
|
||||
///
|
||||
/// Unsafety: any pointer to invalid memory (ie. a GCed node) will trigger a crash.
|
||||
/// TODO: ensure caller uses rooted nodes instead of unsafe node addresses.
|
||||
pub(crate) unsafe fn process_animations_update(mut update: AnimationsUpdate) {
|
||||
if update.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
SCRIPT_THREAD_ROOT.with(|root| {
|
||||
let script_thread = &*root.get().unwrap();
|
||||
|
||||
if !update.events.is_empty() {
|
||||
script_thread
|
||||
.animation_events
|
||||
.borrow_mut()
|
||||
.append(&mut update.events);
|
||||
}
|
||||
|
||||
let js_runtime = script_thread.js_runtime.rt();
|
||||
let new_nodes = nodes
|
||||
let new_nodes = update
|
||||
.newly_animating_nodes
|
||||
.into_iter()
|
||||
.map(|n| Dom::from_ref(&*from_untrusted_node_address(js_runtime, n)));
|
||||
script_thread
|
||||
.animating_nodes
|
||||
.borrow_mut()
|
||||
.entry(pipeline_id)
|
||||
.entry(update.pipeline_id)
|
||||
.or_insert_with(Vec::new)
|
||||
.extend(new_nodes);
|
||||
})
|
||||
|
@ -1354,6 +1373,7 @@ impl ScriptThread {
|
|||
docs_with_no_blocking_loads: Default::default(),
|
||||
|
||||
animating_nodes: Default::default(),
|
||||
animation_events: Default::default(),
|
||||
|
||||
custom_element_reaction_stack: CustomElementReactionStack::new(),
|
||||
|
||||
|
@ -1620,9 +1640,8 @@ impl ScriptThread {
|
|||
}
|
||||
|
||||
// Perform step 11.10 from https://html.spec.whatwg.org/multipage/#event-loops.
|
||||
// TODO(mrobinson): This should also update the current animations and send events
|
||||
// to conform to the HTML specification. This might mean having events for rooting
|
||||
// DOM nodes and ultimately all animations living in script.
|
||||
// TODO(mrobinson): This should also update the current animations to conform to
|
||||
// the HTML specification.
|
||||
fn update_animations_and_send_events(&self) {
|
||||
for (_, document) in self.documents.borrow().iter() {
|
||||
// Only update the time if it isn't being managed by a test.
|
||||
|
@ -1630,6 +1649,13 @@ impl ScriptThread {
|
|||
document.update_animation_timeline();
|
||||
}
|
||||
}
|
||||
|
||||
// We remove the events because handling these events might trigger
|
||||
// a reflow which might want to add more events to the queue.
|
||||
let events = self.animation_events.replace(Vec::new());
|
||||
for event in events.into_iter() {
|
||||
self.handle_transition_or_animation_event(&event);
|
||||
}
|
||||
}
|
||||
|
||||
fn categorize_msg(&self, msg: &MixedMessage) -> ScriptThreadEventCategory {
|
||||
|
@ -1720,7 +1746,6 @@ impl ScriptThread {
|
|||
FocusIFrame(id, ..) => Some(id),
|
||||
WebDriverScriptCommand(id, ..) => Some(id),
|
||||
TickAllAnimations(id, ..) => Some(id),
|
||||
TransitionOrAnimationEvent { .. } => None,
|
||||
WebFontLoaded(id) => Some(id),
|
||||
DispatchIFrameLoadEvent {
|
||||
target: _,
|
||||
|
@ -1921,9 +1946,6 @@ impl ScriptThread {
|
|||
ConstellationControlMsg::TickAllAnimations(pipeline_id, tick_type) => {
|
||||
self.handle_tick_all_animations(pipeline_id, tick_type)
|
||||
},
|
||||
ConstellationControlMsg::TransitionOrAnimationEvent(ref event) => {
|
||||
self.handle_transition_or_animation_event(event);
|
||||
},
|
||||
ConstellationControlMsg::WebFontLoaded(pipeline_id) => {
|
||||
self.handle_web_font_loaded(pipeline_id)
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue