summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cc/animation/animation.cc3
-rw-r--r--cc/animation/animation.h8
-rw-r--r--cc/animation/animation_delegate.h6
-rw-r--r--cc/animation/animation_events.cc33
-rw-r--r--cc/animation/animation_events.h12
-rw-r--r--cc/animation/animation_host.cc22
-rw-r--r--cc/animation/animation_host.h3
-rw-r--r--cc/animation/animation_player.cc18
-rw-r--r--cc/animation/animation_player.h8
-rw-r--r--cc/animation/animation_registrar.cc4
-rw-r--r--cc/animation/element_animations.cc16
-rw-r--r--cc/animation/element_animations.h6
-rw-r--r--cc/animation/layer_animation_controller.cc56
-rw-r--r--cc/animation/layer_animation_controller.h4
-rw-r--r--cc/animation/layer_animation_controller_unittest.cc77
-rw-r--r--cc/animation/scroll_offset_animation_curve.cc7
-rw-r--r--cc/animation/scroll_offset_animation_curve.h2
-rw-r--r--cc/blink/web_to_cc_animation_delegate_adapter.h4
-rw-r--r--cc/layers/layer_impl.cc21
-rw-r--r--cc/layers/layer_impl.h8
-rw-r--r--cc/test/animation_timelines_test_common.h4
-rw-r--r--cc/test/test_hooks.h4
-rw-r--r--cc/trees/layer_tree_host_impl.cc2
-rw-r--r--cc/trees/layer_tree_host_impl_unittest.cc58
-rw-r--r--cc/trees/layer_tree_impl.cc8
-rw-r--r--cc/trees/layer_tree_impl.h4
-rw-r--r--third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.cpp14
-rw-r--r--third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.h2
-rw-r--r--third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.cpp6
-rw-r--r--third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.h1
-rw-r--r--third_party/WebKit/Source/platform/graphics/CompositorFactory.cpp6
-rw-r--r--third_party/WebKit/Source/platform/graphics/CompositorFactory.h3
-rw-r--r--third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp59
-rw-r--r--third_party/WebKit/Source/platform/scroll/ScrollAnimator.h10
-rw-r--r--third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp1
-rw-r--r--third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h5
-rw-r--r--third_party/WebKit/public/platform/WebCompositorAnimationDelegate.h9
37 files changed, 478 insertions, 36 deletions
diff --git a/cc/animation/animation.cc b/cc/animation/animation.cc
index 5c6fcd0..5d34627 100644
--- a/cc/animation/animation.cc
+++ b/cc/animation/animation.cc
@@ -20,7 +20,8 @@ static const char* const s_runStateNames[] = {"WAITING_FOR_TARGET_AVAILABILITY",
"RUNNING",
"PAUSED",
"FINISHED",
- "ABORTED"};
+ "ABORTED",
+ "ABORTED_BUT_NEEDS_COMPLETION"};
static_assert(static_cast<int>(cc::Animation::LAST_RUN_STATE) + 1 ==
arraysize(s_runStateNames),
diff --git a/cc/animation/animation.h b/cc/animation/animation.h
index 645b71f..c146322 100644
--- a/cc/animation/animation.h
+++ b/cc/animation/animation.h
@@ -27,7 +27,10 @@ class CC_EXPORT Animation {
// the STARTING state, and then into the RUNNING state. RUNNING animations may
// toggle between RUNNING and PAUSED, and may be stopped by moving into either
// the ABORTED or FINISHED states. A FINISHED animation was allowed to run to
- // completion, but an ABORTED animation was not.
+ // completion, but an ABORTED animation was not. An animation in the state
+ // ABORTED_BUT_NEEDS_COMPLETION is an animation that was aborted for
+ // some reason, but needs to be finished. Currently this is for impl-only
+ // scroll offset animations that need to be completed on the main thread.
enum RunState {
WAITING_FOR_TARGET_AVAILABILITY = 0,
WAITING_FOR_DELETION,
@@ -36,8 +39,9 @@ class CC_EXPORT Animation {
PAUSED,
FINISHED,
ABORTED,
+ ABORTED_BUT_NEEDS_COMPLETION,
// This sentinel must be last.
- LAST_RUN_STATE = ABORTED
+ LAST_RUN_STATE = ABORTED_BUT_NEEDS_COMPLETION
};
enum Direction {
diff --git a/cc/animation/animation_delegate.h b/cc/animation/animation_delegate.h
index 732e693..aee077c 100644
--- a/cc/animation/animation_delegate.h
+++ b/cc/animation/animation_delegate.h
@@ -7,6 +7,7 @@
#include "base/time/time.h"
#include "cc/animation/animation.h"
+#include "cc/animation/animation_curve.h"
namespace cc {
@@ -23,6 +24,11 @@ class CC_EXPORT AnimationDelegate {
TargetProperty::Type target_property,
int group) = 0;
+ virtual void NotifyAnimationTakeover(base::TimeTicks monotonic_time,
+ TargetProperty::Type target_property,
+ double animation_start_time,
+ scoped_ptr<AnimationCurve> curve) = 0;
+
protected:
virtual ~AnimationDelegate() {}
};
diff --git a/cc/animation/animation_events.cc b/cc/animation/animation_events.cc
index edd435b..e747f8b 100644
--- a/cc/animation/animation_events.cc
+++ b/cc/animation/animation_events.cc
@@ -19,7 +19,38 @@ AnimationEvent::AnimationEvent(AnimationEvent::Type type,
is_impl_only(false),
opacity(0.f) {}
-AnimationEvent::AnimationEvent(const AnimationEvent& other) = default;
+AnimationEvent::AnimationEvent(const AnimationEvent& other) {
+ type = other.type;
+ layer_id = other.layer_id;
+ group_id = other.group_id;
+ target_property = other.target_property;
+ monotonic_time = other.monotonic_time;
+ is_impl_only = other.is_impl_only;
+ opacity = other.opacity;
+ transform = other.transform;
+ filters = other.filters;
+ animation_start_time = other.animation_start_time;
+ if (other.curve)
+ curve = other.curve->Clone();
+}
+
+AnimationEvent& AnimationEvent::operator=(const AnimationEvent& other) {
+ type = other.type;
+ layer_id = other.layer_id;
+ group_id = other.group_id;
+ target_property = other.target_property;
+ monotonic_time = other.monotonic_time;
+ is_impl_only = other.is_impl_only;
+ opacity = other.opacity;
+ transform = other.transform;
+ filters = other.filters;
+ animation_start_time = other.animation_start_time;
+ if (other.curve)
+ curve = other.curve->Clone();
+ return *this;
+}
+
+AnimationEvent::~AnimationEvent() {}
AnimationEvents::AnimationEvents() {}
diff --git a/cc/animation/animation_events.h b/cc/animation/animation_events.h
index 650b9b5..73a7058 100644
--- a/cc/animation/animation_events.h
+++ b/cc/animation/animation_events.h
@@ -7,7 +7,9 @@
#include <vector>
+#include "base/memory/scoped_ptr.h"
#include "cc/animation/animation.h"
+#include "cc/animation/animation_curve.h"
#include "cc/base/cc_export.h"
#include "cc/output/filter_operations.h"
#include "ui/gfx/transform.h"
@@ -15,14 +17,18 @@
namespace cc {
struct CC_EXPORT AnimationEvent {
- enum Type { STARTED, FINISHED, ABORTED, PROPERTY_UPDATE };
+ enum Type { STARTED, FINISHED, ABORTED, PROPERTY_UPDATE, TAKEOVER };
AnimationEvent(Type type,
int layer_id,
int group_id,
TargetProperty::Type target_property,
base::TimeTicks monotonic_time);
+
AnimationEvent(const AnimationEvent& other);
+ AnimationEvent& operator=(const AnimationEvent& other);
+
+ ~AnimationEvent();
Type type;
int layer_id;
@@ -33,6 +39,10 @@ struct CC_EXPORT AnimationEvent {
float opacity;
gfx::Transform transform;
FilterOperations filters;
+
+ // For continuing a scroll offset animation on the main thread.
+ double animation_start_time;
+ scoped_ptr<AnimationCurve> curve;
};
class CC_EXPORT AnimationEvents {
diff --git a/cc/animation/animation_host.cc b/cc/animation/animation_host.cc
index 6803f6c..a4264b0 100644
--- a/cc/animation/animation_host.cc
+++ b/cc/animation/animation_host.cc
@@ -98,10 +98,10 @@ class AnimationHost::ScrollOffsetAnimations : public AnimationDelegate {
return true;
}
- void ScrollAnimationAbort() {
+ void ScrollAnimationAbort(bool needs_completion) {
DCHECK(scroll_offset_animation_player_);
scroll_offset_animation_player_->AbortAnimations(
- TargetProperty::SCROLL_OFFSET);
+ TargetProperty::SCROLL_OFFSET, needs_completion);
}
// AnimationDelegate implementation.
@@ -118,6 +118,10 @@ class AnimationHost::ScrollOffsetAnimations : public AnimationDelegate {
void NotifyAnimationAborted(base::TimeTicks monotonic_time,
TargetProperty::Type target_property,
int group) override {}
+ void NotifyAnimationTakeover(base::TimeTicks monotonic_time,
+ TargetProperty::Type target_property,
+ double animation_start_time,
+ scoped_ptr<AnimationCurve> curve) override {}
private:
void ReattachScrollOffsetPlayerIfNeeded(int layer_id) {
@@ -476,6 +480,16 @@ bool AnimationHost::OpacityIsAnimatingOnImplOnly(int layer_id) const {
return animation && animation->is_impl_only();
}
+bool AnimationHost::ScrollOffsetIsAnimatingOnImplOnly(int layer_id) const {
+ LayerAnimationController* controller = GetControllerForLayerId(layer_id);
+ if (!controller)
+ return false;
+
+ Animation* animation =
+ controller->GetAnimation(TargetProperty::SCROLL_OFFSET);
+ return animation && animation->is_impl_only();
+}
+
bool AnimationHost::TransformIsAnimatingOnImplOnly(int layer_id) const {
LayerAnimationController* controller = GetControllerForLayerId(layer_id);
if (!controller)
@@ -586,9 +600,9 @@ bool AnimationHost::ImplOnlyScrollAnimationUpdateTarget(
layer_id, scroll_delta, max_scroll_offset, frame_monotonic_time);
}
-void AnimationHost::ScrollAnimationAbort() {
+void AnimationHost::ScrollAnimationAbort(bool needs_completion) {
DCHECK(scroll_offset_animations_);
- return scroll_offset_animations_->ScrollAnimationAbort();
+ return scroll_offset_animations_->ScrollAnimationAbort(needs_completion);
}
} // namespace cc
diff --git a/cc/animation/animation_host.h b/cc/animation/animation_host.h
index 64f82be..e8ea9ae 100644
--- a/cc/animation/animation_host.h
+++ b/cc/animation/animation_host.h
@@ -115,6 +115,7 @@ class CC_EXPORT AnimationHost {
bool FilterIsAnimatingOnImplOnly(int layer_id) const;
bool OpacityIsAnimatingOnImplOnly(int layer_id) const;
+ bool ScrollOffsetIsAnimatingOnImplOnly(int layer_id) const;
bool TransformIsAnimatingOnImplOnly(int layer_id) const;
bool HasFilterAnimationThatInflatesBounds(int layer_id) const;
@@ -151,7 +152,7 @@ class CC_EXPORT AnimationHost {
const gfx::ScrollOffset& max_scroll_offset,
base::TimeTicks frame_monotonic_time);
- void ScrollAnimationAbort();
+ void ScrollAnimationAbort(bool needs_completion);
private:
explicit AnimationHost(ThreadInstance thread_instance);
diff --git a/cc/animation/animation_player.cc b/cc/animation/animation_player.cc
index 0c8ad3c..77a7c21 100644
--- a/cc/animation/animation_player.cc
+++ b/cc/animation/animation_player.cc
@@ -160,10 +160,11 @@ void AnimationPlayer::AbortAnimation(int animation_id) {
SetNeedsCommit();
}
-void AnimationPlayer::AbortAnimations(TargetProperty::Type target_property) {
+void AnimationPlayer::AbortAnimations(TargetProperty::Type target_property,
+ bool needs_completion) {
if (element_animations_) {
element_animations_->layer_animation_controller()->AbortAnimations(
- target_property);
+ target_property, needs_completion);
SetNeedsCommit();
} else {
auto animations_to_remove = std::remove_if(
@@ -211,6 +212,19 @@ void AnimationPlayer::NotifyAnimationAborted(
target_property, group);
}
+void AnimationPlayer::NotifyAnimationTakeover(
+ base::TimeTicks monotonic_time,
+ TargetProperty::Type target_property,
+ double animation_start_time,
+ scoped_ptr<AnimationCurve> curve) {
+ if (layer_animation_delegate_) {
+ DCHECK(curve);
+ layer_animation_delegate_->NotifyAnimationTakeover(
+ monotonic_time, target_property, animation_start_time,
+ std::move(curve));
+ }
+}
+
void AnimationPlayer::SetNeedsCommit() {
DCHECK(animation_host_);
animation_host_->SetNeedsCommit();
diff --git a/cc/animation/animation_player.h b/cc/animation/animation_player.h
index 1276c93..a81b498 100644
--- a/cc/animation/animation_player.h
+++ b/cc/animation/animation_player.h
@@ -12,6 +12,7 @@
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "cc/animation/animation.h"
+#include "cc/animation/animation_curve.h"
#include "cc/base/cc_export.h"
namespace cc {
@@ -69,7 +70,8 @@ class CC_EXPORT AnimationPlayer : public base::RefCounted<AnimationPlayer>,
void PauseAnimation(int animation_id, double time_offset);
void RemoveAnimation(int animation_id);
void AbortAnimation(int animation_id);
- void AbortAnimations(TargetProperty::Type target_property);
+ void AbortAnimations(TargetProperty::Type target_property,
+ bool needs_completion);
void PushPropertiesTo(AnimationPlayer* player_impl);
@@ -83,6 +85,10 @@ class CC_EXPORT AnimationPlayer : public base::RefCounted<AnimationPlayer>,
void NotifyAnimationAborted(base::TimeTicks monotonic_time,
TargetProperty::Type target_property,
int group);
+ void NotifyAnimationTakeover(base::TimeTicks monotonic_time,
+ TargetProperty::Type target_property,
+ double animation_start_time,
+ scoped_ptr<AnimationCurve> curve);
// Whether this player has animations waiting to get sent to LAC.
bool has_pending_animations_for_testing() const {
diff --git a/cc/animation/animation_registrar.cc b/cc/animation/animation_registrar.cc
index e5ecf83..e498045 100644
--- a/cc/animation/animation_registrar.cc
+++ b/cc/animation/animation_registrar.cc
@@ -132,6 +132,10 @@ void AnimationRegistrar::SetAnimationEvents(
(*iter).second->NotifyAnimationPropertyUpdate(
events->events_[event_index]);
break;
+
+ case AnimationEvent::TAKEOVER:
+ (*iter).second->NotifyAnimationTakeover(events->events_[event_index]);
+ break;
}
}
}
diff --git a/cc/animation/element_animations.cc b/cc/animation/element_animations.cc
index cded26a..485f3fd 100644
--- a/cc/animation/element_animations.cc
+++ b/cc/animation/element_animations.cc
@@ -270,6 +270,22 @@ void ElementAnimations::NotifyAnimationAborted(
}
}
+void ElementAnimations::NotifyAnimationTakeover(
+ base::TimeTicks monotonic_time,
+ TargetProperty::Type target_property,
+ double animation_start_time,
+ scoped_ptr<AnimationCurve> curve) {
+ DCHECK(curve);
+ for (PlayersListNode* node = players_list_->head();
+ node != players_list_->end(); node = node->next()) {
+ scoped_ptr<AnimationCurve> animation_curve = curve->Clone();
+ AnimationPlayer* player = node->value();
+ player->NotifyAnimationTakeover(monotonic_time, target_property,
+ animation_start_time,
+ std::move(animation_curve));
+ }
+}
+
gfx::ScrollOffset ElementAnimations::ScrollOffsetForAnimation() const {
DCHECK(layer_animation_controller_);
if (animation_host()) {
diff --git a/cc/animation/element_animations.h b/cc/animation/element_animations.h
index 61b85aa..ea33813 100644
--- a/cc/animation/element_animations.h
+++ b/cc/animation/element_animations.h
@@ -8,6 +8,8 @@
#include "base/containers/linked_list.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "cc/animation/animation_curve.h"
#include "cc/animation/animation_delegate.h"
#include "cc/animation/layer_animation_controller.h"
#include "cc/animation/layer_animation_value_provider.h"
@@ -103,6 +105,10 @@ class CC_EXPORT ElementAnimations : public AnimationDelegate,
void NotifyAnimationAborted(base::TimeTicks monotonic_time,
TargetProperty::Type target_property,
int group) override;
+ void NotifyAnimationTakeover(base::TimeTicks monotonic_time,
+ TargetProperty::Type target_property,
+ double animation_start_time,
+ scoped_ptr<AnimationCurve> curve) override;
// LayerAnimationValueProvider implementation.
gfx::ScrollOffset ScrollOffsetForAnimation() const override;
diff --git a/cc/animation/layer_animation_controller.cc b/cc/animation/layer_animation_controller.cc
index 1e8aa02..1f470b5 100644
--- a/cc/animation/layer_animation_controller.cc
+++ b/cc/animation/layer_animation_controller.cc
@@ -10,6 +10,7 @@
#include <vector>
#include "cc/animation/animation.h"
+#include "cc/animation/animation_curve.h"
#include "cc/animation/animation_delegate.h"
#include "cc/animation/animation_events.h"
#include "cc/animation/animation_registrar.h"
@@ -127,12 +128,23 @@ void LayerAnimationController::AbortAnimation(int animation_id) {
}
void LayerAnimationController::AbortAnimations(
- TargetProperty::Type target_property) {
+ TargetProperty::Type target_property,
+ bool needs_completion) {
+ if (needs_completion)
+ DCHECK(target_property == TargetProperty::SCROLL_OFFSET);
+
bool aborted_transform_animation = false;
for (size_t i = 0; i < animations_.size(); ++i) {
if (animations_[i]->target_property() == target_property &&
!animations_[i]->is_finished()) {
- animations_[i]->SetRunState(Animation::ABORTED, last_tick_time_);
+ // Currently only impl-only scroll offset animations can be completed on
+ // the main thread.
+ if (needs_completion && animations_[i]->is_impl_only()) {
+ animations_[i]->SetRunState(Animation::ABORTED_BUT_NEEDS_COMPLETION,
+ last_tick_time_);
+ } else {
+ animations_[i]->SetRunState(Animation::ABORTED, last_tick_time_);
+ }
if (target_property == TargetProperty::TRANSFORM)
aborted_transform_animation = true;
}
@@ -424,6 +436,17 @@ void LayerAnimationController::NotifyAnimationFinished(
}
}
+void LayerAnimationController::NotifyAnimationTakeover(
+ const AnimationEvent& event) {
+ DCHECK(event.target_property == TargetProperty::SCROLL_OFFSET);
+ if (layer_animation_delegate_) {
+ scoped_ptr<AnimationCurve> animation_curve = event.curve->Clone();
+ layer_animation_delegate_->NotifyAnimationTakeover(
+ event.monotonic_time, event.target_property, event.animation_start_time,
+ std::move(animation_curve));
+ }
+}
+
void LayerAnimationController::NotifyAnimationAborted(
const AnimationEvent& event) {
bool aborted_transform_animation = false;
@@ -923,6 +946,35 @@ void LayerAnimationController::MarkAnimationsForDeletion(
continue;
}
+ // If running on the compositor and need to complete an aborted animation
+ // on the main thread.
+ if (events &&
+ animations_[i]->run_state() ==
+ Animation::ABORTED_BUT_NEEDS_COMPLETION) {
+ AnimationEvent aborted_event(AnimationEvent::TAKEOVER, id_, group_id,
+ animations_[i]->target_property(),
+ monotonic_time);
+ aborted_event.animation_start_time =
+ (animations_[i]->start_time() - base::TimeTicks()).InSecondsF();
+ const ScrollOffsetAnimationCurve* scroll_offset_animation_curve =
+ animations_[i]->curve()->ToScrollOffsetAnimationCurve();
+ aborted_event.curve = scroll_offset_animation_curve->Clone();
+ // Notify the compositor that the animation is finished.
+ if (layer_animation_delegate_) {
+ layer_animation_delegate_->NotifyAnimationFinished(
+ aborted_event.monotonic_time, aborted_event.target_property,
+ aborted_event.group_id);
+ }
+ // Notify main thread.
+ events->events_.push_back(aborted_event);
+
+ // Remove the animation from the compositor.
+ animations_[i]->SetRunState(Animation::WAITING_FOR_DELETION,
+ monotonic_time);
+ marked_animations_for_deletions = true;
+ continue;
+ }
+
bool all_anims_with_same_id_are_finished = false;
// Since deleting an animation on the main thread leads to its deletion
diff --git a/cc/animation/layer_animation_controller.h b/cc/animation/layer_animation_controller.h
index a364172..28a4523 100644
--- a/cc/animation/layer_animation_controller.h
+++ b/cc/animation/layer_animation_controller.h
@@ -47,7 +47,8 @@ class CC_EXPORT LayerAnimationController
void PauseAnimation(int animation_id, base::TimeDelta time_offset);
void RemoveAnimation(int animation_id);
void AbortAnimation(int animation_id);
- void AbortAnimations(TargetProperty::Type target_property);
+ void AbortAnimations(TargetProperty::Type target_property,
+ bool needs_completion = false);
// Ensures that the list of active animations on the main thread and the impl
// thread are kept in sync. This function does not take ownership of the impl
@@ -98,6 +99,7 @@ class CC_EXPORT LayerAnimationController
void NotifyAnimationFinished(const AnimationEvent& event);
void NotifyAnimationAborted(const AnimationEvent& event);
void NotifyAnimationPropertyUpdate(const AnimationEvent& event);
+ void NotifyAnimationTakeover(const AnimationEvent& event);
void AddValueObserver(LayerAnimationValueObserver* observer);
void RemoveValueObserver(LayerAnimationValueObserver* observer);
diff --git a/cc/animation/layer_animation_controller_unittest.cc b/cc/animation/layer_animation_controller_unittest.cc
index 764b470..5390d1b 100644
--- a/cc/animation/layer_animation_controller_unittest.cc
+++ b/cc/animation/layer_animation_controller_unittest.cc
@@ -1025,6 +1025,7 @@ class FakeAnimationDelegate : public AnimationDelegate {
: started_(false),
finished_(false),
aborted_(false),
+ takeover_(false),
start_time_(base::TimeTicks()) {}
void NotifyAnimationStarted(TimeTicks monotonic_time,
@@ -1046,18 +1047,28 @@ class FakeAnimationDelegate : public AnimationDelegate {
aborted_ = true;
}
+ void NotifyAnimationTakeover(base::TimeTicks monotonic_time,
+ TargetProperty::Type target_property,
+ double animation_start_time,
+ scoped_ptr<AnimationCurve> curve) override {
+ takeover_ = true;
+ }
+
bool started() { return started_; }
bool finished() { return finished_; }
bool aborted() { return aborted_; }
+ bool takeover() { return takeover_; }
+
TimeTicks start_time() { return start_time_; }
private:
bool started_;
bool finished_;
bool aborted_;
+ bool takeover_;
TimeTicks start_time_;
};
@@ -1906,6 +1917,72 @@ TEST(LayerAnimationControllerTest, ImplThreadAbortedAnimationGetsDeleted) {
EXPECT_FALSE(controller_impl->GetAnimationById(animation_id));
}
+// Test that an impl-only scroll offset animation that needs to be completed on
+// the main thread gets deleted.
+TEST(LayerAnimationControllerTest, ImplThreadTakeoverAnimationGetsDeleted) {
+ FakeLayerAnimationValueObserver dummy_impl;
+ scoped_refptr<LayerAnimationController> controller_impl(
+ LayerAnimationController::Create(0));
+ controller_impl->AddValueObserver(&dummy_impl);
+ FakeLayerAnimationValueObserver dummy;
+ scoped_refptr<LayerAnimationController> controller(
+ LayerAnimationController::Create(0));
+ controller->AddValueObserver(&dummy);
+ FakeAnimationDelegate delegate_impl;
+ controller_impl->set_layer_animation_delegate(&delegate_impl);
+ FakeAnimationDelegate delegate;
+ controller->set_layer_animation_delegate(&delegate);
+
+ // Add impl-only scroll offset animation.
+ int animation_id = 1;
+ gfx::ScrollOffset initial_value(100.f, 300.f);
+ gfx::ScrollOffset target_value(300.f, 200.f);
+ scoped_ptr<ScrollOffsetAnimationCurve> curve(
+ ScrollOffsetAnimationCurve::Create(target_value,
+ EaseInOutTimingFunction::Create()));
+ curve->SetInitialValue(initial_value);
+ scoped_ptr<Animation> animation(Animation::Create(
+ std::move(curve), animation_id, 0, TargetProperty::SCROLL_OFFSET));
+ animation->set_start_time(TicksFromSecondsF(123));
+ animation->set_is_impl_only(true);
+ controller_impl->AddAnimation(std::move(animation));
+
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
+ EXPECT_TRUE(controller_impl->GetAnimationById(animation_id));
+
+ controller_impl->AbortAnimations(TargetProperty::SCROLL_OFFSET,
+ true /* needs_completion*/);
+ EXPECT_EQ(Animation::ABORTED_BUT_NEEDS_COMPLETION,
+ controller_impl->GetAnimation(TargetProperty::SCROLL_OFFSET)
+ ->run_state());
+ EXPECT_FALSE(dummy.animation_waiting_for_deletion());
+ EXPECT_FALSE(dummy_impl.animation_waiting_for_deletion());
+
+ AnimationEvents events;
+ controller_impl->Animate(kInitialTickTime);
+ controller_impl->UpdateState(true, &events);
+ EXPECT_TRUE(delegate_impl.finished());
+ EXPECT_TRUE(dummy_impl.animation_waiting_for_deletion());
+ EXPECT_EQ(1u, events.events_.size());
+ EXPECT_EQ(AnimationEvent::TAKEOVER, events.events_[0].type);
+ EXPECT_EQ(123, events.events_[0].animation_start_time);
+ EXPECT_EQ(
+ target_value,
+ events.events_[0].curve->ToScrollOffsetAnimationCurve()->target_value());
+ EXPECT_EQ(Animation::WAITING_FOR_DELETION,
+ controller_impl->GetAnimation(TargetProperty::SCROLL_OFFSET)
+ ->run_state());
+
+ controller->NotifyAnimationTakeover(events.events_[0]);
+ EXPECT_TRUE(delegate.takeover());
+
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+ controller_impl->ActivateAnimations();
+ EXPECT_FALSE(controller->GetAnimationById(animation_id));
+ EXPECT_FALSE(controller_impl->GetAnimationById(animation_id));
+}
+
// Ensure that we only generate FINISHED events for animations in a group
// once all animations in that group are finished.
TEST(LayerAnimationControllerTest, FinishedEventsForGroup) {
diff --git a/cc/animation/scroll_offset_animation_curve.cc b/cc/animation/scroll_offset_animation_curve.cc
index 1f44bba..86448b7 100644
--- a/cc/animation/scroll_offset_animation_curve.cc
+++ b/cc/animation/scroll_offset_animation_curve.cc
@@ -134,6 +134,11 @@ AnimationCurve::CurveType ScrollOffsetAnimationCurve::Type() const {
}
scoped_ptr<AnimationCurve> ScrollOffsetAnimationCurve::Clone() const {
+ return CloneToScrollOffsetAnimationCurve();
+}
+
+scoped_ptr<ScrollOffsetAnimationCurve>
+ScrollOffsetAnimationCurve::CloneToScrollOffsetAnimationCurve() const {
scoped_ptr<TimingFunction> timing_function(
static_cast<TimingFunction*>(timing_function_->Clone().release()));
scoped_ptr<ScrollOffsetAnimationCurve> curve_clone =
@@ -142,7 +147,7 @@ scoped_ptr<AnimationCurve> ScrollOffsetAnimationCurve::Clone() const {
curve_clone->total_animation_duration_ = total_animation_duration_;
curve_clone->last_retarget_ = last_retarget_;
curve_clone->has_set_initial_value_ = has_set_initial_value_;
- return std::move(curve_clone);
+ return curve_clone;
}
static double VelocityBasedDurationBound(gfx::Vector2dF old_delta,
diff --git a/cc/animation/scroll_offset_animation_curve.h b/cc/animation/scroll_offset_animation_curve.h
index b874f11..8f9530a 100644
--- a/cc/animation/scroll_offset_animation_curve.h
+++ b/cc/animation/scroll_offset_animation_curve.h
@@ -36,6 +36,8 @@ class CC_EXPORT ScrollOffsetAnimationCurve : public AnimationCurve {
base::TimeDelta Duration() const override;
CurveType Type() const override;
scoped_ptr<AnimationCurve> Clone() const override;
+ scoped_ptr<ScrollOffsetAnimationCurve> CloneToScrollOffsetAnimationCurve()
+ const;
private:
ScrollOffsetAnimationCurve(const gfx::ScrollOffset& target_value,
diff --git a/cc/blink/web_to_cc_animation_delegate_adapter.h b/cc/blink/web_to_cc_animation_delegate_adapter.h
index 0978736..6c5453e 100644
--- a/cc/blink/web_to_cc_animation_delegate_adapter.h
+++ b/cc/blink/web_to_cc_animation_delegate_adapter.h
@@ -30,6 +30,10 @@ class WebToCCAnimationDelegateAdapter : public cc::AnimationDelegate {
void NotifyAnimationAborted(base::TimeTicks monotonic_time,
cc::TargetProperty::Type target_property,
int group) override;
+ void NotifyAnimationTakeover(base::TimeTicks monotonic_time,
+ cc::TargetProperty::Type target_property,
+ double animation_start_time,
+ scoped_ptr<cc::AnimationCurve> curve) override {}
blink::WebCompositorAnimationDelegate* delegate_;
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 3f14de8..a382cab 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -14,6 +14,7 @@
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_argument.h"
+#include "cc/animation/animation_host.h"
#include "cc/animation/animation_registrar.h"
#include "cc/animation/mutable_properties.h"
#include "cc/base/math_util.h"
@@ -501,6 +502,26 @@ scoped_ptr<LayerImpl> LayerImpl::CreateLayerImpl(LayerTreeImpl* tree_impl) {
return LayerImpl::Create(tree_impl, layer_id_, scroll_offset_);
}
+void LayerImpl::set_main_thread_scrolling_reasons(
+ uint32_t main_thread_scrolling_reasons) {
+ if (main_thread_scrolling_reasons_ == main_thread_scrolling_reasons)
+ return;
+
+ if (main_thread_scrolling_reasons &
+ MainThreadScrollingReason::kHasNonLayerViewportConstrainedObjects &&
+ layer_tree_impl()) {
+ if (layer_tree_impl()->ScrollOffsetIsAnimatingOnImplOnly(this)) {
+ layer_tree_impl()->animation_host()->ScrollAnimationAbort(
+ true /* needs_completion */);
+ } else if (layer_animation_controller()) {
+ layer_animation_controller()->AbortAnimations(
+ TargetProperty::SCROLL_OFFSET);
+ }
+ }
+
+ main_thread_scrolling_reasons_ = main_thread_scrolling_reasons;
+}
+
void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
layer->SetTransformOrigin(transform_origin_);
layer->SetBackgroundColor(background_color_);
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h
index c36dd9e0..7f4f922 100644
--- a/cc/layers/layer_impl.h
+++ b/cc/layers/layer_impl.h
@@ -128,6 +128,10 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
void NotifyAnimationAborted(base::TimeTicks monotonic_time,
TargetProperty::Type target_property,
int group) override{};
+ void NotifyAnimationTakeover(base::TimeTicks monotonic_time,
+ TargetProperty::Type target_property,
+ double animation_start_time,
+ scoped_ptr<AnimationCurve> curve) override {}
// Tree structure.
LayerImpl* parent() { return parent_; }
@@ -506,9 +510,7 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
void ApplySentScrollDeltasFromAbortedCommit();
void set_main_thread_scrolling_reasons(
- uint32_t main_thread_scrolling_reasons) {
- main_thread_scrolling_reasons_ = main_thread_scrolling_reasons;
- }
+ uint32_t main_thread_scrolling_reasons);
uint32_t main_thread_scrolling_reasons() const {
return main_thread_scrolling_reasons_;
}
diff --git a/cc/test/animation_timelines_test_common.h b/cc/test/animation_timelines_test_common.h
index 9fdd451..e7b74915 100644
--- a/cc/test/animation_timelines_test_common.h
+++ b/cc/test/animation_timelines_test_common.h
@@ -155,6 +155,10 @@ class TestAnimationDelegate : public AnimationDelegate {
void NotifyAnimationAborted(base::TimeTicks monotonic_time,
TargetProperty::Type target_property,
int group) override {}
+ void NotifyAnimationTakeover(base::TimeTicks monotonic_time,
+ TargetProperty::Type target_property,
+ double animation_start_time,
+ scoped_ptr<AnimationCurve> curve) override {}
bool started_;
bool finished_;
};
diff --git a/cc/test/test_hooks.h b/cc/test/test_hooks.h
index a00233d..0a36af6 100644
--- a/cc/test/test_hooks.h
+++ b/cc/test/test_hooks.h
@@ -137,6 +137,10 @@ class TestHooks : public AnimationDelegate {
void NotifyAnimationAborted(base::TimeTicks monotonic_time,
TargetProperty::Type target_property,
int group) override {}
+ void NotifyAnimationTakeover(base::TimeTicks monotonic_time,
+ TargetProperty::Type target_property,
+ double animation_start_time,
+ scoped_ptr<AnimationCurve> curve) override {}
virtual void RequestNewOutputSurface() = 0;
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 26dba53..da79b67 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -3748,7 +3748,7 @@ void LayerTreeHostImpl::UpdateRootLayerStateForSynchronousInputHandler() {
void LayerTreeHostImpl::ScrollAnimationAbort(LayerImpl* layer_impl) {
if (animation_host_)
- return animation_host_->ScrollAnimationAbort();
+ return animation_host_->ScrollAnimationAbort(false /* needs_completion */);
layer_impl->layer_animation_controller()->AbortAnimations(
TargetProperty::SCROLL_OFFSET);
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 2f543e9..25b066c 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -9457,6 +9457,64 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedAborted) {
host_impl_->DidFinishImplFrame();
}
+// Test that a smooth scroll offset animation is marked finished when a main
+// thread scrolling reason is added. The animation is then finished on the
+// main thread.
+TEST_F(LayerTreeHostImplTimelinesTest,
+ ScrollAnimatedFinishedByMainThreadScrollingReason) {
+ const gfx::Size content_size(1000, 1000);
+ const gfx::Size viewport_size(500, 500);
+ CreateBasicVirtualViewportLayers(viewport_size, content_size);
+
+ DrawFrame();
+
+ base::TimeTicks start_time =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
+
+ BeginFrameArgs begin_frame_args =
+ CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+
+ // Perform animated scroll.
+ EXPECT_EQ(
+ InputHandler::SCROLL_ON_IMPL_THREAD,
+ host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 100)).thread);
+
+ LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
+
+ begin_frame_args.frame_time = start_time;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
+ host_impl_->UpdateAnimationState(true);
+
+ EXPECT_TRUE(host_impl_->animation_host()->HasAnyAnimationTargetingProperty(
+ scrolling_layer->id(), TargetProperty::SCROLL_OFFSET));
+
+ EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->CurrentScrollOffset());
+ host_impl_->DidFinishImplFrame();
+
+ begin_frame_args.frame_time =
+ start_time + base::TimeDelta::FromMilliseconds(50);
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
+ host_impl_->UpdateAnimationState(true);
+
+ float y = scrolling_layer->CurrentScrollOffset().y();
+ EXPECT_TRUE(y > 1 && y < 49);
+
+ // Add main thread scrolling reason.
+ scrolling_layer->set_main_thread_scrolling_reasons(
+ MainThreadScrollingReason::kHasNonLayerViewportConstrainedObjects);
+ host_impl_->UpdateAnimationState(true);
+
+ // The main thread scrolling reason should have marked the smooth scroll
+ // animation as finished.
+ EXPECT_FALSE(
+ host_impl_->animation_host()->HasActiveAnimation(scrolling_layer->id()));
+ EXPECT_TRUE(y > 1 && y < 49);
+ EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
+ host_impl_->DidFinishImplFrame();
+}
+
// Evolved from LayerTreeHostImplTest.ScrollAnimated.
TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimated) {
const gfx::Size content_size(1000, 1000);
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index d595b77..3d608f1 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -1866,6 +1866,14 @@ bool LayerTreeImpl::OpacityIsAnimatingOnImplOnly(const LayerImpl* layer) const {
: false;
}
+bool LayerTreeImpl::ScrollOffsetIsAnimatingOnImplOnly(
+ const LayerImpl* layer) const {
+ return layer_tree_host_impl_->animation_host()
+ ? layer_tree_host_impl_->animation_host()
+ ->ScrollOffsetIsAnimatingOnImplOnly(layer->id())
+ : false;
+}
+
bool LayerTreeImpl::TransformIsAnimatingOnImplOnly(
const LayerImpl* layer) const {
return layer_tree_host_impl_->animation_host()
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index 4b8a401..1332f54 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -109,6 +109,9 @@ class CC_EXPORT LayerTreeImpl {
bool RequiresHighResToDraw() const;
bool SmoothnessTakesPriority() const;
VideoFrameControllerClient* GetVideoFrameControllerClient() const;
+ AnimationHost* animation_host() const {
+ return layer_tree_host_impl_->animation_host();
+ }
// Tree specific methods exposed to layer-impl tree.
// ---------------------------------------------------------------------------
@@ -390,6 +393,7 @@ class CC_EXPORT LayerTreeImpl {
bool FilterIsAnimatingOnImplOnly(const LayerImpl* layer) const;
bool OpacityIsAnimatingOnImplOnly(const LayerImpl* layer) const;
+ bool ScrollOffsetIsAnimatingOnImplOnly(const LayerImpl* layer) const;
bool TransformIsAnimatingOnImplOnly(const LayerImpl* layer) const;
bool AnimationsPreserveAxisAlignment(const LayerImpl* layer) const;
diff --git a/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.cpp b/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.cpp
index ca74779..a00f628 100644
--- a/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.cpp
+++ b/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.cpp
@@ -95,4 +95,18 @@ void CompositorAnimationPlayer::NotifyAnimationAborted(
m_delegate->notifyAnimationAborted((monotonicTime - base::TimeTicks()).InSecondsF(), group);
}
+void CompositorAnimationPlayer::NotifyAnimationTakeover(
+ base::TimeTicks monotonicTime,
+ cc::TargetProperty::Type,
+ double animationStartTime,
+ scoped_ptr<cc::AnimationCurve> curve)
+{
+ if (m_delegate) {
+ m_delegate->notifyAnimationTakeover(
+ (monotonicTime - base::TimeTicks()).InSecondsF(),
+ animationStartTime,
+ std::move(curve));
+ }
+}
+
} // namespace blink
diff --git a/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.h b/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.h
index b58d656..f8dcb6a 100644
--- a/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.h
+++ b/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.h
@@ -8,6 +8,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "cc/animation/animation.h"
+#include "cc/animation/animation_curve.h"
#include "cc/animation/animation_delegate.h"
#include "cc/animation/animation_player.h"
#include "platform/PlatformExport.h"
@@ -48,6 +49,7 @@ private:
void NotifyAnimationStarted(base::TimeTicks monotonicTime, cc::TargetProperty::Type, int group) override;
void NotifyAnimationFinished(base::TimeTicks monotonicTime, cc::TargetProperty::Type, int group) override;
void NotifyAnimationAborted(base::TimeTicks monotonicTime, cc::TargetProperty::Type, int group) override;
+ void NotifyAnimationTakeover(base::TimeTicks monotonicTime, cc::TargetProperty::Type, double animationStartTime, scoped_ptr<cc::AnimationCurve>) override;
scoped_refptr<cc::AnimationPlayer> m_animationPlayer;
WebCompositorAnimationDelegate* m_delegate;
diff --git a/third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.cpp b/third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.cpp
index c7d931e..f4202b3 100644
--- a/third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.cpp
+++ b/third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.cpp
@@ -39,6 +39,12 @@ CompositorScrollOffsetAnimationCurve::CompositorScrollOffsetAnimationCurve(
{
}
+CompositorScrollOffsetAnimationCurve::CompositorScrollOffsetAnimationCurve(
+ cc::ScrollOffsetAnimationCurve* curve)
+ : m_curve(curve->CloneToScrollOffsetAnimationCurve())
+{
+}
+
CompositorScrollOffsetAnimationCurve::~CompositorScrollOffsetAnimationCurve()
{
}
diff --git a/third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.h b/third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.h
index 5b927ca..9a0e81b 100644
--- a/third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.h
+++ b/third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.h
@@ -28,6 +28,7 @@ public:
};
CompositorScrollOffsetAnimationCurve(FloatPoint, TimingFunctionType, ScrollDurationBehavior);
+ CompositorScrollOffsetAnimationCurve(cc::ScrollOffsetAnimationCurve*);
~CompositorScrollOffsetAnimationCurve() override;
// CompositorAnimationCurve implementation.
diff --git a/third_party/WebKit/Source/platform/graphics/CompositorFactory.cpp b/third_party/WebKit/Source/platform/graphics/CompositorFactory.cpp
index 6ab41fd..b086028 100644
--- a/third_party/WebKit/Source/platform/graphics/CompositorFactory.cpp
+++ b/third_party/WebKit/Source/platform/graphics/CompositorFactory.cpp
@@ -36,6 +36,12 @@ public:
durationBehavior);
}
+ CompositorScrollOffsetAnimationCurve* createScrollOffsetAnimationCurve(
+ cc::ScrollOffsetAnimationCurve* curve)
+ {
+ return new CompositorScrollOffsetAnimationCurve(curve);
+ }
+
CompositorTransformAnimationCurve* createTransformAnimationCurve() override
{
return new CompositorTransformAnimationCurve();
diff --git a/third_party/WebKit/Source/platform/graphics/CompositorFactory.h b/third_party/WebKit/Source/platform/graphics/CompositorFactory.h
index 612dfda..098e3e0 100644
--- a/third_party/WebKit/Source/platform/graphics/CompositorFactory.h
+++ b/third_party/WebKit/Source/platform/graphics/CompositorFactory.h
@@ -40,6 +40,9 @@ public:
CompositorAnimationCurve::TimingFunctionType,
CompositorScrollOffsetAnimationCurve::ScrollDurationBehavior) { return nullptr; }
+ virtual CompositorScrollOffsetAnimationCurve* createScrollOffsetAnimationCurve(
+ cc::ScrollOffsetAnimationCurve* curve) { return nullptr; }
+
virtual CompositorTransformAnimationCurve* createTransformAnimationCurve() { return nullptr; }
virtual CompositorTransformOperations* createTransformOperations() { return nullptr; }
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp
index 9baaff5..7c5c194 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp
+++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp
@@ -30,6 +30,7 @@
#include "platform/scroll/ScrollAnimator.h"
+#include "cc/animation/scroll_offset_animation_curve.h"
#include "platform/TraceEvent.h"
#include "platform/animation/CompositorAnimation.h"
#include "platform/graphics/CompositorFactory.h"
@@ -120,15 +121,26 @@ ScrollResultOneDimensional ScrollAnimator::userScroll(
FloatPoint targetPos = desiredTargetPosition();
targetPos.moveBy(pixelDelta);
+ if (willAnimateToOffset(targetPos)) {
+ m_lastGranularity = granularity;
+ // Report unused delta only if there is no animation running. See
+ // comment below regarding scroll latching.
+ return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0);
+ }
+ // Report unused delta only if there is no animation and we are not
+ // starting one. This ensures we latch for the duration of the
+ // animation rather than animating multiple scrollers at the same time.
+ return ScrollResultOneDimensional(/* didScroll */ false, delta);
+}
+
+bool ScrollAnimator::willAnimateToOffset(const FloatPoint& targetPos)
+{
if (m_runState == RunState::PostAnimationCleanup)
resetAnimationState();
if (m_animationCurve && m_runState != RunState::WaitingToCancelOnCompositor) {
- 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);
- }
+ if ((targetPos - m_targetOffset).isZero())
+ return true;
m_targetOffset = targetPos;
ASSERT(m_runState == RunState::RunningOnMainThread
@@ -139,30 +151,25 @@ ScrollResultOneDimensional ScrollAnimator::userScroll(
|| m_runState == RunState::RunningOnCompositorButNeedsUpdate) {
if (registerAndScheduleAnimation())
m_runState = RunState::RunningOnCompositorButNeedsUpdate;
- return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0);
+ return true;
}
// 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);
+ return true;
}
- if ((targetPos - currentPosition()).isZero()) {
- // Report unused delta only if there is no animation and we are not
- // starting one. This ensures we latch for the duration of the
- // animation rather than animating multiple scrollers at the same time.
- return ScrollResultOneDimensional(/* didScroll */ false, delta);
- }
+ if ((targetPos - currentPosition()).isZero())
+ return false;
m_targetOffset = targetPos;
m_startTime = m_timeFunction();
- m_lastGranularity = granularity;
if (registerAndScheduleAnimation())
m_runState = RunState::WaitingToSendToCompositor;
- return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0);
+ return true;
}
void ScrollAnimator::scrollToOffsetWithoutAnimation(const FloatPoint& offset)
@@ -328,6 +335,28 @@ void ScrollAnimator::notifyCompositorAnimationFinished(int groupId)
ScrollAnimatorCompositorCoordinator::compositorAnimationFinished(groupId);
}
+void ScrollAnimator::notifyAnimationTakeover(
+ double monotonicTime,
+ double animationStartTime,
+ scoped_ptr<cc::AnimationCurve> curve)
+{
+ // If there is already an animation running and the compositor asks to take
+ // over an animation, do nothing to avoid judder.
+ if (hasRunningAnimation())
+ return;
+
+ cc::ScrollOffsetAnimationCurve* scrollOffsetAnimationCurve =
+ curve->ToScrollOffsetAnimationCurve();
+ FloatPoint targetValue(scrollOffsetAnimationCurve->target_value().x(),
+ scrollOffsetAnimationCurve->target_value().y());
+ if (willAnimateToOffset(targetValue)) {
+ m_animationCurve = adoptPtr(
+ CompositorFactory::current().createScrollOffsetAnimationCurve(
+ std::move(scrollOffsetAnimationCurve)));
+ m_startTime = animationStartTime;
+ }
+}
+
void ScrollAnimator::cancelAnimation()
{
ScrollAnimatorCompositorCoordinator::cancelAnimation();
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h
index 4bd57bd..bf788c9 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h
@@ -67,6 +67,11 @@ public:
DECLARE_VIRTUAL_TRACE();
protected:
+ void notifyAnimationTakeover(
+ double monotonicTime,
+ double animationStartTime,
+ scoped_ptr<cc::AnimationCurve>) override;
+
OwnPtr<CompositorScrollOffsetAnimationCurve> m_animationCurve;
double m_startTime;
WTF::TimeFunction m_timeFunction;
@@ -82,6 +87,11 @@ private:
void addMainThreadScrollingReason();
void removeMainThreadScrollingReason();
+ // Returns true if will animate to the given target position. Returns false
+ // only when there is no animation running and we are not starting one
+ // because we are already at targetPos.
+ bool willAnimateToOffset(const FloatPoint& targetPos);
+
FloatPoint m_targetOffset;
ScrollGranularity m_lastGranularity;
};
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp
index d35fe84..798d468 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp
+++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp
@@ -4,6 +4,7 @@
#include "platform/scroll/ScrollAnimatorCompositorCoordinator.h"
+#include "cc/animation/scroll_offset_animation_curve.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/animation/CompositorAnimationPlayer.h"
#include "platform/animation/CompositorAnimationTimeline.h"
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h
index 55018f4..752b068 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h
@@ -6,6 +6,7 @@
#define ScrollAnimatorCompositorCoordinator_h
#include "base/gtest_prod_util.h"
+#include "cc/animation/animation_curve.h"
#include "platform/PlatformExport.h"
#include "platform/animation/CompositorAnimationPlayerClient.h"
#include "platform/heap/Handle.h"
@@ -60,6 +61,10 @@ protected:
void notifyAnimationStarted(double monotonicTime, int group) override;
void notifyAnimationFinished(double monotonicTime, int group) override;
void notifyAnimationAborted(double monotonicTime, int group) override;
+ void notifyAnimationTakeover(
+ double monotonicTime,
+ double animationStartTime,
+ scoped_ptr<cc::AnimationCurve>) override { };
// CompositorAnimationPlayerClient implementation.
CompositorAnimationPlayer* compositorPlayer() const override;
diff --git a/third_party/WebKit/public/platform/WebCompositorAnimationDelegate.h b/third_party/WebKit/public/platform/WebCompositorAnimationDelegate.h
index 58339f8..78e8959 100644
--- a/third_party/WebKit/public/platform/WebCompositorAnimationDelegate.h
+++ b/third_party/WebKit/public/platform/WebCompositorAnimationDelegate.h
@@ -6,6 +6,7 @@
#define WebCompositorAnimationDelegate_h
#include "WebCommon.h"
+#include "cc/animation/animation_curve.h"
namespace blink {
@@ -16,6 +17,14 @@ public:
virtual void notifyAnimationStarted(double monotonicTime, int group) = 0;
virtual void notifyAnimationFinished(double monotonicTime, int group) = 0;
virtual void notifyAnimationAborted(double monotonicTime, int group) = 0;
+ // In the current state of things, notifyAnimationTakeover only applies to
+ // scroll offset animations since main thread scrolling reasons can be added
+ // while the compositor is animating. Keeping this non-pure virtual since
+ // it doesn't apply to CSS animations.
+ virtual void notifyAnimationTakeover(
+ double monotonicTime,
+ double animationStartTime,
+ scoped_ptr<cc::AnimationCurve> curve) { }
};
} // namespace blink