Bug 1344966 - Add flag that represents the traversal is only for animation-only restyle. r?heycam
We will set the flag when the root node of the traversal has
has-animation-only-dirty-descendants flag or has animation restyle hints.
Also we will use this flag to detect whether we need to trigger CSS transitions
or not.
MozReview-Commit-ID: 1EMQ77e24ab
--- a/servo/components/style/context.rs
+++ b/servo/components/style/context.rs
@@ -82,16 +82,19 @@ pub struct SharedStyleContext<'a> {
pub local_context_creation_data: Mutex<ThreadLocalStyleContextCreationInfo>,
/// The current timer for transitions and animations. This is needed to test
/// them.
pub timer: Timer,
/// The QuirksMode state which the document needs to be rendered with
pub quirks_mode: QuirksMode,
+
+ /// True if the traversal is processing only animation restyles.
+ pub animation_only_restyle: bool,
}
impl<'a> SharedStyleContext<'a> {
/// Return a suitable viewport size in order to be used for viewport units.
pub fn viewport_size(&self) -> Size2D<Au> {
self.stylist.device.au_viewport_size()
}
}
--- a/servo/components/style/dom.rs
+++ b/servo/components/style/dom.rs
@@ -367,16 +367,26 @@ pub trait TElement : PartialEq + Debug +
fn has_selector_flags(&self, flags: ElementSelectorFlags) -> bool;
/// Creates a task to update CSS Animations on a given (pseudo-)element.
/// Note: Gecko only.
fn update_animations(&self, _pseudo: Option<&PseudoElement>);
/// Returns true if the element has a CSS animation.
fn has_css_animations(&self, _pseudo: Option<&PseudoElement>) -> bool;
+
+ /// Returns true if the element has animation restyle hints.
+ fn has_animation_restyle_hints(&self) -> bool {
+ let data = match self.borrow_data() {
+ Some(d) => d,
+ None => return false,
+ };
+ return data.get_restyle()
+ .map_or(false, |r| r.hint.has_animation_hint());
+ }
}
/// TNode and TElement aren't Send because we want to be careful and explicit
/// about our parallel traversal. However, there are certain situations
/// (including but not limited to the traversal) where we need to send DOM
/// objects to other threads.
///
/// That's the reason why `SendNode` exists.
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -120,31 +120,33 @@ pub extern "C" fn Servo_Initialize() {
#[no_mangle]
pub extern "C" fn Servo_Shutdown() {
// Clear some static data to avoid shutdown leaks.
gecko_properties::shutdown();
}
fn create_shared_context<'a>(guard: &'a SharedRwLockReadGuard,
- per_doc_data: &PerDocumentStyleDataImpl) -> SharedStyleContext<'a> {
+ per_doc_data: &PerDocumentStyleDataImpl,
+ animation_only: bool) -> SharedStyleContext<'a> {
let local_context_data =
ThreadLocalStyleContextCreationInfo::new(per_doc_data.new_animations_sender.clone());
SharedStyleContext {
stylist: per_doc_data.stylist.clone(),
guards: StylesheetGuards::same(guard),
running_animations: per_doc_data.running_animations.clone(),
expired_animations: per_doc_data.expired_animations.clone(),
// FIXME(emilio): Stop boxing here.
error_reporter: Box::new(StdoutErrorReporter),
local_context_creation_data: Mutex::new(local_context_data),
timer: Timer::new(),
// FIXME Find the real QuirksMode information for this document
quirks_mode: QuirksMode::NoQuirks,
+ animation_only_restyle: animation_only,
}
}
fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed,
traversal_flags: &TraversalFlags) {
// When new content is inserted in a display:none subtree, we will call into
// servo to try to style it. Detect that here and bail out.
if let Some(parent) = element.parent_element() {
@@ -161,17 +163,18 @@ fn traverse_subtree(element: GeckoElemen
return;
}
debug!("Traversing subtree:");
debug!("{:?}", ShowSubtreeData(element.as_node()));
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
- let shared_style_context = create_shared_context(&guard, &per_doc_data);
+ let shared_style_context = create_shared_context(&guard, &per_doc_data,
+ traversal_flags.for_animation_only());
let traversal_driver = if global_style_data.style_thread_pool.is_none() {
TraversalDriver::Sequential
} else {
TraversalDriver::Parallel
};
let traversal = RecalcStyleOnly::new(shared_style_context, traversal_driver);
@@ -1499,17 +1502,17 @@ pub extern "C" fn Servo_ResolveStyleLazi
// up all the computation machinery.
let mut result = element.mutate_data()
.and_then(|d| d.get_styles().map(&finish));
if result.is_some() {
return result.unwrap().into_strong();
}
// We don't have the style ready. Go ahead and compute it as necessary.
- let shared = create_shared_context(&guard, &mut doc_data.borrow_mut());
+ let shared = create_shared_context(&guard, &mut doc_data.borrow_mut(), false);
let mut tlc = ThreadLocalStyleContext::new(&shared);
let mut context = StyleContext {
shared: &shared,
thread_local: &mut tlc,
};
let ensure = |el: GeckoElement| { unsafe { el.ensure_data(); } };
let clear = |el: GeckoElement| el.clear_data();
resolve_style(&mut context, element, &ensure, &clear,