This patch adds a means of terminating an animation so that is has no effect.
The procedure is defined by Web Animations:
http://w3c.github.io/web-animations/#cancelling-a-player-section
We don't implement all of this, however, since we don't currently support the
finished promise or custom effects.
In a later bug we will expose this as the cancel() method on AnimationPlayer.
We call this method for terminated animations in nsAnimationManager and
nsTransitionManager to ensure they get removed from the pending player tracker
and so that, for example, the ready promise of CSS Animation player objects is
rejected when the corresponding item is removed from animation-name.
Now that there is a public accessor for mStartTime, we can make it a protected
member of AnimationPlayer. The only time mStartTime is ever set is when playing
the animation so we can replace external modifications to mStartTime with calls
to Play(). This simplifies implementing deferred starting of animations
in bug 927349 by isolating the deferred playback logic to AnimationPlayer.
Note that even when we call PauseFromStyle immediately afterwards we still need
to call PlayFromStyle (or Play) first in order to resolve the time at which the
player should be paused. A newly created player doesn't have a current time so
if we were simply to call pause it wouldn't pause at the start of the animation
as we might expect. The call to Play(FromStyle) will cause the current time to
become zero and then we pause at that time.
The existing relationship between the particular versions of
AnimationPlayer::Play* (particularly in the CSSAnimationPlayer) subclass are
confusing because, for example, CSSAnimationPlayer::PlayFromStyle needs to be
careful to *not* call Play on CSSAnimationPlayer, but only on the parent
object (since otherwise we reset the sticky pause behavior).
This patch reworks this relationship by adding a protected DoPlay method that
performs the common pausing behavior. Play/PlayFromJS/PlayFromStyle then add
flushing, sticky pausing etc. as necessary.
This patch also removes the UpdateFlags enum and parameters previously used to
control whether we forced an update to style. This is no longer necessary since
we no longer call 'Play' from style. Instead we make Play always post restyles.
If we come across a case where we want to call Play and *not* post restyles, we
can re-add the flags then.
Roughly the same arrangement is true for Pause except that we don't currently
flush styles for CSS animations in PauseFromJS since it currently won't make any
observable difference.
This patch introduces an abstract method to AnimationPlayer to fetch the manager
object associated with the player. This method is implemented separate by
CSSAnimationPlayer and CSSTransitionPlayer to return the nsAnimationManager or
nsTransitionManager accordingly.
Previously AnimationPlayer::Play() and AnimationPlayer::PlayState() would flush
styles as part of their operation. This, however, is only needed when the player
corresponds to a CSS Animation or CSS Transition. Now that we have concrete
subclasses for each of these cases we can move style flushing to the subclasses
and remove it from the base class (which is expected to be shared with
animations that are not dependent on style).
Now that CheckNeedsRefresh is a member of the base class,
CommonAnimationManager, we no longer need to rely on callers of
AnimationPlayerCollection::EnsureStyleRuleFor to remember to call this method
but can do it automatically.
In order to add AnimationPlayerCollection::NotifyPlayerUpdated, collections
need a way of updating their managers to inform them that their mNeedsRefreshes
flag has changed and hence the manager may need to resume observing the refresh
driver.
Currently, only nsAnimationManager makes use of mNeedsRefreshes and provides
a CheckNeedsRefresh method. In order to allow AnimationPlayerCollection to
operate independently of the type of manager it is attached to (and because
there's a lot of similar code here that we eventually want to move to a common
manager anyway), this patch moves CheckNeedsRefreshes and associated
machinery to CommonAnimationManager.
This patch moves the code for queuing CSS animation events from
nsAnimationManager to CSSAnimationPlayer. In doing so, it also moves the
mLastNotification member and associated enum values.
This patch takes the CSSAnimationPlayer object, currently defined in
dom/animation/AnimationPlayer.{cpp,h}, and moves it to
layout/style/nsAnimationManager.{cpp,h} where the rest of the CSS
Animations-specific code lives.
At the same time it extends the scope of the mozilla namespace block in
nsAnimationManager.h to also include the AnimationEventInfo and EventArray types
since these classes, which don't have an ns* prefix, probably should be in the
mozilla namespace anyway.
This patch uses the PlayFromStyle/PauseFromStyle methods on CSSAnimationPlayer
to perform play/pause control. (This allows us to encapsulate mHoldTime and
mPaused. We will encapsulate mStartTime etc. in subsequent bugs.
The override behavior of play()/pause() with regard to animation-play-state is:
* pause()/play() override the current animation-play-state
* pause() causes the player to remain paused until play() is called regardless
of changes to animation-play-state
(* Calling play() will override the animation-play-state but won't "stick". i.e.
subsequently setting animation-play-state: paused will pause the animation.)
These different permutations are tested in the next patch in this series.
This interaction will probably become more complicated once we introduce
finishing behavior (since we might not want animations to restart when
setting animation-play-state: running).
We only need to store if an animation is paused or not, hence a bool is
sufficient. Furthermore, the convenience of using the same type as the specified
style of animation-play-state will disappear once pausing behavior is wrapped up
behind Play() and Pause() methods.
This patch takes the StickyTimeDuration defined in the previous patch and
uses it within the calculation of animation timing for parameters that are
expected to be +/- Forever.
This patch fixes a regression from bug 1033114, m-c changeset 9db3e43c19c1.
That changeset changed the meaning of mHoldTime (despite the commit message
which erroneously refers to mStartTime) to make it an offset from the start time
rather than a timestamp. However, it failed to update the case when we have an
initially-paused player. In that case the offset should be zero but the existing
code set it to the same value as the start time (which is, itself, an offset
from the beginning of the timeline) and the above changeset failed to update
that.
This patch stores the animation name on the Animation object rather than its
AnimationPlayer. This is because Animation objects don't have a reference to
their AnimationPlayer but their AnimationEffect needs access to the animation
name.
This patch also adds an accessor for AnimationPlayer to get the name from its
Animation (since players *do* have a reference to their source animation
content).
In this fourth step of dividing functionality between AnimationPlayer and
Animation, we move the mIsLastNotification and related methods/enums from
AnimationPlayer to Animation.
It is somewhat unclear where this belongs. This member is used to determine
which event to send for CSS Animations. The thinking behind moving this to
Animation is that if an animation that has already dispatched its animationstart
event was transferred to a new animation player with a similar current time then
I think it is expected that such an animation would *not* dispatch another
animationstart event. That suggests that event-state is a property of the
Animation not the AnimationPlayer.
Obviously, this needs to be defined somewhere (namely, the CSS Animations <->
Web Animations integration spec likely to become "CSS Animations Level 4"). Once
that behavior is agreed upon, if AnimationPlayer proves to be the more suitable
home for this member then it should be relatively straightforward to move the
member back at that time.
As the second step in dividing functionality between AnimationPlayer and
Animation, this patch moves the AnimationTiming member from AnimationPlayer to
Animation.
Most of this patch is simply moving code around. However, one significant
functional difference is that Animation::GetLocalTime() uses the mParentTime
member which is set when the Animation is updated by the player it is attached
to.
Other less significant differences are:
* AnimationPlayer::GetLocalTime is renamed to GetCurrentTimeDuration
In Web Animations, animation players have a (writeable) "current time" and
animations have a (read-only) "local time".
We would call the method simply "GetCurrentTime" (instead of
"GetCurrentTimeDuration") but GetCurrentTime is the name of the method used in
the content-facing API where it returns a double.
* "IsCurrent" is defined on both AnimationPlayer and Animation with the version
in AnimationPlayer serving mostly as a convenience shortcut to the version on
Animation.
* Animation::GetComputedTiming (previously on AnimationPlayer) now makes the
timing parameter optional since most of the time it is not needed.
As the first step in dividing the functionality currently contained in
AnimationPlayer between AnimationPlayer and Animation this patch moves the set
of keyframe properties to the Animation.
These properties are returned from the Animation by a couple of Properties()
methods that provide direct access to the member variable. In future it is
anticipated that the non-const version will be replaced with an appropriate
setter function. This will likely happen when we implement a separate
KeyframeEffect object as defined by the Web Animations API.
With regards to error checking, nsAnimationManager checks the result of
AnimationPlayer::GetSource() and handles the case where it is nullptr.
nsTransitionManager, however, simply asserts that GetSource() is never null much
like it also asserts that there is only one property with one segment in the
animation. Eventually this code should be made more generic which will probably
happen in bug 999927.
Now that we have both AnimationPlayer and Animation in use we need to clarify
which object we are referring to. This patch renames a number of member and
local variables to better reflect whether they point to an AnimationPlayer or an
Animation.
This patch is mostly renaming only with one exception. Since we are touching
a number of local variables used in loops (for looping over the array of
animation players) we take the opportunity to replace a number of instances of
uint32_t with size_t since that is the preferred type for array indices now.
This patch makes AnimationPlayers pass their current time down to the Animation
they are playing.
Since all Animations need from their players is their time, this avoids adding
a pointer back to their AnimationPlayer.
This patch renames mozilla::ElementAnimations to mozilla::dom::AnimationPlayer
and moves the code from layout/style/AnimationCommon.cpp to
dom/animation/AnimationPlayer.cpp.
It also moves various helper classes needed by AnimationPlayer to
AnimationPlayer.cpp and moves them from the mozilla::css namespace to the
mozilla namespace.
Beyond that, there are no functional changes contained in this patch.
The renaming of various members and variables that used to refer to
ElementAnimation objects but now refer to AnimationPlayer objects--to give them
a more appropriate name--is performed in a subsequent patch.
--HG--
rename : layout/style/AnimationCommon.cpp => dom/animation/AnimationPlayer.cpp
rename : layout/style/AnimationCommon.h => dom/animation/AnimationPlayer.h
This patch changes the order in which we look for matches when updating existing
animations. Previously we would iterate through new animations in a forwards
direction but match old animations by going through the list of animations
backwards.
This patch makes us iterate through both lists in a backwards direction. That
means that if we have:
animation: anim 100s
and later we make it
animation: anim 100s, anim 100s
Then the new animation will be added to the *start* of the list, i.e. prepended,
and the resulting animation will not restart.
Previously when updating animations we'd generate a new list of animation
objects then try to match up animations from the existing list and copy across
state such as start times and notification flags. However, this means that from
the API we end up returning different objects.
This patch makes us maintain the same object identity when updating an existing
animation. It does this by looking for matching animations in both lists. If it
finds a match it copies the necessary information from the *new* animation to
the *existing* animation (but preserving the start time, last notification
etc.). Then, finally, it puts the *existing* animation in the list of *new*
animations and removes the corresponding *new* animation. The existing
animation is also removed from the list of existing animations so that it only
matches once.
The method used for matching is probably not intuitive but this is addressed in
a subsequent patch in this series.
This patch introduces a method GetComputedTiming that calls GetComputedTimingAt
supplying the current time of the animation's timeline.
We still keep the GetComputedTimingAt static method since it is used for
off-main thread animation. Furthermore, we keep the second argument to
GetComputedTiming--the animation's timing properties--since on some occasions we
want to override those properties (ElementPropertyTransition::ValuePortionFor
does this). We could also add another overload that also supplies the
animation's timing properties but that can happen as a separate step.
This patch changes ElementAnimation::GetLocalTimeAt so that instead of taking
the current time as input, it uses the animation's mTimeline member to look up
the current time of the associated timeline. As a result of this, it is possible
to remove a few instances of querying the refresh driver for the current time.
Further instances are removed in subsequent patches.
Furthermore, in order to keep the use of time sources consistent, the mStartTime
of new transitions and animations is initialized with the current time from the
animation's timeline rather than with the latest refresh driver tick.
Since this time could, in future, be null, GetLocalTime(At) is updated to check
for a null start time.
GetLocalTimeAt is also renamed to GetLocalTime in the process.
Once we support arbitrary timelines which can return null current time values,
the local time of an animation can also become null so this patch updates
ElementAnimation::GetLocalTimeAt to return a Nullable<TimeDuration>.
Doing this also allows us to pass the result of GetLocalTimeAt directly to
GetComputedTimingAt.
In order to support arbitrary timelines which may provide a "null" current time,
we need a suitable value to return from GetComputedTimingAt for the animation's
phase when the timeline time is null.
This patch introduces a null animation phase for this purpose.
When we expose ElementAnimation objects to script they need to have a parent
object so they can be associated with a Window.
This patch adds a pointer from an ElementAnimation to its AnimationTimeline.
When animation-name does not match a keyframes rule, we should not dispatch
animation events as per:
"Any animation for which both a valid keyframe rule and a non-zero duration
are defined will run and generate events; this includes animations with empty
keyframe rules."
http://dev.w3.org/csswg/css-animations/#events
Since bug 1004377, however, we started dispatching events in this case because
we no longer ignore animations whose set of keyframes is empty.
This patch checks for a matching keyframes rule in BuildAnimations and if one is
not found, no corresponding animation is generated.
This patch causes animations whose corresponding animation-name is "none" to be
dropped from the list of generated ElementAnimation objects. This means we avoid
generating events for these animations.