diff options
author | noel <noel@chromium.org> | 2015-12-23 03:37:55 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-23 11:38:50 +0000 |
commit | ae22bfdbb0ca73fd84c1eece143da72e30b08f66 (patch) | |
tree | 9ab8d0258fc3b2b38b55cdcd17414f730c9938c4 | |
parent | 2b7b5550416097a10d9373bc5f0810201d5f127d (diff) | |
download | chromium_src-ae22bfdbb0ca73fd84c1eece143da72e30b08f66.zip chromium_src-ae22bfdbb0ca73fd84c1eece143da72e30b08f66.tar.gz chromium_src-ae22bfdbb0ca73fd84c1eece143da72e30b08f66.tar.bz2 |
Reland of un smooth scroll animations on the compositor when possible (patchset #1 id:1 of https://codereview.chromium.org/1548883002/ )
Reason for revert:
The revert did not help, the tests
virtual/threaded/fast/scroll-behavior/overflow-scroll-root-frame-animates.html
virtual/threaded/fast/scroll-behavior/overflow-scroll-animates.html
are now slower and hitting test timeout limits.
Original issue's description:
> Revert of Run smooth scroll animations on the compositor when possible (patchset #4 id:60001 of https://codereview.chromium.org/1534813004/ )
>
> Reason for revert:
> Appears to have made Linux debug builds fail the following tests:
>
> virtual/threaded/fast/scroll-behavior/overflow-scroll-root-frame-animates.html
> virtual/threaded/fast/scroll-behavior/overflow-scroll-animates.html
>
> https://build.chromium.org/p/chromium.webkit/builders/WebKit%20Linux%20%28dbg%29/builds/5360
>
> Reverting to green the Blink tree.
>
> Original issue's description:
> > Run smooth scroll animations on the compositor when possible
> >
> > This CL implements "immediate retargeting" shown in the following diagram:
> > https://docs.google.com/drawings/d/1z76m-GMDgLI-clkfroLJ-5yhsHkmriZr_swP0kn5iw4
> >
> > This CL does the following
> > - Add a new state to ScrollAnimatorCompositorCoordinator to update the target
> > offset on the compositor
> > - Use the ScrollAnimatorCompositorCoordinator to schedule anim
> > - Add plumbing from the animators to the animation controller to abort
> > animations
> >
> > Sample test pages:
> > yashmalik.com/nested_scroll_mousewheel_listener.html
> > yashmalik.com/nested_scroll_mousewheel_listener_15ms_janky.html (tight loop in RAF)
> >
> > BUG=552556
> > CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel
> >
> > Committed: https://crrev.com/5534a2b2972534b523014c803e1e0e0541855cc7
> > Cr-Commit-Position: refs/heads/master@{#366685}
>
> TBR=skobes@chromium.org,ajuma@chromium.org,vollick@chromium.org,rbyers@chromium.org,ymalik@chromium.org
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=552556
>
> Committed: https://crrev.com/51059d9d038aa255afdddfcbd3d418eb42b718ff
> Cr-Commit-Position: refs/heads/master@{#366733}
TBR=skobes@chromium.org,ajuma@chromium.org,vollick@chromium.org,rbyers@chromium.org,ymalik@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=552556
Review URL: https://codereview.chromium.org/1543043004
Cr-Commit-Position: refs/heads/master@{#366739}
31 files changed, 469 insertions, 70 deletions
diff --git a/cc/animation/animation_player.cc b/cc/animation/animation_player.cc index dee19ea..68a6294 100644 --- a/cc/animation/animation_player.cc +++ b/cc/animation/animation_player.cc @@ -153,6 +153,13 @@ void AnimationPlayer::RemoveAnimation(int animation_id) { } } +void AnimationPlayer::AbortAnimation(int animation_id) { + DCHECK(element_animations_); + element_animations_->layer_animation_controller()->AbortAnimation( + animation_id); + SetNeedsCommit(); +} + void AnimationPlayer::PushPropertiesTo(AnimationPlayer* player_impl) { if (layer_id_ != player_impl->layer_id()) { if (player_impl->layer_id()) diff --git a/cc/animation/animation_player.h b/cc/animation/animation_player.h index d028930..f53c9b6 100644 --- a/cc/animation/animation_player.h +++ b/cc/animation/animation_player.h @@ -68,6 +68,7 @@ class CC_EXPORT AnimationPlayer : public base::RefCounted<AnimationPlayer>, void AddAnimation(scoped_ptr<Animation> animation); void PauseAnimation(int animation_id, double time_offset); void RemoveAnimation(int animation_id); + void AbortAnimation(int animation_id); void PushPropertiesTo(AnimationPlayer* player_impl); diff --git a/cc/blink/web_compositor_animation_player_impl.cc b/cc/blink/web_compositor_animation_player_impl.cc index b73d8d8..150ec93 100644 --- a/cc/blink/web_compositor_animation_player_impl.cc +++ b/cc/blink/web_compositor_animation_player_impl.cc @@ -68,4 +68,8 @@ void WebCompositorAnimationPlayerImpl::pauseAnimation(int animation_id, animation_player_->PauseAnimation(animation_id, time_offset); } +void WebCompositorAnimationPlayerImpl::abortAnimation(int animation_id) { + animation_player_->AbortAnimation(animation_id); +} + } // namespace cc_blink diff --git a/cc/blink/web_compositor_animation_player_impl.h b/cc/blink/web_compositor_animation_player_impl.h index 0cc6975..429438f 100644 --- a/cc/blink/web_compositor_animation_player_impl.h +++ b/cc/blink/web_compositor_animation_player_impl.h @@ -36,6 +36,7 @@ class WebCompositorAnimationPlayerImpl void addAnimation(blink::WebCompositorAnimation* animation) override; void removeAnimation(int animation_id) override; void pauseAnimation(int animation_id, double time_offset) override; + void abortAnimation(int animation_id) override; private: scoped_refptr<cc::AnimationPlayer> animation_player_; diff --git a/cc/blink/web_layer_impl.cc b/cc/blink/web_layer_impl.cc index 2210a9e..88601b5 100644 --- a/cc/blink/web_layer_impl.cc +++ b/cc/blink/web_layer_impl.cc @@ -278,6 +278,10 @@ void WebLayerImpl::pauseAnimation(int animation_id, double time_offset) { layer_->PauseAnimation(animation_id, time_offset); } +void WebLayerImpl::abortAnimation(int animation_id) { + layer_->AbortAnimation(animation_id); +} + bool WebLayerImpl::hasActiveAnimation() { return layer_->HasActiveAnimation(); } diff --git a/cc/blink/web_layer_impl.h b/cc/blink/web_layer_impl.h index a1b762b..3fd0bcc 100644 --- a/cc/blink/web_layer_impl.h +++ b/cc/blink/web_layer_impl.h @@ -113,6 +113,7 @@ class WebLayerImpl : public blink::WebLayer { void removeAnimation(int animation_id, blink::WebCompositorAnimation::TargetProperty) override; void pauseAnimation(int animation_id, double time_offset) override; + void abortAnimation(int animation_id) override; bool hasActiveAnimation() override; void setForceRenderSurface(bool force) override; void setScrollPositionDouble(blink::WebDoublePoint position) override; diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index c085f16..c933aa9 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc @@ -1880,6 +1880,12 @@ void Layer::RemoveAnimation(int animation_id, SetNeedsCommit(); } +void Layer::AbortAnimation(int animation_id) { + DCHECK(layer_animation_controller_); + layer_animation_controller_->AbortAnimation(animation_id); + SetNeedsCommit(); +} + void Layer::SetLayerAnimationControllerForTest( scoped_refptr<LayerAnimationController> controller) { DCHECK(layer_animation_controller_); diff --git a/cc/layers/layer.h b/cc/layers/layer.h index 6c9036c..7dfe6d0 100644 --- a/cc/layers/layer.h +++ b/cc/layers/layer.h @@ -417,6 +417,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, void PauseAnimation(int animation_id, double time_offset); void RemoveAnimation(int animation_id); void RemoveAnimation(int animation_id, Animation::TargetProperty property); + void AbortAnimation(int animation_id); LayerAnimationController* layer_animation_controller() const { return layer_animation_controller_.get(); } diff --git a/third_party/WebKit/LayoutTests/fast/scroll-behavior/smooth-scroll/keyboard-scroll-expected.txt b/third_party/WebKit/LayoutTests/fast/scroll-behavior/smooth-scroll/keyboard-scroll-expected.txt new file mode 100644 index 0000000..9c6d0e3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/scroll-behavior/smooth-scroll/keyboard-scroll-expected.txt @@ -0,0 +1,18 @@ +Test keyboard smooth scroll. The main purpose of this test is to ensure that smooth scrolling on the compositor works as intended (tested via virtual suite virtual/threaded/). + +On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". + + +PASS downArrow reached target +PASS upArrow reached target +PASS rightArrow reached target +PASS leftArrow reached target +PASS end reached target +PASS home reached target +PASS pageDown reached target +PASS pageUp reached target +PASS reached target +PASS successfullyParsed is true + +TEST COMPLETE +Top of pageBottom of pageLeft of pageRight of pageMiddle of page diff --git a/third_party/WebKit/LayoutTests/fast/scroll-behavior/smooth-scroll/keyboard-scroll.html b/third_party/WebKit/LayoutTests/fast/scroll-behavior/smooth-scroll/keyboard-scroll.html new file mode 100644 index 0000000..310b4e2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/scroll-behavior/smooth-scroll/keyboard-scroll.html @@ -0,0 +1,114 @@ +<!DOCTYPE html> +<script src="../../../resources/js-test.js"></script> +<script> + window.jsTestIsAsync = true; + var pageHeight = 1200; + var pageWidth = 1000; + + var testScrolls = [ + {key: 'downArrow', expectedX: 0, expectedY: pageHeight - window.innerHeight}, + {key: 'upArrow', expectedX: 0, expectedY: 0}, + {key: 'rightArrow', expectedX: pageWidth - window.innerWidth, expectedY: 0}, + {key: 'leftArrow', expectedX: 0, expectedY: 0}, + {key: 'end', expectedX: 0, expectedY: pageHeight - window.innerHeight}, + {key: 'home', expectedX: 0, expectedY: 0}, + {key: 'pageDown', expectedX: 0, expectedY: pageHeight - window.innerHeight}, + {key: 'pageUp', expectedX: 0, expectedY: 0}, + {key: ' ', expectedX: 0, expectedY: pageHeight - window.innerHeight}, + ]; + var currentTest = -1; + + description("Test keyboard smooth scroll. The main purpose of this\ + test is to ensure that smooth scrolling on the compositor\ + works as intended (tested via virtual suite virtual/threaded/)."); + + function runTestCase(testCase) { + window.eventSender.keyDown(testCase.key); + if (window.scrollX == testCase.expectedX && window.scrollY == testCase.expectedY) { + testPassed(testCase.key + ' reached target'); + startNextTestCase(); + } else { + requestAnimationFrame(function() { + runTestCase(testCase); + }); + } + } + + function startNextTestCase() { + currentTest++; + if (currentTest >= testScrolls.length) { + finishJSTest(); + return; + } + runTestCase(testScrolls[currentTest]); + } + + function runTest() { + if (!window.eventSender || !window.internals) { + finishJSTest(); + return; + } + // Turn on smooth scrolling. + internals.settings.setScrollAnimatorEnabled(true); + + startNextTestCase(); + } + addEventListener('load', runTest); +</script> + +<style> + ::-webkit-scrollbar { + width: 0px; + height: 0px; + } + + div { + width: 200px; + height: 20px; + background-color: red; + } + + html{ + padding: 0px; + margin: 0px; + width: 1000px; + height: 1200px; + } + + .top { + position: absolute; + top: 0px; + left: 300px; + } + + .middle{ + position: absolute; + top: 575px; + left: 300px; + } + + .bottom { + position: absolute; + top: 1180px; + left: 300px; + } + + .left { + position: absolute; + top: 275px; + left: 0px; + } + + .right { + position: absolute; + top: 275px; + left: 800px; + } +</style> +<p id="description" style="width: 800px"></p> +<p id="console" style="width: 800px"></p> +<div class="top">Top of page</div> +<div class="bottom">Bottom of page</div> +<div class="left">Left of page</div> +<div class="right">Right of page</div> +<div class="middle">Middle of page</div> diff --git a/third_party/WebKit/LayoutTests/fast/scroll-behavior/smooth-scroll/mousewheel-scroll-expected.txt b/third_party/WebKit/LayoutTests/fast/scroll-behavior/smooth-scroll/mousewheel-scroll-expected.txt new file mode 100644 index 0000000..c7cb861 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/scroll-behavior/smooth-scroll/mousewheel-scroll-expected.txt @@ -0,0 +1,10 @@ +This test ensures that consecutive mouse wheel ticks scroll to the right offset. The main purpose of this test is to ensure that smooth scrolling on the compositor works as intended (tested via virtual suite virtual/threaded/). + +On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". + + +PASS document.scrollingElement.scrollTop == 80 && document.scrollingElement.scrollLeft == 80 became true +PASS successfullyParsed is true + +TEST COMPLETE + diff --git a/third_party/WebKit/LayoutTests/fast/scroll-behavior/smooth-scroll/mousewheel-scroll.html b/third_party/WebKit/LayoutTests/fast/scroll-behavior/smooth-scroll/mousewheel-scroll.html new file mode 100644 index 0000000..702dbf1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/scroll-behavior/smooth-scroll/mousewheel-scroll.html @@ -0,0 +1,46 @@ +<!DOCTYPE html> +<script src="../../../resources/js-test.js"></script> +<style> + body { + height: 2000px; + width: 2000px; + } +</style> + +<script> + window.jsTestIsAsync = true; + + description("This test ensures that consecutive mouse wheel ticks scroll\ + to the right offset. The main purpose of this test is to ensure that\ + smooth scrolling on the compositor works as intended (tested via\ + virtual suite virtual/threaded/)."); + + function runTest() { + if (!window.eventSender || !window.internals) { + finishJSTest(); + return; + } + + // Turn on smooth scrolling. + internals.settings.setScrollAnimatorEnabled(true); + + eventSender.mouseMoveTo(20, 20); + // Scroll down 3 ticks. + eventSender.mouseScrollBy(0, -1); + eventSender.mouseScrollBy(0, -1); + eventSender.mouseScrollBy(0, -1); + // Scroll right 3 ticks. + eventSender.mouseScrollBy(-1, 0); + eventSender.mouseScrollBy(-1, 0); + eventSender.mouseScrollBy(-1, 0); + // Undo 1 tick in each direction. + eventSender.mouseScrollBy(0, 1); + eventSender.mouseScrollBy(1, 0); + + // 40px per tick. + shouldBecomeEqual("document.scrollingElement.scrollTop == 80 && " + + "document.scrollingElement.scrollLeft == 80", "true", finishJSTest); + } +</script> + +<body onload="runTest()"></body> diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp index 2b39cef..de49f4b 100644 --- a/third_party/WebKit/Source/core/frame/FrameView.cpp +++ b/third_party/WebKit/Source/core/frame/FrameView.cpp @@ -264,7 +264,7 @@ void FrameView::dispose() RELEASE_ASSERT(!isInPerformLayout()); if (ScrollAnimatorBase* scrollAnimator = existingScrollAnimator()) - scrollAnimator->cancelAnimations(); + scrollAnimator->cancelAnimation(); cancelProgrammaticScrollAnimation(); detachScrollbars(); diff --git a/third_party/WebKit/Source/core/input/EventHandler.cpp b/third_party/WebKit/Source/core/input/EventHandler.cpp index 515e550..47861ee 100644 --- a/third_party/WebKit/Source/core/input/EventHandler.cpp +++ b/third_party/WebKit/Source/core/input/EventHandler.cpp @@ -2036,14 +2036,14 @@ WebInputEventResult EventHandler::handleGestureShowPress() if (!view) return WebInputEventResult::NotHandled; if (ScrollAnimatorBase* scrollAnimator = view->existingScrollAnimator()) - scrollAnimator->cancelAnimations(); + scrollAnimator->cancelAnimation(); const FrameView::ScrollableAreaSet* areas = view->scrollableAreas(); if (!areas) return WebInputEventResult::NotHandled; for (const ScrollableArea* scrollableArea : *areas) { ScrollAnimatorBase* animator = scrollableArea->existingScrollAnimator(); if (animator) - animator->cancelAnimations(); + animator->cancelAnimation(); } return WebInputEventResult::NotHandled; } diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp index eefb444..bbb2640 100644 --- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp +++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp @@ -1128,6 +1128,11 @@ void GraphicsLayer::removeAnimation(int animationId) platformLayer()->removeAnimation(animationId); } +void GraphicsLayer::abortAnimation(int animationId) +{ + platformLayer()->abortAnimation(animationId); +} + WebLayer* GraphicsLayer::platformLayer() const { return m_layer->layer(); diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h index 8f52c48..caa5158 100644 --- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h +++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h @@ -203,6 +203,7 @@ public: bool addAnimation(PassOwnPtr<WebCompositorAnimation>); void pauseAnimation(int animationId, double /*timeOffset*/); void removeAnimation(int animationId); + void abortAnimation(int animationId); // Layer contents void setContentsToImage(Image*, RespectImageOrientationEnum = DoNotRespectImageOrientation); diff --git a/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.h b/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.h index b5805bc..35c19f4e 100644 --- a/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.h +++ b/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.h @@ -93,7 +93,7 @@ private: void handleWheelEventPhase(PlatformWheelEventPhase) override; - void cancelAnimations() override; + void cancelAnimation() override; void setIsActive() override; void contentAreaWillPaint() const override; diff --git a/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.mm b/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.mm index c99941a..a731a46 100644 --- a/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.mm +++ b/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.mm @@ -1041,7 +1041,7 @@ bool ScrollAnimatorMac::setScrollbarsVisibleForTesting(bool show) return false; } -void ScrollAnimatorMac::cancelAnimations() +void ScrollAnimatorMac::cancelAnimation() { m_haveScrolledSincePageLoad = false; diff --git a/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp b/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp index 6910c4f..3e29f04 100644 --- a/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp +++ b/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp @@ -64,6 +64,12 @@ void ProgrammaticScrollAnimator::animateToOffset(FloatPoint offset) m_runState = RunState::WaitingToSendToCompositor; } +void ProgrammaticScrollAnimator::cancelAnimation() +{ + ASSERT(m_runState != RunState::RunningOnCompositorButNeedsUpdate); + ScrollAnimatorCompositorCoordinator::cancelAnimation(); +} + void ProgrammaticScrollAnimator::tickAnimation(double monotonicTime) { if (m_runState != RunState::RunningOnMainThread) @@ -154,6 +160,7 @@ void ProgrammaticScrollAnimator::layerForCompositedScrollingDidChange(WebComposi void ProgrammaticScrollAnimator::notifyCompositorAnimationFinished(int groupId) { + ASSERT(m_runState != RunState::RunningOnCompositorButNeedsUpdate); ScrollAnimatorCompositorCoordinator::compositorAnimationFinished(groupId); } diff --git a/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.h b/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.h index c700414..fa05677 100644 --- a/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.h +++ b/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.h @@ -34,6 +34,7 @@ public: // ScrollAnimatorCompositorCoordinator implementation. void resetAnimationState() override; + void cancelAnimation() override; ScrollableArea* scrollableArea() const override { return m_scrollableArea; } void tickAnimation(double monotonicTime) override; void updateCompositorAnimations() override; diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp index e9610b0..fa45f0f 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp @@ -31,12 +31,13 @@ #include "platform/scroll/ScrollAnimator.h" #include "platform/TraceEvent.h" +#include "platform/graphics/GraphicsLayer.h" #include "platform/scroll/ScrollableArea.h" #include "public/platform/Platform.h" +#include "public/platform/WebCompositorAnimation.h" #include "public/platform/WebCompositorSupport.h" #include "wtf/CurrentTime.h" #include "wtf/PassRefPtr.h" -#include <algorithm> namespace blink { @@ -49,21 +50,22 @@ PassOwnPtrWillBeRawPtr<ScrollAnimatorBase> ScrollAnimatorBase::create(Scrollable ScrollAnimator::ScrollAnimator(ScrollableArea* scrollableArea, WTF::TimeFunction timeFunction) : ScrollAnimatorBase(scrollableArea) + , m_lastTickTime(0.0) , m_timeFunction(timeFunction) { } ScrollAnimator::~ScrollAnimator() { - cancelAnimations(); } FloatPoint ScrollAnimator::desiredTargetPosition() const { - return m_animationCurve ? FloatPoint(m_animationCurve->targetValue()) : currentPosition(); + return m_animationCurve ? m_targetOffset : currentPosition(); } -float ScrollAnimator::computeDeltaToConsume(ScrollbarOrientation orientation, float pixelDelta) const +float ScrollAnimator::computeDeltaToConsume( + ScrollbarOrientation orientation, float pixelDelta) const { FloatPoint pos = desiredTargetPosition(); float currentPos = (orientation == HorizontalScrollbar) ? pos.x() : pos.y(); @@ -71,7 +73,16 @@ float ScrollAnimator::computeDeltaToConsume(ScrollbarOrientation orientation, fl return (currentPos == newPos) ? 0.0f : (newPos - currentPos); } -ScrollResultOneDimensional ScrollAnimator::userScroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float delta) +void ScrollAnimator::resetAnimationState() +{ + ScrollAnimatorCompositorCoordinator::resetAnimationState(); + if (m_animationCurve) + m_animationCurve.clear(); + m_startTime = 0.0; +} + +ScrollResultOneDimensional ScrollAnimator::userScroll( + ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float delta) { if (!m_scrollableArea->scrollAnimatorEnabled()) return ScrollAnimatorBase::userScroll(orientation, granularity, step, delta); @@ -82,14 +93,33 @@ ScrollResultOneDimensional ScrollAnimator::userScroll(ScrollbarOrientation orien return ScrollAnimatorBase::userScroll(orientation, granularity, step, delta); float usedPixelDelta = computeDeltaToConsume(orientation, step * delta); - FloatPoint pixelDelta = (orientation == VerticalScrollbar ? FloatPoint(0, usedPixelDelta) : FloatPoint(usedPixelDelta, 0)); + FloatPoint pixelDelta = (orientation == VerticalScrollbar + ? FloatPoint(0, usedPixelDelta) : FloatPoint(usedPixelDelta, 0)); FloatPoint targetPos = desiredTargetPosition(); targetPos.moveBy(pixelDelta); if (m_animationCurve) { - if (!(targetPos - m_animationCurve->targetValue()).isZero()) - m_animationCurve->updateTarget(m_timeFunction() - m_startTime, targetPos); + if ((targetPos - m_targetOffset).isZero()) { + // Report unused delta only if there is no animation running. See + // comment below regarding scroll latching. + return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0); + } + + m_targetOffset = targetPos; + ASSERT(m_runState == RunState::RunningOnMainThread + || m_runState == RunState::RunningOnCompositor + || m_runState == RunState::RunningOnCompositorButNeedsUpdate); + + if (m_runState == RunState::RunningOnCompositor + || m_runState == RunState::RunningOnCompositorButNeedsUpdate) { + m_runState = RunState::RunningOnCompositorButNeedsUpdate; + return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0); + } + + // Running on the main thread, simply update the target offset instead + // of sending to the compositor. + m_animationCurve->updateTarget(m_timeFunction() - m_startTime, targetPos); return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0); } @@ -100,16 +130,17 @@ ScrollResultOneDimensional ScrollAnimator::userScroll(ScrollbarOrientation orien return ScrollResultOneDimensional(/* didScroll */ false, delta); } - m_animationCurve = adoptPtr(Platform::current()->compositorSupport()->createScrollOffsetAnimationCurve( - targetPos, - WebCompositorAnimationCurve::TimingFunctionTypeEaseInOut, - WebScrollOffsetAnimationCurve::ScrollDurationConstant)); - - m_animationCurve->setInitialValue(currentPosition()); + m_targetOffset = targetPos; m_startTime = m_timeFunction(); scrollableArea()->registerForAnimation(); - animationTimerFired(); + if (!m_scrollableArea->scheduleAnimation()) { + scrollToOffsetWithoutAnimation(targetPos); + resetAnimationState(); + return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0); + } + + m_runState = RunState::WaitingToSendToCompositor; return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0); } @@ -118,34 +149,23 @@ void ScrollAnimator::scrollToOffsetWithoutAnimation(const FloatPoint& offset) m_currentPosX = offset.x(); m_currentPosY = offset.y(); - cancelAnimations(); + resetAnimationState(); notifyPositionChanged(); } -void ScrollAnimator::cancelAnimations() +void ScrollAnimator::tickAnimation(double monotonicTime) { - if (m_animationCurve) - m_animationCurve.clear(); -} + m_lastTickTime = monotonicTime; -void ScrollAnimator::serviceScrollAnimations() -{ - if (hasRunningAnimation()) - animationTimerFired(); -} + if (m_runState != RunState::RunningOnMainThread) + return; -bool ScrollAnimator::hasRunningAnimation() const -{ - return m_animationCurve; -} - -void ScrollAnimator::animationTimerFired() -{ - TRACE_EVENT0("blink", "ScrollAnimator::animationTimerFired"); - double elapsedTime = m_timeFunction() - m_startTime; + TRACE_EVENT0("blink", "ScrollAnimator::tickAnimation"); + double elapsedTime = monotonicTime - m_startTime; bool isFinished = (elapsedTime > m_animationCurve->duration()); - FloatPoint offset = isFinished ? m_animationCurve->targetValue() : m_animationCurve->getValue(elapsedTime); + FloatPoint offset = isFinished ? m_animationCurve->targetValue() + : m_animationCurve->getValue(elapsedTime); offset = FloatPoint(m_scrollableArea->clampScrollPosition(offset)); @@ -153,7 +173,7 @@ void ScrollAnimator::animationTimerFired() m_currentPosY = offset.y(); if (isFinished) - m_animationCurve.clear(); + resetAnimationState(); else scrollableArea()->scheduleAnimation(); @@ -161,6 +181,105 @@ void ScrollAnimator::animationTimerFired() notifyPositionChanged(); } +void ScrollAnimator::updateCompositorAnimations() +{ + if (m_compositorAnimationId && m_runState != RunState::RunningOnCompositor + && m_runState != RunState::RunningOnCompositorButNeedsUpdate) { + // If the current run state is WaitingToSendToCompositor but we have a + // non-zero compositor animation id, there's a currently running + // compositor animation that needs to be removed here before the new + // animation is added below. + ASSERT(m_runState == RunState::WaitingToCancelOnCompositor + || m_runState == RunState::WaitingToSendToCompositor); + + abortAnimation(); + + m_compositorAnimationId = 0; + m_compositorAnimationGroupId = 0; + if (m_runState == RunState::WaitingToCancelOnCompositor) { + resetAnimationState(); + return; + } + } + + if (m_runState == RunState::WaitingToSendToCompositor + || m_runState == RunState::RunningOnCompositorButNeedsUpdate) { + if (m_runState == RunState::RunningOnCompositorButNeedsUpdate) { + // Abort the running animation before a new one with an updated + // target is added. + abortAnimation(); + + m_compositorAnimationId = 0; + m_compositorAnimationGroupId = 0; + + m_animationCurve->updateTarget(m_lastTickTime - m_startTime, + m_targetOffset); + m_runState = RunState::WaitingToSendToCompositor; + } + + if (!m_animationCurve) { + m_animationCurve = adoptPtr(Platform::current()->compositorSupport() + ->createScrollOffsetAnimationCurve( + m_targetOffset, + WebCompositorAnimationCurve::TimingFunctionTypeEaseInOut, + WebScrollOffsetAnimationCurve::ScrollDurationConstant)); + m_animationCurve->setInitialValue(currentPosition()); + } + + bool sentToCompositor = false; + if (GraphicsLayer* layer = m_scrollableArea->layerForScrolling()) { + ASSERT(layer->scrollableArea() == m_scrollableArea); + if (!layer->platformLayer()->shouldScrollOnMainThread()) { + OwnPtr<WebCompositorAnimation> animation = adoptPtr( + Platform::current()->compositorSupport()->createAnimation( + *m_animationCurve, + WebCompositorAnimation::TargetPropertyScrollOffset)); + // Being here means that either there is an animation that needs + // to be sent to the compositor, or an animation that needs to + // be updated (a new scroll event before the previous animation + // is finished). In either case, the start time is when the + // first animation was initiated. This re-targets the animation + // using the current time on main thread. + animation->setStartTime(m_startTime); + + int animationId = animation->id(); + int animationGroupId = animation->group(); + + sentToCompositor = addAnimation(animation.release()); + if (sentToCompositor) { + m_runState = RunState::RunningOnCompositor; + m_compositorAnimationId = animationId; + m_compositorAnimationGroupId = animationGroupId; + } + } + } + + if (!sentToCompositor) { + m_runState = RunState::RunningOnMainThread; + if (!m_scrollableArea->scheduleAnimation()) { + scrollToOffsetWithoutAnimation(m_targetOffset); + resetAnimationState(); + } + } + } +} + +void ScrollAnimator::notifyCompositorAnimationFinished(int groupId) +{ + ScrollAnimatorCompositorCoordinator::compositorAnimationFinished(groupId); +} + +void ScrollAnimator::cancelAnimation() +{ + ScrollAnimatorCompositorCoordinator::cancelAnimation(); +} + +void ScrollAnimator::layerForCompositedScrollingDidChange( + WebCompositorAnimationTimeline* timeline) +{ + reattachCompositorPlayerIfNeeded(timeline); +} + DEFINE_TRACE(ScrollAnimator) { ScrollAnimatorBase::trace(visitor); diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h index 01746e68..5d8f20a 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h @@ -34,11 +34,14 @@ #include "platform/Timer.h" #include "platform/geometry/FloatPoint.h" #include "platform/scroll/ScrollAnimatorBase.h" +#include "public/platform/WebCompositorAnimationDelegate.h" +#include "public/platform/WebCompositorAnimationPlayerClient.h" #include "public/platform/WebScrollOffsetAnimationCurve.h" namespace blink { class ScrollAnimatorTest; +class WebCompositorAnimationTimeline; class PLATFORM_EXPORT ScrollAnimator final : public ScrollAnimatorBase { public: @@ -50,20 +53,26 @@ public: ScrollResultOneDimensional userScroll(ScrollbarOrientation, ScrollGranularity, float step, float delta) override; void scrollToOffsetWithoutAnimation(const FloatPoint&) override; - void cancelAnimations() override; - void serviceScrollAnimations() override; - bool hasRunningAnimation() const override; + // ScrollAnimatorCompositorCoordinator implementation. + void tickAnimation(double monotonicTime) override; + void cancelAnimation() override; + void resetAnimationState() override; + void updateCompositorAnimations() override; + void notifyCompositorAnimationFinished(int groupId) override; + void layerForCompositedScrollingDidChange(WebCompositorAnimationTimeline*) override; DECLARE_VIRTUAL_TRACE(); protected: - void animationTimerFired(); - OwnPtr<WebScrollOffsetAnimationCurve> m_animationCurve; + double m_lastTickTime; double m_startTime; WTF::TimeFunction m_timeFunction; + private: FloatPoint desiredTargetPosition() const; + + FloatPoint m_targetOffset; }; } // namespace blink diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorBase.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorBase.cpp index ce86e06..75306cc 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorBase.cpp +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorBase.cpp @@ -104,6 +104,7 @@ float ScrollAnimatorBase::clampScrollPosition(ScrollbarOrientation orientation, DEFINE_TRACE(ScrollAnimatorBase) { visitor->trace(m_scrollableArea); + ScrollAnimatorCompositorCoordinator::trace(visitor); } } // namespace blink diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorBase.h b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorBase.h index 3503b7f..5926f86 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorBase.h +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorBase.h @@ -35,6 +35,7 @@ #include "platform/PlatformWheelEvent.h" #include "platform/geometry/FloatSize.h" #include "platform/heap/Handle.h" +#include "platform/scroll/ScrollAnimatorCompositorCoordinator.h" #include "platform/scroll/ScrollTypes.h" #include "wtf/Forward.h" @@ -43,8 +44,9 @@ namespace blink { class FloatPoint; class ScrollableArea; class Scrollbar; +class WebCompositorAnimationTimeline; -class PLATFORM_EXPORT ScrollAnimatorBase : public NoBaseWillBeGarbageCollectedFinalized<ScrollAnimatorBase> { +class PLATFORM_EXPORT ScrollAnimatorBase : public ScrollAnimatorCompositorCoordinator { public: static PassOwnPtrWillBeRawPtr<ScrollAnimatorBase> create(ScrollableArea*); @@ -61,8 +63,6 @@ public: virtual void scrollToOffsetWithoutAnimation(const FloatPoint&); - ScrollableArea* scrollableArea() const { return m_scrollableArea; } - virtual void setIsActive() { } #if OS(MACOSX) @@ -76,9 +76,14 @@ public: // area. virtual float computeDeltaToConsume(ScrollbarOrientation, float pixelDelta) const; - virtual void cancelAnimations() { } - virtual void serviceScrollAnimations() { } - virtual bool hasRunningAnimation() const { return false; } + + // ScrollAnimatorCompositorCoordinator implementation. + ScrollableArea* scrollableArea() const override { return m_scrollableArea; } + void tickAnimation(double monotonicTime) override { }; + void cancelAnimation() override { } + void updateCompositorAnimations() override { }; + void notifyCompositorAnimationFinished(int groupId) override { }; + void layerForCompositedScrollingDidChange(WebCompositorAnimationTimeline*) override { }; virtual void contentAreaWillPaint() const { } virtual void mouseEnteredContentArea() const { } diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp index 9245749..4f0528f 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp @@ -51,6 +51,7 @@ bool ScrollAnimatorCompositorCoordinator::hasAnimationThatRequiresService() cons return false; case RunState::WaitingToSendToCompositor: case RunState::RunningOnMainThread: + case RunState::RunningOnCompositorButNeedsUpdate: case RunState::WaitingToCancelOnCompositor: return true; } @@ -83,6 +84,17 @@ void ScrollAnimatorCompositorCoordinator::removeAnimation() } } +void ScrollAnimatorCompositorCoordinator::abortAnimation() +{ + if (m_compositorPlayer) { + if (m_compositorPlayer->isLayerAttached()) + m_compositorPlayer->abortAnimation(m_compositorAnimationId); + } else { + if (GraphicsLayer* layer = scrollableArea()->layerForScrolling()) + layer->abortAnimation(m_compositorAnimationId); + } +} + void ScrollAnimatorCompositorCoordinator::cancelAnimation() { switch (m_runState) { @@ -100,6 +112,7 @@ void ScrollAnimatorCompositorCoordinator::cancelAnimation() case RunState::RunningOnMainThread: resetAnimationState(); break; + case RunState::RunningOnCompositorButNeedsUpdate: case RunState::RunningOnCompositor: m_runState = RunState::WaitingToCancelOnCompositor; @@ -125,6 +138,7 @@ void ScrollAnimatorCompositorCoordinator::compositorAnimationFinished( case RunState::WaitingToSendToCompositor: break; case RunState::RunningOnCompositor: + case RunState::RunningOnCompositorButNeedsUpdate: case RunState::WaitingToCancelOnCompositor: resetAnimationState(); } diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h index f10acb3..440aa7e 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h @@ -22,9 +22,9 @@ public: virtual ~ScrollAnimatorCompositorCoordinator(); bool hasAnimationThatRequiresService() const; - void cancelAnimation(); virtual void resetAnimationState(); + virtual void cancelAnimation(); virtual ScrollableArea* scrollableArea() const = 0; virtual void tickAnimation(double monotonicTime) = 0; @@ -39,6 +39,7 @@ protected: bool addAnimation(PassOwnPtr<WebCompositorAnimation>); void removeAnimation(); + void abortAnimation(); void compositorAnimationFinished(int groupId); void reattachCompositorPlayerIfNeeded(WebCompositorAnimationTimeline*); @@ -62,6 +63,9 @@ protected: // Running an animation on the compositor. RunningOnCompositor, + // Running an animation on the compositor but needs update. + RunningOnCompositorButNeedsUpdate, + // Running an animation on the main thread. RunningOnMainThread, diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp index 2a398a0..cbb5be1 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp @@ -72,6 +72,7 @@ public: MOCK_CONST_METHOD0(scrollbarsCanBeActive, bool()); MOCK_CONST_METHOD0(scrollableAreaBoundingBox, IntRect()); MOCK_METHOD0(registerForAnimation, void()); + MOCK_METHOD0(scheduleAnimation, bool()); bool userInputScrollable(ScrollbarOrientation) const override { return true; } bool shouldPlaceVerticalScrollbarOnLeft() const override { return false; } @@ -100,30 +101,32 @@ static void reset(ScrollAnimator& scrollAnimator) scrollAnimator.scrollToOffsetWithoutAnimation(FloatPoint()); } -TEST(ScrollAnimatorTest, Enabled) +TEST(ScrollAnimatorTest, MainThreadEnabled) { OwnPtrWillBeRawPtr<MockScrollableArea> scrollableArea = MockScrollableArea::create(true); OwnPtrWillBeRawPtr<ScrollAnimator> scrollAnimator = adoptPtrWillBeNoop(new ScrollAnimator(scrollableArea.get(), getMockedTime)); EXPECT_CALL(*scrollableArea, minimumScrollPosition()).Times(AtLeast(1)).WillRepeatedly(Return(IntPoint())); EXPECT_CALL(*scrollableArea, maximumScrollPosition()).Times(AtLeast(1)).WillRepeatedly(Return(IntPoint(1000, 1000))); - EXPECT_CALL(*scrollableArea, setScrollOffset(_, _)).Times(12); + EXPECT_CALL(*scrollableArea, setScrollOffset(_, _)).Times(9); EXPECT_CALL(*scrollableArea, registerForAnimation()).Times(3); + EXPECT_CALL(*scrollableArea, scheduleAnimation()).Times(AtLeast(1)).WillRepeatedly(Return(true)); - EXPECT_FALSE(scrollAnimator->hasRunningAnimation()); + EXPECT_FALSE(scrollAnimator->hasAnimationThatRequiresService()); ScrollResultOneDimensional result = scrollAnimator->userScroll(HorizontalScrollbar, ScrollByLine, 100, -1); - EXPECT_FALSE(scrollAnimator->hasRunningAnimation()); + EXPECT_FALSE(scrollAnimator->hasAnimationThatRequiresService()); EXPECT_FALSE(result.didScroll); EXPECT_FLOAT_EQ(-1.0f, result.unusedScrollDelta); result = scrollAnimator->userScroll(HorizontalScrollbar, ScrollByLine, 100, 1); - EXPECT_TRUE(scrollAnimator->hasRunningAnimation()); + EXPECT_TRUE(scrollAnimator->hasAnimationThatRequiresService()); EXPECT_TRUE(result.didScroll); EXPECT_FLOAT_EQ(0.0, result.unusedScrollDelta); gMockedTime += 0.05; - scrollAnimator->serviceScrollAnimations(); + scrollAnimator->updateCompositorAnimations(); + scrollAnimator->tickAnimation(getMockedTime()); EXPECT_NE(100, scrollAnimator->currentPosition().x()); EXPECT_NE(0, scrollAnimator->currentPosition().x()); @@ -131,10 +134,11 @@ TEST(ScrollAnimatorTest, Enabled) reset(*scrollAnimator); scrollAnimator->userScroll(HorizontalScrollbar, ScrollByPage, 100, 1); - EXPECT_TRUE(scrollAnimator->hasRunningAnimation()); + EXPECT_TRUE(scrollAnimator->hasAnimationThatRequiresService()); gMockedTime += 0.05; - scrollAnimator->serviceScrollAnimations(); + scrollAnimator->updateCompositorAnimations(); + scrollAnimator->tickAnimation(getMockedTime()); EXPECT_NE(100, scrollAnimator->currentPosition().x()); EXPECT_NE(0, scrollAnimator->currentPosition().x()); @@ -142,25 +146,27 @@ TEST(ScrollAnimatorTest, Enabled) reset(*scrollAnimator); scrollAnimator->userScroll(HorizontalScrollbar, ScrollByPixel, 4, 25); - EXPECT_TRUE(scrollAnimator->hasRunningAnimation()); + EXPECT_TRUE(scrollAnimator->hasAnimationThatRequiresService()); gMockedTime += 0.05; - scrollAnimator->serviceScrollAnimations(); + scrollAnimator->updateCompositorAnimations(); + scrollAnimator->tickAnimation(getMockedTime()); EXPECT_NE(100, scrollAnimator->currentPosition().x()); EXPECT_NE(0, scrollAnimator->currentPosition().x()); EXPECT_EQ(0, scrollAnimator->currentPosition().y()); gMockedTime += 1.0; - scrollAnimator->serviceScrollAnimations(); + scrollAnimator->updateCompositorAnimations(); + scrollAnimator->tickAnimation(getMockedTime()); - EXPECT_FALSE(scrollAnimator->hasRunningAnimation()); + EXPECT_FALSE(scrollAnimator->hasAnimationThatRequiresService()); EXPECT_EQ(100, scrollAnimator->currentPosition().x()); reset(*scrollAnimator); scrollAnimator->userScroll(HorizontalScrollbar, ScrollByPrecisePixel, 4, 25); - EXPECT_FALSE(scrollAnimator->hasRunningAnimation()); + EXPECT_FALSE(scrollAnimator->hasAnimationThatRequiresService()); EXPECT_EQ(100, scrollAnimator->currentPosition().x()); EXPECT_NE(0, scrollAnimator->currentPosition().x()); diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp b/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp index fb93af9..365aa95 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp +++ b/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp @@ -453,6 +453,8 @@ void ScrollableArea::layerForScrollingDidChange(WebCompositorAnimationTimeline* { if (ProgrammaticScrollAnimator* programmaticScrollAnimator = existingProgrammaticScrollAnimator()) programmaticScrollAnimator->layerForCompositedScrollingDidChange(timeline); + if (ScrollAnimatorBase* scrollAnimator = existingScrollAnimator()) + scrollAnimator->layerForCompositedScrollingDidChange(timeline); } bool ScrollableArea::scheduleAnimation() @@ -468,8 +470,8 @@ void ScrollableArea::serviceScrollAnimations(double monotonicTime) { bool requiresAnimationService = false; if (ScrollAnimatorBase* scrollAnimator = existingScrollAnimator()) { - scrollAnimator->serviceScrollAnimations(); - if (scrollAnimator->hasRunningAnimation()) + scrollAnimator->tickAnimation(monotonicTime); + if (scrollAnimator->hasAnimationThatRequiresService()) requiresAnimationService = true; } if (ProgrammaticScrollAnimator* programmaticScrollAnimator = existingProgrammaticScrollAnimator()) { @@ -485,18 +487,24 @@ void ScrollableArea::updateCompositorScrollAnimations() { if (ProgrammaticScrollAnimator* programmaticScrollAnimator = existingProgrammaticScrollAnimator()) programmaticScrollAnimator->updateCompositorAnimations(); + + if (ScrollAnimatorBase* scrollAnimator = existingScrollAnimator()) + scrollAnimator->updateCompositorAnimations(); } void ScrollableArea::notifyCompositorAnimationFinished(int groupId) { if (ProgrammaticScrollAnimator* programmaticScrollAnimator = existingProgrammaticScrollAnimator()) programmaticScrollAnimator->notifyCompositorAnimationFinished(groupId); + + if (ScrollAnimatorBase* scrollAnimator = existingScrollAnimator()) + scrollAnimator->notifyCompositorAnimationFinished(groupId); } void ScrollableArea::cancelScrollAnimation() { if (ScrollAnimatorBase* scrollAnimator = existingScrollAnimator()) - scrollAnimator->cancelAnimations(); + scrollAnimator->cancelAnimation(); } void ScrollableArea::cancelProgrammaticScrollAnimation() diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h index 71e221b..50d99bf 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h +++ b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h @@ -212,7 +212,7 @@ public: // Let subclasses provide a way of asking for and servicing scroll // animations. - bool scheduleAnimation(); + virtual bool scheduleAnimation(); virtual void serviceScrollAnimations(double monotonicTime); virtual void updateCompositorScrollAnimations(); virtual void registerForAnimation() { } diff --git a/third_party/WebKit/public/platform/WebCompositorAnimationPlayer.h b/third_party/WebKit/public/platform/WebCompositorAnimationPlayer.h index 9df4e55..92abb1e 100644 --- a/third_party/WebKit/public/platform/WebCompositorAnimationPlayer.h +++ b/third_party/WebKit/public/platform/WebCompositorAnimationPlayer.h @@ -29,6 +29,7 @@ public: virtual void addAnimation(WebCompositorAnimation*) = 0; virtual void removeAnimation(int animationId) = 0; virtual void pauseAnimation(int animationId, double timeOffset) = 0; + virtual void abortAnimation(int animationId) = 0; }; } // namespace blink diff --git a/third_party/WebKit/public/platform/WebLayer.h b/third_party/WebKit/public/platform/WebLayer.h index a0e21b2..6ef2535 100644 --- a/third_party/WebKit/public/platform/WebLayer.h +++ b/third_party/WebKit/public/platform/WebLayer.h @@ -160,6 +160,11 @@ public: // Pauses all animations with the given id. virtual void pauseAnimation(int animationId, double timeOffset) = 0; + // Aborts all animations with the given id. Different from removeAnimation + // in that aborting an animation stops it from affecting both the pending + // and active tree. + virtual void abortAnimation(int animationId) = 0; + // Returns true if this layer has any active animations - useful for tests. virtual bool hasActiveAnimation() = 0; |