mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Implement animationiteration event
This event is triggered when an animation iterates. This change also moves iteration out of style calculation to an "update animations" which is the next part of having animation event handling match the HTML spec.
This commit is contained in:
parent
f02aba1ed2
commit
873cdd1336
12 changed files with 93 additions and 80 deletions
|
@ -35,6 +35,30 @@ impl Animations {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn update_for_new_timeline_value(
|
||||
&mut self,
|
||||
window: &Window,
|
||||
now: f64,
|
||||
) -> AnimationsUpdate {
|
||||
let mut update = AnimationsUpdate::new(window.pipeline_id());
|
||||
let mut sets = self.sets.write();
|
||||
|
||||
for set in sets.values_mut() {
|
||||
// When necessary, iterate our running animations to the next iteration.
|
||||
for animation in set.animations.iter_mut() {
|
||||
if animation.iterate_if_necessary(now) {
|
||||
update.add_event(
|
||||
animation.node,
|
||||
animation.name.to_string(),
|
||||
TransitionOrAnimationEventType::AnimationIteration,
|
||||
animation.active_duration(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
update
|
||||
}
|
||||
|
||||
/// Processes any new animations that were discovered after reflow. Collect messages
|
||||
/// that trigger events for any animations that changed state.
|
||||
/// TODO(mrobinson): The specification dictates that this should happen before reflow.
|
||||
|
@ -255,6 +279,9 @@ pub enum TransitionOrAnimationEventType {
|
|||
TransitionCancel,
|
||||
/// "The animationend event occurs when the animation finishes"
|
||||
AnimationEnd,
|
||||
/// "The animationiteration event occurs at the end of each iteration of an
|
||||
/// animation, except when an animationend event would fire at the same time."
|
||||
AnimationIteration,
|
||||
}
|
||||
|
||||
impl TransitionOrAnimationEventType {
|
||||
|
@ -263,7 +290,7 @@ impl TransitionOrAnimationEventType {
|
|||
pub fn finalizes_transition_or_animation(&self) -> bool {
|
||||
match *self {
|
||||
Self::TransitionEnd | Self::TransitionCancel | Self::AnimationEnd => true,
|
||||
Self::TransitionRun => false,
|
||||
Self::TransitionRun | Self::AnimationIteration => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -271,7 +298,7 @@ impl TransitionOrAnimationEventType {
|
|||
pub fn is_transition_event(&self) -> bool {
|
||||
match *self {
|
||||
Self::TransitionRun | Self::TransitionEnd | Self::TransitionCancel => true,
|
||||
Self::AnimationEnd => false,
|
||||
Self::AnimationEnd | Self::AnimationIteration => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3750,12 +3750,26 @@ impl Document {
|
|||
.collect()
|
||||
}
|
||||
|
||||
pub(crate) fn advance_animation_timeline_for_testing(&self, delta: f64) {
|
||||
pub(crate) fn advance_animation_timeline_for_testing(&self, delta: f64) -> AnimationsUpdate {
|
||||
self.animation_timeline.borrow_mut().advance_specific(delta);
|
||||
let current_timeline_value = self.current_animation_timeline_value();
|
||||
self.animations
|
||||
.borrow_mut()
|
||||
.update_for_new_timeline_value(&self.window, current_timeline_value)
|
||||
}
|
||||
|
||||
pub(crate) fn update_animation_timeline(&self) {
|
||||
self.animation_timeline.borrow_mut().update();
|
||||
pub(crate) fn update_animation_timeline(&self) -> AnimationsUpdate {
|
||||
// Only update the time if it isn't being managed by a test.
|
||||
if !pref!(layout.animations.test.enabled) {
|
||||
self.animation_timeline.borrow_mut().update();
|
||||
}
|
||||
|
||||
// We still want to update the animations, because our timeline
|
||||
// value might have been advanced previously via the TestBinding.
|
||||
let current_timeline_value = self.current_animation_timeline_value();
|
||||
self.animations
|
||||
.borrow_mut()
|
||||
.update_for_new_timeline_value(&self.window, current_timeline_value)
|
||||
}
|
||||
|
||||
pub(crate) fn current_animation_timeline_value(&self) -> f64 {
|
||||
|
@ -3766,7 +3780,7 @@ impl Document {
|
|||
self.animations.borrow()
|
||||
}
|
||||
|
||||
pub(crate) fn update_animations(&self) -> AnimationsUpdate {
|
||||
pub(crate) fn update_animations_post_reflow(&self) -> AnimationsUpdate {
|
||||
self.animations
|
||||
.borrow_mut()
|
||||
.do_post_reflow_update(&self.window, self.current_animation_timeline_value())
|
||||
|
|
|
@ -443,6 +443,7 @@ macro_rules! global_event_handlers(
|
|||
(NoOnload) => (
|
||||
event_handler!(abort, GetOnabort, SetOnabort);
|
||||
event_handler!(animationend, GetOnanimationend, SetOnanimationend);
|
||||
event_handler!(animationiteration, GetOnanimationiteration, SetOnanimationiteration);
|
||||
event_handler!(cancel, GetOncancel, SetOncancel);
|
||||
event_handler!(canplay, GetOncanplay, SetOncanplay);
|
||||
event_handler!(canplaythrough, GetOncanplaythrough, SetOncanplaythrough);
|
||||
|
|
|
@ -93,6 +93,7 @@ interface mixin GlobalEventHandlers {
|
|||
// https://drafts.csswg.org/css-animations/#interface-globaleventhandlers-idl
|
||||
partial interface mixin GlobalEventHandlers {
|
||||
attribute EventHandler onanimationend;
|
||||
attribute EventHandler onanimationiteration;
|
||||
};
|
||||
|
||||
// https://drafts.csswg.org/css-transitions/#interface-globaleventhandlers-idl
|
||||
|
|
|
@ -1578,10 +1578,15 @@ impl Window {
|
|||
|
||||
/// Prepares to tick animations and then does a reflow which also advances the
|
||||
/// layout animation clock.
|
||||
pub fn advance_animation_clock(&self, delta: i32) {
|
||||
#[allow(unsafe_code)]
|
||||
pub fn advance_animation_clock(&self, delta_ms: i32) {
|
||||
let pipeline_id = self.upcast::<GlobalScope>().pipeline_id();
|
||||
self.Document()
|
||||
.advance_animation_timeline_for_testing(delta as f64 / 1000.);
|
||||
let update = self
|
||||
.Document()
|
||||
.advance_animation_timeline_for_testing(delta_ms as f64 / 1000.);
|
||||
unsafe {
|
||||
ScriptThread::process_animations_update(update);
|
||||
}
|
||||
ScriptThread::handle_tick_all_animations_for_testing(pipeline_id);
|
||||
}
|
||||
|
||||
|
@ -1747,7 +1752,7 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
let update = document.update_animations();
|
||||
let update = document.update_animations_post_reflow();
|
||||
unsafe {
|
||||
ScriptThread::process_animations_update(update);
|
||||
}
|
||||
|
|
|
@ -151,7 +151,6 @@ use script_traits::{
|
|||
};
|
||||
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;
|
||||
|
@ -1650,19 +1649,17 @@ impl ScriptThread {
|
|||
// 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.
|
||||
if !pref!(layout.animations.test.enabled) {
|
||||
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);
|
||||
}
|
||||
|
||||
for (_, document) in self.documents.borrow().iter() {
|
||||
let update = document.update_animation_timeline();
|
||||
unsafe { ScriptThread::process_animations_update(update) };
|
||||
}
|
||||
}
|
||||
|
||||
fn categorize_msg(&self, msg: &MixedMessage) -> ScriptThreadEventCategory {
|
||||
|
@ -3021,6 +3018,7 @@ impl ScriptThread {
|
|||
|
||||
let event_atom = match event.event_type {
|
||||
TransitionOrAnimationEventType::AnimationEnd => atom!("animationend"),
|
||||
TransitionOrAnimationEventType::AnimationIteration => atom!("animationiteration"),
|
||||
TransitionOrAnimationEventType::TransitionCancel => atom!("transitioncancel"),
|
||||
TransitionOrAnimationEventType::TransitionEnd => atom!("transitionend"),
|
||||
TransitionOrAnimationEventType::TransitionRun => atom!("transitionrun"),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue