layout/style/nsAnimationManager.h

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     1 /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #ifndef nsAnimationManager_h_
     6 #define nsAnimationManager_h_
     8 #include "mozilla/Attributes.h"
     9 #include "mozilla/ContentEvents.h"
    10 #include "AnimationCommon.h"
    11 #include "nsCSSPseudoElements.h"
    12 #include "mozilla/MemoryReporting.h"
    13 #include "mozilla/TimeStamp.h"
    15 class nsCSSKeyframesRule;
    16 class nsStyleContext;
    18 namespace mozilla {
    19 namespace css {
    20 class Declaration;
    21 }
    22 }
    24 struct AnimationEventInfo {
    25   nsRefPtr<mozilla::dom::Element> mElement;
    26   mozilla::InternalAnimationEvent mEvent;
    28   AnimationEventInfo(mozilla::dom::Element *aElement,
    29                      const nsString& aAnimationName,
    30                      uint32_t aMessage, mozilla::TimeDuration aElapsedTime,
    31                      const nsAString& aPseudoElement)
    32     : mElement(aElement), mEvent(true, aMessage)
    33   {
    34     // XXX Looks like nobody initialize WidgetEvent::time
    35     mEvent.animationName = aAnimationName;
    36     mEvent.elapsedTime = aElapsedTime.ToSeconds();
    37     mEvent.pseudoElement = aPseudoElement;
    38   }
    40   // InternalAnimationEvent doesn't support copy-construction, so we need
    41   // to ourselves in order to work with nsTArray
    42   AnimationEventInfo(const AnimationEventInfo &aOther)
    43     : mElement(aOther.mElement), mEvent(true, aOther.mEvent.message)
    44   {
    45     mEvent.AssignAnimationEventData(aOther.mEvent, false);
    46   }
    47 };
    49 typedef InfallibleTArray<AnimationEventInfo> EventArray;
    51 /**
    52  * Data about all of the animations running on an element.
    53  */
    54 struct ElementAnimations MOZ_FINAL
    55   : public mozilla::css::CommonElementAnimationData
    56 {
    57   typedef mozilla::TimeStamp TimeStamp;
    58   typedef mozilla::TimeDuration TimeDuration;
    60   ElementAnimations(mozilla::dom::Element *aElement, nsIAtom *aElementProperty,
    61                     nsAnimationManager *aAnimationManager, TimeStamp aNow);
    63   // This function takes as input the start time, duration, and direction of an
    64   // animation and returns the position in the current iteration.  Note that
    65   // this only works when we know that the animation is currently running.
    66   // This way of calling the function can be used from the compositor.  Note
    67   // that if the animation has not started yet, has already ended, or is paused,
    68   // it should not be run from the compositor.  When this function is called
    69   // from the main thread, we need the actual StyleAnimation* in order to
    70   // get correct animation-fill behavior and to fire animation events.
    71   // This function returns -1 for the position if the animation should not be
    72   // run (because it is not currently active and has no fill behavior), but
    73   // only does so if aAnimation is non-null; with a null aAnimation it is an
    74   // error to give aElapsedDuration < 0, and fill-forwards is assumed.
    75   // After calling GetPositionInIteration with non-null aAnimation and aEa, be
    76   // sure to call CheckNeedsRefresh on the animation manager afterwards.
    77   static double GetPositionInIteration(TimeDuration aElapsedDuration,
    78                                        TimeDuration aIterationDuration,
    79                                        double aIterationCount,
    80                                        uint32_t aDirection,
    81                                        mozilla::StyleAnimation* aAnimation =
    82                                          nullptr,
    83                                        ElementAnimations* aEa = nullptr,
    84                                        EventArray* aEventsToDispatch = nullptr);
    86   void EnsureStyleRuleFor(TimeStamp aRefreshTime,
    87                           EventArray &aEventsToDispatch,
    88                           bool aIsThrottled);
    90   bool IsForElement() const { // rather than for a pseudo-element
    91     return mElementProperty == nsGkAtoms::animationsProperty;
    92   }
    94   nsString PseudoElement()
    95   {
    96     return mElementProperty == nsGkAtoms::animationsProperty ?
    97              EmptyString() :
    98              mElementProperty == nsGkAtoms::animationsOfBeforeProperty ?
    99                NS_LITERAL_STRING("::before") :
   100                NS_LITERAL_STRING("::after");
   101   }
   103   void PostRestyleForAnimation(nsPresContext *aPresContext) {
   104     nsRestyleHint styleHint = IsForElement() ? eRestyle_Self : eRestyle_Subtree;
   105     aPresContext->PresShell()->RestyleForAnimation(mElement, styleHint);
   106   }
   108   // If aFlags contains CanAnimate_AllowPartial, returns whether the
   109   // state of this element's animations at the current refresh driver
   110   // time contains animation data that can be done on the compositor
   111   // thread.  (This is useful for determining whether a layer should be
   112   // active, or whether to send data to the layer.)
   113   // If aFlags does not contain CanAnimate_AllowPartial, returns whether
   114   // the state of this element's animations at the current refresh driver
   115   // time can be fully represented by data sent to the compositor.
   116   // (This is useful for determining whether throttle the animation
   117   // (suppress main-thread style updates).)
   118   // Note that when CanPerformOnCompositorThread returns true, it also,
   119   // as a side-effect, notifies the ActiveLayerTracker.  FIXME:  This
   120   // should probably move to the relevant callers.
   121   virtual bool CanPerformOnCompositorThread(CanAnimateFlags aFlags) const MOZ_OVERRIDE;
   123   virtual bool HasAnimationOfProperty(nsCSSProperty aProperty) const MOZ_OVERRIDE;
   125   // False when we know that our current style rule is valid
   126   // indefinitely into the future (because all of our animations are
   127   // either completed or paused).  May be invalidated by a style change.
   128   bool mNeedsRefreshes;
   130   InfallibleTArray<mozilla::StyleAnimation> mAnimations;
   131 };
   133 class nsAnimationManager MOZ_FINAL
   134   : public mozilla::css::CommonAnimationManager
   135 {
   136 public:
   137   nsAnimationManager(nsPresContext *aPresContext)
   138     : mozilla::css::CommonAnimationManager(aPresContext)
   139     , mObservingRefreshDriver(false)
   140   {
   141   }
   143   static ElementAnimations* GetAnimationsForCompositor(nsIContent* aContent,
   144                                                        nsCSSProperty aProperty)
   145   {
   146     if (!aContent->MayHaveAnimations())
   147       return nullptr;
   148     ElementAnimations* animations = static_cast<ElementAnimations*>(
   149       aContent->GetProperty(nsGkAtoms::animationsProperty));
   150     if (!animations)
   151       return nullptr;
   152     bool propertyMatches = animations->HasAnimationOfProperty(aProperty);
   153     return (propertyMatches &&
   154             animations->CanPerformOnCompositorThread(
   155               mozilla::css::CommonElementAnimationData::CanAnimate_AllowPartial))
   156            ? animations
   157            : nullptr;
   158   }
   160   // Returns true if aContent or any of its ancestors has an animation.
   161   static bool ContentOrAncestorHasAnimation(nsIContent* aContent) {
   162     do {
   163       if (aContent->GetProperty(nsGkAtoms::animationsProperty)) {
   164         return true;
   165       }
   166     } while ((aContent = aContent->GetParent()));
   168     return false;
   169   }
   171   void EnsureStyleRuleFor(ElementAnimations* aET);
   173   // nsIStyleRuleProcessor (parts)
   174   virtual void RulesMatching(ElementRuleProcessorData* aData) MOZ_OVERRIDE;
   175   virtual void RulesMatching(PseudoElementRuleProcessorData* aData) MOZ_OVERRIDE;
   176   virtual void RulesMatching(AnonBoxRuleProcessorData* aData) MOZ_OVERRIDE;
   177 #ifdef MOZ_XUL
   178   virtual void RulesMatching(XULTreeRuleProcessorData* aData) MOZ_OVERRIDE;
   179 #endif
   180   virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
   181     const MOZ_MUST_OVERRIDE MOZ_OVERRIDE;
   182   virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
   183     const MOZ_MUST_OVERRIDE MOZ_OVERRIDE;
   185   // nsARefreshObserver
   186   virtual void WillRefresh(mozilla::TimeStamp aTime) MOZ_OVERRIDE;
   188   void FlushAnimations(FlushFlags aFlags);
   190   /**
   191    * Return the style rule that RulesMatching should add for
   192    * aStyleContext.  This might be different from what RulesMatching
   193    * actually added during aStyleContext's construction because the
   194    * element's animation-name may have changed.  (However, this does
   195    * return null during the non-animation restyling phase, as
   196    * RulesMatching does.)
   197    *
   198    * aStyleContext may be a style context for aElement or for its
   199    * :before or :after pseudo-element.
   200    */
   201   nsIStyleRule* CheckAnimationRule(nsStyleContext* aStyleContext,
   202                                    mozilla::dom::Element* aElement);
   204   /**
   205    * Dispatch any pending events.  We accumulate animationend and
   206    * animationiteration events only during refresh driver notifications
   207    * (and dispatch them at the end of such notifications), but we
   208    * accumulate animationstart events at other points when style
   209    * contexts are created.
   210    */
   211   void DispatchEvents() {
   212     // Fast-path the common case: no events
   213     if (!mPendingEvents.IsEmpty()) {
   214       DoDispatchEvents();
   215     }
   216   }
   218   ElementAnimations* GetElementAnimations(mozilla::dom::Element *aElement,
   219                                           nsCSSPseudoElements::Type aPseudoType,
   220                                           bool aCreateIfNeeded);
   222   // Updates styles on throttled animations. See note on nsTransitionManager
   223   void UpdateAllThrottledStyles();
   225 protected:
   226   virtual void ElementDataRemoved() MOZ_OVERRIDE
   227   {
   228     CheckNeedsRefresh();
   229   }
   230   virtual void AddElementData(mozilla::css::CommonElementAnimationData* aData) MOZ_OVERRIDE;
   232   /**
   233    * Check to see if we should stop or start observing the refresh driver
   234    */
   235   void CheckNeedsRefresh();
   237 private:
   238   void BuildAnimations(nsStyleContext* aStyleContext,
   239                        InfallibleTArray<mozilla::StyleAnimation>& aAnimations);
   240   bool BuildSegment(InfallibleTArray<mozilla::AnimationPropertySegment>&
   241                       aSegments,
   242                     nsCSSProperty aProperty, const nsAnimation& aAnimation,
   243                     float aFromKey, nsStyleContext* aFromContext,
   244                     mozilla::css::Declaration* aFromDeclaration,
   245                     float aToKey, nsStyleContext* aToContext);
   246   nsIStyleRule* GetAnimationRule(mozilla::dom::Element* aElement,
   247                                  nsCSSPseudoElements::Type aPseudoType);
   249   // Update the animated styles of an element and its descendants.
   250   // If the element has an animation, it is flushed back to its primary frame.
   251   // If the element does not have an animation, then its style is reparented.
   252   void UpdateThrottledStylesForSubtree(nsIContent* aContent,
   253                                        nsStyleContext* aParentStyle,
   254                                        nsStyleChangeList &aChangeList);
   255   void UpdateAllThrottledStylesInternal();
   257   // The guts of DispatchEvents
   258   void DoDispatchEvents();
   260   EventArray mPendingEvents;
   262   bool mObservingRefreshDriver;
   263 };
   265 #endif /* !defined(nsAnimationManager_h_) */

mercurial