layout/style/nsTransitionManager.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

michael@0 1 /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /* Code to start and animate CSS transitions. */
michael@0 7
michael@0 8 #ifndef nsTransitionManager_h_
michael@0 9 #define nsTransitionManager_h_
michael@0 10
michael@0 11 #include "mozilla/Attributes.h"
michael@0 12 #include "mozilla/MemoryReporting.h"
michael@0 13 #include "AnimationCommon.h"
michael@0 14 #include "nsCSSPseudoElements.h"
michael@0 15
michael@0 16 class nsStyleContext;
michael@0 17 class nsPresContext;
michael@0 18 class nsCSSPropertySet;
michael@0 19 struct nsTransition;
michael@0 20 struct ElementDependentRuleProcessorData;
michael@0 21
michael@0 22 /*****************************************************************************
michael@0 23 * Per-Element data *
michael@0 24 *****************************************************************************/
michael@0 25
michael@0 26 struct ElementPropertyTransition : public mozilla::StyleAnimation
michael@0 27 {
michael@0 28 // This is the start value to be used for a check for whether a
michael@0 29 // transition is being reversed. Normally the same as
michael@0 30 // mProperties[0].mSegments[0].mFromValue, except when this transition
michael@0 31 // started as the reversal of another in-progress transition.
michael@0 32 // Needed so we can handle two reverses in a row.
michael@0 33 nsStyleAnimation::Value mStartForReversingTest;
michael@0 34 // Likewise, the portion (in value space) of the "full" reversed
michael@0 35 // transition that we're actually covering. For example, if a :hover
michael@0 36 // effect has a transition that moves the element 10px to the right
michael@0 37 // (by changing 'left' from 0px to 10px), and the mouse moves in to
michael@0 38 // the element (starting the transition) but then moves out after the
michael@0 39 // transition has advanced 4px, the second transition (from 10px/4px
michael@0 40 // to 0px) will have mReversePortion of 0.4. (If the mouse then moves
michael@0 41 // in again when the transition is back to 2px, the mReversePortion
michael@0 42 // for the third transition (from 0px/2px to 10px) will be 0.8.
michael@0 43 double mReversePortion;
michael@0 44
michael@0 45 // Compute the portion of the *value* space that we should be through
michael@0 46 // at the given time. (The input to the transition timing function
michael@0 47 // has time units, the output has value units.)
michael@0 48 double ValuePortionFor(mozilla::TimeStamp aRefreshTime) const;
michael@0 49
michael@0 50 bool IsRemovedSentinel() const
michael@0 51 {
michael@0 52 // Note that mozilla::StyleAnimation::IsRunningAt depends on removed
michael@0 53 // sentinels being represented by a null mStartTime.
michael@0 54 return mStartTime.IsNull();
michael@0 55 }
michael@0 56
michael@0 57 void SetRemovedSentinel()
michael@0 58 {
michael@0 59 // assign the null time stamp
michael@0 60 mStartTime = mozilla::TimeStamp();
michael@0 61 }
michael@0 62 };
michael@0 63
michael@0 64 struct ElementTransitions MOZ_FINAL
michael@0 65 : public mozilla::css::CommonElementAnimationData
michael@0 66 {
michael@0 67 ElementTransitions(mozilla::dom::Element *aElement, nsIAtom *aElementProperty,
michael@0 68 nsTransitionManager *aTransitionManager,
michael@0 69 mozilla::TimeStamp aNow);
michael@0 70
michael@0 71 void EnsureStyleRuleFor(mozilla::TimeStamp aRefreshTime);
michael@0 72
michael@0 73 virtual bool HasAnimationOfProperty(nsCSSProperty aProperty) const MOZ_OVERRIDE;
michael@0 74
michael@0 75 // If aFlags contains CanAnimate_AllowPartial, returns whether the
michael@0 76 // state of this element's transitions at the current refresh driver
michael@0 77 // time contains transition data that can be done on the compositor
michael@0 78 // thread. (This is useful for determining whether a layer should be
michael@0 79 // active, or whether to send data to the layer.)
michael@0 80 // If aFlags does not contain CanAnimate_AllowPartial, returns whether
michael@0 81 // the state of this element's transitions at the current refresh driver
michael@0 82 // time can be fully represented by data sent to the compositor.
michael@0 83 // (This is useful for determining whether throttle the transition
michael@0 84 // (suppress main-thread style updates).)
michael@0 85 // Note that when CanPerformOnCompositorThread returns true, it also,
michael@0 86 // as a side-effect, notifies the ActiveLayerTracker. FIXME: This
michael@0 87 // should probably move to the relevant callers.
michael@0 88 virtual bool CanPerformOnCompositorThread(CanAnimateFlags aFlags) const MOZ_OVERRIDE;
michael@0 89
michael@0 90 // Either zero or one for each CSS property:
michael@0 91 nsTArray<ElementPropertyTransition> mPropertyTransitions;
michael@0 92 };
michael@0 93
michael@0 94
michael@0 95
michael@0 96 class nsTransitionManager MOZ_FINAL
michael@0 97 : public mozilla::css::CommonAnimationManager
michael@0 98 {
michael@0 99 public:
michael@0 100 nsTransitionManager(nsPresContext *aPresContext)
michael@0 101 : mozilla::css::CommonAnimationManager(aPresContext)
michael@0 102 {
michael@0 103 }
michael@0 104
michael@0 105 static ElementTransitions* GetTransitions(nsIContent* aContent) {
michael@0 106 return static_cast<ElementTransitions*>
michael@0 107 (aContent->GetProperty(nsGkAtoms::transitionsProperty));
michael@0 108 }
michael@0 109
michael@0 110 // Returns true if aContent or any of its ancestors has a transition.
michael@0 111 static bool ContentOrAncestorHasTransition(nsIContent* aContent) {
michael@0 112 do {
michael@0 113 if (GetTransitions(aContent)) {
michael@0 114 return true;
michael@0 115 }
michael@0 116 } while ((aContent = aContent->GetParent()));
michael@0 117
michael@0 118 return false;
michael@0 119 }
michael@0 120
michael@0 121 typedef mozilla::css::CommonElementAnimationData CommonElementAnimationData;
michael@0 122
michael@0 123 static ElementTransitions*
michael@0 124 GetTransitionsForCompositor(nsIContent* aContent,
michael@0 125 nsCSSProperty aProperty)
michael@0 126 {
michael@0 127 if (!aContent->MayHaveAnimations()) {
michael@0 128 return nullptr;
michael@0 129 }
michael@0 130 ElementTransitions* transitions = GetTransitions(aContent);
michael@0 131 if (!transitions ||
michael@0 132 !transitions->HasAnimationOfProperty(aProperty) ||
michael@0 133 !transitions->CanPerformOnCompositorThread(
michael@0 134 CommonElementAnimationData::CanAnimate_AllowPartial)) {
michael@0 135 return nullptr;
michael@0 136 }
michael@0 137 return transitions;
michael@0 138 }
michael@0 139
michael@0 140 /**
michael@0 141 * StyleContextChanged
michael@0 142 *
michael@0 143 * To be called from nsFrameManager::ReResolveStyleContext when the
michael@0 144 * style of an element has changed, to initiate transitions from
michael@0 145 * that style change. For style contexts with :before and :after
michael@0 146 * pseudos, aElement is expected to be the generated before/after
michael@0 147 * element.
michael@0 148 *
michael@0 149 * It may return a "cover rule" (see CoverTransitionStartStyleRule) to
michael@0 150 * cover up some of the changes for the duration of the restyling of
michael@0 151 * descendants. If it does, this function will take care of causing
michael@0 152 * the necessary restyle afterwards, but the caller must restyle the
michael@0 153 * element *again* with the original sequence of rules plus the
michael@0 154 * returned cover rule as the most specific rule.
michael@0 155 */
michael@0 156 already_AddRefed<nsIStyleRule>
michael@0 157 StyleContextChanged(mozilla::dom::Element *aElement,
michael@0 158 nsStyleContext *aOldStyleContext,
michael@0 159 nsStyleContext *aNewStyleContext);
michael@0 160
michael@0 161 // nsIStyleRuleProcessor (parts)
michael@0 162 virtual void RulesMatching(ElementRuleProcessorData* aData) MOZ_OVERRIDE;
michael@0 163 virtual void RulesMatching(PseudoElementRuleProcessorData* aData) MOZ_OVERRIDE;
michael@0 164 virtual void RulesMatching(AnonBoxRuleProcessorData* aData) MOZ_OVERRIDE;
michael@0 165 #ifdef MOZ_XUL
michael@0 166 virtual void RulesMatching(XULTreeRuleProcessorData* aData) MOZ_OVERRIDE;
michael@0 167 #endif
michael@0 168 virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
michael@0 169 MOZ_MUST_OVERRIDE MOZ_OVERRIDE;
michael@0 170 virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
michael@0 171 MOZ_MUST_OVERRIDE MOZ_OVERRIDE;
michael@0 172
michael@0 173 // nsARefreshObserver
michael@0 174 virtual void WillRefresh(mozilla::TimeStamp aTime) MOZ_OVERRIDE;
michael@0 175
michael@0 176 void FlushTransitions(FlushFlags aFlags);
michael@0 177
michael@0 178 // Performs a 'mini-flush' to make styles from throttled transitions
michael@0 179 // up-to-date prior to processing an unrelated style change, so that
michael@0 180 // any transitions triggered by that style change produce correct
michael@0 181 // results.
michael@0 182 //
michael@0 183 // In more detail: when we're able to run animations on the
michael@0 184 // compositor, we sometimes "throttle" these animations by skipping
michael@0 185 // updating style data on the main thread. However, whenever we
michael@0 186 // process a normal (non-animation) style change, any changes in
michael@0 187 // computed style on elements that have transition-* properties set
michael@0 188 // may need to trigger new transitions; this process requires knowing
michael@0 189 // both the old and new values of the property. To do this correctly,
michael@0 190 // we need to have an up-to-date *old* value of the property on the
michael@0 191 // primary frame. So the purpose of the mini-flush is to update the
michael@0 192 // style for all throttled transitions and animations to the current
michael@0 193 // animation state without making any other updates, so that when we
michael@0 194 // process the queued style updates we'll have correct old data to
michael@0 195 // compare against. When we do this, we don't bother touching frames
michael@0 196 // other than primary frames.
michael@0 197 void UpdateAllThrottledStyles();
michael@0 198
michael@0 199 ElementTransitions* GetElementTransitions(mozilla::dom::Element *aElement,
michael@0 200 nsCSSPseudoElements::Type aPseudoType,
michael@0 201 bool aCreateIfNeeded);
michael@0 202
michael@0 203 protected:
michael@0 204 virtual void ElementDataRemoved() MOZ_OVERRIDE;
michael@0 205 virtual void AddElementData(mozilla::css::CommonElementAnimationData* aData) MOZ_OVERRIDE;
michael@0 206
michael@0 207 private:
michael@0 208 void ConsiderStartingTransition(nsCSSProperty aProperty,
michael@0 209 const nsTransition& aTransition,
michael@0 210 mozilla::dom::Element *aElement,
michael@0 211 ElementTransitions *&aElementTransitions,
michael@0 212 nsStyleContext *aOldStyleContext,
michael@0 213 nsStyleContext *aNewStyleContext,
michael@0 214 bool *aStartedAny,
michael@0 215 nsCSSPropertySet *aWhichStarted);
michael@0 216 void WalkTransitionRule(ElementDependentRuleProcessorData* aData,
michael@0 217 nsCSSPseudoElements::Type aPseudoType);
michael@0 218 // Update the animated styles of an element and its descendants.
michael@0 219 // If the element has a transition, it is flushed back to its primary frame.
michael@0 220 // If the element does not have a transition, then its style is reparented.
michael@0 221 void UpdateThrottledStylesForSubtree(nsIContent* aContent,
michael@0 222 nsStyleContext* aParentStyle,
michael@0 223 nsStyleChangeList &aChangeList);
michael@0 224 void UpdateAllThrottledStylesInternal();
michael@0 225 };
michael@0 226
michael@0 227 #endif /* !defined(nsTransitionManager_h_) */

mercurial