Diff
Modified: trunk/LayoutTests/ChangeLog (181654 => 181655)
--- trunk/LayoutTests/ChangeLog 2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/LayoutTests/ChangeLog 2015-03-17 19:01:46 UTC (rev 181655)
@@ -1,3 +1,16 @@
+2015-03-17 Dean Jackson <[email protected]>
+
+ Implement Scroll Container Animation Triggers
+ https://bugs.webkit.org/show_bug.cgi?id=142732
+
+ Reviewed by Simon Fraser.
+
+ Test that checks if an animation only triggers when the page
+ is scrolled.
+
+ * animations/trigger-container-scroll-simple-expected.txt: Added.
+ * animations/trigger-container-scroll-simple.html: Added.
+
2015-03-17 Brent Fulgham <[email protected]>
[Win] Skip some IndexDB tests that don't apply on Windows.
Added: trunk/LayoutTests/animations/trigger-container-scroll-simple-expected.txt (0 => 181655)
--- trunk/LayoutTests/animations/trigger-container-scroll-simple-expected.txt (rev 0)
+++ trunk/LayoutTests/animations/trigger-container-scroll-simple-expected.txt 2015-03-17 19:01:46 UTC (rev 181655)
@@ -0,0 +1,6 @@
+This element should begin animating only when the page scrolls to 20px from the top. The animation is almost instantaneous, so it will snap to its final position. Remember to scroll to the top of the page before reloading!
+
+Value before animation is applied: auto (should be auto)
+Value with animation but no scroll: 0px (should be 0px)
+Value with animation after scroll: 100px (should be 100px)
+
Property changes on: trunk/LayoutTests/animations/trigger-container-scroll-simple-expected.txt
___________________________________________________________________
Added: svn:mime-type
Added: svn:keywords
Added: svn:eol-style
Added: trunk/LayoutTests/animations/trigger-container-scroll-simple.html (0 => 181655)
--- trunk/LayoutTests/animations/trigger-container-scroll-simple.html (rev 0)
+++ trunk/LayoutTests/animations/trigger-container-scroll-simple.html 2015-03-17 19:01:46 UTC (rev 181655)
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<style>
+body {
+ height: 2000px;
+}
+
+#box {
+ position: relative;
+ width: 20px;
+ height: 20px;
+ background-color: blue;
+}
+
+.animating {
+ animation-name: slide;
+ animation-duration: 1ms;
+ animation-fill-mode: forwards;
+ -webkit-animation-trigger: container-scroll(20px);
+}
+
+@-webkit-keyframes slide {
+ from {
+ left: 0px;
+ }
+ to {
+ left: 100px;
+ }
+}
+</style>
+<script>
+
+var results;
+var box;
+
+if (window.testRunner) {
+ window.testRunner.dumpAsText();
+ window.testRunner.waitUntilDone();
+}
+
+function runTest() {
+ results = document.getElementById("results");
+ box = document.getElementById("box");
+ results.innerHTML = "Value before animation is applied: " + window.getComputedStyle(box).left + " (should be auto)<br>";
+ box.className = "animating";
+ setTimeout(checkValueWithoutScroll, 0);
+}
+
+function checkValueWithoutScroll() {
+ results.innerHTML += "Value with animation but no scroll: " + window.getComputedStyle(box).left + " (should be 0px)<br>";
+ window.scrollTo(0, 30);
+ setTimeout(checkValueWithScroll, 0);
+}
+
+function checkValueWithScroll() {
+ results.innerHTML += "Value with animation after scroll: " + window.getComputedStyle(box).left + " (should be 100px)<br>";
+ if (window.testRunner)
+ window.testRunner.notifyDone();
+}
+
+window.addEventListener("load", runTest, false);
+
+</script>
+
+<p>This element should begin animating only when the page scrolls to 20px from
+the top. The animation is almost instantaneous, so it will snap to its final
+position. Remember to scroll to the top of the page before reloading!</p>
+<div id="box"></div>
+
+<div id="results"></div>
Property changes on: trunk/LayoutTests/animations/trigger-container-scroll-simple.html
___________________________________________________________________
Added: svn:mime-type
Added: svn:keywords
Added: svn:eol-style
Modified: trunk/Source/WebCore/ChangeLog (181654 => 181655)
--- trunk/Source/WebCore/ChangeLog 2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/ChangeLog 2015-03-17 19:01:46 UTC (rev 181655)
@@ -1,3 +1,47 @@
+2015-03-17 Dean Jackson <[email protected]>
+
+ Implement Scroll Container Animation Triggers
+ https://bugs.webkit.org/show_bug.cgi?id=142732
+
+ Reviewed by Simon Fraser.
+
+ Test: animations/trigger-container-scroll-simple.html
+
+ Basic implementation of container-scroll. It only checks
+ the page scroll position for trigger values (not the scrolling
+ container in an overflow).
+
+ * css/CSSComputedStyleDeclaration.cpp: Add CSSPropertyWebkitAnimationTrigger
+ so that this property will appear in the inspector.
+
+ * page/FrameView.cpp:
+ (WebCore::FrameView::sendScrollEvent): If the page has scrolled, let the animation
+ controller know about it.
+
+ * page/animation/AnimationBase.cpp:
+ (WebCore::AnimationBase::updateStateMachine): Whitespace fix.
+ (WebCore::AnimationBase::fireAnimationEventsIfNeeded): If there is a trigger,
+ and the scroll position is past it, then tell the state machine that
+ we should start.
+ (WebCore::AnimationBase::timeToNextService): Use the scroll position as
+ an input to the update timer if a trigger is involved.
+
+ * page/animation/AnimationController.cpp:
+ (WebCore::AnimationControllerPrivate::ensureCompositeAnimation): Add whitespace.
+ (WebCore::AnimationControllerPrivate::scrollWasUpdated): Call updateAnimations.
+ (WebCore::AnimationController::scrollWasUpdated): Call into AnimationControllerPrivate.
+ * page/animation/AnimationController.h:
+ * page/animation/AnimationControllerPrivate.h:
+
+ * page/animation/CompositeAnimation.cpp: Keep a record of whether we have a scroll
+ triggered animation.
+ (WebCore::CompositeAnimation::CompositeAnimation):
+ (WebCore::CompositeAnimation::updateKeyframeAnimations):
+ * page/animation/CompositeAnimation.h:
+ (WebCore::CompositeAnimation::hasScrollTriggeredAnimation):
+ * platform/animation/Animation.cpp:
+ (WebCore::Animation::operator=):
+
2015-03-17 Simon Fraser <[email protected]>
Move some code from LogicalSelectionOffsetCaches into RenderElement
Modified: trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp (181654 => 181655)
--- trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp 2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp 2015-03-17 19:01:46 UTC (rev 181655)
@@ -245,6 +245,7 @@
CSSPropertyWebkitAnimationName,
CSSPropertyWebkitAnimationPlayState,
CSSPropertyWebkitAnimationTimingFunction,
+ CSSPropertyWebkitAnimationTrigger,
CSSPropertyWebkitAppearance,
CSSPropertyWebkitBackfaceVisibility,
CSSPropertyWebkitBackgroundClip,
Modified: trunk/Source/WebCore/page/FrameView.cpp (181654 => 181655)
--- trunk/Source/WebCore/page/FrameView.cpp 2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/page/FrameView.cpp 2015-03-17 19:01:46 UTC (rev 181655)
@@ -4374,6 +4374,9 @@
{
frame().eventHandler().sendScrollEvent();
frame().eventHandler().dispatchFakeMouseMoveEventSoon();
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+ frame().animation().scrollWasUpdated();
+#endif
}
void FrameView::removeChild(Widget& widget)
Modified: trunk/Source/WebCore/page/animation/AnimationBase.cpp (181654 => 181655)
--- trunk/Source/WebCore/page/animation/AnimationBase.cpp 2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/page/animation/AnimationBase.cpp 2015-03-17 19:01:46 UTC (rev 181655)
@@ -40,6 +40,7 @@
#include "Logging.h"
#include "RenderBox.h"
#include "RenderStyle.h"
+#include "RenderView.h"
#include "UnitBezier.h"
#include <algorithm>
#include <wtf/CurrentTime.h>
@@ -198,6 +199,7 @@
switch (m_animationState) {
case AnimationState::New:
ASSERT(input == AnimationStateInput::StartAnimation || input == AnimationStateInput::PlayStateRunning || input == AnimationStateInput::PlayStatePaused);
+
if (input == AnimationStateInput::StartAnimation || input == AnimationStateInput::PlayStateRunning) {
m_requestedStartTime = beginAnimationUpdateTime();
LOG(Animations, "%p AnimationState %s -> StartWaitTimer", this, nameForState(m_animationState));
@@ -457,12 +459,29 @@
// Check for start timeout
if (m_animationState == AnimationState::StartWaitTimer) {
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+ if (m_animation->trigger() && m_animation->trigger()->isScrollAnimationTrigger()) {
+ if (m_object) {
+ LayoutSize offset = m_object->view().frameView().scrollOffsetForFixedPosition();
+ ScrollAnimationTrigger* scrollTrigger = static_cast<ScrollAnimationTrigger*>(m_animation->trigger().get());
+ if (offset.height().toFloat() > scrollTrigger->startValue().value())
+ updateStateMachine(AnimationStateInput::StartTimerFired, 0);
+ }
+
+ return;
+ }
+#endif
if (beginAnimationUpdateTime() - m_requestedStartTime >= m_animation->delay())
updateStateMachine(AnimationStateInput::StartTimerFired, 0);
return;
}
double elapsedDuration = beginAnimationUpdateTime() - m_startTime;
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+ if (m_animation->trigger() && m_animation->trigger()->isScrollAnimationTrigger())
+ elapsedDuration = getElapsedTime();
+#endif
+
// FIXME: we need to ensure that elapsedDuration is never < 0. If it is, this suggests that
// we had a recalcStyle() outside of beginAnimationUpdate()/endAnimationUpdate().
// Also check in getTimeToNextEvent().
@@ -521,6 +540,17 @@
return -1;
if (m_animationState == AnimationState::StartWaitTimer) {
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+ if (m_animation->trigger()->isScrollAnimationTrigger()) {
+ if (m_object) {
+ float currentScrollOffset = m_object->view().frameView().scrollOffsetForFixedPosition().height().toFloat();
+ ScrollAnimationTrigger* scrollTrigger = static_cast<ScrollAnimationTrigger*>(m_animation->trigger().get());
+ if (currentScrollOffset >= scrollTrigger->startValue().value() && (!scrollTrigger->hasEndValue() || currentScrollOffset <= scrollTrigger->endValue().value()))
+ return 0;
+ }
+ return -1;
+ }
+#endif
double timeFromNow = m_animation->delay() - (beginAnimationUpdateTime() - m_requestedStartTime);
return std::max(timeFromNow, 0.0);
}
@@ -672,7 +702,7 @@
double AnimationBase::getElapsedTime() const
{
- if (paused())
+ if (paused())
return m_pauseTime - m_startTime;
if (m_startTime <= 0)
return 0;
Modified: trunk/Source/WebCore/page/animation/AnimationController.cpp (181654 => 181655)
--- trunk/Source/WebCore/page/animation/AnimationController.cpp 2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/page/animation/AnimationController.cpp 2015-03-17 19:01:46 UTC (rev 181655)
@@ -92,6 +92,7 @@
result.iterator->value = CompositeAnimation::create(this);
renderer.setIsCSSAnimating(true);
}
+
return *result.iterator->value;
}
@@ -514,6 +515,13 @@
removeFromAnimationsWaitingForStartTimeResponse(animation);
}
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+void AnimationControllerPrivate::scrollWasUpdated()
+{
+ updateAnimations(CallSetChanged);
+}
+#endif
+
AnimationController::AnimationController(Frame& frame)
: m_data(std::make_unique<AnimationControllerPrivate>(frame))
{
@@ -700,4 +708,11 @@
return CSSPropertyAnimation::animationOfPropertyIsAccelerated(property);
}
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+void AnimationController::scrollWasUpdated()
+{
+ m_data->scrollWasUpdated();
+}
+#endif
+
} // namespace WebCore
Modified: trunk/Source/WebCore/page/animation/AnimationController.h (181654 => 181655)
--- trunk/Source/WebCore/page/animation/AnimationController.h 2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/page/animation/AnimationController.h 2015-03-17 19:01:46 UTC (rev 181655)
@@ -86,6 +86,10 @@
static bool supportsAcceleratedAnimationOfProperty(CSSPropertyID);
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+ void scrollWasUpdated();
+#endif
+
private:
const std::unique_ptr<AnimationControllerPrivate> m_data;
};
Modified: trunk/Source/WebCore/page/animation/AnimationControllerPrivate.h (181654 => 181655)
--- trunk/Source/WebCore/page/animation/AnimationControllerPrivate.h 2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/page/animation/AnimationControllerPrivate.h 2015-03-17 19:01:46 UTC (rev 181655)
@@ -117,6 +117,10 @@
bool allowsNewAnimationsWhileSuspended() const { return m_allowsNewAnimationsWhileSuspended; }
void setAllowsNewAnimationsWhileSuspended(bool);
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+ void scrollWasUpdated();
+#endif
+
private:
void animationTimerFired();
Modified: trunk/Source/WebCore/page/animation/CompositeAnimation.cpp (181654 => 181655)
--- trunk/Source/WebCore/page/animation/CompositeAnimation.cpp 2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/page/animation/CompositeAnimation.cpp 2015-03-17 19:01:46 UTC (rev 181655)
@@ -43,6 +43,9 @@
CompositeAnimation::CompositeAnimation(AnimationControllerPrivate* animationController)
: m_animationController(animationController)
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+ , m_hasScrollTriggeredAnimation(false)
+#endif
{
m_suspended = animationController->isSuspended() && !animationController->allowsNewAnimationsWhileSuspended();
}
@@ -222,7 +225,11 @@
// Mark all existing animations as no longer active.
for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it)
it->value->setIndex(-1);
-
+
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+ m_hasScrollTriggeredAnimation = false;
+#endif
+
// Toss the animation order map.
m_keyframeAnimationOrderMap.clear();
@@ -245,7 +252,12 @@
// If this animation is postActive, skip it so it gets removed at the end of this function.
if (keyframeAnim->postActive())
continue;
-
+
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+ if (animation.trigger()->isScrollAnimationTrigger())
+ m_hasScrollTriggeredAnimation = true;
+#endif
+
// This one is still active.
// Animations match, but play states may differ. Update if needed.
@@ -265,6 +277,12 @@
for (auto it = keyframeAnim->keyframes().beginProperties(), end = keyframeAnim->keyframes().endProperties(); it != end; ++it)
LOG(Animations, " property %s", getPropertyName(*it));
#endif
+
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+ if (animation.trigger()->isScrollAnimationTrigger())
+ m_hasScrollTriggeredAnimation = true;
+#endif
+
m_keyframeAnimations.set(keyframeAnim->name().impl(), keyframeAnim);
}
Modified: trunk/Source/WebCore/page/animation/CompositeAnimation.h (181654 => 181655)
--- trunk/Source/WebCore/page/animation/CompositeAnimation.h 2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/page/animation/CompositeAnimation.h 2015-03-17 19:01:46 UTC (rev 181655)
@@ -80,6 +80,10 @@
bool pauseTransitionAtTime(CSSPropertyID, double);
unsigned numberOfActiveAnimations() const;
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+ bool hasScrollTriggeredAnimation() const { return m_hasScrollTriggeredAnimation; }
+#endif
+
private:
CompositeAnimation(AnimationControllerPrivate*);
@@ -87,13 +91,16 @@
void updateKeyframeAnimations(RenderElement*, RenderStyle* currentStyle, RenderStyle* targetStyle);
typedef HashMap<int, RefPtr<ImplicitAnimation>> CSSPropertyTransitionsMap;
- typedef HashMap<AtomicStringImpl*, RefPtr<KeyframeAnimation>> AnimationNameMap;
+ typedef HashMap<AtomicStringImpl*, RefPtr<KeyframeAnimation>> AnimationNameMap;
AnimationControllerPrivate* m_animationController;
CSSPropertyTransitionsMap m_transitions;
AnimationNameMap m_keyframeAnimations;
Vector<AtomicStringImpl*> m_keyframeAnimationOrderMap;
bool m_suspended;
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+ bool m_hasScrollTriggeredAnimation;
+#endif
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/animation/Animation.cpp (181654 => 181655)
--- trunk/Source/WebCore/platform/animation/Animation.cpp 2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/platform/animation/Animation.cpp 2015-03-17 19:01:46 UTC (rev 181655)
@@ -94,6 +94,9 @@
m_delay = o.m_delay;
m_duration = o.m_duration;
m_timingFunction = o.m_timingFunction;
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+ m_trigger = o.m_trigger;
+#endif
m_direction = o.m_direction;
m_fillMode = o.m_fillMode;
m_playState = o.m_playState;