Bug 1344966 - Add flag that represents the traversal is only for animation-only restyle. r? draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Wed, 22 Mar 2017 05:38:03 +0900
changeset 502511 e89f0866757502337383e10a29f1fd7c2821c903
parent 502510 9e5baad7c6cd6ad944b927918743d0e1a38845e1
child 502512 579721f9eb7bfa708fe682ac36375721b2daf139
push id50306
push userhikezoe@mozilla.com
push dateTue, 21 Mar 2017 21:34:19 +0000
bugs1344966
milestone55.0a1
Bug 1344966 - Add flag that represents the traversal is only for animation-only restyle. r? We will set the flag when the root node of the traversal has has-animating-descendants flag. Also we will use this flag to detect whether we need to trigger CSS transitions or not. MozReview-Commit-ID: 1EMQ77e24ab
servo/components/style/context.rs
servo/components/style/traversal.rs
servo/ports/geckolib/glue.rs
--- 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 processed 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/traversal.rs
+++ b/servo/components/style/traversal.rs
@@ -31,28 +31,34 @@ pub struct PerLevelTraversalData {
     pub current_dom_depth: Option<usize>,
 }
 
 /// This structure exists to enforce that callers invoke pre_traverse, and also
 /// to pass information from the pre-traversal into the primary traversal.
 pub struct PreTraverseToken {
     traverse: bool,
     unstyled_children_only: bool,
+    animation_only: bool,
 }
 
 impl PreTraverseToken {
     /// Whether we should traverse children.
     pub fn should_traverse(&self) -> bool {
         self.traverse
     }
 
     /// Whether we should traverse only unstyled children.
     pub fn traverse_unstyled_children_only(&self) -> bool {
         self.unstyled_children_only
     }
+
+    /// Whether we should traverse only animations.
+    pub fn traverse_animation_only(&self) -> bool {
+        self.animation_only
+    }
 }
 
 /// Enum to prevent duplicate logging.
 pub enum LogBehavior {
     /// We should log.
     MayLog,
     /// We shouldn't log.
     DontLog,
@@ -113,16 +119,17 @@ pub trait DomTraversal<E: TElement> : Sy
     /// appended children without restyling the parent.
     fn pre_traverse(root: E, stylist: &Stylist, unstyled_children_only: bool)
                     -> PreTraverseToken
     {
         if unstyled_children_only {
             return PreTraverseToken {
                 traverse: true,
                 unstyled_children_only: true,
+                animation_only: root.has_animating_descendants(),
             };
         }
 
         // Expand the snapshot, if any. This is normally handled by the parent, so
         // we need a special case for the root.
         //
         // Expanding snapshots here may create a LATER_SIBLINGS restyle hint, which
         // we will drop on the floor. To prevent missed restyles, we assert against
@@ -132,16 +139,17 @@ pub trait DomTraversal<E: TElement> : Sy
                 debug_assert!(root.next_sibling_element().is_none());
                 let _later_siblings = r.compute_final_hint(root, stylist);
             }
         }
 
         PreTraverseToken {
             traverse: Self::node_needs_traversal(root.as_node()),
             unstyled_children_only: false,
+            animation_only: root.has_animating_descendants(),
         }
     }
 
     /// Returns true if traversal should visit a text node. The style system never
     /// processes text nodes, but Servo overrides this to visit them for flow
     /// construction when necessary.
     fn text_node_needs_traversal(node: E::ConcreteNode) -> bool {
         debug_assert!(node.is_text_node());
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -118,31 +118,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,
                     unstyled_children_only: bool) {
     // 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() {
@@ -159,17 +161,17 @@ 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, token.traverse_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);
@@ -1508,17 +1510,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(), true);
     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,