diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index c24c608d44231..4d23bf5e0f3fe 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -890,6 +890,7 @@ crbug.com/364614 [ Mac ] virtual/threaded/fast/scroll-behavior/overflow-scroll-r
crbug.com/364614 [ Mac ] virtual/scroll_customization/fast/scroll-behavior/overflow-scroll-root-frame-animates.html [ Skip ]
crbug.com/574283 [ Mac ] virtual/threaded/fast/scroll-behavior/smooth-scroll/fixed-background-in-iframe.html [ Skip ]
+crbug.com/574283 [ Mac ] virtual/threaded/fast/scroll-behavior/smooth-scroll/horizontal-smooth-scroll-in-rtl.html [ Skip ]
crbug.com/574283 [ Mac ] virtual/threaded/fast/scroll-behavior/smooth-scroll/main-thread-scrolling-reason-added.html [ Skip ]
crbug.com/574283 [ Mac ] virtual/threaded/fast/scroll-behavior/smooth-scroll/main-thread-scrolling-reason-correctness.html [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/virtual/threaded/fast/scroll-behavior/smooth-scroll/horizontal-smooth-scroll-in-rtl-expected.txt b/third_party/WebKit/LayoutTests/virtual/threaded/fast/scroll-behavior/smooth-scroll/horizontal-smooth-scroll-in-rtl-expected.txt
new file mode 100644
index 0000000000000..955b971667452
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/threaded/fast/scroll-behavior/smooth-scroll/horizontal-smooth-scroll-in-rtl-expected.txt
@@ -0,0 +1,11 @@
+This test verifies that both input-driven and programmatic smooth scrolls serviced by the compositor thread go to the correct scroll position on RTL pages with horizontal overflow.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS scrollX became -80
+PASS scrollX became -40
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/virtual/threaded/fast/scroll-behavior/smooth-scroll/horizontal-smooth-scroll-in-rtl.html b/third_party/WebKit/LayoutTests/virtual/threaded/fast/scroll-behavior/smooth-scroll/horizontal-smooth-scroll-in-rtl.html
new file mode 100644
index 0000000000000..e011d22e294cc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/threaded/fast/scroll-behavior/smooth-scroll/horizontal-smooth-scroll-in-rtl.html
@@ -0,0 +1,40 @@
+
+
+
+
diff --git a/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp b/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp
index 99f58fd7b3390..437bee38681c0 100644
--- a/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp
+++ b/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp
@@ -56,7 +56,7 @@ void ProgrammaticScrollAnimator::animateToOffset(FloatPoint offset)
m_startTime = 0.0;
m_targetOffset = offset;
m_animationCurve = adoptPtr(CompositorFactory::current().createScrollOffsetAnimationCurve(
- m_targetOffset,
+ compositorOffsetFromBlinkOffset(m_targetOffset),
CompositorAnimationCurve::TimingFunctionTypeEaseInOut,
CompositorScrollOffsetAnimationCurve::ScrollDurationDeltaBased));
@@ -83,7 +83,7 @@ void ProgrammaticScrollAnimator::tickAnimation(double monotonicTime)
m_startTime = monotonicTime;
double elapsedTime = monotonicTime - m_startTime;
bool isFinished = (elapsedTime > m_animationCurve->duration());
- FloatPoint offset = m_animationCurve->getValue(elapsedTime);
+ FloatPoint offset = blinkOffsetFromCompositorOffset(m_animationCurve->getValue(elapsedTime));
notifyPositionChanged(IntPoint(offset.x(), offset.y()));
if (isFinished) {
@@ -139,7 +139,8 @@ void ProgrammaticScrollAnimator::updateCompositorAnimations()
if (!sentToCompositor) {
m_runState = RunState::RunningOnMainThread;
- m_animationCurve->setInitialValue(FloatPoint(m_scrollableArea->scrollPosition()));
+ m_animationCurve->setInitialValue(compositorOffsetFromBlinkOffset(
+ FloatPoint(m_scrollableArea->scrollPosition())));
if (!m_scrollableArea->scheduleAnimation()) {
notifyPositionChanged(IntPoint(m_targetOffset.x(), m_targetOffset.y()));
resetAnimationState();
@@ -158,7 +159,8 @@ void ProgrammaticScrollAnimator::layerForCompositedScrollingDidChange(Compositor
m_runState = RunState::RunningOnMainThread;
m_compositorAnimationId = 0;
m_compositorAnimationGroupId = 0;
- m_animationCurve->setInitialValue(FloatPoint(m_scrollableArea->scrollPosition()));
+ m_animationCurve->setInitialValue(compositorOffsetFromBlinkOffset(
+ FloatPoint(m_scrollableArea->scrollPosition())));
m_scrollableArea->registerForAnimation();
if (!m_scrollableArea->scheduleAnimation()) {
resetAnimationState();
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp
index 21ffb6ebec345..bd01119154a16 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp
+++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp
@@ -149,7 +149,8 @@ bool ScrollAnimator::willAnimateToOffset(const FloatPoint& targetPos)
// Running on the main thread, simply update the target offset instead
// of sending to the compositor.
if (m_runState == RunState::RunningOnMainThread) {
- m_animationCurve->updateTarget(m_timeFunction() - m_startTime, targetPos);
+ m_animationCurve->updateTarget(m_timeFunction() - m_startTime,
+ compositorOffsetFromBlinkOffset(targetPos));
return true;
}
@@ -187,8 +188,9 @@ void ScrollAnimator::tickAnimation(double monotonicTime)
double elapsedTime = monotonicTime - m_startTime;
bool isFinished = (elapsedTime > m_animationCurve->duration());
- FloatPoint offset = isFinished ? m_animationCurve->targetValue()
- : m_animationCurve->getValue(elapsedTime);
+ FloatPoint offset = blinkOffsetFromCompositorOffset(isFinished
+ ? m_animationCurve->targetValue()
+ : m_animationCurve->getValue(elapsedTime));
offset = FloatPoint(m_scrollableArea->clampScrollPosition(offset));
@@ -286,18 +288,18 @@ void ScrollAnimator::updateCompositorAnimations()
m_compositorAnimationGroupId = 0;
m_animationCurve->updateTarget(m_timeFunction() - m_startTime,
- m_targetOffset);
+ compositorOffsetFromBlinkOffset(m_targetOffset));
m_runState = RunState::WaitingToSendToCompositor;
}
if (!m_animationCurve) {
m_animationCurve = adoptPtr(CompositorFactory::current().createScrollOffsetAnimationCurve(
- m_targetOffset,
+ compositorOffsetFromBlinkOffset(m_targetOffset),
CompositorAnimationCurve::TimingFunctionTypeEaseInOut,
m_lastGranularity == ScrollByPixel ?
CompositorScrollOffsetAnimationCurve::ScrollDurationInverseDelta :
CompositorScrollOffsetAnimationCurve::ScrollDurationConstant));
- m_animationCurve->setInitialValue(currentPosition());
+ m_animationCurve->setInitialValue(compositorOffsetFromBlinkOffset(currentPosition()));
}
bool runningOnMainThread = false;
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp
index 294fcbeee926d..b340b18f3654c 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp
+++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp
@@ -227,4 +227,16 @@ CompositorAnimationPlayer* ScrollAnimatorCompositorCoordinator::compositorPlayer
return m_compositorPlayer.get();
}
+FloatPoint ScrollAnimatorCompositorCoordinator::compositorOffsetFromBlinkOffset(FloatPoint offset)
+{
+ offset.moveBy(scrollableArea()->scrollOrigin());
+ return offset;
+}
+
+FloatPoint ScrollAnimatorCompositorCoordinator::blinkOffsetFromCompositorOffset(FloatPoint offset)
+{
+ offset.moveBy(-scrollableArea()->scrollOrigin());
+ return offset;
+}
+
} // namespace blink
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h
index 49daf59c314f5..bedc476b8fcac 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h
@@ -10,6 +10,7 @@
#include "platform/PlatformExport.h"
#include "platform/animation/CompositorAnimationDelegate.h"
#include "platform/animation/CompositorAnimationPlayerClient.h"
+#include "platform/geometry/FloatPoint.h"
#include "platform/heap/Handle.h"
#include "wtf/Allocator.h"
#include "wtf/Noncopyable.h"
@@ -57,6 +58,9 @@ class PLATFORM_EXPORT ScrollAnimatorCompositorCoordinator : public NoBaseWillBeG
void removeAnimation();
virtual void abortAnimation();
+ FloatPoint compositorOffsetFromBlinkOffset(FloatPoint);
+ FloatPoint blinkOffsetFromCompositorOffset(FloatPoint);
+
void compositorAnimationFinished(int groupId);
// Returns true if the compositor player was attached to a new layer.
bool reattachCompositorPlayerIfNeeded(CompositorAnimationTimeline*);