2 * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/sysctl.h>
31 #include "ScrollAnimatorChromiumMac.h"
33 #include "FloatPoint.h"
34 #include "PlatformGestureEvent.h"
35 #include "PlatformWheelEvent.h"
36 #include "ScrollView.h"
37 #include "ScrollableArea.h"
38 #include "ScrollbarTheme.h"
39 #include "ScrollbarThemeChromiumMac.h"
40 #include "WebCoreSystemInterface.h"
41 #include <wtf/PassOwnPtr.h>
42 #include <wtf/UnusedParam.h>
43 #include <QuartzCore/QuartzCore.h>
45 using namespace WebCore;
48 #if !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
49 @protocol NSAnimationDelegate
52 @interface NSProcessInfo (ScrollAnimatorChromiumMacExt)
53 - (NSTimeInterval)systemUptime;
56 @implementation NSProcessInfo (ScrollAnimatorChromiumMacExt)
57 - (NSTimeInterval)systemUptime
59 // Get how long system has been up. Found by looking getting "boottime" from the kernel.
60 static struct timeval boottime = {0};
61 if (!boottime.tv_sec) {
62 int mib[2] = {CTL_KERN, KERN_BOOTTIME};
63 size_t size = sizeof(boottime);
64 if (-1 == sysctl(mib, 2, &boottime, &size, 0, 0))
68 if (boottime.tv_sec && -1 != gettimeofday(&now, 0)) {
69 struct timeval uptime;
70 timersub(&now, &boottime, &uptime);
71 NSTimeInterval result = uptime.tv_sec + (uptime.tv_usec / 1E+6);
79 @interface NSObject (ScrollAnimationHelperDetails)
80 - (id)initWithDelegate:(id)delegate;
83 - (NSPoint)targetOrigin;
87 @interface ScrollAnimationHelperDelegate : NSObject
89 WebCore::ScrollAnimatorChromiumMac* _animator;
91 - (id)initWithScrollAnimator:(WebCore::ScrollAnimatorChromiumMac*)scrollAnimator;
94 static NSSize abs(NSSize size)
96 NSSize finalSize = size;
97 if (finalSize.width < 0)
98 finalSize.width = -finalSize.width;
99 if (finalSize.height < 0)
100 finalSize.height = -finalSize.height;
104 @implementation ScrollAnimationHelperDelegate
106 - (id)initWithScrollAnimator:(WebCore::ScrollAnimatorChromiumMac*)scrollAnimator
112 _animator = scrollAnimator;
116 - (void)scrollAnimatorDestroyed
126 WebCore::FloatPoint currentPosition = _animator->currentPosition();
127 return NSMakeRect(currentPosition.x(), currentPosition.y(), 0, 0);
130 - (void)_immediateScrollToPoint:(NSPoint)newPosition
134 _animator->immediateScrollToPointForScrollAnimation(newPosition);
137 - (NSPoint)_pixelAlignProposedScrollPosition:(NSPoint)newOrigin
142 - (NSSize)convertSizeToBase:(NSSize)size
147 - (NSSize)convertSizeFromBase:(NSSize)size
152 - (NSSize)convertSizeToBacking:(NSSize)size
157 - (NSSize)convertSizeFromBacking:(NSSize)size
177 - (void)_recursiveRecomputeToolTips
183 #if USE(WK_SCROLLBAR_PAINTER)
185 @interface ScrollbarPainterControllerDelegate : NSObject
187 WebCore::ScrollAnimatorChromiumMac* _animator;
189 - (id)initWithScrollAnimator:(WebCore::ScrollAnimatorChromiumMac*)scrollAnimator;
192 @implementation ScrollbarPainterControllerDelegate
194 - (id)initWithScrollAnimator:(WebCore::ScrollAnimatorChromiumMac*)scrollAnimator
200 _animator = scrollAnimator;
204 - (void)scrollAnimatorDestroyed
209 - (NSRect)contentAreaRectForScrollerImpPair:(id)scrollerImpPair
211 UNUSED_PARAM(scrollerImpPair);
215 WebCore::IntSize contentsSize = _animator->scrollableArea()->contentsSize();
216 return NSMakeRect(0, 0, contentsSize.width(), contentsSize.height());
219 - (BOOL)inLiveResizeForScrollerImpPair:(id)scrollerImpPair
221 UNUSED_PARAM(scrollerImpPair);
225 return _animator->scrollableArea()->inLiveResize();
228 - (NSPoint)mouseLocationInContentAreaForScrollerImpPair:(id)scrollerImpPair
230 UNUSED_PARAM(scrollerImpPair);
234 return _animator->scrollableArea()->currentMousePosition();
237 - (NSPoint)scrollerImpPair:(id)scrollerImpPair convertContentPoint:(NSPoint)pointInContentArea toScrollerImp:(id)scrollerImp
239 UNUSED_PARAM(scrollerImpPair);
243 WebCore::Scrollbar* scrollbar = 0;
244 if (wkScrollbarPainterIsHorizontal((WKScrollbarPainterRef)scrollerImp))
245 scrollbar = _animator->scrollableArea()->horizontalScrollbar();
247 scrollbar = _animator->scrollableArea()->verticalScrollbar();
249 // It is possible to have a null scrollbar here since it is possible for this delegate
250 // method to be called between the moment when a scrollbar has been set to 0 and the
251 // moment when its destructor has been called. We should probably de-couple some
252 // of the clean-up work in ScrollbarThemeChromiumMac::unregisterScrollbar() to avoid this
255 return WebCore::IntPoint();
257 return scrollbar->convertFromContainingView(WebCore::IntPoint(pointInContentArea));
260 - (void)scrollerImpPair:(id)scrollerImpPair setContentAreaNeedsDisplayInRect:(NSRect)rect
262 UNUSED_PARAM(scrollerImpPair);
266 - (void)scrollerImpPair:(id)scrollerImpPair updateScrollerStyleForNewRecommendedScrollerStyle:(NSScrollerStyle)newRecommendedScrollerStyle
271 wkSetScrollbarPainterControllerStyle((WKScrollbarPainterControllerRef)scrollerImpPair, newRecommendedScrollerStyle);
272 _animator->updateScrollerStyle();
277 @interface ScrollbarPartAnimation : NSAnimation
279 RetainPtr<WKScrollbarPainterRef> _scrollerPainter;
280 WebCore::ScrollbarPart _part;
281 WebCore::ScrollAnimatorChromiumMac* _animator;
282 CGFloat _initialAlpha;
285 - (id)initWithScrollbarPainter:(WKScrollbarPainterRef)scrollerPainter part:(WebCore::ScrollbarPart)part scrollAnimator:(WebCore::ScrollAnimatorChromiumMac*)scrollAnimator animateAlphaTo:(CGFloat)newAlpha duration:(NSTimeInterval)duration;
288 @implementation ScrollbarPartAnimation
290 - (id)initWithScrollbarPainter:(WKScrollbarPainterRef)scrollerPainter part:(WebCore::ScrollbarPart)part scrollAnimator:(WebCore::ScrollAnimatorChromiumMac*)scrollAnimator animateAlphaTo:(CGFloat)newAlpha duration:(NSTimeInterval)duration
292 self = [super initWithDuration:duration animationCurve:NSAnimationEaseInOut];
296 _scrollerPainter = scrollerPainter;
298 _animator = scrollAnimator;
299 _initialAlpha = _part == WebCore::ThumbPart ? wkScrollbarPainterKnobAlpha(_scrollerPainter.get()) : wkScrollbarPainterTrackAlpha(_scrollerPainter.get());
300 _newAlpha = newAlpha;
305 - (void)setCurrentProgress:(NSAnimationProgress)progress
307 [super setCurrentProgress:progress];
312 CGFloat currentAlpha;
313 if (_initialAlpha > _newAlpha)
314 currentAlpha = 1 - progress;
316 currentAlpha = progress;
318 if (_part == WebCore::ThumbPart)
319 wkSetScrollbarPainterKnobAlpha(_scrollerPainter.get(), currentAlpha);
321 wkSetScrollbarPainterTrackAlpha(_scrollerPainter.get(), currentAlpha);
323 // Invalidate the scrollbars so that they paint the animation
324 if (WebCore::Scrollbar* verticalScrollbar = _animator->scrollableArea()->verticalScrollbar())
325 verticalScrollbar->invalidateRect(WebCore::IntRect(0, 0, verticalScrollbar->width(), verticalScrollbar->height()));
326 if (WebCore::Scrollbar* horizontalScrollbar = _animator->scrollableArea()->horizontalScrollbar())
327 horizontalScrollbar->invalidateRect(WebCore::IntRect(0, 0, horizontalScrollbar->width(), horizontalScrollbar->height()));
330 - (void)scrollAnimatorDestroyed
332 [self stopAnimation];
338 @interface ScrollbarPainterDelegate : NSObject<NSAnimationDelegate>
340 WebCore::ScrollAnimatorChromiumMac* _animator;
342 RetainPtr<ScrollbarPartAnimation> _verticalKnobAnimation;
343 RetainPtr<ScrollbarPartAnimation> _horizontalKnobAnimation;
345 RetainPtr<ScrollbarPartAnimation> _verticalTrackAnimation;
346 RetainPtr<ScrollbarPartAnimation> _horizontalTrackAnimation;
348 - (id)initWithScrollAnimator:(WebCore::ScrollAnimatorChromiumMac*)scrollAnimator;
349 - (void)cancelAnimations;
352 @implementation ScrollbarPainterDelegate
354 - (id)initWithScrollAnimator:(WebCore::ScrollAnimatorChromiumMac*)scrollAnimator
360 _animator = scrollAnimator;
364 - (void)cancelAnimations
366 [_verticalKnobAnimation.get() stopAnimation];
367 [_horizontalKnobAnimation.get() stopAnimation];
368 [_verticalTrackAnimation.get() stopAnimation];
369 [_horizontalTrackAnimation.get() stopAnimation];
372 - (NSRect)convertRectToBacking:(NSRect)aRect
377 - (NSRect)convertRectFromBacking:(NSRect)aRect
382 #if !PLATFORM(CHROMIUM)
387 if (!_animator->isDrawingIntoLayer())
390 // FIXME: This should attempt to return an actual layer.
391 static CALayer *dummyLayer = [[CALayer alloc] init];
396 - (void)setUpAnimation:(RetainPtr<ScrollbarPartAnimation>&)scrollbarPartAnimation scrollerPainter:(WKScrollbarPainterRef)scrollerPainter part:(WebCore::ScrollbarPart)part animateAlphaTo:(CGFloat)newAlpha duration:(NSTimeInterval)duration
398 // If the user has scrolled the page, then the scrollbars must be animated here.
399 // This overrides the early returns.
400 bool mustAnimate = _animator->haveScrolledSincePageLoad();
402 if (_animator->scrollbarPaintTimerIsActive() && !mustAnimate)
405 if (_animator->scrollableArea()->shouldSuspendScrollAnimations() && !mustAnimate) {
406 _animator->startScrollbarPaintTimer();
410 // At this point, we are definitely going to animate now, so stop the timer.
411 _animator->stopScrollbarPaintTimer();
413 // If we are currently animating, stop
414 if (scrollbarPartAnimation) {
415 [scrollbarPartAnimation.get() stopAnimation];
416 scrollbarPartAnimation = nil;
419 if (part == WebCore::ThumbPart && !wkScrollbarPainterIsHorizontal(scrollerPainter)) {
421 IntRect thumbRect = IntRect(wkScrollbarPainterKnobRect(scrollerPainter));
422 _animator->setVisibleScrollerThumbRect(thumbRect);
424 _animator->setVisibleScrollerThumbRect(IntRect());
427 [NSAnimationContext beginGrouping];
428 [[NSAnimationContext currentContext] setDuration:duration];
429 scrollbarPartAnimation.adoptNS([[ScrollbarPartAnimation alloc] initWithScrollbarPainter:scrollerPainter
431 scrollAnimator:_animator
432 animateAlphaTo:newAlpha
434 [scrollbarPartAnimation.get() setAnimationBlockingMode:NSAnimationNonblocking];
435 [scrollbarPartAnimation.get() startAnimation];
436 [NSAnimationContext endGrouping];
439 - (void)scrollerImp:(id)scrollerImp animateKnobAlphaTo:(CGFloat)newKnobAlpha duration:(NSTimeInterval)duration
444 WKScrollbarPainterRef scrollerPainter = (WKScrollbarPainterRef)scrollerImp;
445 if (wkScrollbarPainterIsHorizontal(scrollerPainter))
446 [self setUpAnimation:_horizontalKnobAnimation scrollerPainter:scrollerPainter part:WebCore::ThumbPart animateAlphaTo:newKnobAlpha duration:duration];
448 [self setUpAnimation:_verticalKnobAnimation scrollerPainter:scrollerPainter part:WebCore::ThumbPart animateAlphaTo:newKnobAlpha duration:duration];
451 - (void)scrollerImp:(id)scrollerImp animateTrackAlphaTo:(CGFloat)newTrackAlpha duration:(NSTimeInterval)duration
456 WKScrollbarPainterRef scrollerPainter = (WKScrollbarPainterRef)scrollerImp;
457 if (wkScrollbarPainterIsHorizontal(scrollerPainter))
458 [self setUpAnimation:_horizontalTrackAnimation scrollerPainter:scrollerPainter part:WebCore::BackTrackPart animateAlphaTo:newTrackAlpha duration:duration];
460 [self setUpAnimation:_verticalTrackAnimation scrollerPainter:scrollerPainter part:WebCore::BackTrackPart animateAlphaTo:newTrackAlpha duration:duration];
463 - (void)scrollerImp:(id)scrollerImp overlayScrollerStateChangedTo:(NSUInteger)newOverlayScrollerState
465 UNUSED_PARAM(scrollerImp);
466 UNUSED_PARAM(newOverlayScrollerState);
469 - (void)scrollAnimatorDestroyed
472 [_verticalKnobAnimation.get() scrollAnimatorDestroyed];
473 [_horizontalKnobAnimation.get() scrollAnimatorDestroyed];
474 [_verticalTrackAnimation.get() scrollAnimatorDestroyed];
475 [_horizontalTrackAnimation.get() scrollAnimatorDestroyed];
480 #endif // USE(WK_SCROLLBAR_PAINTER)
484 PassOwnPtr<ScrollAnimator> ScrollAnimator::create(ScrollableArea* scrollableArea)
486 return adoptPtr(new ScrollAnimatorChromiumMac(scrollableArea));
489 static ScrollbarThemeChromiumMac* chromiumScrollbarTheme()
491 ScrollbarTheme* scrollbarTheme = ScrollbarTheme::theme();
492 return !scrollbarTheme->isMockTheme() ? static_cast<ScrollbarThemeChromiumMac*>(scrollbarTheme) : 0;
495 ScrollAnimatorChromiumMac::ScrollAnimatorChromiumMac(ScrollableArea* scrollableArea)
496 : ScrollAnimator(scrollableArea)
497 #if USE(WK_SCROLLBAR_PAINTER)
498 , m_initialScrollbarPaintTimer(this, &ScrollAnimatorChromiumMac::initialScrollbarPaintTimerFired)
500 #if ENABLE(RUBBER_BANDING)
501 , m_inScrollGesture(false)
502 , m_momentumScrollInProgress(false)
503 , m_ignoreMomentumScrolls(false)
504 , m_lastMomentumScrollTimestamp(0)
506 , m_snapRubberBandTimer(this, &ScrollAnimatorChromiumMac::snapRubberBandTimerFired)
508 , m_drawingIntoLayer(false)
509 , m_haveScrolledSincePageLoad(false)
510 , m_needsScrollerStyleUpdate(false)
512 m_scrollAnimationHelperDelegate.adoptNS([[ScrollAnimationHelperDelegate alloc] initWithScrollAnimator:this]);
513 m_scrollAnimationHelper.adoptNS([[NSClassFromString(@"NSScrollAnimationHelper") alloc] initWithDelegate:m_scrollAnimationHelperDelegate.get()]);
515 if (isScrollbarOverlayAPIAvailable()) {
516 m_scrollbarPainterControllerDelegate.adoptNS([[ScrollbarPainterControllerDelegate alloc] initWithScrollAnimator:this]);
517 m_scrollbarPainterController = wkMakeScrollbarPainterController(m_scrollbarPainterControllerDelegate.get());
518 m_scrollbarPainterDelegate.adoptNS([[ScrollbarPainterDelegate alloc] initWithScrollAnimator:this]);
522 ScrollAnimatorChromiumMac::~ScrollAnimatorChromiumMac()
524 if (isScrollbarOverlayAPIAvailable()) {
525 [m_scrollbarPainterControllerDelegate.get() scrollAnimatorDestroyed];
526 [(id)m_scrollbarPainterController.get() setDelegate:nil];
527 [m_scrollbarPainterDelegate.get() scrollAnimatorDestroyed];
528 [m_scrollAnimationHelperDelegate.get() scrollAnimatorDestroyed];
532 bool ScrollAnimatorChromiumMac::scroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float multiplier)
534 m_haveScrolledSincePageLoad = true;
536 #if !ENABLE(SMOOTH_SCROLLING)
537 return ScrollAnimator::scroll(orientation, granularity, step, multiplier);
540 if (![[NSUserDefaults standardUserDefaults] boolForKey:@"AppleScrollAnimationEnabled"] || !m_scrollableArea->scrollAnimatorEnabled())
541 return ScrollAnimator::scroll(orientation, granularity, step, multiplier);
543 if (granularity == ScrollByPixel)
544 return ScrollAnimator::scroll(orientation, granularity, step, multiplier);
546 float currentPos = orientation == HorizontalScrollbar ? m_currentPosX : m_currentPosY;
547 float newPos = std::max<float>(std::min<float>(currentPos + (step * multiplier), static_cast<float>(m_scrollableArea->scrollSize(orientation))), 0);
548 if (currentPos == newPos)
552 if ([m_scrollAnimationHelper.get() _isAnimating]) {
553 NSPoint targetOrigin = [m_scrollAnimationHelper.get() targetOrigin];
554 newPoint = orientation == HorizontalScrollbar ? NSMakePoint(newPos, targetOrigin.y) : NSMakePoint(targetOrigin.x, newPos);
556 newPoint = orientation == HorizontalScrollbar ? NSMakePoint(newPos, m_currentPosY) : NSMakePoint(m_currentPosX, newPos);
557 m_scrollableArea->didStartAnimatedScroll();
559 [m_scrollAnimationHelper.get() scrollToPoint:newPoint];
563 void ScrollAnimatorChromiumMac::scrollToOffsetWithoutAnimation(const FloatPoint& offset)
565 [m_scrollAnimationHelper.get() _stopRun];
566 immediateScrollToPoint(offset);
569 float ScrollAnimatorChromiumMac::adjustScrollXPositionIfNecessary(float position) const
571 if (!m_scrollableArea->constrainsScrollingToContentEdge())
574 return max<float>(min<float>(position, m_scrollableArea->contentsSize().width() - m_scrollableArea->visibleWidth()), 0);
577 float ScrollAnimatorChromiumMac::adjustScrollYPositionIfNecessary(float position) const
579 if (!m_scrollableArea->constrainsScrollingToContentEdge())
582 return max<float>(min<float>(position, m_scrollableArea->contentsSize().height() - m_scrollableArea->visibleHeight()), 0);
585 FloatPoint ScrollAnimatorChromiumMac::adjustScrollPositionIfNecessary(const FloatPoint& position) const
587 if (!m_scrollableArea->constrainsScrollingToContentEdge())
590 float newX = max<float>(min<float>(position.x(), m_scrollableArea->contentsSize().width() - m_scrollableArea->visibleWidth()), 0);
591 float newY = max<float>(min<float>(position.y(), m_scrollableArea->contentsSize().height() - m_scrollableArea->visibleHeight()), 0);
593 return FloatPoint(newX, newY);
596 void ScrollAnimatorChromiumMac::immediateScrollToPoint(const FloatPoint& newPosition)
598 FloatPoint adjustedPosition = adjustScrollPositionIfNecessary(newPosition);
600 m_currentPosX = adjustedPosition.x();
601 m_currentPosY = adjustedPosition.y();
602 notifyPositionChanged();
605 void ScrollAnimatorChromiumMac::immediateScrollByDeltaX(float deltaX)
607 float newPosX = adjustScrollXPositionIfNecessary(m_currentPosX + deltaX);
609 if (newPosX == m_currentPosX)
612 m_currentPosX = newPosX;
613 notifyPositionChanged();
616 void ScrollAnimatorChromiumMac::immediateScrollByDeltaY(float deltaY)
618 float newPosY = adjustScrollYPositionIfNecessary(m_currentPosY + deltaY);
620 if (newPosY == m_currentPosY)
623 m_currentPosY = newPosY;
624 notifyPositionChanged();
627 void ScrollAnimatorChromiumMac::immediateScrollToPointForScrollAnimation(const FloatPoint& newPosition)
629 ASSERT(m_scrollAnimationHelper);
630 CGFloat progress = [m_scrollAnimationHelper.get() _progress];
632 immediateScrollToPoint(newPosition);
635 m_scrollableArea->didCompleteAnimatedScroll();
638 void ScrollAnimatorChromiumMac::notifyPositionChanged()
640 if (isScrollbarOverlayAPIAvailable())
641 wkContentAreaScrolled(m_scrollbarPainterController.get());
642 ScrollAnimator::notifyPositionChanged();
645 void ScrollAnimatorChromiumMac::contentAreaWillPaint() const
647 if (isScrollbarOverlayAPIAvailable())
648 wkContentAreaWillPaint(m_scrollbarPainterController.get());
651 void ScrollAnimatorChromiumMac::mouseEnteredContentArea() const
653 if (isScrollbarOverlayAPIAvailable())
654 wkMouseEnteredContentArea(m_scrollbarPainterController.get());
657 void ScrollAnimatorChromiumMac::mouseExitedContentArea() const
659 if (isScrollbarOverlayAPIAvailable())
660 wkMouseExitedContentArea(m_scrollbarPainterController.get());
663 void ScrollAnimatorChromiumMac::mouseMovedInContentArea() const
665 if (isScrollbarOverlayAPIAvailable())
666 wkMouseMovedInContentArea(m_scrollbarPainterController.get());
669 void ScrollAnimatorChromiumMac::willStartLiveResize()
671 if (isScrollbarOverlayAPIAvailable())
672 wkWillStartLiveResize(m_scrollbarPainterController.get());
675 void ScrollAnimatorChromiumMac::contentsResized() const
677 if (isScrollbarOverlayAPIAvailable())
678 wkContentAreaResized(m_scrollbarPainterController.get());
681 void ScrollAnimatorChromiumMac::willEndLiveResize()
683 if (isScrollbarOverlayAPIAvailable())
684 wkWillEndLiveResize(m_scrollbarPainterController.get());
687 void ScrollAnimatorChromiumMac::contentAreaDidShow() const
689 if (isScrollbarOverlayAPIAvailable())
690 wkContentAreaDidShow(m_scrollbarPainterController.get());
693 void ScrollAnimatorChromiumMac::contentAreaDidHide() const
695 if (isScrollbarOverlayAPIAvailable())
696 wkContentAreaDidHide(m_scrollbarPainterController.get());
699 void ScrollAnimatorChromiumMac::didBeginScrollGesture() const
701 if (isScrollbarOverlayAPIAvailable())
702 wkDidBeginScrollGesture(m_scrollbarPainterController.get());
705 void ScrollAnimatorChromiumMac::didEndScrollGesture() const
707 if (isScrollbarOverlayAPIAvailable())
708 wkDidEndScrollGesture(m_scrollbarPainterController.get());
711 void ScrollAnimatorChromiumMac::didAddVerticalScrollbar(Scrollbar* scrollbar)
713 if (!isScrollbarOverlayAPIAvailable())
716 if (ScrollbarThemeChromiumMac* theme = chromiumScrollbarTheme()) {
717 WKScrollbarPainterRef painter = theme->painterForScrollbar(scrollbar);
718 wkScrollbarPainterSetDelegate(painter, m_scrollbarPainterDelegate.get());
719 wkSetPainterForPainterController(m_scrollbarPainterController.get(), painter, false);
720 if (scrollableArea()->inLiveResize())
721 wkSetScrollbarPainterKnobAlpha(painter, 1);
725 void ScrollAnimatorChromiumMac::willRemoveVerticalScrollbar(Scrollbar* scrollbar)
727 if (!isScrollbarOverlayAPIAvailable())
730 if (ScrollbarThemeChromiumMac* theme = chromiumScrollbarTheme()) {
731 WKScrollbarPainterRef painter = theme->painterForScrollbar(scrollbar);
732 wkScrollbarPainterSetDelegate(painter, nil);
733 wkSetPainterForPainterController(m_scrollbarPainterController.get(), nil, false);
737 void ScrollAnimatorChromiumMac::didAddHorizontalScrollbar(Scrollbar* scrollbar)
739 if (!isScrollbarOverlayAPIAvailable())
742 if (ScrollbarThemeChromiumMac* theme = chromiumScrollbarTheme()) {
743 WKScrollbarPainterRef painter = theme->painterForScrollbar(scrollbar);
744 wkScrollbarPainterSetDelegate(painter, m_scrollbarPainterDelegate.get());
745 wkSetPainterForPainterController(m_scrollbarPainterController.get(), painter, true);
746 if (scrollableArea()->inLiveResize())
747 wkSetScrollbarPainterKnobAlpha(painter, 1);
751 void ScrollAnimatorChromiumMac::willRemoveHorizontalScrollbar(Scrollbar* scrollbar)
753 if (!isScrollbarOverlayAPIAvailable())
756 if (ScrollbarThemeChromiumMac* theme = chromiumScrollbarTheme()) {
757 WKScrollbarPainterRef painter = theme->painterForScrollbar(scrollbar);
758 wkScrollbarPainterSetDelegate(painter, nil);
759 wkSetPainterForPainterController(m_scrollbarPainterController.get(), nil, true);
763 void ScrollAnimatorChromiumMac::cancelAnimations()
765 m_haveScrolledSincePageLoad = false;
767 if (isScrollbarOverlayAPIAvailable()) {
768 if (scrollbarPaintTimerIsActive())
769 stopScrollbarPaintTimer();
770 [m_scrollbarPainterDelegate.get() cancelAnimations];
774 #if ENABLE(RUBBER_BANDING)
776 static const float scrollVelocityZeroingTimeout = 0.10f;
777 static const float rubberbandStiffness = 20;
778 static const float rubberbandDirectionLockStretchRatio = 1;
779 static const float rubberbandMinimumRequiredDeltaBeforeStretch = 10;
780 static const float rubberbandAmplitude = 0.31f;
781 static const float rubberbandPeriod = 1.6f;
783 static float elasticDeltaForTimeDelta(float initialPosition, float initialVelocity, float elapsedTime)
785 float amplitude = rubberbandAmplitude;
786 float period = rubberbandPeriod;
787 float criticalDampeningFactor = expf((-elapsedTime * rubberbandStiffness) / period);
789 return (initialPosition + (-initialVelocity * elapsedTime * amplitude)) * criticalDampeningFactor;
792 static float elasticDeltaForReboundDelta(float delta)
794 float stiffness = std::max(rubberbandStiffness, 1.0f);
795 return delta / stiffness;
798 static float reboundDeltaForElasticDelta(float delta)
800 return delta * rubberbandStiffness;
803 static float scrollWheelMultiplier()
805 static float multiplier = -1;
806 if (multiplier < 0) {
807 multiplier = [[NSUserDefaults standardUserDefaults] floatForKey:@"NSScrollWheelMultiplier"];
814 static inline bool isScrollingLeftAndShouldNotRubberBand(const PlatformWheelEvent& wheelEvent, ScrollableArea* scrollableArea)
816 return wheelEvent.deltaX() > 0 && !scrollableArea->shouldRubberBandInDirection(ScrollLeft);
819 static inline bool isScrollingRightAndShouldNotRubberBand(const PlatformWheelEvent& wheelEvent, ScrollableArea* scrollableArea)
821 return wheelEvent.deltaX() < 0 && !scrollableArea->shouldRubberBandInDirection(ScrollRight);
824 bool ScrollAnimatorChromiumMac::handleWheelEvent(const PlatformWheelEvent& wheelEvent)
826 m_haveScrolledSincePageLoad = true;
828 if (!wheelEvent.hasPreciseScrollingDeltas())
829 return ScrollAnimator::handleWheelEvent(wheelEvent);
831 // FIXME: This is somewhat roundabout hack to allow forwarding wheel events
832 // up to the parent scrollable area. It takes advantage of the fact that
833 // the base class implemenatation of handleWheelEvent will not accept the
834 // wheel event if there is nowhere to scroll.
835 if (fabsf(wheelEvent.deltaY()) >= fabsf(wheelEvent.deltaX())) {
836 if (!allowsVerticalStretching())
837 return ScrollAnimator::handleWheelEvent(wheelEvent);
839 if (!allowsHorizontalStretching())
840 return ScrollAnimator::handleWheelEvent(wheelEvent);
842 if (m_scrollableArea->horizontalScrollbar()) {
843 // If there is a scrollbar, we aggregate the wheel events to get an
844 // overall trend of the scroll. If the direction of the scroll is ever
845 // in the opposite direction of the pin location, then we switch the
846 // boolean, and rubber band. That is, if we were pinned to the left,
847 // and we ended up scrolling to the right, we rubber band.
848 m_cumulativeHorizontalScroll += wheelEvent.deltaX();
849 if (m_scrollerInitiallyPinnedOnLeft && m_cumulativeHorizontalScroll < 0)
850 m_didCumulativeHorizontalScrollEverSwitchToOppositeDirectionOfPin = true;
851 if (m_scrollerInitiallyPinnedOnRight && m_cumulativeHorizontalScroll > 0)
852 m_didCumulativeHorizontalScrollEverSwitchToOppositeDirectionOfPin = true;
855 // After a gesture begins, we go through:
856 // 1+ PlatformWheelEventPhaseNone
857 // 0+ PlatformWheelEventPhaseChanged
858 // 1 PlatformWheelEventPhaseEnded if there was at least one changed event
859 if (wheelEvent.momentumPhase() == PlatformWheelEventPhaseNone && !m_didCumulativeHorizontalScrollEverSwitchToOppositeDirectionOfPin) {
860 if ((isScrollingLeftAndShouldNotRubberBand(wheelEvent, m_scrollableArea) &&
861 m_scrollerInitiallyPinnedOnLeft &&
862 m_scrollableArea->isHorizontalScrollerPinnedToMinimumPosition()) ||
863 (isScrollingRightAndShouldNotRubberBand(wheelEvent, m_scrollableArea) &&
864 m_scrollerInitiallyPinnedOnRight &&
865 m_scrollableArea->isHorizontalScrollerPinnedToMaximumPosition())) {
866 return ScrollAnimator::handleWheelEvent(wheelEvent);
871 bool isMomentumScrollEvent = (wheelEvent.momentumPhase() != PlatformWheelEventPhaseNone);
872 if (m_ignoreMomentumScrolls && (isMomentumScrollEvent || m_snapRubberBandTimer.isActive())) {
873 if (wheelEvent.momentumPhase() == PlatformWheelEventPhaseEnded) {
874 m_ignoreMomentumScrolls = false;
880 smoothScrollWithEvent(wheelEvent);
884 void ScrollAnimatorChromiumMac::handleGestureEvent(const PlatformGestureEvent& gestureEvent)
886 if (gestureEvent.type() == PlatformGestureEvent::ScrollBeginType)
887 beginScrollGesture();
888 else if (gestureEvent.type() == PlatformGestureEvent::ScrollEndType)
892 bool ScrollAnimatorChromiumMac::pinnedInDirection(float deltaX, float deltaY)
894 FloatSize limitDelta;
895 if (fabsf(deltaY) >= fabsf(deltaX)) {
897 // We are trying to scroll up. Make sure we are not pinned to the top
898 limitDelta.setHeight(m_scrollableArea->visibleContentRect().y() + + m_scrollableArea->scrollOrigin().y());
900 // We are trying to scroll down. Make sure we are not pinned to the bottom
901 limitDelta.setHeight(m_scrollableArea->contentsSize().height() - (m_scrollableArea->visibleContentRect().maxY() + m_scrollableArea->scrollOrigin().y()));
903 } else if (deltaX != 0) {
905 // We are trying to scroll left. Make sure we are not pinned to the left
906 limitDelta.setWidth(m_scrollableArea->visibleContentRect().x() + m_scrollableArea->scrollOrigin().x());
908 // We are trying to scroll right. Make sure we are not pinned to the right
909 limitDelta.setWidth(m_scrollableArea->contentsSize().width() - (m_scrollableArea->visibleContentRect().maxX() + m_scrollableArea->scrollOrigin().x()));
913 if ((deltaX != 0 || deltaY != 0) && (limitDelta.width() < 1 && limitDelta.height() < 1))
918 bool ScrollAnimatorChromiumMac::allowsVerticalStretching() const
920 switch (m_scrollableArea->verticalScrollElasticity()) {
921 case ScrollElasticityAutomatic: {
922 Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
923 Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
924 return (((vScroller && vScroller->enabled()) || (!hScroller || !hScroller->enabled())));
926 case ScrollElasticityNone:
928 case ScrollElasticityAllowed:
932 ASSERT_NOT_REACHED();
936 bool ScrollAnimatorChromiumMac::allowsHorizontalStretching() const
938 switch (m_scrollableArea->horizontalScrollElasticity()) {
939 case ScrollElasticityAutomatic: {
940 Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
941 Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
942 return (((hScroller && hScroller->enabled()) || (!vScroller || !vScroller->enabled())));
944 case ScrollElasticityNone:
946 case ScrollElasticityAllowed:
950 ASSERT_NOT_REACHED();
954 void ScrollAnimatorChromiumMac::smoothScrollWithEvent(const PlatformWheelEvent& wheelEvent)
956 m_haveScrolledSincePageLoad = true;
958 float deltaX = m_overflowScrollDelta.width();
959 float deltaY = m_overflowScrollDelta.height();
961 // Reset overflow values because we may decide to remove delta at various points and put it into overflow.
962 m_overflowScrollDelta = FloatSize();
964 float eventCoalescedDeltaX = -wheelEvent.deltaX();
965 float eventCoalescedDeltaY = -wheelEvent.deltaY();
967 deltaX += eventCoalescedDeltaX;
968 deltaY += eventCoalescedDeltaY;
970 // Slightly prefer scrolling vertically by applying the = case to deltaY
971 if (fabsf(deltaY) >= fabsf(deltaX))
976 bool isVerticallyStretched = false;
977 bool isHorizontallyStretched = false;
978 bool shouldStretch = false;
980 IntSize stretchAmount = m_scrollableArea->overhangAmount();
982 isHorizontallyStretched = stretchAmount.width();
983 isVerticallyStretched = stretchAmount.height();
985 PlatformWheelEventPhase phase = wheelEvent.momentumPhase();
987 // If we are starting momentum scrolling then do some setup.
988 if (!m_momentumScrollInProgress && (phase == PlatformWheelEventPhaseBegan || phase == PlatformWheelEventPhaseChanged))
989 m_momentumScrollInProgress = true;
991 CFTimeInterval timeDelta = wheelEvent.timestamp() - m_lastMomentumScrollTimestamp;
992 if (m_inScrollGesture || m_momentumScrollInProgress) {
993 if (m_lastMomentumScrollTimestamp && timeDelta > 0 && timeDelta < scrollVelocityZeroingTimeout) {
994 m_momentumVelocity.setWidth(eventCoalescedDeltaX / (float)timeDelta);
995 m_momentumVelocity.setHeight(eventCoalescedDeltaY / (float)timeDelta);
996 m_lastMomentumScrollTimestamp = wheelEvent.timestamp();
998 m_lastMomentumScrollTimestamp = wheelEvent.timestamp();
999 m_momentumVelocity = FloatSize();
1002 if (isVerticallyStretched) {
1003 if (!isHorizontallyStretched && pinnedInDirection(deltaX, 0)) {
1004 // Stretching only in the vertical.
1005 if (deltaY != 0 && (fabsf(deltaX / deltaY) < rubberbandDirectionLockStretchRatio))
1007 else if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
1008 m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
1011 m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
1013 } else if (isHorizontallyStretched) {
1014 // Stretching only in the horizontal.
1015 if (pinnedInDirection(0, deltaY)) {
1016 if (deltaX != 0 && (fabsf(deltaY / deltaX) < rubberbandDirectionLockStretchRatio))
1018 else if (fabsf(deltaY) < rubberbandMinimumRequiredDeltaBeforeStretch) {
1019 m_overflowScrollDelta.setHeight(m_overflowScrollDelta.height() + deltaY);
1022 m_overflowScrollDelta.setHeight(m_overflowScrollDelta.height() + deltaY);
1025 // Not stretching at all yet.
1026 if (pinnedInDirection(deltaX, deltaY)) {
1027 if (fabsf(deltaY) >= fabsf(deltaX)) {
1028 if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
1029 m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
1032 m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
1034 shouldStretch = true;
1039 if (deltaX != 0 || deltaY != 0) {
1040 if (!(shouldStretch || isVerticallyStretched || isHorizontallyStretched)) {
1042 deltaY *= scrollWheelMultiplier();
1043 immediateScrollByDeltaY(deltaY);
1046 deltaX *= scrollWheelMultiplier();
1047 immediateScrollByDeltaX(deltaX);
1050 if (!allowsHorizontalStretching()) {
1052 eventCoalescedDeltaX = 0;
1053 } else if ((deltaX != 0) && !isHorizontallyStretched && !pinnedInDirection(deltaX, 0)) {
1054 deltaX *= scrollWheelMultiplier();
1056 m_scrollableArea->setConstrainsScrollingToContentEdge(false);
1057 immediateScrollByDeltaX(deltaX);
1058 m_scrollableArea->setConstrainsScrollingToContentEdge(true);
1063 if (!allowsVerticalStretching()) {
1065 eventCoalescedDeltaY = 0;
1066 } else if ((deltaY != 0) && !isVerticallyStretched && !pinnedInDirection(0, deltaY)) {
1067 deltaY *= scrollWheelMultiplier();
1069 m_scrollableArea->setConstrainsScrollingToContentEdge(false);
1070 immediateScrollByDeltaY(deltaY);
1071 m_scrollableArea->setConstrainsScrollingToContentEdge(true);
1076 IntSize stretchAmount = m_scrollableArea->overhangAmount();
1078 if (m_momentumScrollInProgress) {
1079 if ((pinnedInDirection(eventCoalescedDeltaX, eventCoalescedDeltaY) || (fabsf(eventCoalescedDeltaX) + fabsf(eventCoalescedDeltaY) <= 0)) && m_lastMomentumScrollTimestamp) {
1080 m_ignoreMomentumScrolls = true;
1081 m_momentumScrollInProgress = false;
1086 m_stretchScrollForce.setWidth(m_stretchScrollForce.width() + deltaX);
1087 m_stretchScrollForce.setHeight(m_stretchScrollForce.height() + deltaY);
1089 FloatSize dampedDelta(ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.width())), ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.height())));
1090 FloatPoint origOrigin = (m_scrollableArea->visibleContentRect().location() + m_scrollableArea->scrollOrigin()) - stretchAmount;
1091 FloatPoint newOrigin = origOrigin + dampedDelta;
1093 if (origOrigin != newOrigin) {
1094 m_scrollableArea->setConstrainsScrollingToContentEdge(false);
1095 immediateScrollToPoint(newOrigin);
1096 m_scrollableArea->setConstrainsScrollingToContentEdge(true);
1101 if (m_momentumScrollInProgress && phase == PlatformWheelEventPhaseEnded) {
1102 m_momentumScrollInProgress = false;
1103 m_ignoreMomentumScrolls = false;
1104 m_lastMomentumScrollTimestamp = 0;
1108 void ScrollAnimatorChromiumMac::beginScrollGesture()
1110 didBeginScrollGesture();
1112 m_haveScrolledSincePageLoad = true;
1113 m_inScrollGesture = true;
1114 m_momentumScrollInProgress = false;
1115 m_ignoreMomentumScrolls = false;
1116 m_lastMomentumScrollTimestamp = 0;
1117 m_momentumVelocity = FloatSize();
1118 m_scrollerInitiallyPinnedOnLeft = m_scrollableArea->isHorizontalScrollerPinnedToMinimumPosition();
1119 m_scrollerInitiallyPinnedOnRight = m_scrollableArea->isHorizontalScrollerPinnedToMaximumPosition();
1120 m_cumulativeHorizontalScroll = 0;
1121 m_didCumulativeHorizontalScrollEverSwitchToOppositeDirectionOfPin = false;
1123 IntSize stretchAmount = m_scrollableArea->overhangAmount();
1124 m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(stretchAmount.width()));
1125 m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(stretchAmount.height()));
1127 m_overflowScrollDelta = FloatSize();
1129 if (m_snapRubberBandTimer.isActive())
1130 m_snapRubberBandTimer.stop();
1133 void ScrollAnimatorChromiumMac::endScrollGesture()
1135 didEndScrollGesture();
1140 void ScrollAnimatorChromiumMac::snapRubberBand()
1142 CFTimeInterval timeDelta = [[NSProcessInfo processInfo] systemUptime] - m_lastMomentumScrollTimestamp;
1143 if (m_lastMomentumScrollTimestamp && timeDelta >= scrollVelocityZeroingTimeout)
1144 m_momentumVelocity = FloatSize();
1146 m_inScrollGesture = false;
1148 if (m_snapRubberBandTimer.isActive())
1151 m_startTime = [NSDate timeIntervalSinceReferenceDate];
1152 m_startStretch = FloatSize();
1153 m_origOrigin = FloatPoint();
1154 m_origVelocity = FloatSize();
1156 m_snapRubberBandTimer.startRepeating(1.0/60.0);
1159 static inline float roundTowardZero(float num)
1161 return num > 0 ? ceilf(num - 0.5f) : floorf(num + 0.5f);
1164 static inline float roundToDevicePixelTowardZero(float num)
1166 float roundedNum = roundf(num);
1167 if (fabs(num - roundedNum) < 0.125)
1170 return roundTowardZero(num);
1173 void ScrollAnimatorChromiumMac::snapRubberBandTimerFired(Timer<ScrollAnimatorChromiumMac>*)
1175 if (!m_momentumScrollInProgress || m_ignoreMomentumScrolls) {
1176 CFTimeInterval timeDelta = [NSDate timeIntervalSinceReferenceDate] - m_startTime;
1178 if (m_startStretch == FloatSize()) {
1179 m_startStretch = m_scrollableArea->overhangAmount();
1180 if (m_startStretch == FloatSize()) {
1181 m_snapRubberBandTimer.stop();
1182 m_stretchScrollForce = FloatSize();
1184 m_startStretch = FloatSize();
1185 m_origOrigin = FloatPoint();
1186 m_origVelocity = FloatSize();
1191 m_scrollableArea->didStartRubberBand(roundedIntSize(m_startStretch));
1193 m_origOrigin = (m_scrollableArea->visibleContentRect().location() + m_scrollableArea->scrollOrigin()) - m_startStretch;
1194 m_origVelocity = m_momentumVelocity;
1196 // Just like normal scrolling, prefer vertical rubberbanding
1197 if (fabsf(m_origVelocity.height()) >= fabsf(m_origVelocity.width()))
1198 m_origVelocity.setWidth(0);
1200 // Don't rubber-band horizontally if it's not possible to scroll horizontally
1201 Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
1202 if (!hScroller || !hScroller->enabled())
1203 m_origVelocity.setWidth(0);
1205 // Don't rubber-band vertically if it's not possible to scroll horizontally
1206 Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
1207 if (!vScroller || !vScroller->enabled())
1208 m_origVelocity.setHeight(0);
1211 FloatPoint delta(roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.width(), -m_origVelocity.width(), (float)timeDelta)),
1212 roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.height(), -m_origVelocity.height(), (float)timeDelta)));
1214 if (fabs(delta.x()) >= 1 || fabs(delta.y()) >= 1) {
1215 FloatPoint newOrigin = m_origOrigin + delta;
1217 m_scrollableArea->setConstrainsScrollingToContentEdge(false);
1218 immediateScrollToPoint(newOrigin);
1219 m_scrollableArea->setConstrainsScrollingToContentEdge(true);
1221 FloatSize newStretch = m_scrollableArea->overhangAmount();
1223 m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(newStretch.width()));
1224 m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(newStretch.height()));
1226 immediateScrollToPoint(m_origOrigin);
1228 m_scrollableArea->didCompleteRubberBand(roundedIntSize(m_startStretch));
1230 m_snapRubberBandTimer.stop();
1231 m_stretchScrollForce = FloatSize();
1234 m_startStretch = FloatSize();
1235 m_origOrigin = FloatPoint();
1236 m_origVelocity = FloatSize();
1239 m_startTime = [NSDate timeIntervalSinceReferenceDate];
1240 m_startStretch = FloatSize();
1245 void ScrollAnimatorChromiumMac::setIsActive()
1247 if (isScrollbarOverlayAPIAvailable()) {
1248 if (needsScrollerStyleUpdate())
1249 updateScrollerStyle();
1253 #if USE(WK_SCROLLBAR_PAINTER)
1254 void ScrollAnimatorChromiumMac::updateScrollerStyle()
1256 if (!scrollableArea()->isOnActivePage()) {
1257 setNeedsScrollerStyleUpdate(true);
1261 ScrollbarThemeChromiumMac* macTheme = chromiumScrollbarTheme();
1263 setNeedsScrollerStyleUpdate(false);
1267 int newStyle = wkScrollbarPainterControllerStyle(m_scrollbarPainterController.get());
1269 if (Scrollbar* verticalScrollbar = scrollableArea()->verticalScrollbar()) {
1270 verticalScrollbar->invalidate();
1272 WKScrollbarPainterRef oldVerticalPainter = wkVerticalScrollbarPainterForController(m_scrollbarPainterController.get());
1273 WKScrollbarPainterRef newVerticalPainter = wkMakeScrollbarReplacementPainter(oldVerticalPainter,
1275 verticalScrollbar->controlSize(),
1277 macTheme->setNewPainterForScrollbar(verticalScrollbar, newVerticalPainter);
1278 wkSetPainterForPainterController(m_scrollbarPainterController.get(), newVerticalPainter, false);
1280 // The different scrollbar styles have different thicknesses, so we must re-set the
1281 // frameRect to the new thickness, and the re-layout below will ensure the position
1282 // and length are properly updated.
1283 int thickness = macTheme->scrollbarThickness(verticalScrollbar->controlSize());
1284 verticalScrollbar->setFrameRect(IntRect(0, 0, thickness, thickness));
1287 if (Scrollbar* horizontalScrollbar = scrollableArea()->horizontalScrollbar()) {
1288 horizontalScrollbar->invalidate();
1290 WKScrollbarPainterRef oldHorizontalPainter = wkHorizontalScrollbarPainterForController(m_scrollbarPainterController.get());
1291 WKScrollbarPainterRef newHorizontalPainter = wkMakeScrollbarReplacementPainter(oldHorizontalPainter,
1293 horizontalScrollbar->controlSize(),
1295 macTheme->setNewPainterForScrollbar(horizontalScrollbar, newHorizontalPainter);
1296 wkSetPainterForPainterController(m_scrollbarPainterController.get(), newHorizontalPainter, true);
1298 // The different scrollbar styles have different thicknesses, so we must re-set the
1299 // frameRect to the new thickness, and the re-layout below will ensure the position
1300 // and length are properly updated.
1301 int thickness = macTheme->scrollbarThickness(horizontalScrollbar->controlSize());
1302 horizontalScrollbar->setFrameRect(IntRect(0, 0, thickness, thickness));
1305 // If needsScrollerStyleUpdate() is true, then the page is restoring from the page cache, and
1306 // a relayout will happen on its own. Otherwise, we must initiate a re-layout ourselves.
1307 scrollableArea()->scrollbarStyleChanged(newStyle, !needsScrollerStyleUpdate());
1309 setNeedsScrollerStyleUpdate(false);
1312 void ScrollAnimatorChromiumMac::startScrollbarPaintTimer()
1314 m_initialScrollbarPaintTimer.startOneShot(0.1);
1317 bool ScrollAnimatorChromiumMac::scrollbarPaintTimerIsActive() const
1319 return m_initialScrollbarPaintTimer.isActive();
1322 void ScrollAnimatorChromiumMac::stopScrollbarPaintTimer()
1324 m_initialScrollbarPaintTimer.stop();
1327 void ScrollAnimatorChromiumMac::initialScrollbarPaintTimerFired(Timer<ScrollAnimatorChromiumMac>*)
1329 wkScrollbarPainterForceFlashScrollers(m_scrollbarPainterController.get());
1333 void ScrollAnimatorChromiumMac::setVisibleScrollerThumbRect(const IntRect& scrollerThumb)
1335 IntRect rectInViewCoordinates = scrollerThumb;
1336 if (Scrollbar* verticalScrollbar = m_scrollableArea->verticalScrollbar())
1337 rectInViewCoordinates = verticalScrollbar->convertToContainingView(scrollerThumb);
1339 if (rectInViewCoordinates == m_visibleScrollerThumbRect)
1342 m_scrollableArea->setVisibleScrollerThumbRect(rectInViewCoordinates);
1343 m_visibleScrollerThumbRect = rectInViewCoordinates;
1346 } // namespace WebCore