layout/style/nsTransitionManager.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/style/nsTransitionManager.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,227 @@
     1.4 +/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +/* Code to start and animate CSS transitions. */
    1.10 +
    1.11 +#ifndef nsTransitionManager_h_
    1.12 +#define nsTransitionManager_h_
    1.13 +
    1.14 +#include "mozilla/Attributes.h"
    1.15 +#include "mozilla/MemoryReporting.h"
    1.16 +#include "AnimationCommon.h"
    1.17 +#include "nsCSSPseudoElements.h"
    1.18 +
    1.19 +class nsStyleContext;
    1.20 +class nsPresContext;
    1.21 +class nsCSSPropertySet;
    1.22 +struct nsTransition;
    1.23 +struct ElementDependentRuleProcessorData;
    1.24 +
    1.25 +/*****************************************************************************
    1.26 + * Per-Element data                                                          *
    1.27 + *****************************************************************************/
    1.28 +
    1.29 +struct ElementPropertyTransition : public mozilla::StyleAnimation
    1.30 +{
    1.31 +  // This is the start value to be used for a check for whether a
    1.32 +  // transition is being reversed.  Normally the same as
    1.33 +  // mProperties[0].mSegments[0].mFromValue, except when this transition
    1.34 +  // started as the reversal of another in-progress transition.
    1.35 +  // Needed so we can handle two reverses in a row.
    1.36 +  nsStyleAnimation::Value mStartForReversingTest;
    1.37 +  // Likewise, the portion (in value space) of the "full" reversed
    1.38 +  // transition that we're actually covering.  For example, if a :hover
    1.39 +  // effect has a transition that moves the element 10px to the right
    1.40 +  // (by changing 'left' from 0px to 10px), and the mouse moves in to
    1.41 +  // the element (starting the transition) but then moves out after the
    1.42 +  // transition has advanced 4px, the second transition (from 10px/4px
    1.43 +  // to 0px) will have mReversePortion of 0.4.  (If the mouse then moves
    1.44 +  // in again when the transition is back to 2px, the mReversePortion
    1.45 +  // for the third transition (from 0px/2px to 10px) will be 0.8.
    1.46 +  double mReversePortion;
    1.47 +
    1.48 +  // Compute the portion of the *value* space that we should be through
    1.49 +  // at the given time.  (The input to the transition timing function
    1.50 +  // has time units, the output has value units.)
    1.51 +  double ValuePortionFor(mozilla::TimeStamp aRefreshTime) const;
    1.52 +
    1.53 +  bool IsRemovedSentinel() const
    1.54 +  {
    1.55 +    // Note that mozilla::StyleAnimation::IsRunningAt depends on removed
    1.56 +    // sentinels being represented by a null mStartTime.
    1.57 +    return mStartTime.IsNull();
    1.58 +  }
    1.59 +
    1.60 +  void SetRemovedSentinel()
    1.61 +  {
    1.62 +    // assign the null time stamp
    1.63 +    mStartTime = mozilla::TimeStamp();
    1.64 +  }
    1.65 +};
    1.66 +
    1.67 +struct ElementTransitions MOZ_FINAL
    1.68 +  : public mozilla::css::CommonElementAnimationData 
    1.69 +{
    1.70 +  ElementTransitions(mozilla::dom::Element *aElement, nsIAtom *aElementProperty,
    1.71 +                     nsTransitionManager *aTransitionManager,
    1.72 +                     mozilla::TimeStamp aNow);
    1.73 +
    1.74 +  void EnsureStyleRuleFor(mozilla::TimeStamp aRefreshTime);
    1.75 +
    1.76 +  virtual bool HasAnimationOfProperty(nsCSSProperty aProperty) const MOZ_OVERRIDE;
    1.77 +
    1.78 +  // If aFlags contains CanAnimate_AllowPartial, returns whether the
    1.79 +  // state of this element's transitions at the current refresh driver
    1.80 +  // time contains transition data that can be done on the compositor
    1.81 +  // thread.  (This is useful for determining whether a layer should be
    1.82 +  // active, or whether to send data to the layer.)
    1.83 +  // If aFlags does not contain CanAnimate_AllowPartial, returns whether
    1.84 +  // the state of this element's transitions at the current refresh driver
    1.85 +  // time can be fully represented by data sent to the compositor.
    1.86 +  // (This is useful for determining whether throttle the transition
    1.87 +  // (suppress main-thread style updates).)
    1.88 +  // Note that when CanPerformOnCompositorThread returns true, it also,
    1.89 +  // as a side-effect, notifies the ActiveLayerTracker.  FIXME:  This
    1.90 +  // should probably move to the relevant callers.
    1.91 +  virtual bool CanPerformOnCompositorThread(CanAnimateFlags aFlags) const MOZ_OVERRIDE;
    1.92 +
    1.93 +  // Either zero or one for each CSS property:
    1.94 +  nsTArray<ElementPropertyTransition> mPropertyTransitions;
    1.95 +};
    1.96 +
    1.97 +
    1.98 +
    1.99 +class nsTransitionManager MOZ_FINAL
   1.100 +  : public mozilla::css::CommonAnimationManager
   1.101 +{
   1.102 +public:
   1.103 +  nsTransitionManager(nsPresContext *aPresContext)
   1.104 +    : mozilla::css::CommonAnimationManager(aPresContext)
   1.105 +  {
   1.106 +  }
   1.107 +
   1.108 +  static ElementTransitions* GetTransitions(nsIContent* aContent) {
   1.109 +    return static_cast<ElementTransitions*>
   1.110 +      (aContent->GetProperty(nsGkAtoms::transitionsProperty));
   1.111 +  }
   1.112 +
   1.113 +  // Returns true if aContent or any of its ancestors has a transition.
   1.114 +  static bool ContentOrAncestorHasTransition(nsIContent* aContent) {
   1.115 +    do {
   1.116 +      if (GetTransitions(aContent)) {
   1.117 +        return true;
   1.118 +      }
   1.119 +    } while ((aContent = aContent->GetParent()));
   1.120 +
   1.121 +    return false;
   1.122 +  }
   1.123 +
   1.124 +  typedef mozilla::css::CommonElementAnimationData CommonElementAnimationData;
   1.125 +
   1.126 +  static ElementTransitions*
   1.127 +    GetTransitionsForCompositor(nsIContent* aContent,
   1.128 +                                nsCSSProperty aProperty)
   1.129 +  {
   1.130 +    if (!aContent->MayHaveAnimations()) {
   1.131 +      return nullptr;
   1.132 +    }
   1.133 +    ElementTransitions* transitions = GetTransitions(aContent);
   1.134 +    if (!transitions ||
   1.135 +        !transitions->HasAnimationOfProperty(aProperty) ||
   1.136 +        !transitions->CanPerformOnCompositorThread(
   1.137 +          CommonElementAnimationData::CanAnimate_AllowPartial)) {
   1.138 +      return nullptr;
   1.139 +    }
   1.140 +    return transitions;
   1.141 +  }
   1.142 +
   1.143 +  /**
   1.144 +   * StyleContextChanged
   1.145 +   *
   1.146 +   * To be called from nsFrameManager::ReResolveStyleContext when the
   1.147 +   * style of an element has changed, to initiate transitions from
   1.148 +   * that style change.  For style contexts with :before and :after
   1.149 +   * pseudos, aElement is expected to be the generated before/after
   1.150 +   * element.
   1.151 +   *
   1.152 +   * It may return a "cover rule" (see CoverTransitionStartStyleRule) to
   1.153 +   * cover up some of the changes for the duration of the restyling of
   1.154 +   * descendants.  If it does, this function will take care of causing
   1.155 +   * the necessary restyle afterwards, but the caller must restyle the
   1.156 +   * element *again* with the original sequence of rules plus the
   1.157 +   * returned cover rule as the most specific rule.
   1.158 +   */
   1.159 +  already_AddRefed<nsIStyleRule>
   1.160 +    StyleContextChanged(mozilla::dom::Element *aElement,
   1.161 +                        nsStyleContext *aOldStyleContext,
   1.162 +                        nsStyleContext *aNewStyleContext);
   1.163 +
   1.164 +  // nsIStyleRuleProcessor (parts)
   1.165 +  virtual void RulesMatching(ElementRuleProcessorData* aData) MOZ_OVERRIDE;
   1.166 +  virtual void RulesMatching(PseudoElementRuleProcessorData* aData) MOZ_OVERRIDE;
   1.167 +  virtual void RulesMatching(AnonBoxRuleProcessorData* aData) MOZ_OVERRIDE;
   1.168 +#ifdef MOZ_XUL
   1.169 +  virtual void RulesMatching(XULTreeRuleProcessorData* aData) MOZ_OVERRIDE;
   1.170 +#endif
   1.171 +  virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
   1.172 +    MOZ_MUST_OVERRIDE MOZ_OVERRIDE;
   1.173 +  virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
   1.174 +    MOZ_MUST_OVERRIDE MOZ_OVERRIDE;
   1.175 +
   1.176 +  // nsARefreshObserver
   1.177 +  virtual void WillRefresh(mozilla::TimeStamp aTime) MOZ_OVERRIDE;
   1.178 +
   1.179 +  void FlushTransitions(FlushFlags aFlags);
   1.180 +
   1.181 +  // Performs a 'mini-flush' to make styles from throttled transitions
   1.182 +  // up-to-date prior to processing an unrelated style change, so that
   1.183 +  // any transitions triggered by that style change produce correct
   1.184 +  // results.
   1.185 +  //
   1.186 +  // In more detail:  when we're able to run animations on the
   1.187 +  // compositor, we sometimes "throttle" these animations by skipping
   1.188 +  // updating style data on the main thread.  However, whenever we
   1.189 +  // process a normal (non-animation) style change, any changes in
   1.190 +  // computed style on elements that have transition-* properties set
   1.191 +  // may need to trigger new transitions; this process requires knowing
   1.192 +  // both the old and new values of the property.  To do this correctly,
   1.193 +  // we need to have an up-to-date *old* value of the property on the
   1.194 +  // primary frame.  So the purpose of the mini-flush is to update the
   1.195 +  // style for all throttled transitions and animations to the current
   1.196 +  // animation state without making any other updates, so that when we
   1.197 +  // process the queued style updates we'll have correct old data to
   1.198 +  // compare against.  When we do this, we don't bother touching frames
   1.199 +  // other than primary frames.
   1.200 +  void UpdateAllThrottledStyles();
   1.201 +
   1.202 +  ElementTransitions* GetElementTransitions(mozilla::dom::Element *aElement,
   1.203 +                                          nsCSSPseudoElements::Type aPseudoType,
   1.204 +                                          bool aCreateIfNeeded);
   1.205 +
   1.206 +protected:
   1.207 +  virtual void ElementDataRemoved() MOZ_OVERRIDE;
   1.208 +  virtual void AddElementData(mozilla::css::CommonElementAnimationData* aData) MOZ_OVERRIDE;
   1.209 +
   1.210 +private:
   1.211 +  void ConsiderStartingTransition(nsCSSProperty aProperty,
   1.212 +                                  const nsTransition& aTransition,
   1.213 +                                  mozilla::dom::Element *aElement,
   1.214 +                                  ElementTransitions *&aElementTransitions,
   1.215 +                                  nsStyleContext *aOldStyleContext,
   1.216 +                                  nsStyleContext *aNewStyleContext,
   1.217 +                                  bool *aStartedAny,
   1.218 +                                  nsCSSPropertySet *aWhichStarted);
   1.219 +  void WalkTransitionRule(ElementDependentRuleProcessorData* aData,
   1.220 +                          nsCSSPseudoElements::Type aPseudoType);
   1.221 +  // Update the animated styles of an element and its descendants.
   1.222 +  // If the element has a transition, it is flushed back to its primary frame.
   1.223 +  // If the element does not have a transition, then its style is reparented.
   1.224 +  void UpdateThrottledStylesForSubtree(nsIContent* aContent,
   1.225 +                                       nsStyleContext* aParentStyle,
   1.226 +                                       nsStyleChangeList &aChangeList);
   1.227 +  void UpdateAllThrottledStylesInternal();
   1.228 +};
   1.229 +
   1.230 +#endif /* !defined(nsTransitionManager_h_) */

mercurial