Since bug 960465 patch 14, we've retained finished transitions in order
to handle the issues described in
https://lists.w3.org/Archives/Public/www-style/2015Jan/0444.html . The
code that did this made the assumption that the transition manager is
notified of the full sequence of style changes that happen to an
element. However, when an element becomes part of a display:none
subtree and then later becomes displayed again, the transition manager
is not notified of a style change when it becomes displayed again (when
we do not have the old style context).
This patch introduces code to prune the finished transitions when that
happens.
This really fixes only part of the set of problems described in bug
1158431, which also affect running transitions. However, it's the part
of that set that was a regression from bug 960465, which introduced the
retention of finished transitions, and which makes these issues
substantially easier to hit.
I'd like to fix this part quickly because it's a regression and we
should backport the fix.
Without the patch, I confirmed that the following two tests fail:
INFO TEST-UNEXPECTED-FAIL | layout/style/test/test_transitions_dynamic_changes.html | bug 1144410 test - opacity after starting second transition - got 0, expected 1
INFO TEST-UNEXPECTED-FAIL | layout/style/test/test_transitions_dynamic_changes.html | bug 1144410 test - opacity during second transition - got 0, expected 0.5
With the patch, all the added tests pass.
This patch is a fairly minimal rename of the AnimationPlayer interface. It
leaves a bunch of local variables and helper classes still using the word
"player". These will be addressed in subsequent patches that don't require DOM
peer review.
We define KeyframeEffectReadonly in KeyframeEffect.cpp since Web Animations also
defines KeyframeEffect and when we come to implement that I expect we'll define
it in the same class, maybe even using the same object.
This patch also adds a few missing includes in places where
KeyframeEffectReadonly is used so that we're not just cargo-culting it in.
Most of this is fairly obvious. However, the addition of 'override' to
ElementPropertyTransition::Name() is not strictly necessary. It was simply added
because while making these changes I accidentally dropped the 'virtual' keyword
from the method in the superclass and the compiler didn't complain. Adding this
will hopefully make it harder to create the same bug in the future.
This is a bit awkward. We lazily set mName to the transition property and then
return it. The reasons for this approach are:
* We don't really want to eagerly fill in mName for all transitions since in
99% of cases we'll never use it and this will lead to wasted allocations.
* The signature of Name() returns a const nsString reference. This is because
Name() is used when building CSS Animations (to compare different copies of
the same animation when updating). For that case we don't really want to
generate unnecessary copies of nsString objects so we return a reference.
However, that means for transitions as well we need to return a reference so
we can't just generate a temporary string on-demand.
As a result we also have to const-cast ourselves so we can update the mName
member. We could make mName mutable but seeing as it's only set once, the
const_cast seems more appropriate.
This patch adds an options flag to GetAnimationsForCompositor for two reasons.
a) We want to reuse this functionality in nsLayoutUtils.cpp rather than
duplicating the same logic. To do that and maintain the existing behavior,
however, we need to *not* update the active layer tracker when calling this
from nsLayoutUtils.cpp.
b) It's surprising that GetAnimationsForCompositor also has this side effect of
updating the active layer tracker. Adding this as an option makes it clear at
the call site that this is what will happen.
I don't have a test case that requires this, but it seems like a good
idea. (It was an incorrect theory for fixing a test failure that I was
debugging, but still seems worth doing.)
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.
nsAnimationManager provides GetAnimationPlayers while nsTransitionManager
provides GetElementTransitions. Both perform the same function, namely, fetching
(and optionally creating if it does not exist) the AnimationPlayerCollection for
the specified element/pseudo. Furthermore, both take the same arguments.
This patch aligns the method names and makes this a virtual method on the base
class CommonAnimationManager so that it can be used generically from a pointer
to a CommonAnimationManager.
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).
In order to be able to find the collection a player belongs to from its source
content, we first need to be able to determine which manager--the animation
manager or transition manager--to look up.
We eventually plan to push transition event dispatch down to a CSS
transitions-specific subclass of AnimationPlayer, so this seems like a suitable
point to introduce this class.
Using this subclass we can define a virtual GetManager method that will
return the appropriate animation/transition manager for the player.
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.
I originally wrote this to see if it would fix bug 1086937, but it
didn't.
Note that this conflicts a bit with the patch in bug 1085769; whoever
lands second will have some merging (though it shouldn't be difficult).
The updating of the style rule is needed as part of the animation-only
style update, but it shouldn't be in the general restyling code, so it
has moved there.
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).
This patch changes the inheritance of ElementPropertyTransition so that it is
a subclass of Animation not AnimationPlayer.
The only thing special about ElementPropertyTransition is it stores some extra
state for reversing transitions and an extra ValuePortionFor convenience method.
This reversing behavior is implemented by the transition manager by creating
a new AnimationPlayer (i.e. it is *not* a property of the AnimationPlayer). As
a result this extra state can be pushed down to Animation which simplifies the
code significantly.
In future if we implement KeyframeEffect as a separate object we may be able to
push transition-specific state down to KeyframeEffect instead.
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.
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.
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.