summaryrefslogtreecommitdiffstats
path: root/WebCore/page/animation/AnimationController.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/page/animation/AnimationController.cpp')
-rw-r--r--WebCore/page/animation/AnimationController.cpp243
1 files changed, 131 insertions, 112 deletions
diff --git a/WebCore/page/animation/AnimationController.cpp b/WebCore/page/animation/AnimationController.cpp
index f85e6c1..f9c9a47 100644
--- a/WebCore/page/animation/AnimationController.cpp
+++ b/WebCore/page/animation/AnimationController.cpp
@@ -28,84 +28,22 @@
#include "config.h"
#include "AnimationController.h"
+
#include "AnimationBase.h"
-#include "CompositeAnimation.h"
+#include "AnimationControllerPrivate.h"
#include "CSSParser.h"
+#include "CompositeAnimation.h"
#include "EventNames.h"
#include "Frame.h"
-#include "Timer.h"
+#include "RenderObject.h"
#include <wtf/CurrentTime.h>
+#include <wtf/UnusedParam.h>
namespace WebCore {
static const double cAnimationTimerDelay = 0.025;
static const double cBeginAnimationUpdateTimeNotSet = -1;
-class AnimationControllerPrivate {
-public:
- AnimationControllerPrivate(Frame*);
- ~AnimationControllerPrivate();
-
- PassRefPtr<CompositeAnimation> accessCompositeAnimation(RenderObject*);
- bool clear(RenderObject*);
-
- void animationTimerFired(Timer<AnimationControllerPrivate>*);
- void updateAnimationTimer(bool callSetChanged = false);
-
- void updateRenderingDispatcherFired(Timer<AnimationControllerPrivate>*);
- void startUpdateRenderingDispatcher();
- void addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime);
- void addNodeChangeToDispatch(PassRefPtr<Node>);
-
- bool hasAnimations() const { return !m_compositeAnimations.isEmpty(); }
-
- void suspendAnimations(Document*);
- void resumeAnimations(Document*);
-
- void styleAvailable();
-
- bool isAnimatingPropertyOnRenderer(RenderObject*, int property, bool isRunningNow) const;
-
- bool pauseAnimationAtTime(RenderObject*, const String& name, double t);
- bool pauseTransitionAtTime(RenderObject*, const String& property, double t);
- unsigned numberOfActiveAnimations() const;
-
- double beginAnimationUpdateTime()
- {
- if (m_beginAnimationUpdateTime == cBeginAnimationUpdateTimeNotSet)
- m_beginAnimationUpdateTime = currentTime();
- return m_beginAnimationUpdateTime;
- }
-
- void setBeginAnimationUpdateTime(double t) { m_beginAnimationUpdateTime = t; }
-
- void addToStyleAvailableWaitList(AnimationBase*);
- void removeFromStyleAvailableWaitList(AnimationBase*);
-
-private:
- typedef HashMap<RenderObject*, RefPtr<CompositeAnimation> > RenderObjectAnimationMap;
-
- RenderObjectAnimationMap m_compositeAnimations;
- Timer<AnimationControllerPrivate> m_animationTimer;
- Timer<AnimationControllerPrivate> m_updateRenderingDispatcher;
- Frame* m_frame;
-
- class EventToDispatch {
- public:
- RefPtr<Element> element;
- AtomicString eventType;
- String name;
- double elapsedTime;
- };
-
- Vector<EventToDispatch> m_eventsToDispatch;
- Vector<RefPtr<Node> > m_nodeChangesToDispatch;
-
- double m_beginAnimationUpdateTime;
- AnimationBase* m_styleAvailableWaiters;
- AnimationBase* m_lastStyleAvailableWaiter;
-};
-
AnimationControllerPrivate::AnimationControllerPrivate(Frame* frame)
: m_animationTimer(this, &AnimationControllerPrivate::animationTimerFired)
, m_updateRenderingDispatcher(this, &AnimationControllerPrivate::updateRenderingDispatcherFired)
@@ -113,6 +51,9 @@ AnimationControllerPrivate::AnimationControllerPrivate(Frame* frame)
, m_beginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet)
, m_styleAvailableWaiters(0)
, m_lastStyleAvailableWaiter(0)
+ , m_responseWaiters(0)
+ , m_lastResponseWaiter(0)
+ , m_waitingForAResponse(false)
{
}
@@ -124,7 +65,7 @@ PassRefPtr<CompositeAnimation> AnimationControllerPrivate::accessCompositeAnimat
{
RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(renderer);
if (!animation) {
- animation = CompositeAnimation::create(m_frame->animation());
+ animation = CompositeAnimation::create(this);
m_compositeAnimations.set(renderer, animation);
}
return animation;
@@ -155,7 +96,7 @@ void AnimationControllerPrivate::updateAnimationTimer(bool callSetChanged/* = fa
needsService = t;
if (needsService == 0) {
if (callSetChanged) {
- Node* node = it->first->element();
+ Node* node = it->first->node();
ASSERT(!node || (node->document() && !node->document()->inPageCache()));
node->setChanged(AnimationStyleChange);
calledSetChanged = true;
@@ -209,7 +150,7 @@ void AnimationControllerPrivate::updateRenderingDispatcherFired(Timer<AnimationC
m_nodeChangesToDispatch.clear();
- if (m_frame && m_frame->document())
+ if (m_frame)
m_frame->document()->updateRendering();
}
@@ -233,6 +174,10 @@ void AnimationControllerPrivate::addEventToDispatch(PassRefPtr<Element> element,
void AnimationControllerPrivate::addNodeChangeToDispatch(PassRefPtr<Node> node)
{
+ ASSERT(!node || (node->document() && !node->document()->inPageCache()));
+ if (!node)
+ return;
+
m_nodeChangesToDispatch.append(node);
startUpdateRenderingDispatcher();
}
@@ -240,7 +185,7 @@ void AnimationControllerPrivate::addNodeChangeToDispatch(PassRefPtr<Node> node)
void AnimationControllerPrivate::animationTimerFired(Timer<AnimationControllerPrivate>*)
{
// Make sure animationUpdateTime is updated, so that it is current even if no
- // styleChange has happened (e.g. hardware animations)
+ // styleChange has happened (e.g. accelerated animations)
setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet);
// When the timer fires, all we do is call setChanged on all DOM nodes with running animations and then do an immediate
@@ -248,7 +193,7 @@ void AnimationControllerPrivate::animationTimerFired(Timer<AnimationControllerPr
updateAnimationTimer(true);
}
-bool AnimationControllerPrivate::isAnimatingPropertyOnRenderer(RenderObject* renderer, int property, bool isRunningNow) const
+bool AnimationControllerPrivate::isAnimatingPropertyOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const
{
RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(renderer);
if (!animation)
@@ -294,6 +239,7 @@ bool AnimationControllerPrivate::pauseAnimationAtTime(RenderObject* renderer, co
if (compAnim->pauseAnimationAtTime(name, t)) {
renderer->node()->setChanged(AnimationStyleChange);
+ startUpdateRenderingDispatcher();
return true;
}
@@ -311,12 +257,39 @@ bool AnimationControllerPrivate::pauseTransitionAtTime(RenderObject* renderer, c
if (compAnim->pauseTransitionAtTime(cssPropertyID(property), t)) {
renderer->node()->setChanged(AnimationStyleChange);
+ startUpdateRenderingDispatcher();
return true;
}
return false;
}
+double AnimationControllerPrivate::beginAnimationUpdateTime()
+{
+ if (m_beginAnimationUpdateTime == cBeginAnimationUpdateTimeNotSet)
+ m_beginAnimationUpdateTime = currentTime();
+ return m_beginAnimationUpdateTime;
+}
+
+PassRefPtr<RenderStyle> AnimationControllerPrivate::getAnimatedStyleForRenderer(RenderObject* renderer)
+{
+ if (!renderer)
+ return 0;
+
+ RefPtr<CompositeAnimation> rendererAnimations = m_compositeAnimations.get(renderer);
+ if (!rendererAnimations)
+ return renderer->style();
+
+ // Make sure animationUpdateTime is updated, so that it is current even if no
+ // styleChange has happened (e.g. accelerated animations).
+ setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet);
+ RefPtr<RenderStyle> animatingStyle = rendererAnimations->getAnimatedStyle();
+ if (!animatingStyle)
+ animatingStyle = renderer->style();
+
+ return animatingStyle.release();
+}
+
unsigned AnimationControllerPrivate::numberOfActiveAnimations() const
{
unsigned count = 0;
@@ -364,13 +337,83 @@ void AnimationControllerPrivate::removeFromStyleAvailableWaitList(AnimationBase*
void AnimationControllerPrivate::styleAvailable()
{
// Go through list of waiters and send them on their way
- for (AnimationBase* animation = m_styleAvailableWaiters; animation; animation = animation->next())
+ for (AnimationBase* animation = m_styleAvailableWaiters; animation; ) {
+ AnimationBase* nextAnimation = animation->next();
+ animation->setNext(0);
animation->styleAvailable();
+ animation = nextAnimation;
+ }
m_styleAvailableWaiters = 0;
m_lastStyleAvailableWaiter = 0;
}
+void AnimationControllerPrivate::addToStartTimeResponseWaitList(AnimationBase* animation, bool willGetResponse)
+{
+ // If willGetResponse is true, it means this animation is actually waiting for a response
+ // (which will come in as a call to notifyAnimationStarted()).
+ // In that case we don't need to add it to this list. We just set a waitingForAResponse flag
+ // which says we are waiting for the response. If willGetResponse is false, this animation
+ // is not waiting for a response for itself, but rather for a notifyXXXStarted() call for
+ // another animation to which it will sync.
+ //
+ // When endAnimationUpdate() is called we check to see if the waitingForAResponse flag is
+ // true. If so, we just return and will do our work when the first notifyXXXStarted() call
+ // comes in. If it is false, we will not be getting a notifyXXXStarted() call, so we will
+ // do our work right away. In both cases we call the onAnimationStartResponse() method
+ // on each animation. In the first case we send in the time we got from notifyXXXStarted().
+ // In the second case, we just pass in the beginAnimationUpdateTime().
+ //
+ // This will synchronize all software and accelerated animations started in the same
+ // updateRendering cycle.
+ //
+ ASSERT(!animation->next());
+
+ if (willGetResponse)
+ m_waitingForAResponse = true;
+
+ if (m_responseWaiters)
+ m_lastResponseWaiter->setNext(animation);
+ else
+ m_responseWaiters = animation;
+
+ m_lastResponseWaiter = animation;
+ animation->setNext(0);
+}
+
+void AnimationControllerPrivate::removeFromStartTimeResponseWaitList(AnimationBase* animationToRemove)
+{
+ AnimationBase* prevAnimation = 0;
+ for (AnimationBase* animation = m_responseWaiters; animation; animation = animation->next()) {
+ if (animation == animationToRemove) {
+ if (prevAnimation)
+ prevAnimation->setNext(animation->next());
+ else
+ m_responseWaiters = animation->next();
+
+ if (m_lastResponseWaiter == animation)
+ m_lastResponseWaiter = prevAnimation;
+
+ animationToRemove->setNext(0);
+ }
+ prevAnimation = animation;
+ }
+}
+
+void AnimationControllerPrivate::startTimeResponse(double t)
+{
+ // Go through list of waiters and send them on their way
+ for (AnimationBase* animation = m_responseWaiters; animation; ) {
+ AnimationBase* nextAnimation = animation->next();
+ animation->setNext(0);
+ animation->onAnimationStartResponse(t);
+ animation = nextAnimation;
+ }
+
+ m_responseWaiters = 0;
+ m_lastResponseWaiter = 0;
+}
+
AnimationController::AnimationController(Frame* frame)
: m_data(new AnimationControllerPrivate(frame))
{
@@ -387,7 +430,7 @@ void AnimationController::cancelAnimations(RenderObject* renderer)
return;
if (m_data->clear(renderer)) {
- Node* node = renderer->element();
+ Node* node = renderer->node();
ASSERT(!node || (node->document() && !node->document()->inPageCache()));
node->setChanged(AnimationStyleChange);
}
@@ -408,7 +451,7 @@ PassRefPtr<RenderStyle> AnimationController::updateAnimations(RenderObject* rend
// against the animations in the style and make sure we're in sync. If destination values
// have changed, we reset the animation. We then do a blend to get new values and we return
// a new style.
- ASSERT(renderer->element()); // FIXME: We do not animate generated content yet.
+ ASSERT(renderer->node()); // FIXME: We do not animate generated content yet.
RefPtr<CompositeAnimation> rendererAnimations = m_data->accessCompositeAnimation(renderer);
RefPtr<RenderStyle> blendedStyle = rendererAnimations->animate(renderer, oldStyle, newStyle);
@@ -425,16 +468,14 @@ PassRefPtr<RenderStyle> AnimationController::updateAnimations(RenderObject* rend
return blendedStyle.release();
}
-void AnimationController::setAnimationStartTime(RenderObject* renderer, double t)
+PassRefPtr<RenderStyle> AnimationController::getAnimatedStyleForRenderer(RenderObject* renderer)
{
- RefPtr<CompositeAnimation> rendererAnimations = m_data->accessCompositeAnimation(renderer);
- rendererAnimations->setAnimationStartTime(t);
+ return m_data->getAnimatedStyleForRenderer(renderer);
}
-void AnimationController::setTransitionStartTime(RenderObject* renderer, int property, double t)
+void AnimationController::notifyAnimationStarted(RenderObject*, double startTime)
{
- RefPtr<CompositeAnimation> rendererAnimations = m_data->accessCompositeAnimation(renderer);
- rendererAnimations->setTransitionStartTime(property, t);
+ m_data->receivedStartTimeResponse(startTime);
}
bool AnimationController::pauseAnimationAtTime(RenderObject* renderer, const String& name, double t)
@@ -452,7 +493,7 @@ bool AnimationController::pauseTransitionAtTime(RenderObject* renderer, const St
return m_data->pauseTransitionAtTime(renderer, property, t);
}
-bool AnimationController::isAnimatingPropertyOnRenderer(RenderObject* renderer, int property, bool isRunningNow) const
+bool AnimationController::isAnimatingPropertyOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const
{
return m_data->isAnimatingPropertyOnRenderer(renderer, property, isRunningNow);
}
@@ -467,28 +508,6 @@ void AnimationController::resumeAnimations(Document* document)
m_data->resumeAnimations(document);
}
-void AnimationController::startUpdateRenderingDispatcher()
-{
- m_data->startUpdateRenderingDispatcher();
-}
-
-void AnimationController::addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime)
-{
- m_data->addEventToDispatch(element, eventType, name, elapsedTime);
-}
-
-void AnimationController::addNodeChangeToDispatch(PassRefPtr<Node> node)
-{
- ASSERT(!node || (node->document() && !node->document()->inPageCache()));
- if (node)
- m_data->addNodeChangeToDispatch(node);
-}
-
-double AnimationController::beginAnimationUpdateTime()
-{
- return m_data->beginAnimationUpdateTime();
-}
-
void AnimationController::beginAnimationUpdate()
{
m_data->setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet);
@@ -496,17 +515,17 @@ void AnimationController::beginAnimationUpdate()
void AnimationController::endAnimationUpdate()
{
- m_data->styleAvailable();
+ m_data->endAnimationUpdate();
}
-void AnimationController::addToStyleAvailableWaitList(AnimationBase* animation)
+bool AnimationController::supportsAcceleratedAnimationOfProperty(CSSPropertyID property)
{
- m_data->addToStyleAvailableWaitList(animation);
-}
-
-void AnimationController::removeFromStyleAvailableWaitList(AnimationBase* animation)
-{
- m_data->removeFromStyleAvailableWaitList(animation);
+#if USE(ACCELERATED_COMPOSITING)
+ return AnimationBase::animationOfPropertyIsAccelerated(property);
+#else
+ UNUSED_PARAM(property);
+ return false;
+#endif
}
} // namespace WebCore