tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CSSTransition.h (10033B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_dom_CSSTransition_h
      8 #define mozilla_dom_CSSTransition_h
      9 
     10 #include "AnimationCommon.h"
     11 #include "mozilla/CSSPropertyId.h"
     12 #include "mozilla/ComputedTiming.h"
     13 #include "mozilla/StyleAnimationValue.h"
     14 #include "mozilla/dom/Animation.h"
     15 
     16 class nsIGlobalObject;
     17 
     18 namespace mozilla {
     19 namespace dom {
     20 
     21 class CSSTransition final : public Animation {
     22 public:
     23  explicit CSSTransition(nsIGlobalObject* aGlobal,
     24                         const CSSPropertyId& aProperty)
     25      : Animation(aGlobal),
     26        mPreviousTransitionPhase(TransitionPhase::Idle),
     27        mNeedsNewAnimationIndexWhenRun(false),
     28        mTransitionProperty(aProperty) {}
     29 
     30  JSObject* WrapObject(JSContext* aCx,
     31                       JS::Handle<JSObject*> aGivenProto) override;
     32 
     33  CSSTransition* AsCSSTransition() override { return this; }
     34  const CSSTransition* AsCSSTransition() const override { return this; }
     35 
     36  // CSSTransition interface
     37  void GetTransitionProperty(nsString& aRetVal) const;
     38 
     39  // Animation interface overrides
     40  AnimationPlayState PlayStateFromJS() const override;
     41  bool PendingFromJS() const override;
     42  void PlayFromJS(ErrorResult& aRv) override;
     43 
     44  // A variant of Play() that avoids posting style updates since this method
     45  // is expected to be called whilst already updating style.
     46  void PlayFromStyle() {
     47    ErrorResult rv;
     48    PlayNoUpdate(rv, Animation::LimitBehavior::Continue);
     49    // play() should not throw when LimitBehavior is Continue
     50    MOZ_ASSERT(!rv.Failed(), "Unexpected exception playing transition");
     51  }
     52 
     53  void CancelFromStyle(PostRestyleMode aPostRestyle) {
     54    Animation::Cancel(aPostRestyle);
     55 
     56    // The animation index to use for compositing will be established when
     57    // this transition next transitions out of the idle state but we still
     58    // update it now so that the sort order of this transition remains
     59    // defined until that moment.
     60    //
     61    // See longer explanation in CSSAnimation::CancelFromStyle.
     62    //
     63    // Note: We have to update |mAnimationIndex| after calling
     64    // Animation::Cancel(), which enqueues transitioncancel event, to make sure
     65    // we have the correct |mAnimationIndex| in AnimationEventInfo.
     66    mAnimationIndex = sNextAnimationIndex++;
     67    mNeedsNewAnimationIndexWhenRun = true;
     68 
     69    // It is important we do this *after* calling Cancel().
     70    // This is because Cancel() will end up posting a restyle and
     71    // that restyle should target the *transitions* level of the cascade.
     72    // However, once we clear the owning element, CascadeLevel() will begin
     73    // returning CascadeLevel::Animations.
     74    mOwningElement = OwningElementRef();
     75  }
     76 
     77  void SetEffectFromStyle(KeyframeEffect*);
     78 
     79  void Tick(TickState&) override;
     80 
     81  const CSSPropertyId& TransitionProperty() const;
     82  AnimationValue ToValue() const;
     83 
     84  int32_t CompareCompositeOrder(const Maybe<EventContext>& aContext,
     85                                const CSSTransition& aOther,
     86                                const Maybe<EventContext>& aOtherContext,
     87                                nsContentUtils::NodeIndexCache&) const;
     88 
     89  EffectCompositor::CascadeLevel CascadeLevel() const override {
     90    return IsTiedToMarkup() ? EffectCompositor::CascadeLevel::Transitions
     91                            : EffectCompositor::CascadeLevel::Animations;
     92  }
     93 
     94  void SetCreationSequence(uint64_t aIndex) {
     95    MOZ_ASSERT(IsTiedToMarkup());
     96    mAnimationIndex = aIndex;
     97  }
     98 
     99  // Sets the owning element which is used for determining the composite
    100  // oder of CSSTransition objects generated from CSS markup.
    101  //
    102  // @see mOwningElement
    103  void SetOwningElement(const OwningElementRef& aElement) {
    104    mOwningElement = aElement;
    105  }
    106  // True for transitions that are generated from CSS markup and continue to
    107  // reflect changes to that markup.
    108  bool IsTiedToMarkup() const { return mOwningElement.IsSet(); }
    109 
    110  // Return the animation current time based on a given TimeStamp, a given
    111  // start time and a given playbackRate on a given timeline.  This is useful
    112  // when we estimate the current animated value running on the compositor
    113  // because the animation on the compositor may be running ahead while
    114  // main-thread is busy.
    115  static Nullable<TimeDuration> GetCurrentTimeAt(
    116      const AnimationTimeline& aTimeline, const TimeStamp& aBaseTime,
    117      const TimeDuration& aStartTime, double aPlaybackRate);
    118 
    119  void MaybeQueueCancelEvent(const StickyTimeDuration& aActiveTime) override {
    120    QueueEvents(aActiveTime);
    121  }
    122 
    123  // Compute the portion of the *value* space that we should be through
    124  // at the current time.  (The input to the transition timing function
    125  // has time units, the output has value units.)
    126  double CurrentValuePortion() const;
    127 
    128  const AnimationValue& StartForReversingTest() const {
    129    return mStartForReversingTest;
    130  }
    131  double ReversePortion() const { return mReversePortion; }
    132 
    133  void SetReverseParameters(AnimationValue&& aStartForReversingTest,
    134                            double aReversePortion) {
    135    mStartForReversingTest = std::move(aStartForReversingTest);
    136    mReversePortion = aReversePortion;
    137  }
    138 
    139  struct ReplacedTransitionProperties {
    140    TimeDuration mStartTime;
    141    double mPlaybackRate;
    142    TimingParams mTiming;
    143    Maybe<StyleComputedTimingFunction> mTimingFunction;
    144    AnimationValue mFromValue, mToValue;
    145  };
    146  void SetReplacedTransition(
    147      ReplacedTransitionProperties&& aReplacedTransition) {
    148    mReplacedTransition.emplace(std::move(aReplacedTransition));
    149  }
    150 
    151  // For a new transition interrupting an existing transition on the
    152  // compositor, update the start value to match the value of the replaced
    153  // transitions at the current time.
    154  bool UpdateStartValueFromReplacedTransition();
    155 
    156  // Compute the output progress based on the ReplacedTransitionProperties
    157  // object.
    158  // https://drafts.csswg.org/web-animations-1/#calculating-the-transformed-progress
    159  static Maybe<double> ComputeTransformedProgress(
    160      const AnimationTimeline& aTimeline,
    161      const CSSTransition::ReplacedTransitionProperties& aProperties);
    162 
    163 protected:
    164  virtual ~CSSTransition() {
    165    MOZ_ASSERT(!mOwningElement.IsSet(),
    166               "Owning element should be cleared "
    167               "before a CSS transition is destroyed");
    168  }
    169 
    170  // Animation overrides
    171  void UpdateTiming(SeekFlag aSeekFlag,
    172                    SyncNotifyFlag aSyncNotifyFlag) override;
    173 
    174  void QueueEvents(const StickyTimeDuration& activeTime = StickyTimeDuration());
    175 
    176  enum class TransitionPhase;
    177 
    178  // The (pseudo-)element whose computed transition-property refers to this
    179  // transition (if any).
    180  //
    181  // This is used for determining the relative composite order of transitions
    182  // generated from CSS markup.
    183  //
    184  // Typically this will be the same as the target element of the keyframe
    185  // effect associated with this transition. However, it can differ in the
    186  // following circumstances:
    187  //
    188  // a) If script removes or replaces the effect of this transition,
    189  // b) If this transition is cancelled (e.g. by updating the
    190  //    transition-property or removing the owning element from the document),
    191  // c) If this object is generated from script using the CSSTransition
    192  //    constructor.
    193  //
    194  // For (b) and (c) the owning element will return !IsSet().
    195  OwningElementRef mOwningElement;
    196 
    197  // The 'transition phase' used to determine which transition events need
    198  // to be queued on this tick.
    199  // See: https://drafts.csswg.org/css-transitions-2/#transition-phase
    200  enum class TransitionPhase {
    201    Idle = static_cast<int>(ComputedTiming::AnimationPhase::Idle),
    202    Before = static_cast<int>(ComputedTiming::AnimationPhase::Before),
    203    Active = static_cast<int>(ComputedTiming::AnimationPhase::Active),
    204    After = static_cast<int>(ComputedTiming::AnimationPhase::After),
    205    Pending
    206  };
    207  TransitionPhase mPreviousTransitionPhase;
    208 
    209  // When true, indicates that when this transition next leaves the idle state,
    210  // its animation index should be updated.
    211  bool mNeedsNewAnimationIndexWhenRun;
    212 
    213  // Store the transition property and to-value here since we need that
    214  // information in order to determine if there is an existing transition
    215  // for a given style change. We can't store that information on the
    216  // effect however since it can be replaced using the Web Animations API.
    217  CSSPropertyId mTransitionProperty;
    218  AnimationValue mTransitionToValue;
    219 
    220  // This is the start value to be used for a check for whether a
    221  // transition is being reversed.  Normally the same as
    222  // mEffect->mProperties[0].mSegments[0].mFromValue, except when this
    223  // transition started as the reversal of another in-progress transition
    224  // or when the effect has been mutated using the Web Animations API.
    225  //
    226  // Needed so we can handle two reverses in a row.
    227  AnimationValue mStartForReversingTest;
    228 
    229  // Likewise, the portion (in value space) of the "full" reversed
    230  // transition that we're actually covering.  For example, if a :hover
    231  // effect has a transition that moves the element 10px to the right
    232  // (by changing 'left' from 0px to 10px), and the mouse moves in to
    233  // the element (starting the transition) but then moves out after the
    234  // transition has advanced 4px, the second transition (from 10px/4px
    235  // to 0px) will have mReversePortion of 0.4.  (If the mouse then moves
    236  // in again when the transition is back to 2px, the mReversePortion
    237  // for the third transition (from 0px/2px to 10px) will be 0.8.
    238  double mReversePortion = 1.0;
    239 
    240  // The information of the old transition we'd like to replace with "this"
    241  // transition.
    242  Maybe<ReplacedTransitionProperties> mReplacedTransition;
    243 };
    244 
    245 }  // namespace dom
    246 
    247 }  // namespace mozilla
    248 
    249 #endif  // mozilla_dom_CSSTransition_h