aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2020-05-05 13:36:57 +0200
committerMartin Robinson <mrobinson@igalia.com>2020-05-05 20:08:44 +0200
commit3a74013abcec241d67d2685e52a031409dc59dd4 (patch)
tree0fc6791d087797120dd960aa0fb1e0a9a6ebce92 /components
parentb585ce5b1f181996b2f8109a4e045eb6f5b3e2a0 (diff)
downloadservo-3a74013abcec241d67d2685e52a031409dc59dd4.tar.gz
servo-3a74013abcec241d67d2685e52a031409dc59dd4.zip
Start having animations conform to the HTML spec
This is a small step toward fixing #19242. The main idea is that the clock for animations should advance as the event loop ticks. We accomplish this by moving the clock from layout and naming it the "animation timeline" which is the spec language. This should fix flakiness with animations and transitions tests where a reflow could move animations forward while script was running. This change also starts to break out transition and animation events into their own data structure, because it's quite likely that the next step in fixing #19242 is to no longer send these events through a channel.
Diffstat (limited to 'components')
-rw-r--r--components/layout/animation.rs18
-rw-r--r--components/layout_thread/lib.rs23
-rw-r--r--components/layout_thread_2020/lib.rs23
-rw-r--r--components/script/animation_timeline.rs49
-rw-r--r--components/script/dom/document.rs21
-rw-r--r--components/script/dom/window.rs53
-rw-r--r--components/script/lib.rs1
-rw-r--r--components/script/script_thread.rs96
-rw-r--r--components/script_layout_interface/message.rs4
-rw-r--r--components/script_traits/lib.rs30
-rw-r--r--components/style/lib.rs1
-rw-r--r--components/style/timer.rs63
12 files changed, 159 insertions, 223 deletions
diff --git a/components/layout/animation.rs b/components/layout/animation.rs
index 09e3c75ec2c..c85d962008c 100644
--- a/components/layout/animation.rs
+++ b/components/layout/animation.rs
@@ -13,7 +13,7 @@ use msg::constellation_msg::PipelineId;
use script_traits::UntrustedNodeAddress;
use script_traits::{
AnimationState, ConstellationControlMsg, LayoutMsg as ConstellationMsg,
- TransitionOrAnimationEventType,
+ TransitionOrAnimationEvent, TransitionOrAnimationEventType,
};
use style::animation::{Animation, ElementAnimationState};
@@ -120,13 +120,15 @@ fn update_animation_state(
};
script_channel
- .send(ConstellationControlMsg::TransitionOrAnimationEvent {
- pipeline_id,
- event_type,
- node: node.to_untrusted_node_address(),
- property_or_animation_name,
- elapsed_time,
- })
+ .send(ConstellationControlMsg::TransitionOrAnimationEvent(
+ TransitionOrAnimationEvent {
+ pipeline_id,
+ event_type,
+ node: node.to_untrusted_node_address(),
+ property_or_animation_name,
+ elapsed_time,
+ },
+ ))
.unwrap()
};
diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs
index 38982fa826b..dfc3a2966df 100644
--- a/components/layout_thread/lib.rs
+++ b/components/layout_thread/lib.rs
@@ -87,7 +87,6 @@ use script_traits::{ScrollState, UntrustedNodeAddress, WindowSizeData};
use servo_arc::Arc as ServoArc;
use servo_atoms::Atom;
use servo_config::opts;
-use servo_config::pref;
use servo_url::{ImmutableOrigin, ServoUrl};
use std::borrow::ToOwned;
use std::cell::{Cell, RefCell};
@@ -117,7 +116,6 @@ use style::stylesheets::{
};
use style::stylist::Stylist;
use style::thread_state::{self, ThreadState};
-use style::timer::Timer;
use style::traversal::DomTraversal;
use style::traversal_flags::TraversalFlags;
use style_traits::CSSPixel;
@@ -220,10 +218,6 @@ pub struct LayoutThread {
/// Webrender document.
webrender_document: webrender_api::DocumentId,
- /// The timer object to control the timing of the animations. This should
- /// only be a test-mode timer during testing for animations.
- timer: Timer,
-
/// Paint time metrics.
paint_time_metrics: PaintTimeMetrics,
@@ -583,11 +577,6 @@ impl LayoutThread {
inner_window_dimensions_response: None,
})),
webrender_image_cache: Arc::new(RwLock::new(FnvHashMap::default())),
- timer: if pref!(layout.animations.test.enabled) {
- Timer::test_mode()
- } else {
- Timer::new()
- },
paint_time_metrics: paint_time_metrics,
layout_query_waiting_time: Histogram::new(),
last_iframe_sizes: Default::default(),
@@ -623,6 +612,7 @@ impl LayoutThread {
guards: StylesheetGuards<'a>,
snapshot_map: &'a SnapshotMap,
origin: ImmutableOrigin,
+ animation_timeline_value: f64,
) -> LayoutContext<'a> {
LayoutContext {
id: self.id,
@@ -634,7 +624,7 @@ impl LayoutThread {
visited_styles_enabled: false,
animation_states: self.animation_states.clone(),
registered_speculative_painters: &self.registered_painters,
- current_time_for_animations: self.timer.seconds(),
+ current_time_for_animations: animation_timeline_value,
traversal_flags: TraversalFlags::empty(),
snapshot_map: snapshot_map,
},
@@ -1306,12 +1296,6 @@ impl LayoutThread {
let device = Device::new(MediaType::screen(), initial_viewport, device_pixel_ratio);
let sheet_origins_affected_by_device_change = self.stylist.set_device(device, &guards);
- if pref!(layout.animations.test.enabled) {
- if let Some(delta) = data.advance_clock_delta {
- self.timer.increment(delta as f64 / 1000.0);
- }
- }
-
self.stylist
.force_stylesheet_origins_dirty(sheet_origins_affected_by_device_change);
self.viewport_size =
@@ -1429,7 +1413,8 @@ impl LayoutThread {
self.stylist.flush(&guards, Some(element), Some(&map));
// Create a layout context for use throughout the following passes.
- let mut layout_context = self.build_layout_context(guards.clone(), &map, origin);
+ let mut layout_context =
+ self.build_layout_context(guards.clone(), &map, origin, data.animation_timeline_value);
let pool;
let (thread_pool, num_threads) = if self.parallel_flag {
diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs
index 1b8366a4881..7639c2dc70c 100644
--- a/components/layout_thread_2020/lib.rs
+++ b/components/layout_thread_2020/lib.rs
@@ -71,7 +71,6 @@ use script_traits::{ScrollState, UntrustedNodeAddress, WindowSizeData};
use servo_arc::Arc as ServoArc;
use servo_atoms::Atom;
use servo_config::opts;
-use servo_config::pref;
use servo_url::{ImmutableOrigin, ServoUrl};
use std::cell::{Cell, RefCell};
use std::collections::HashMap;
@@ -98,7 +97,6 @@ use style::stylesheets::{
};
use style::stylist::Stylist;
use style::thread_state::{self, ThreadState};
-use style::timer::Timer;
use style::traversal::DomTraversal;
use style::traversal_flags::TraversalFlags;
use style_traits::CSSPixel;
@@ -195,10 +193,6 @@ pub struct LayoutThread {
/// Webrender document.
webrender_document: webrender_api::DocumentId,
- /// The timer object to control the timing of the animations. This should
- /// only be a test-mode timer during testing for animations.
- timer: Timer,
-
/// Paint time metrics.
paint_time_metrics: PaintTimeMetrics,
@@ -545,11 +539,6 @@ impl LayoutThread {
inner_window_dimensions_response: None,
})),
webrender_image_cache: Default::default(),
- timer: if pref!(layout.animations.test.enabled) {
- Timer::test_mode()
- } else {
- Timer::new()
- },
paint_time_metrics: paint_time_metrics,
busy,
load_webfonts_synchronously,
@@ -582,6 +571,7 @@ impl LayoutThread {
guards: StylesheetGuards<'a>,
snapshot_map: &'a SnapshotMap,
origin: ImmutableOrigin,
+ animation_timeline_value: f64,
) -> LayoutContext<'a> {
LayoutContext {
id: self.id,
@@ -593,7 +583,7 @@ impl LayoutThread {
visited_styles_enabled: false,
animation_states: Default::default(),
registered_speculative_painters: &self.registered_painters,
- timer: self.timer.clone(),
+ current_time_for_animations: animation_timeline_value,
traversal_flags: TraversalFlags::empty(),
snapshot_map: snapshot_map,
},
@@ -977,12 +967,6 @@ impl LayoutThread {
let device = Device::new(MediaType::screen(), initial_viewport, device_pixel_ratio);
let sheet_origins_affected_by_device_change = self.stylist.set_device(device, &guards);
- if pref!(layout.animations.test.enabled) {
- if let Some(delta) = data.advance_clock_delta {
- self.timer.increment(delta as f64 / 1000.0);
- }
- }
-
self.stylist
.force_stylesheet_origins_dirty(sheet_origins_affected_by_device_change);
self.viewport_size =
@@ -1082,7 +1066,8 @@ impl LayoutThread {
self.stylist.flush(&guards, Some(element), Some(&map));
// Create a layout context for use throughout the following passes.
- let mut layout_context = self.build_layout_context(guards.clone(), &map, origin);
+ let mut layout_context =
+ self.build_layout_context(guards.clone(), &map, origin, data.animation_timeline_value);
let traversal = RecalcStyle::new(layout_context);
let token = {
diff --git a/components/script/animation_timeline.rs b/components/script/animation_timeline.rs
new file mode 100644
index 00000000000..e0ad520db61
--- /dev/null
+++ b/components/script/animation_timeline.rs
@@ -0,0 +1,49 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+#![deny(missing_docs)]
+
+//! A timeline module, used to specify an `AnimationTimeline` which determines
+//! the time used for synchronizing animations in the script thread.
+
+use time;
+
+/// A `AnimationTimeline` which is used to synchronize animations during the script
+/// event loop.
+#[derive(Clone, Copy, Debug, JSTraceable, MallocSizeOf)]
+pub struct AnimationTimeline {
+ current_value: f64,
+}
+
+impl AnimationTimeline {
+ /// Creates a new "normal" timeline, i.e., a "Current" mode timer.
+ #[inline]
+ pub fn new() -> Self {
+ Self {
+ current_value: time::precise_time_s(),
+ }
+ }
+
+ /// Creates a new "test mode" timeline, with initial time 0.
+ #[inline]
+ pub fn new_for_testing() -> Self {
+ Self { current_value: 0. }
+ }
+
+ /// Returns the current value of the timeline in seconds.
+ pub fn current_value(&self) -> f64 {
+ self.current_value
+ }
+
+ /// Updates the value of the `AnimationTimeline` to the current clock time.
+ pub fn update(&mut self) {
+ self.current_value = time::precise_time_s();
+ }
+
+ /// Increments the current value of the timeline by a specific number of seconds.
+ /// This is used for testing.
+ pub fn advance_specific(&mut self, by: f64) {
+ self.current_value += by;
+ }
+}
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index eacd6a11745..5e40f433da5 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+use crate::animation_timeline::AnimationTimeline;
use crate::document_loader::{DocumentLoader, LoadType};
use crate::dom::attr::Attr;
use crate::dom::beforeunloadevent::BeforeUnloadEvent;
@@ -380,6 +381,9 @@ pub struct Document {
csp_list: DomRefCell<Option<CspList>>,
/// https://w3c.github.io/slection-api/#dfn-selection
selection: MutNullableDom<Selection>,
+ /// A timeline for animations which is used for synchronizing animations.
+ /// https://drafts.csswg.org/web-animations/#timeline
+ animation_timeline: DomRefCell<AnimationTimeline>,
}
#[derive(JSTraceable, MallocSizeOf)]
@@ -2904,6 +2908,11 @@ impl Document {
dirty_webgl_contexts: DomRefCell::new(HashMap::new()),
csp_list: DomRefCell::new(None),
selection: MutNullableDom::new(None),
+ animation_timeline: if pref!(layout.animations.test.enabled) {
+ DomRefCell::new(AnimationTimeline::new_for_testing())
+ } else {
+ DomRefCell::new(AnimationTimeline::new())
+ },
}
}
@@ -3605,6 +3614,18 @@ impl Document {
})
.collect()
}
+
+ pub fn advance_animation_timeline_for_testing(&self, delta: f64) {
+ self.animation_timeline.borrow_mut().advance_specific(delta);
+ }
+
+ pub fn update_animation_timeline(&self) {
+ self.animation_timeline.borrow_mut().update();
+ }
+
+ pub fn current_animation_timeline_value(&self) -> f64 {
+ self.animation_timeline.borrow().current_value()
+ }
}
impl Element {
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 481586a71ae..414ef0f2e45 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -173,8 +173,7 @@ pub enum ReflowReason {
IFrameLoadEvent,
MissingExplicitReflow,
ElementStateChanged,
- TickAnimations,
- AdvanceClock(i32),
+ PendingReflow,
}
#[dom_struct]
@@ -1550,12 +1549,9 @@ impl Window {
/// layout animation clock.
pub fn advance_animation_clock(&self, delta: i32) {
let pipeline_id = self.upcast::<GlobalScope>().pipeline_id();
- ScriptThread::restyle_animating_nodes_for_advancing_clock(&pipeline_id);
- self.force_reflow(
- ReflowGoal::TickAnimations,
- ReflowReason::AdvanceClock(delta),
- None,
- );
+ self.Document()
+ .advance_animation_timeline_for_testing(delta as f64 / 1000.);
+ ScriptThread::handle_tick_all_animations_for_testing(pipeline_id);
}
/// Reflows the page unconditionally if possible and not suppressed. This
@@ -1632,11 +1628,6 @@ impl Window {
document.flush_dirty_canvases();
}
- let advance_clock_delta = match reason {
- ReflowReason::AdvanceClock(delta) => Some(delta),
- _ => None,
- };
-
// Send new document and relevant styles to layout.
let needs_display = reflow_goal.needs_display();
let reflow = ScriptReflow {
@@ -1651,7 +1642,7 @@ impl Window {
script_join_chan: join_chan,
dom_count: document.dom_count(),
pending_restyles: document.drain_pending_restyles(),
- advance_clock_delta,
+ animation_timeline_value: document.current_animation_timeline_value(),
};
self.layout_chan
@@ -2453,8 +2444,7 @@ fn should_move_clip_rect(clip_rect: UntypedRect<Au>, new_viewport: UntypedRect<f
}
fn debug_reflow_events(id: PipelineId, reflow_goal: &ReflowGoal, reason: &ReflowReason) {
- let mut debug_msg = format!("**** pipeline={}", id);
- debug_msg.push_str(match *reflow_goal {
+ let goal_string = match *reflow_goal {
ReflowGoal::Full => "\tFull",
ReflowGoal::TickAnimations => "\tTickAnimations",
ReflowGoal::LayoutQuery(ref query_msg, _) => match query_msg {
@@ -2471,34 +2461,9 @@ fn debug_reflow_events(id: PipelineId, reflow_goal: &ReflowGoal, reason: &Reflow
&QueryMsg::ElementInnerTextQuery(_) => "\tElementInnerTextQuery",
&QueryMsg::InnerWindowDimensionsQuery(_) => "\tInnerWindowDimensionsQuery",
},
- });
-
- debug_msg.push_str(match *reason {
- ReflowReason::CachedPageNeededReflow => "\tCachedPageNeededReflow",
- ReflowReason::RefreshTick => "\tRefreshTick",
- ReflowReason::FirstLoad => "\tFirstLoad",
- ReflowReason::KeyEvent => "\tKeyEvent",
- ReflowReason::MouseEvent => "\tMouseEvent",
- ReflowReason::Query => "\tQuery",
- ReflowReason::Timer => "\tTimer",
- ReflowReason::Viewport => "\tViewport",
- ReflowReason::WindowResize => "\tWindowResize",
- ReflowReason::DOMContentLoaded => "\tDOMContentLoaded",
- ReflowReason::DocumentLoaded => "\tDocumentLoaded",
- ReflowReason::StylesheetLoaded => "\tStylesheetLoaded",
- ReflowReason::ImageLoaded => "\tImageLoaded",
- ReflowReason::RequestAnimationFrame => "\tRequestAnimationFrame",
- ReflowReason::WebFontLoaded => "\tWebFontLoaded",
- ReflowReason::WorkletLoaded => "\tWorkletLoaded",
- ReflowReason::FramedContentChanged => "\tFramedContentChanged",
- ReflowReason::IFrameLoadEvent => "\tIFrameLoadEvent",
- ReflowReason::MissingExplicitReflow => "\tMissingExplicitReflow",
- ReflowReason::ElementStateChanged => "\tElementStateChanged",
- ReflowReason::TickAnimations => "\tTickAnimations",
- ReflowReason::AdvanceClock(..) => "\tAdvanceClock",
- });
-
- println!("{}", debug_msg);
+ };
+
+ println!("**** pipeline={}\t{}\t{:?}", id, goal_string, reason);
}
impl Window {
diff --git a/components/script/lib.rs b/components/script/lib.rs
index 4eeca229e01..cd73045456a 100644
--- a/components/script/lib.rs
+++ b/components/script/lib.rs
@@ -47,6 +47,7 @@ extern crate servo_atoms;
#[macro_use]
extern crate style;
+mod animation_timeline;
#[warn(deprecated)]
#[macro_use]
mod task;
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 5a99d800799..008274ded47 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -141,11 +141,12 @@ use script_traits::{
LayoutMsg, LoadData, LoadOrigin, MediaSessionActionType, MouseButton, MouseEventType,
NewLayoutInfo, Painter, ProgressiveWebMetricType, ScriptMsg, ScriptThreadFactory,
ScriptToConstellationChan, StructuredSerializedData, TimerSchedulerMsg, TouchEventType,
- TouchId, TransitionOrAnimationEventType, UntrustedNodeAddress, UpdatePipelineIdReason,
- WebrenderIpcSender, WheelDelta, WindowSizeData, WindowSizeType,
+ TouchId, TransitionOrAnimationEvent, TransitionOrAnimationEventType, UntrustedNodeAddress,
+ UpdatePipelineIdReason, WebrenderIpcSender, WheelDelta, WindowSizeData, WindowSizeType,
};
use servo_atoms::Atom;
use servo_config::opts;
+use servo_config::pref;
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
use std::borrow::Cow;
use std::cell::Cell;
@@ -1498,7 +1499,6 @@ impl ScriptThread {
})
},
FromConstellation(ConstellationControlMsg::TickAllAnimations(pipeline_id, _)) => {
- // step 7.8
if !animation_ticks.contains(&pipeline_id) {
animation_ticks.insert(pipeline_id);
sequential.push(event);
@@ -1544,6 +1544,9 @@ impl ScriptThread {
}
}
+ // Step 11.10 from https://html.spec.whatwg.org/multipage/#event-loops.
+ self.update_animations_and_send_events();
+
// Process the gathered events.
debug!("Processing events.");
for msg in sequential {
@@ -1603,7 +1606,7 @@ impl ScriptThread {
let pending_reflows = window.get_pending_reflow_count();
if pending_reflows > 0 {
- window.reflow(ReflowGoal::Full, ReflowReason::ImageLoaded);
+ window.reflow(ReflowGoal::Full, ReflowReason::PendingReflow);
} else {
// Reflow currently happens when explicitly invoked by code that
// knows the document could have been modified. This should really
@@ -1616,6 +1619,19 @@ impl ScriptThread {
true
}
+ // 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.
+ 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.
+ if !pref!(layout.animations.test.enabled) {
+ document.update_animation_timeline();
+ }
+ }
+ }
+
fn categorize_msg(&self, msg: &MixedMessage) -> ScriptThreadEventCategory {
match *msg {
MixedMessage::FromConstellation(ref inner_msg) => match *inner_msg {
@@ -1905,20 +1921,8 @@ impl ScriptThread {
ConstellationControlMsg::TickAllAnimations(pipeline_id, tick_type) => {
self.handle_tick_all_animations(pipeline_id, tick_type)
},
- ConstellationControlMsg::TransitionOrAnimationEvent {
- pipeline_id,
- event_type,
- node,
- property_or_animation_name,
- elapsed_time,
- } => {
- self.handle_transition_or_animation_event(
- pipeline_id,
- event_type,
- node,
- property_or_animation_name,
- elapsed_time,
- );
+ ConstellationControlMsg::TransitionOrAnimationEvent(ref event) => {
+ self.handle_transition_or_animation_event(event);
},
ConstellationControlMsg::WebFontLoaded(pipeline_id) => {
self.handle_web_font_loaded(pipeline_id)
@@ -2914,22 +2918,12 @@ impl ScriptThread {
debug!("Exited script thread.");
}
- fn restyle_animating_nodes(&self, id: &PipelineId) -> bool {
- match self.animating_nodes.borrow().get(id) {
- Some(nodes) => {
- for node in nodes.iter() {
- node.dirty(NodeDamage::NodeStyleDamaged);
- }
- true
- },
- None => false,
- }
- }
-
- pub fn restyle_animating_nodes_for_advancing_clock(id: &PipelineId) {
+ /// Handles animation tick requested during testing.
+ pub fn handle_tick_all_animations_for_testing(id: PipelineId) {
SCRIPT_THREAD_ROOT.with(|root| {
let script_thread = unsafe { &*root.get().unwrap() };
- script_thread.restyle_animating_nodes(id);
+ script_thread
+ .handle_tick_all_animations(id, AnimationTickType::CSS_ANIMATIONS_AND_TRANSITIONS);
});
}
@@ -2943,38 +2937,32 @@ impl ScriptThread {
document.run_the_animation_frame_callbacks();
}
if tick_type.contains(AnimationTickType::CSS_ANIMATIONS_AND_TRANSITIONS) {
- if !self.restyle_animating_nodes(&id) {
- return;
+ match self.animating_nodes.borrow().get(&id) {
+ Some(nodes) => {
+ for node in nodes.iter() {
+ node.dirty(NodeDamage::NodeStyleDamaged);
+ }
+ },
+ None => return,
}
- document.window().force_reflow(
- ReflowGoal::TickAnimations,
- ReflowReason::TickAnimations,
- None,
- );
+ document.window().add_pending_reflow();
}
}
/// Handles firing of transition-related events.
///
/// TODO(mrobinson): Add support for more events.
- fn handle_transition_or_animation_event(
- &self,
- pipeline_id: PipelineId,
- event_type: TransitionOrAnimationEventType,
- unsafe_node: UntrustedNodeAddress,
- property_or_animation_name: String,
- elapsed_time: f64,
- ) {
+ fn handle_transition_or_animation_event(&self, event: &TransitionOrAnimationEvent) {
let js_runtime = self.js_runtime.rt();
- let node = unsafe { from_untrusted_node_address(js_runtime, unsafe_node) };
+ let node = unsafe { from_untrusted_node_address(js_runtime, event.node) };
// We limit the scope of the borrow here, so that we don't maintain this borrow
// and then incidentally trigger another layout. That might result in a double
// mutable borrow of `animating_nodes`.
{
let mut animating_nodes = self.animating_nodes.borrow_mut();
- let nodes = match animating_nodes.get_mut(&pipeline_id) {
+ let nodes = match animating_nodes.get_mut(&event.pipeline_id) {
Some(nodes) => nodes,
None => {
return warn!(
@@ -2996,12 +2984,12 @@ impl ScriptThread {
},
};
- if event_type.finalizes_transition_or_animation() {
+ if event.event_type.finalizes_transition_or_animation() {
nodes.remove(node_index);
}
}
- let event_atom = match event_type {
+ let event_atom = match event.event_type {
TransitionOrAnimationEventType::AnimationEnd => atom!("animationend"),
TransitionOrAnimationEventType::TransitionCancel => atom!("transitioncancel"),
TransitionOrAnimationEventType::TransitionEnd => atom!("transitionend"),
@@ -3013,11 +3001,11 @@ impl ScriptThread {
};
// TODO: Handle pseudo-elements properly
- let property_or_animation_name = DOMString::from(property_or_animation_name);
- let elapsed_time = Finite::new(elapsed_time as f32).unwrap();
+ let property_or_animation_name = DOMString::from(event.property_or_animation_name.clone());
+ let elapsed_time = Finite::new(event.elapsed_time as f32).unwrap();
let window = window_from_node(&*node);
- if event_type.is_transition_event() {
+ if event.event_type.is_transition_event() {
let event_init = TransitionEventInit {
parent,
propertyName: property_or_animation_name,
diff --git a/components/script_layout_interface/message.rs b/components/script_layout_interface/message.rs
index f42304ed5b5..ac5c0c59ba0 100644
--- a/components/script_layout_interface/message.rs
+++ b/components/script_layout_interface/message.rs
@@ -207,8 +207,8 @@ pub struct ScriptReflow {
pub origin: ImmutableOrigin,
/// Restyle snapshot map.
pub pending_restyles: Vec<(TrustedNodeAddress, PendingRestyle)>,
- /// How much to advance the clock when testing.
- pub advance_clock_delta: Option<i32>,
+ /// The current animation timeline value.
+ pub animation_timeline_value: f64,
}
pub struct LayoutThreadInit {
diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs
index caa3cf2d34a..aeac1ff6087 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -318,6 +318,22 @@ impl TransitionOrAnimationEventType {
}
}
+#[derive(Deserialize, Serialize)]
+/// A transition or animation event.
+pub struct TransitionOrAnimationEvent {
+ /// The pipeline id of the layout task that sent this message.
+ pub pipeline_id: PipelineId,
+ /// The type of transition event this should trigger.
+ pub event_type: TransitionOrAnimationEventType,
+ /// The address of the node which owns this transition.
+ pub node: UntrustedNodeAddress,
+ /// The name of the property that is transitioning (in the case of a transition)
+ /// or the name of the animation (in the case of an animation).
+ pub property_or_animation_name: String,
+ /// The elapsed time property to send with this transition event.
+ pub elapsed_time: f64,
+}
+
/// Messages sent from the constellation or layout to the script thread.
#[derive(Deserialize, Serialize)]
pub enum ConstellationControlMsg {
@@ -405,19 +421,7 @@ pub enum ConstellationControlMsg {
/// Notifies script thread that all animations are done
TickAllAnimations(PipelineId, AnimationTickType),
/// Notifies the script thread that a transition or animation related event should be sent.
- TransitionOrAnimationEvent {
- /// The pipeline id of the layout task that sent this message.
- pipeline_id: PipelineId,
- /// The type of transition event this should trigger.
- event_type: TransitionOrAnimationEventType,
- /// The address of the node which owns this transition.
- node: UntrustedNodeAddress,
- /// The name of the property that is transitioning (in the case of a transition)
- /// or the name of the animation (in the case of an animation).
- property_or_animation_name: String,
- /// The elapsed time property to send with this transition event.
- elapsed_time: f64,
- },
+ TransitionOrAnimationEvent(TransitionOrAnimationEvent),
/// Notifies the script thread that a new Web font has been loaded, and thus the page should be
/// reflowed.
WebFontLoaded(PipelineId),
diff --git a/components/style/lib.rs b/components/style/lib.rs
index 1abb740686d..7ec3ded3395 100644
--- a/components/style/lib.rs
+++ b/components/style/lib.rs
@@ -157,7 +157,6 @@ pub mod stylesheet_set;
pub mod stylesheets;
pub mod stylist;
pub mod thread_state;
-pub mod timer;
pub mod traversal;
pub mod traversal_flags;
pub mod use_counters;
diff --git a/components/style/timer.rs b/components/style/timer.rs
deleted file mode 100644
index 1b5ff8d370c..00000000000
--- a/components/style/timer.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-
-#![deny(missing_docs)]
-
-//! A timer module, used to define a `Timer` type, that is controlled by script.
-
-use time;
-
-/// The `TimerMode` is used to determine what time should the `Timer` return.
-#[derive(Clone, Debug)]
-enum TimerMode {
- /// The timer should return a fixed value.
- Test(f64),
- /// The timer should return the actual time.
- Current,
-}
-
-/// A `Timer` struct that takes care of giving the current time for animations.
-///
-/// This is needed to be allowed to hook the time in the animations' test-mode.
-#[derive(Clone, Debug)]
-pub struct Timer {
- mode: TimerMode,
-}
-
-impl Timer {
- /// Creates a new "normal" timer, i.e., a "Current" mode timer.
- #[inline]
- pub fn new() -> Self {
- Timer {
- mode: TimerMode::Current,
- }
- }
-
- /// Creates a new "test mode" timer, with initial time 0.
- #[inline]
- pub fn test_mode() -> Self {
- Timer {
- mode: TimerMode::Test(0.),
- }
- }
-
- /// Returns the current time, at least from the caller's perspective. In
- /// test mode returns whatever the value is.
- pub fn seconds(&self) -> f64 {
- match self.mode {
- TimerMode::Test(test_value) => test_value,
- TimerMode::Current => time::precise_time_s(),
- }
- }
-
- /// Increments the current clock. Panics if the clock is not on test mode.
- pub fn increment(&mut self, by: f64) {
- match self.mode {
- TimerMode::Test(ref mut val) => *val += by,
- TimerMode::Current => {
- panic!("Timer::increment called for a non-test mode timer. This is a bug.")
- },
- }
- }
-}