2014-08-10 11:06:44 +04:00
|
|
|
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#ifndef mozilla_dom_AnimationPlayer_h
|
|
|
|
#define mozilla_dom_AnimationPlayer_h
|
|
|
|
|
|
|
|
#include "nsWrapperCache.h"
|
|
|
|
#include "nsCycleCollectionParticipant.h"
|
|
|
|
#include "mozilla/Attributes.h"
|
|
|
|
#include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration
|
2014-08-10 11:06:46 +04:00
|
|
|
#include "mozilla/dom/Animation.h" // for Animation
|
2014-10-20 08:55:45 +04:00
|
|
|
#include "mozilla/dom/AnimationPlayerBinding.h" // for AnimationPlayState
|
2014-08-10 11:06:44 +04:00
|
|
|
#include "mozilla/dom/AnimationTimeline.h" // for AnimationTimeline
|
2014-12-18 02:42:40 +03:00
|
|
|
#include "mozilla/dom/Promise.h" // for Promise
|
2014-08-10 11:06:44 +04:00
|
|
|
#include "nsCSSProperty.h" // for nsCSSProperty
|
|
|
|
|
|
|
|
// X11 has a #define for CurrentTime.
|
|
|
|
#ifdef CurrentTime
|
|
|
|
#undef CurrentTime
|
|
|
|
#endif
|
|
|
|
|
|
|
|
struct JSContext;
|
2014-10-20 08:55:46 +04:00
|
|
|
class nsCSSPropertySet;
|
2014-11-17 07:45:58 +03:00
|
|
|
class nsIDocument;
|
2014-11-17 07:45:58 +03:00
|
|
|
class nsPresContext;
|
2014-08-10 11:06:44 +04:00
|
|
|
|
|
|
|
namespace mozilla {
|
2014-11-17 07:45:59 +03:00
|
|
|
struct AnimationPlayerCollection;
|
2014-10-20 08:55:46 +04:00
|
|
|
namespace css {
|
|
|
|
class AnimValuesStyleRule;
|
2014-11-17 07:45:58 +03:00
|
|
|
class CommonAnimationManager;
|
2014-10-20 08:55:46 +04:00
|
|
|
} // namespace css
|
2014-10-20 08:55:44 +04:00
|
|
|
|
|
|
|
class CSSAnimationPlayer;
|
2014-11-17 07:45:57 +03:00
|
|
|
class CSSTransitionPlayer;
|
2014-10-20 08:55:44 +04:00
|
|
|
|
2014-08-10 11:06:44 +04:00
|
|
|
namespace dom {
|
|
|
|
|
2014-12-18 02:42:40 +03:00
|
|
|
class AnimationPlayer : public nsISupports,
|
|
|
|
public nsWrapperCache
|
2014-08-10 11:06:44 +04:00
|
|
|
{
|
|
|
|
protected:
|
|
|
|
virtual ~AnimationPlayer() { }
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit AnimationPlayer(AnimationTimeline* aTimeline)
|
2014-10-20 08:55:46 +04:00
|
|
|
: mTimeline(aTimeline)
|
2014-12-18 02:42:41 +03:00
|
|
|
, mIsPending(false)
|
2014-10-20 08:55:46 +04:00
|
|
|
, mIsRunningOnCompositor(false)
|
Bug 1078122 part 6 - Store the previous finished state; r=dholbert
AnimationPlayer::CanThrottle determines if an animation player has just finished
by inspecting the value of mLastNotification. This is problematic for two
reasons:
1. mLastNotification is intended to be used for events (as the XXX comment
notes)
2. mLastNotification is specific to CSS Animations and should be moved to
CSSAnimationPlayer.
To address this, this patch adds an extra member mIsPreviousStateFinished. The
Web Animations spec already defines animation players as having such a member:
http://w3c.github.io/web-animations/#previous-finished-state
We set it to true when we calculate the style for an animation that has
finished. This differs slightly from the code it is replacing as explained
below.
In the case of CSS Animations we perform the following sequence of steps on each
sample.
1. EnsureStyleRuleFor (calls CanThrottle, and maybe ComposeStyle)
2. GetEventsForCurrentTime
In the existing code, we update mLastNotification in (2) which happens on every
sample, even throttled samples.
In this patch, however, we update mIsPreviousStateFinished in (1) during the
ComposeStyle step which only happens for unthrottled samples. So, as of this
patch, in CanThrottle, we ask "have we newly entered the finished state since
the last *unthrottled* sample?", whereas previously we simply looked for
a change since the last sample, throttled or not. However, if the answer to the
question is "yes", then we'll run an unthrottled sample and update
mIsPreviousStateFinished so these should be functionally equivalent.
Another subtle difference is that this patch looks at the player's finished
state rather than the animation phase of its source content, and these will
produce different results in the case where the player is paused. However, since
paused animations are not run on the compositor, this should not matter.
In the case of CSS Transitions, AnimationPlayer::CanThrottle() is not currently
used and so mIsPreviousStateFinished is irrelevant.
Ultimately, both the existing and the new code is somewhat fragile but hopefully
this will be addressed by:
* Replacing mIsPreviousStateFinished with inspecting whether the finished
promise is settled (bug 1074630),
* Merging more of the code in nsAnimationManager and nsTransitionManager and
applying a unified approach to sampling that better accommodates these
considerations.
2014-10-20 08:55:47 +04:00
|
|
|
, mIsPreviousStateFinished(false)
|
2014-08-10 11:06:44 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-12-18 02:42:40 +03:00
|
|
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
|
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AnimationPlayer)
|
2014-08-10 11:06:44 +04:00
|
|
|
|
|
|
|
AnimationTimeline* GetParentObject() const { return mTimeline; }
|
|
|
|
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
|
|
|
|
2014-10-20 08:55:44 +04:00
|
|
|
virtual CSSAnimationPlayer* AsCSSAnimationPlayer() { return nullptr; }
|
2014-11-17 07:45:57 +03:00
|
|
|
virtual CSSTransitionPlayer* AsCSSTransitionPlayer() { return nullptr; }
|
2014-10-20 08:55:44 +04:00
|
|
|
|
2014-08-10 11:06:44 +04:00
|
|
|
// AnimationPlayer methods
|
2014-08-10 11:06:47 +04:00
|
|
|
Animation* GetSource() const { return mSource; }
|
2014-08-10 11:06:44 +04:00
|
|
|
AnimationTimeline* Timeline() const { return mTimeline; }
|
2014-12-04 19:28:38 +03:00
|
|
|
Nullable<TimeDuration> GetStartTime() const { return mStartTime; }
|
2014-10-20 08:55:45 +04:00
|
|
|
Nullable<TimeDuration> GetCurrentTime() const;
|
2014-10-20 08:55:45 +04:00
|
|
|
AnimationPlayState PlayState() const;
|
2014-12-18 02:42:41 +03:00
|
|
|
virtual Promise* GetReady(ErrorResult& aRv);
|
2014-11-17 07:46:01 +03:00
|
|
|
virtual void Play();
|
|
|
|
virtual void Pause();
|
2014-08-22 16:42:47 +04:00
|
|
|
bool IsRunningOnCompositor() const { return mIsRunningOnCompositor; }
|
2014-08-10 11:06:44 +04:00
|
|
|
|
2014-10-20 08:55:45 +04:00
|
|
|
// Wrapper functions for AnimationPlayer DOM methods when called
|
|
|
|
// from script. We often use the same methods internally and from
|
2014-11-17 07:46:01 +03:00
|
|
|
// script but when called from script we (or one of our subclasses) perform
|
|
|
|
// extra steps such as flushing style or converting the return type.
|
2014-12-04 19:28:38 +03:00
|
|
|
Nullable<double> GetStartTimeAsDouble() const;
|
2014-10-20 08:55:45 +04:00
|
|
|
Nullable<double> GetCurrentTimeAsDouble() const;
|
2014-11-17 07:45:58 +03:00
|
|
|
virtual AnimationPlayState PlayStateFromJS() const { return PlayState(); }
|
2014-11-17 07:46:01 +03:00
|
|
|
virtual void PlayFromJS() { Play(); }
|
|
|
|
// PauseFromJS is currently only here for symmetry with PlayFromJS but
|
|
|
|
// in future we will likely have to flush style in
|
|
|
|
// CSSAnimationPlayer::PauseFromJS so we leave it for now.
|
|
|
|
void PauseFromJS() { Pause(); }
|
2014-10-20 08:55:43 +04:00
|
|
|
|
2014-08-10 11:06:47 +04:00
|
|
|
void SetSource(Animation* aSource);
|
2014-08-10 11:06:48 +04:00
|
|
|
void Tick();
|
2014-12-04 19:28:38 +03:00
|
|
|
// Sets the start time of the player to the current time of its timeline.
|
|
|
|
// This should only be called on a player that is currently waiting to play
|
|
|
|
// (and therefore has a null start time but a fixed hold time).
|
|
|
|
void ResolveStartTime();
|
2014-12-18 02:42:41 +03:00
|
|
|
void Cancel();
|
2014-08-10 11:06:47 +04:00
|
|
|
|
2014-08-22 16:42:48 +04:00
|
|
|
const nsString& Name() const {
|
|
|
|
return mSource ? mSource->Name() : EmptyString();
|
|
|
|
}
|
|
|
|
|
2014-12-04 19:28:37 +03:00
|
|
|
bool IsPaused() const { return PlayState() == AnimationPlayState::Paused; }
|
2014-08-10 11:06:44 +04:00
|
|
|
bool IsRunning() const;
|
2014-10-02 10:14:13 +04:00
|
|
|
|
|
|
|
bool HasCurrentSource() const {
|
|
|
|
return GetSource() && GetSource()->IsCurrent();
|
|
|
|
}
|
2014-10-02 10:14:14 +04:00
|
|
|
bool HasInEffectSource() const {
|
|
|
|
return GetSource() && GetSource()->IsInEffect();
|
|
|
|
}
|
2014-08-10 11:06:44 +04:00
|
|
|
|
2014-10-20 08:55:46 +04:00
|
|
|
void SetIsRunningOnCompositor() { mIsRunningOnCompositor = true; }
|
|
|
|
void ClearIsRunningOnCompositor() { mIsRunningOnCompositor = false; }
|
|
|
|
|
2014-10-20 08:55:45 +04:00
|
|
|
// Returns true if this animation does not currently need to update
|
|
|
|
// style on the main thread (e.g. because it is empty, or is
|
|
|
|
// running on the compositor).
|
|
|
|
bool CanThrottle() const;
|
|
|
|
|
2014-10-20 08:55:46 +04:00
|
|
|
// Updates |aStyleRule| with the animation values of this player's source
|
|
|
|
// content, if any.
|
|
|
|
// Any properties already contained in |aSetProperties| are not changed. Any
|
|
|
|
// properties that are changed are added to |aSetProperties|.
|
|
|
|
// |aNeedsRefreshes| will be set to true if this player expects to update
|
|
|
|
// the style rule on the next refresh driver tick as well (because it
|
|
|
|
// is running and has source content to sample).
|
|
|
|
void ComposeStyle(nsRefPtr<css::AnimValuesStyleRule>& aStyleRule,
|
|
|
|
nsCSSPropertySet& aSetProperties,
|
|
|
|
bool& aNeedsRefreshes);
|
|
|
|
|
2014-10-20 08:55:43 +04:00
|
|
|
protected:
|
2014-11-17 07:46:01 +03:00
|
|
|
void DoPlay();
|
|
|
|
void DoPause();
|
|
|
|
|
2014-10-20 08:55:43 +04:00
|
|
|
void FlushStyle() const;
|
2014-11-17 07:45:59 +03:00
|
|
|
void PostUpdate();
|
2014-12-18 02:42:41 +03:00
|
|
|
// Remove this player from the pending player tracker and resets mIsPending
|
|
|
|
// as necessary. The caller is responsible for resolving or aborting the
|
|
|
|
// mReady promise as necessary.
|
|
|
|
void CancelPendingPlay();
|
2014-10-20 08:55:45 +04:00
|
|
|
StickyTimeDuration SourceContentEnd() const;
|
2014-10-20 08:55:44 +04:00
|
|
|
|
2014-11-17 07:45:58 +03:00
|
|
|
nsIDocument* GetRenderedDocument() const;
|
2014-11-17 07:45:58 +03:00
|
|
|
nsPresContext* GetPresContext() const;
|
2014-11-17 07:45:58 +03:00
|
|
|
virtual css::CommonAnimationManager* GetAnimationManager() const = 0;
|
2014-11-17 07:45:59 +03:00
|
|
|
AnimationPlayerCollection* GetCollection() const;
|
2014-11-17 07:45:58 +03:00
|
|
|
|
2014-10-20 08:55:46 +04:00
|
|
|
nsRefPtr<AnimationTimeline> mTimeline;
|
|
|
|
nsRefPtr<Animation> mSource;
|
2014-12-04 19:28:38 +03:00
|
|
|
// The beginning of the delay period.
|
|
|
|
Nullable<TimeDuration> mStartTime; // Timeline timescale
|
2014-10-20 08:55:44 +04:00
|
|
|
Nullable<TimeDuration> mHoldTime; // Player timescale
|
2014-12-18 02:42:40 +03:00
|
|
|
|
2014-12-18 02:42:41 +03:00
|
|
|
// A Promise that is replaced on each call to Play() (and in future Pause())
|
|
|
|
// and fulfilled when Play() is successfully completed.
|
|
|
|
// This object is lazily created by GetReady.
|
2014-12-18 02:42:40 +03:00
|
|
|
nsRefPtr<Promise> mReady;
|
|
|
|
|
2014-12-18 02:42:41 +03:00
|
|
|
// Indicates if the player is in the pending state. We use this rather
|
|
|
|
// than checking if this player is tracked by a PendingPlayerTracker.
|
|
|
|
// This is because the PendingPlayerTracker is associated with the source
|
|
|
|
// content's document but we need to know if we're pending even if the
|
|
|
|
// source content loses association with its document.
|
|
|
|
bool mIsPending;
|
2014-10-20 08:55:46 +04:00
|
|
|
bool mIsRunningOnCompositor;
|
Bug 1078122 part 6 - Store the previous finished state; r=dholbert
AnimationPlayer::CanThrottle determines if an animation player has just finished
by inspecting the value of mLastNotification. This is problematic for two
reasons:
1. mLastNotification is intended to be used for events (as the XXX comment
notes)
2. mLastNotification is specific to CSS Animations and should be moved to
CSSAnimationPlayer.
To address this, this patch adds an extra member mIsPreviousStateFinished. The
Web Animations spec already defines animation players as having such a member:
http://w3c.github.io/web-animations/#previous-finished-state
We set it to true when we calculate the style for an animation that has
finished. This differs slightly from the code it is replacing as explained
below.
In the case of CSS Animations we perform the following sequence of steps on each
sample.
1. EnsureStyleRuleFor (calls CanThrottle, and maybe ComposeStyle)
2. GetEventsForCurrentTime
In the existing code, we update mLastNotification in (2) which happens on every
sample, even throttled samples.
In this patch, however, we update mIsPreviousStateFinished in (1) during the
ComposeStyle step which only happens for unthrottled samples. So, as of this
patch, in CanThrottle, we ask "have we newly entered the finished state since
the last *unthrottled* sample?", whereas previously we simply looked for
a change since the last sample, throttled or not. However, if the answer to the
question is "yes", then we'll run an unthrottled sample and update
mIsPreviousStateFinished so these should be functionally equivalent.
Another subtle difference is that this patch looks at the player's finished
state rather than the animation phase of its source content, and these will
produce different results in the case where the player is paused. However, since
paused animations are not run on the compositor, this should not matter.
In the case of CSS Transitions, AnimationPlayer::CanThrottle() is not currently
used and so mIsPreviousStateFinished is irrelevant.
Ultimately, both the existing and the new code is somewhat fragile but hopefully
this will be addressed by:
* Replacing mIsPreviousStateFinished with inspecting whether the finished
promise is settled (bug 1074630),
* Merging more of the code in nsAnimationManager and nsTransitionManager and
applying a unified approach to sampling that better accommodates these
considerations.
2014-10-20 08:55:47 +04:00
|
|
|
// Indicates whether we were in the finished state during our
|
|
|
|
// most recent unthrottled sample (our last ComposeStyle call).
|
|
|
|
// FIXME: When we implement the finished promise (bug 1074630) we can
|
|
|
|
// probably remove this and check if the promise has been settled yet
|
|
|
|
// or not instead.
|
|
|
|
bool mIsPreviousStateFinished; // Spec calls this "previous finished state"
|
2014-08-10 11:06:44 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
#endif // mozilla_dom_AnimationPlayer_h
|