aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/document.rs59
-rw-r--r--components/script/dom/element.rs2
2 files changed, 39 insertions, 22 deletions
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index da3b5db052c..d603d898f5c 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -1538,28 +1538,29 @@ impl Document {
self.animation_frame_ident.set(ident);
self.animation_frame_list.borrow_mut().push((ident, Some(callback)));
- // No need to send a `ChangeRunningAnimationsState` if we're running animation callbacks:
- // we're guaranteed to already be in the "animation callbacks present" state.
- //
- // This reduces CPU usage by avoiding needless thread wakeups in the common case of
- // repeated rAF.
- //
// TODO: Should tick animation only when document is visible
- if !self.running_animation_callbacks.get() {
- if !self.is_faking_animation_frames() {
- let global_scope = self.window.upcast::<GlobalScope>();
- let event = ConstellationMsg::ChangeRunningAnimationsState(
- global_scope.pipeline_id(),
- AnimationState::AnimationCallbacksPresent);
- global_scope.constellation_chan().send(event).unwrap();
- } else {
- let callback = FakeRequestAnimationFrameCallback {
- document: Trusted::new(self),
- };
- self.global()
- .schedule_callback(OneshotTimerCallback::FakeRequestAnimationFrame(callback),
- MsDuration::new(FAKE_REQUEST_ANIMATION_FRAME_DELAY));
- }
+
+ // If we are running 'fake' animation frames, we unconditionally
+ // set up a one-shot timer for script to execute the rAF callbacks.
+ if self.is_faking_animation_frames() {
+ let callback = FakeRequestAnimationFrameCallback {
+ document: Trusted::new(self),
+ };
+ self.global()
+ .schedule_callback(OneshotTimerCallback::FakeRequestAnimationFrame(callback),
+ MsDuration::new(FAKE_REQUEST_ANIMATION_FRAME_DELAY));
+ } else if !self.running_animation_callbacks.get() {
+ // No need to send a `ChangeRunningAnimationsState` if we're running animation callbacks:
+ // we're guaranteed to already be in the "animation callbacks present" state.
+ //
+ // This reduces CPU usage by avoiding needless thread wakeups in the common case of
+ // repeated rAF.
+
+ let global_scope = self.window.upcast::<GlobalScope>();
+ let event = ConstellationMsg::ChangeRunningAnimationsState(
+ global_scope.pipeline_id(),
+ AnimationState::AnimationCallbacksPresent);
+ global_scope.constellation_chan().send(event).unwrap();
}
ident
@@ -1596,6 +1597,22 @@ impl Document {
ReflowQueryType::NoQuery,
ReflowReason::RequestAnimationFrame);
+ if spurious && !was_faking_animation_frames {
+ // If the rAF callbacks did not mutate the DOM, then the
+ // reflow call above means that layout will not be invoked,
+ // and therefore no new frame will be sent to the compositor.
+ // If this happens, the compositor will not tick the animation
+ // and the next rAF will never be called! When this happens
+ // for several frames, then the spurious rAF detection below
+ // will kick in and use a timer to tick the callbacks. However,
+ // for the interim frames where we are deciding whether this rAF
+ // is considered spurious, we need to ensure that the layout
+ // and compositor *do* tick the animation.
+ self.window.force_reflow(ReflowGoal::ForDisplay,
+ ReflowQueryType::NoQuery,
+ ReflowReason::RequestAnimationFrame);
+ }
+
// Only send the animation change state message after running any callbacks.
// This means that if the animation callback adds a new callback for
// the next frame (which is the common case), we won't send a NoAnimationCallbacksPresent
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index f279c2c279b..a431d0c9dbb 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -89,6 +89,7 @@ use selectors::attr::{AttrSelectorOperation, NamespaceConstraint, CaseSensitivit
use selectors::matching::{ElementSelectorFlags, LocalMatchingContext, MatchingContext, MatchingMode};
use selectors::matching::{HAS_EDGE_CHILD_SELECTOR, HAS_SLOW_SELECTOR, HAS_SLOW_SELECTOR_LATER_SIBLINGS};
use selectors::matching::{RelevantLinkStatus, matches_selector_list};
+use selectors::sink::Push;
use servo_atoms::Atom;
use std::ascii::AsciiExt;
use std::borrow::Cow;
@@ -109,7 +110,6 @@ use style::rule_tree::CascadeLevel;
use style::selector_parser::{NonTSPseudoClass, PseudoElement, RestyleDamage, SelectorImpl, SelectorParser};
use style::selector_parser::extended_filtering;
use style::shared_lock::{SharedRwLock, Locked};
-use style::sink::Push;
use style::stylearc::Arc;
use style::thread_state;
use style::values::{CSSFloat, Either};