#include "platform/PlatformGestureEvent.h"
#include "platform/PlatformWheelEvent.h"
-#include "platform/geometry/FloatPoint.h"
+#include "platform/Timer.h"
+#include "platform/animation/TimingFunction.h"
+#include "platform/geometry/FloatRect.h"
+#include "platform/geometry/IntRect.h"
#include "platform/mac/BlockExceptions.h"
-#include "platform/mac/EmptyProtocolDefinitions.h"
#include "platform/mac/NSScrollerImpDetails.h"
-#include "platform/scroll/ScrollView.h"
#include "platform/scroll/ScrollableArea.h"
#include "platform/scroll/ScrollbarTheme.h"
#include "platform/scroll/ScrollbarThemeMacCommon.h"
#include "platform/scroll/ScrollbarThemeMacOverlayAPI.h"
#include "wtf/MainThread.h"
-#include "wtf/PassOwnPtr.h"
+#include "wtf/PassRefPtr.h"
-using namespace WebCore;
-using namespace std;
+using namespace blink;
static bool supportsUIStateTransitionProgress()
{
@interface WebScrollAnimationHelperDelegate : NSObject
{
- WebCore::ScrollAnimatorMac* _animator;
+ blink::ScrollAnimatorMac* _animator;
}
-- (id)initWithScrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator;
+- (id)initWithScrollAnimator:(blink::ScrollAnimatorMac*)scrollAnimator;
@end
static NSSize abs(NSSize size)
@implementation WebScrollAnimationHelperDelegate
-- (id)initWithScrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator
+- (id)initWithScrollAnimator:(blink::ScrollAnimatorMac*)scrollAnimator
{
self = [super init];
if (!self)
if (!_animator)
return NSZeroRect;
- WebCore::FloatPoint currentPosition = _animator->currentPosition();
+ blink::FloatPoint currentPosition = _animator->currentPosition();
return NSMakeRect(currentPosition.x(), currentPosition.y(), 0, 0);
}
if (!_scrollableArea)
return NSZeroRect;
- WebCore::IntSize contentsSize = _scrollableArea->contentsSize();
+ blink::IntSize contentsSize = _scrollableArea->contentsSize();
return NSMakeRect(0, 0, contentsSize.width(), contentsSize.height());
}
if (!_scrollableArea || !scrollerImp)
return NSZeroPoint;
- WebCore::Scrollbar* scrollbar = 0;
+ blink::Scrollbar* scrollbar = 0;
if ([scrollerImp isHorizontal])
scrollbar = _scrollableArea->horizontalScrollbar();
else
ASSERT(scrollerImp == scrollbarPainterForScrollbar(scrollbar));
- return scrollbar->convertFromContainingView(WebCore::IntPoint(pointInContentArea));
+ return scrollbar->convertFromContainingView(blink::IntPoint(pointInContentArea));
}
- (void)scrollerImpPair:(id)scrollerImpPair setContentAreaNeedsDisplayInRect:(NSRect)rect
ExpansionTransition
};
-@interface WebScrollbarPartAnimation : NSAnimation
-{
+@class WebScrollbarPartAnimation;
+
+namespace blink {
+
+// This class is used to drive the animation timer for WebScrollbarPartAnimation
+// objects. This is used instead of NSAnimation because CoreAnimation
+// establishes connections to the WindowServer, which should not be done in a
+// sandboxed renderer process.
+class WebScrollbarPartAnimationTimer {
+public:
+ WebScrollbarPartAnimationTimer(WebScrollbarPartAnimation* animation,
+ CFTimeInterval duration)
+ : m_timer(this, &WebScrollbarPartAnimationTimer::timerFired)
+ , m_startTime(0.0)
+ , m_duration(duration)
+ , m_animation(animation)
+ , m_timingFunction(CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseInOut))
+ {
+ }
+
+ ~WebScrollbarPartAnimationTimer() {}
+
+ void start()
+ {
+ m_startTime = WTF::currentTime();
+ // Set the framerate of the animation. NSAnimation uses a default
+ // framerate of 60 Hz, so use that here.
+ m_timer.startRepeating(1.0 / 60.0, FROM_HERE);
+ }
+
+ void stop()
+ {
+ m_timer.stop();
+ [m_animation setCurrentProgress:1];
+ }
+
+ void setDuration(CFTimeInterval duration)
+ {
+ m_duration = duration;
+ }
+
+private:
+ void timerFired(Timer<WebScrollbarPartAnimationTimer>*)
+ {
+ double currentTime = WTF::currentTime();
+ double delta = currentTime - m_startTime;
+
+ if (delta >= m_duration) {
+ stop();
+ return;
+ }
+
+ double fraction = delta / m_duration;
+ double progress = m_timingFunction->evaluate(fraction, 0.001);
+ [m_animation setCurrentProgress:progress];
+ }
+
+ Timer<WebScrollbarPartAnimationTimer> m_timer;
+ double m_startTime; // In seconds.
+ double m_duration; // In seconds.
+ WebScrollbarPartAnimation* m_animation; // Weak, owns this.
+ RefPtr<CubicBezierTimingFunction> m_timingFunction;
+};
+
+} // namespace blink
+
+@interface WebScrollbarPartAnimation : NSObject {
Scrollbar* _scrollbar;
+ OwnPtr<WebScrollbarPartAnimationTimer> _timer;
RetainPtr<ScrollbarPainter> _scrollbarPainter;
FeatureToAnimate _featureToAnimate;
CGFloat _startValue;
- (id)initWithScrollbar:(Scrollbar*)scrollbar featureToAnimate:(FeatureToAnimate)featureToAnimate animateFrom:(CGFloat)startValue animateTo:(CGFloat)endValue duration:(NSTimeInterval)duration
{
- self = [super initWithDuration:duration animationCurve:NSAnimationEaseInOut];
+ self = [super init];
if (!self)
return nil;
+ _timer = adoptPtr(new WebScrollbarPartAnimationTimer(self, duration));
_scrollbar = scrollbar;
_featureToAnimate = featureToAnimate;
_startValue = startValue;
_endValue = endValue;
- [self setAnimationBlockingMode:NSAnimationNonblocking];
-
return self;
}
ASSERT(_scrollbar);
_scrollbarPainter = scrollbarPainterForScrollbar(_scrollbar);
+ _timer->start();
+}
+
+- (void)stopAnimation
+{
+ _timer->stop();
+}
- [super startAnimation];
+- (void)setDuration:(CFTimeInterval)duration
+{
+ _timer->setDuration(duration);
}
- (void)setStartValue:(CGFloat)startValue
- (void)setCurrentProgress:(NSAnimationProgress)progress
{
- [super setCurrentProgress:progress];
-
ASSERT(_scrollbar);
CGFloat currentValue;
@interface WebScrollbarPainterDelegate : NSObject<NSAnimationDelegate>
{
- WebCore::Scrollbar* _scrollbar;
+ blink::Scrollbar* _scrollbar;
RetainPtr<WebScrollbarPartAnimation> _knobAlphaAnimation;
RetainPtr<WebScrollbarPartAnimation> _trackAlphaAnimation;
RetainPtr<WebScrollbarPartAnimation> _uiStateTransitionAnimation;
RetainPtr<WebScrollbarPartAnimation> _expansionTransitionAnimation;
}
-- (id)initWithScrollbar:(WebCore::Scrollbar*)scrollbar;
+- (id)initWithScrollbar:(blink::Scrollbar*)scrollbar;
- (void)cancelAnimations;
@end
@implementation WebScrollbarPainterDelegate
-- (id)initWithScrollbar:(WebCore::Scrollbar*)scrollbar
+- (id)initWithScrollbar:(blink::Scrollbar*)scrollbar
{
self = [super init];
if (!self)
return _scrollbar->convertFromContainingView(_scrollbar->scrollableArea()->lastKnownMousePosition());
}
-- (void)setUpAlphaAnimation:(RetainPtr<WebScrollbarPartAnimation>&)scrollbarPartAnimation scrollerPainter:(ScrollbarPainter)scrollerPainter part:(WebCore::ScrollbarPart)part animateAlphaTo:(CGFloat)newAlpha duration:(NSTimeInterval)duration
+- (void)setUpAlphaAnimation:(RetainPtr<WebScrollbarPartAnimation>&)scrollbarPartAnimation scrollerPainter:(ScrollbarPainter)scrollerPainter part:(blink::ScrollbarPart)part animateAlphaTo:(CGFloat)newAlpha duration:(NSTimeInterval)duration
{
// If the user has scrolled the page, then the scrollbars must be animated here.
// This overrides the early returns.
// If we are currently animating, stop
if (scrollbarPartAnimation) {
[scrollbarPartAnimation.get() stopAnimation];
- scrollbarPartAnimation = nil;
+ scrollbarPartAnimation = nullptr;
}
- if (part == WebCore::ThumbPart && _scrollbar->orientation() == VerticalScrollbar) {
+ if (part == blink::ThumbPart && _scrollbar->orientation() == VerticalScrollbar) {
if (newAlpha == 1) {
IntRect thumbRect = IntRect([scrollerPainter rectForPart:NSScrollerKnob]);
[self scrollAnimator]->setVisibleScrollerThumbRect(thumbRect);
ASSERT(scrollerImp == scrollbarPainterForScrollbar(_scrollbar));
ScrollbarPainter scrollerPainter = (ScrollbarPainter)scrollerImp;
- [self setUpAlphaAnimation:_knobAlphaAnimation scrollerPainter:scrollerPainter part:WebCore::ThumbPart animateAlphaTo:newKnobAlpha duration:duration];
+ [self setUpAlphaAnimation:_knobAlphaAnimation scrollerPainter:scrollerPainter part:blink::ThumbPart animateAlphaTo:newKnobAlpha duration:duration];
}
- (void)scrollerImp:(id)scrollerImp animateTrackAlphaTo:(CGFloat)newTrackAlpha duration:(NSTimeInterval)duration
ASSERT(scrollerImp == scrollbarPainterForScrollbar(_scrollbar));
ScrollbarPainter scrollerPainter = (ScrollbarPainter)scrollerImp;
- [self setUpAlphaAnimation:_trackAlphaAnimation scrollerPainter:scrollerPainter part:WebCore::BackTrackPart animateAlphaTo:newTrackAlpha duration:duration];
+ [self setUpAlphaAnimation:_trackAlphaAnimation scrollerPainter:scrollerPainter part:blink::BackTrackPart animateAlphaTo:newTrackAlpha duration:duration];
}
- (void)scrollerImp:(id)scrollerImp animateUIStateTransitionWithDuration:(NSTimeInterval)duration
@end
-namespace WebCore {
+namespace blink {
-PassOwnPtr<ScrollAnimator> ScrollAnimator::create(ScrollableArea* scrollableArea)
+PassRefPtr<ScrollAnimator> ScrollAnimator::create(ScrollableArea* scrollableArea)
{
- return adoptPtr(new ScrollAnimatorMac(scrollableArea));
+ return adoptRef(new ScrollAnimatorMac(scrollableArea));
}
ScrollAnimatorMac::ScrollAnimatorMac(ScrollableArea* scrollableArea)
IntPoint minPos = m_scrollableArea->minimumScrollPosition();
IntPoint maxPos = m_scrollableArea->maximumScrollPosition();
- float newX = max<float>(min<float>(position.x(), maxPos.x()), minPos.x());
- float newY = max<float>(min<float>(position.y(), maxPos.y()), minPos.y());
+ float newX = std::max<float>(std::min<float>(position.x(), maxPos.x()), minPos.x());
+ float newY = std::max<float>(std::min<float>(position.y(), maxPos.y()), minPos.y());
return FloatPoint(newX, newY);
}
+void ScrollAnimatorMac::adjustScrollPositionToBoundsIfNecessary()
+{
+ bool currentlyConstrainsToContentEdge = m_scrollableArea->constrainsScrollingToContentEdge();
+ m_scrollableArea->setConstrainsScrollingToContentEdge(true);
+
+ IntPoint currentScrollPosition = absoluteScrollPosition();
+ FloatPoint nearestPointWithinBounds = adjustScrollPositionIfNecessary(absoluteScrollPosition());
+ immediateScrollBy(nearestPointWithinBounds - currentScrollPosition);
+
+ m_scrollableArea->setConstrainsScrollingToContentEdge(currentlyConstrainsToContentEdge);
+}
+
void ScrollAnimatorMac::immediateScrollTo(const FloatPoint& newPosition)
{
FloatPoint adjustedPosition = adjustScrollPositionIfNecessary(newPosition);
m_currentPosX = adjustedPosition.x();
m_currentPosY = adjustedPosition.y();
- notifyPositionChanged(delta);
+ notifyContentAreaScrolled(delta);
+ notifyPositionChanged();
}
bool ScrollAnimatorMac::isRubberBandInProgress() const
immediateScrollTo(newPosition);
}
-void ScrollAnimatorMac::notifyPositionChanged(const FloatSize& delta)
-{
- notifyContentAreaScrolled(delta);
- ScrollAnimator::notifyPositionChanged(delta);
-}
-
void ScrollAnimatorMac::contentAreaWillPaint() const
{
if (!scrollableArea()->scrollbarsCanBeActive())
return scrollbar->enabled();
}
-bool ScrollAnimatorMac::shouldRubberBandInDirection(ScrollDirection direction)
-{
- return m_scrollableArea->shouldRubberBandInDirection(direction);
-}
-
IntPoint ScrollAnimatorMac::absoluteScrollPosition()
{
return m_scrollableArea->visibleContentRect().location() + m_scrollableArea->scrollOrigin();
m_currentPosX = newPos.x();
m_currentPosY = newPos.y();
- notifyPositionChanged(adjustedDelta);
+ notifyContentAreaScrolled(adjustedDelta);
+ notifyPositionChanged();
}
void ScrollAnimatorMac::startSnapRubberbandTimer()
// If m_needsScrollerStyleUpdate is true, then the page is restoring from the page cache, and
// a relayout will happen on its own. Otherwise, we must initiate a re-layout ourselves.
- scrollableArea()->scrollbarStyleChanged(newStyle, !m_needsScrollerStyleUpdate);
+ if (!m_needsScrollerStyleUpdate)
+ scrollableArea()->scrollbarStyleChanged();
m_needsScrollerStyleUpdate = false;
}
return ScrollbarThemeMacCommon::isOverlayAPIAvailable();
}
-} // namespace WebCore
+} // namespace blink