Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: Source/core/platform/mac/ScrollAnimatorMac.mm

Issue 99103006: Moving GraphicsContext and dependencies from core to platform. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Final patch - fixes Android Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
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.
24 */
25
26 #include "config.h"
27
28 #include "core/platform/mac/ScrollAnimatorMac.h"
29
30 #include "core/platform/ScrollView.h"
31 #include "core/platform/ScrollableArea.h"
32 #include "core/platform/ScrollbarTheme.h"
33 #include "core/platform/ScrollbarThemeMacCommon.h"
34 #include "core/platform/ScrollbarThemeMacOverlayAPI.h"
35 #include "core/platform/mac/EmptyProtocolDefinitions.h"
36 #include "core/platform/mac/NSScrollerImpDetails.h"
37 #include "platform/PlatformGestureEvent.h"
38 #include "platform/PlatformWheelEvent.h"
39 #include "platform/geometry/FloatPoint.h"
40 #include "platform/mac/BlockExceptions.h"
41 #include "wtf/MainThread.h"
42 #include "wtf/PassOwnPtr.h"
43 #include "wtf/UnusedParam.h"
44
45 using namespace WebCore;
46 using namespace std;
47
48 static bool supportsUIStateTransitionProgress()
49 {
50 // FIXME: This is temporary until all platforms that support ScrollbarPainte r support this part of the API.
51 static bool globalSupportsUIStateTransitionProgress = [NSClassFromString(@"N SScrollerImp") instancesRespondToSelector:@selector(mouseEnteredScroller)];
52 return globalSupportsUIStateTransitionProgress;
53 }
54
55 static bool supportsExpansionTransitionProgress()
56 {
57 static bool globalSupportsExpansionTransitionProgress = [NSClassFromString(@ "NSScrollerImp") instancesRespondToSelector:@selector(expansionTransitionProgres s)];
58 return globalSupportsExpansionTransitionProgress;
59 }
60
61 static bool supportsContentAreaScrolledInDirection()
62 {
63 static bool globalSupportsContentAreaScrolledInDirection = [NSClassFromStrin g(@"NSScrollerImpPair") instancesRespondToSelector:@selector(contentAreaScrolled InDirection:)];
64 return globalSupportsContentAreaScrolledInDirection;
65 }
66
67 static ScrollbarThemeMacOverlayAPI* macOverlayScrollbarTheme()
68 {
69 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(isScrollbarOverlayAPIAvailable());
70 ScrollbarTheme* scrollbarTheme = ScrollbarTheme::theme();
71 return !scrollbarTheme->isMockTheme() ? static_cast<ScrollbarThemeMacOverlay API*>(scrollbarTheme) : 0;
72 }
73
74 static ScrollbarPainter scrollbarPainterForScrollbar(Scrollbar* scrollbar)
75 {
76 if (ScrollbarThemeMacOverlayAPI* scrollbarTheme = macOverlayScrollbarTheme() )
77 return scrollbarTheme->painterForScrollbar(scrollbar);
78
79 return nil;
80 }
81
82 @interface NSObject (ScrollAnimationHelperDetails)
83 - (id)initWithDelegate:(id)delegate;
84 - (void)_stopRun;
85 - (BOOL)_isAnimating;
86 - (NSPoint)targetOrigin;
87 - (CGFloat)_progress;
88 @end
89
90 @interface WebScrollAnimationHelperDelegate : NSObject
91 {
92 WebCore::ScrollAnimatorMac* _animator;
93 }
94 - (id)initWithScrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator;
95 @end
96
97 static NSSize abs(NSSize size)
98 {
99 NSSize finalSize = size;
100 if (finalSize.width < 0)
101 finalSize.width = -finalSize.width;
102 if (finalSize.height < 0)
103 finalSize.height = -finalSize.height;
104 return finalSize;
105 }
106
107 @implementation WebScrollAnimationHelperDelegate
108
109 - (id)initWithScrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator
110 {
111 self = [super init];
112 if (!self)
113 return nil;
114
115 _animator = scrollAnimator;
116 return self;
117 }
118
119 - (void)invalidate
120 {
121 _animator = 0;
122 }
123
124 - (NSRect)bounds
125 {
126 if (!_animator)
127 return NSZeroRect;
128
129 WebCore::FloatPoint currentPosition = _animator->currentPosition();
130 return NSMakeRect(currentPosition.x(), currentPosition.y(), 0, 0);
131 }
132
133 - (void)_immediateScrollToPoint:(NSPoint)newPosition
134 {
135 if (!_animator)
136 return;
137 _animator->immediateScrollToPointForScrollAnimation(newPosition);
138 }
139
140 - (NSPoint)_pixelAlignProposedScrollPosition:(NSPoint)newOrigin
141 {
142 return newOrigin;
143 }
144
145 - (NSSize)convertSizeToBase:(NSSize)size
146 {
147 return abs(size);
148 }
149
150 - (NSSize)convertSizeFromBase:(NSSize)size
151 {
152 return abs(size);
153 }
154
155 - (NSSize)convertSizeToBacking:(NSSize)size
156 {
157 return abs(size);
158 }
159
160 - (NSSize)convertSizeFromBacking:(NSSize)size
161 {
162 return abs(size);
163 }
164
165 - (id)superview
166 {
167 return nil;
168 }
169
170 - (id)documentView
171 {
172 return nil;
173 }
174
175 - (id)window
176 {
177 return nil;
178 }
179
180 - (void)_recursiveRecomputeToolTips
181 {
182 }
183
184 @end
185
186 @interface WebScrollbarPainterControllerDelegate : NSObject
187 {
188 ScrollableArea* _scrollableArea;
189 }
190 - (id)initWithScrollableArea:(ScrollableArea*)scrollableArea;
191 @end
192
193 @implementation WebScrollbarPainterControllerDelegate
194
195 - (id)initWithScrollableArea:(ScrollableArea*)scrollableArea
196 {
197 self = [super init];
198 if (!self)
199 return nil;
200
201 _scrollableArea = scrollableArea;
202 return self;
203 }
204
205 - (void)invalidate
206 {
207 _scrollableArea = 0;
208 }
209
210 - (NSRect)contentAreaRectForScrollerImpPair:(id)scrollerImpPair
211 {
212 UNUSED_PARAM(scrollerImpPair);
213 if (!_scrollableArea)
214 return NSZeroRect;
215
216 WebCore::IntSize contentsSize = _scrollableArea->contentsSize();
217 return NSMakeRect(0, 0, contentsSize.width(), contentsSize.height());
218 }
219
220 - (BOOL)inLiveResizeForScrollerImpPair:(id)scrollerImpPair
221 {
222 UNUSED_PARAM(scrollerImpPair);
223 if (!_scrollableArea)
224 return NO;
225
226 return _scrollableArea->inLiveResize();
227 }
228
229 - (NSPoint)mouseLocationInContentAreaForScrollerImpPair:(id)scrollerImpPair
230 {
231 UNUSED_PARAM(scrollerImpPair);
232 if (!_scrollableArea)
233 return NSZeroPoint;
234
235 return _scrollableArea->lastKnownMousePosition();
236 }
237
238 - (NSPoint)scrollerImpPair:(id)scrollerImpPair convertContentPoint:(NSPoint)poin tInContentArea toScrollerImp:(id)scrollerImp
239 {
240 UNUSED_PARAM(scrollerImpPair);
241
242 if (!_scrollableArea || !scrollerImp)
243 return NSZeroPoint;
244
245 WebCore::Scrollbar* scrollbar = 0;
246 if ([scrollerImp isHorizontal])
247 scrollbar = _scrollableArea->horizontalScrollbar();
248 else
249 scrollbar = _scrollableArea->verticalScrollbar();
250
251 // It is possible to have a null scrollbar here since it is possible for thi s delegate
252 // method to be called between the moment when a scrollbar has been set to 0 and the
253 // moment when its destructor has been called. We should probably de-couple some
254 // of the clean-up work in ScrollbarThemeMac::unregisterScrollbar() to avoid this
255 // issue.
256 if (!scrollbar)
257 return NSZeroPoint;
258
259 ASSERT(scrollerImp == scrollbarPainterForScrollbar(scrollbar));
260
261 return scrollbar->convertFromContainingView(WebCore::IntPoint(pointInContent Area));
262 }
263
264 - (void)scrollerImpPair:(id)scrollerImpPair setContentAreaNeedsDisplayInRect:(NS Rect)rect
265 {
266 UNUSED_PARAM(scrollerImpPair);
267 UNUSED_PARAM(rect);
268
269 if (!_scrollableArea)
270 return;
271
272 if (!_scrollableArea->scrollbarsCanBeActive())
273 return;
274
275 _scrollableArea->scrollAnimator()->contentAreaWillPaint();
276 }
277
278 - (void)scrollerImpPair:(id)scrollerImpPair updateScrollerStyleForNewRecommended ScrollerStyle:(NSScrollerStyle)newRecommendedScrollerStyle
279 {
280 // Chrome has a single process mode which is used for testing on Mac. In tha t mode, WebKit runs on a thread in the
281 // browser process. This notification is called by the OS on the main thread in the browser process, and not on the
282 // the WebKit thread. Better to not update the style than crash.
283 // http://crbug.com/126514
284 if (!isMainThread())
285 return;
286
287 if (!_scrollableArea)
288 return;
289
290 [scrollerImpPair setScrollerStyle:newRecommendedScrollerStyle];
291
292 static_cast<ScrollAnimatorMac*>(_scrollableArea->scrollAnimator())->updateSc rollerStyle();
293 }
294
295 @end
296
297 enum FeatureToAnimate {
298 ThumbAlpha,
299 TrackAlpha,
300 UIStateTransition,
301 ExpansionTransition
302 };
303
304 @interface WebScrollbarPartAnimation : NSAnimation
305 {
306 Scrollbar* _scrollbar;
307 RetainPtr<ScrollbarPainter> _scrollbarPainter;
308 FeatureToAnimate _featureToAnimate;
309 CGFloat _startValue;
310 CGFloat _endValue;
311 }
312 - (id)initWithScrollbar:(Scrollbar*)scrollbar featureToAnimate:(FeatureToAnimate )featureToAnimate animateFrom:(CGFloat)startValue animateTo:(CGFloat)endValue du ration:(NSTimeInterval)duration;
313 @end
314
315 @implementation WebScrollbarPartAnimation
316
317 - (id)initWithScrollbar:(Scrollbar*)scrollbar featureToAnimate:(FeatureToAnimate )featureToAnimate animateFrom:(CGFloat)startValue animateTo:(CGFloat)endValue du ration:(NSTimeInterval)duration
318 {
319 self = [super initWithDuration:duration animationCurve:NSAnimationEaseInOut] ;
320 if (!self)
321 return nil;
322
323 _scrollbar = scrollbar;
324 _featureToAnimate = featureToAnimate;
325 _startValue = startValue;
326 _endValue = endValue;
327
328 [self setAnimationBlockingMode:NSAnimationNonblocking];
329
330 return self;
331 }
332
333 - (void)startAnimation
334 {
335 ASSERT(_scrollbar);
336
337 _scrollbarPainter = scrollbarPainterForScrollbar(_scrollbar);
338
339 [super startAnimation];
340 }
341
342 - (void)setStartValue:(CGFloat)startValue
343 {
344 _startValue = startValue;
345 }
346
347 - (void)setEndValue:(CGFloat)endValue
348 {
349 _endValue = endValue;
350 }
351
352 - (void)setCurrentProgress:(NSAnimationProgress)progress
353 {
354 [super setCurrentProgress:progress];
355
356 ASSERT(_scrollbar);
357
358 CGFloat currentValue;
359 if (_startValue > _endValue)
360 currentValue = 1 - progress;
361 else
362 currentValue = progress;
363
364 switch (_featureToAnimate) {
365 case ThumbAlpha:
366 [_scrollbarPainter.get() setKnobAlpha:currentValue];
367 break;
368 case TrackAlpha:
369 [_scrollbarPainter.get() setTrackAlpha:currentValue];
370 break;
371 case UIStateTransition:
372 [_scrollbarPainter.get() setUiStateTransitionProgress:currentValue];
373 break;
374 case ExpansionTransition:
375 [_scrollbarPainter.get() setExpansionTransitionProgress:currentValue];
376 break;
377 }
378
379 _scrollbar->invalidate();
380 }
381
382 - (void)invalidate
383 {
384 BEGIN_BLOCK_OBJC_EXCEPTIONS;
385 [self stopAnimation];
386 END_BLOCK_OBJC_EXCEPTIONS;
387 _scrollbar = 0;
388 }
389
390 @end
391
392 @interface WebScrollbarPainterDelegate : NSObject<NSAnimationDelegate>
393 {
394 WebCore::Scrollbar* _scrollbar;
395
396 RetainPtr<WebScrollbarPartAnimation> _knobAlphaAnimation;
397 RetainPtr<WebScrollbarPartAnimation> _trackAlphaAnimation;
398 RetainPtr<WebScrollbarPartAnimation> _uiStateTransitionAnimation;
399 RetainPtr<WebScrollbarPartAnimation> _expansionTransitionAnimation;
400 }
401 - (id)initWithScrollbar:(WebCore::Scrollbar*)scrollbar;
402 - (void)cancelAnimations;
403 @end
404
405 @implementation WebScrollbarPainterDelegate
406
407 - (id)initWithScrollbar:(WebCore::Scrollbar*)scrollbar
408 {
409 self = [super init];
410 if (!self)
411 return nil;
412
413 _scrollbar = scrollbar;
414 return self;
415 }
416
417 - (void)cancelAnimations
418 {
419 BEGIN_BLOCK_OBJC_EXCEPTIONS;
420 [_knobAlphaAnimation.get() stopAnimation];
421 [_trackAlphaAnimation.get() stopAnimation];
422 [_uiStateTransitionAnimation.get() stopAnimation];
423 [_expansionTransitionAnimation.get() stopAnimation];
424 END_BLOCK_OBJC_EXCEPTIONS;
425 }
426
427 - (ScrollAnimatorMac*)scrollAnimator
428 {
429 return static_cast<ScrollAnimatorMac*>(_scrollbar->scrollableArea()->scrollA nimator());
430 }
431
432 - (NSRect)convertRectToBacking:(NSRect)aRect
433 {
434 return aRect;
435 }
436
437 - (NSRect)convertRectFromBacking:(NSRect)aRect
438 {
439 return aRect;
440 }
441
442 - (NSPoint)mouseLocationInScrollerForScrollerImp:(id)scrollerImp
443 {
444 if (!_scrollbar)
445 return NSZeroPoint;
446
447 ASSERT_UNUSED(scrollerImp, scrollerImp == scrollbarPainterForScrollbar(_scro llbar));
448
449 return _scrollbar->convertFromContainingView(_scrollbar->scrollableArea()->l astKnownMousePosition());
450 }
451
452 - (void)setUpAlphaAnimation:(RetainPtr<WebScrollbarPartAnimation>&)scrollbarPart Animation scrollerPainter:(ScrollbarPainter)scrollerPainter part:(WebCore::Scrol lbarPart)part animateAlphaTo:(CGFloat)newAlpha duration:(NSTimeInterval)duration
453 {
454 // If the user has scrolled the page, then the scrollbars must be animated h ere.
455 // This overrides the early returns.
456 bool mustAnimate = [self scrollAnimator]->haveScrolledSincePageLoad();
457
458 if ([self scrollAnimator]->scrollbarPaintTimerIsActive() && !mustAnimate)
459 return;
460
461 if (_scrollbar->scrollableArea()->shouldSuspendScrollAnimations() && !mustAn imate) {
462 [self scrollAnimator]->startScrollbarPaintTimer();
463 return;
464 }
465
466 // At this point, we are definitely going to animate now, so stop the timer.
467 [self scrollAnimator]->stopScrollbarPaintTimer();
468
469 // If we are currently animating, stop
470 if (scrollbarPartAnimation) {
471 [scrollbarPartAnimation.get() stopAnimation];
472 scrollbarPartAnimation = nil;
473 }
474
475 if (part == WebCore::ThumbPart && _scrollbar->orientation() == VerticalScrol lbar) {
476 if (newAlpha == 1) {
477 IntRect thumbRect = IntRect([scrollerPainter rectForPart:NSScrollerK nob]);
478 [self scrollAnimator]->setVisibleScrollerThumbRect(thumbRect);
479 } else
480 [self scrollAnimator]->setVisibleScrollerThumbRect(IntRect());
481 }
482
483 scrollbarPartAnimation.adoptNS([[WebScrollbarPartAnimation alloc] initWithSc rollbar:_scrollbar
484 featureTo Animate:part == ThumbPart ? ThumbAlpha : TrackAlpha
485 anim ateFrom:part == ThumbPart ? [scrollerPainter knobAlpha] : [scrollerPainter track Alpha]
486 an imateTo:newAlpha
487 d uration:duration]);
488 [scrollbarPartAnimation.get() startAnimation];
489 }
490
491 - (void)scrollerImp:(id)scrollerImp animateKnobAlphaTo:(CGFloat)newKnobAlpha dur ation:(NSTimeInterval)duration
492 {
493 if (!_scrollbar)
494 return;
495
496 ASSERT(scrollerImp == scrollbarPainterForScrollbar(_scrollbar));
497
498 ScrollbarPainter scrollerPainter = (ScrollbarPainter)scrollerImp;
499 [self setUpAlphaAnimation:_knobAlphaAnimation scrollerPainter:scrollerPainte r part:WebCore::ThumbPart animateAlphaTo:newKnobAlpha duration:duration];
500 }
501
502 - (void)scrollerImp:(id)scrollerImp animateTrackAlphaTo:(CGFloat)newTrackAlpha d uration:(NSTimeInterval)duration
503 {
504 if (!_scrollbar)
505 return;
506
507 ASSERT(scrollerImp == scrollbarPainterForScrollbar(_scrollbar));
508
509 ScrollbarPainter scrollerPainter = (ScrollbarPainter)scrollerImp;
510 [self setUpAlphaAnimation:_trackAlphaAnimation scrollerPainter:scrollerPaint er part:WebCore::BackTrackPart animateAlphaTo:newTrackAlpha duration:duration];
511 }
512
513 - (void)scrollerImp:(id)scrollerImp animateUIStateTransitionWithDuration:(NSTime Interval)duration
514 {
515 if (!_scrollbar)
516 return;
517
518 if (!supportsUIStateTransitionProgress())
519 return;
520
521 ASSERT(scrollerImp == scrollbarPainterForScrollbar(_scrollbar));
522
523 ScrollbarPainter scrollbarPainter = (ScrollbarPainter)scrollerImp;
524
525 // UIStateTransition always animates to 1. In case an animation is in progre ss this avoids a hard transition.
526 [scrollbarPainter setUiStateTransitionProgress:1 - [scrollerImp uiStateTrans itionProgress]];
527
528 if (!_uiStateTransitionAnimation)
529 _uiStateTransitionAnimation.adoptNS([[WebScrollbarPartAnimation alloc] i nitWithScrollbar:_scrollbar
530 featureToAnimate:UIStateTransition
531 animateFrom:[scrollbarPainter uiStateTransitionProgress]
532 animateTo:1.0
533 duration:duration]);
534 else {
535 // If we don't need to initialize the animation, just reset the values i n case they have changed.
536 [_uiStateTransitionAnimation.get() setStartValue:[scrollbarPainter uiSta teTransitionProgress]];
537 [_uiStateTransitionAnimation.get() setEndValue:1.0];
538 [_uiStateTransitionAnimation.get() setDuration:duration];
539 }
540 [_uiStateTransitionAnimation.get() startAnimation];
541 }
542
543 - (void)scrollerImp:(id)scrollerImp animateExpansionTransitionWithDuration:(NSTi meInterval)duration
544 {
545 if (!_scrollbar)
546 return;
547
548 if (!supportsExpansionTransitionProgress())
549 return;
550
551 ASSERT(scrollerImp == scrollbarPainterForScrollbar(_scrollbar));
552
553 ScrollbarPainter scrollbarPainter = (ScrollbarPainter)scrollerImp;
554
555 // ExpansionTransition always animates to 1. In case an animation is in prog ress this avoids a hard transition.
556 [scrollbarPainter setExpansionTransitionProgress:1 - [scrollerImp expansionT ransitionProgress]];
557
558 if (!_expansionTransitionAnimation) {
559 _expansionTransitionAnimation.adoptNS([[WebScrollbarPartAnimation alloc] initWithScrollbar:_scrollbar
560 featureToAnimate:ExpansionTransition
561 animateFrom:[scrollbarPainter expansionTransitionProgress]
562 animateTo:1.0
563 duration:duration]);
564 } else {
565 // If we don't need to initialize the animation, just reset the values i n case they have changed.
566 [_expansionTransitionAnimation.get() setStartValue:[scrollbarPainter uiS tateTransitionProgress]];
567 [_expansionTransitionAnimation.get() setEndValue:1.0];
568 [_expansionTransitionAnimation.get() setDuration:duration];
569 }
570 [_expansionTransitionAnimation.get() startAnimation];
571 }
572
573 - (void)scrollerImp:(id)scrollerImp overlayScrollerStateChangedTo:(NSUInteger)ne wOverlayScrollerState
574 {
575 UNUSED_PARAM(scrollerImp);
576 UNUSED_PARAM(newOverlayScrollerState);
577 }
578
579 - (void)invalidate
580 {
581 _scrollbar = 0;
582 BEGIN_BLOCK_OBJC_EXCEPTIONS;
583 [_knobAlphaAnimation.get() invalidate];
584 [_trackAlphaAnimation.get() invalidate];
585 [_uiStateTransitionAnimation.get() invalidate];
586 [_expansionTransitionAnimation.get() invalidate];
587 END_BLOCK_OBJC_EXCEPTIONS;
588 }
589
590 @end
591
592 namespace WebCore {
593
594 PassOwnPtr<ScrollAnimator> ScrollAnimator::create(ScrollableArea* scrollableArea )
595 {
596 return adoptPtr(new ScrollAnimatorMac(scrollableArea));
597 }
598
599 ScrollAnimatorMac::ScrollAnimatorMac(ScrollableArea* scrollableArea)
600 : ScrollAnimator(scrollableArea)
601 , m_initialScrollbarPaintTimer(this, &ScrollAnimatorMac::initialScrollbarPai ntTimerFired)
602 , m_sendContentAreaScrolledTimer(this, &ScrollAnimatorMac::sendContentAreaSc rolledTimerFired)
603 #if USE(RUBBER_BANDING)
604 , m_scrollElasticityController(this)
605 , m_snapRubberBandTimer(this, &ScrollAnimatorMac::snapRubberBandTimerFired)
606 #endif
607 , m_haveScrolledSincePageLoad(false)
608 , m_needsScrollerStyleUpdate(false)
609 {
610 m_scrollAnimationHelperDelegate.adoptNS([[WebScrollAnimationHelperDelegate a lloc] initWithScrollAnimator:this]);
611 m_scrollAnimationHelper.adoptNS([[NSClassFromString(@"NSScrollAnimationHelpe r") alloc] initWithDelegate:m_scrollAnimationHelperDelegate.get()]);
612
613 if (isScrollbarOverlayAPIAvailable()) {
614 m_scrollbarPainterControllerDelegate.adoptNS([[WebScrollbarPainterContro llerDelegate alloc] initWithScrollableArea:scrollableArea]);
615 m_scrollbarPainterController = [[[NSClassFromString(@"NSScrollerImpPair" ) alloc] init] autorelease];
616 [m_scrollbarPainterController.get() setDelegate:m_scrollbarPainterContro llerDelegate.get()];
617 [m_scrollbarPainterController.get() setScrollerStyle:recommendedScroller Style()];
618 }
619 }
620
621 ScrollAnimatorMac::~ScrollAnimatorMac()
622 {
623 if (isScrollbarOverlayAPIAvailable()) {
624 BEGIN_BLOCK_OBJC_EXCEPTIONS;
625 [m_scrollbarPainterControllerDelegate.get() invalidate];
626 [m_scrollbarPainterController.get() setDelegate:nil];
627 [m_horizontalScrollbarPainterDelegate.get() invalidate];
628 [m_verticalScrollbarPainterDelegate.get() invalidate];
629 [m_scrollAnimationHelperDelegate.get() invalidate];
630 END_BLOCK_OBJC_EXCEPTIONS;
631 }
632 }
633
634 static bool scrollAnimationEnabledForSystem()
635 {
636 NSString* scrollAnimationDefaultsKey =
637 @"AppleScrollAnimationEnabled";
638 static bool enabled = [[NSUserDefaults standardUserDefaults] boolForKey:scro llAnimationDefaultsKey];
639 return enabled;
640 }
641
642 #if USE(RUBBER_BANDING)
643 static bool rubberBandingEnabledForSystem()
644 {
645 static bool initialized = false;
646 static bool enabled = true;
647 // Caches the result, which is consistent with other apps like the Finder, w hich all
648 // require a restart after changing this default.
649 if (!initialized) {
650 // Uses -objectForKey: and not -boolForKey: in order to default to true if the value wasn't set.
651 id value = [[NSUserDefaults standardUserDefaults] objectForKey:@"NSScrol lViewRubberbanding"];
652 if ([value isKindOfClass:[NSNumber class]])
653 enabled = [value boolValue];
654 initialized = true;
655 }
656 return enabled;
657 }
658 #endif
659
660 bool ScrollAnimatorMac::scroll(ScrollbarOrientation orientation, ScrollGranulari ty granularity, float step, float multiplier)
661 {
662 m_haveScrolledSincePageLoad = true;
663
664 if (!scrollAnimationEnabledForSystem() || !m_scrollableArea->scrollAnimatorE nabled())
665 return ScrollAnimator::scroll(orientation, granularity, step, multiplier );
666
667 if (granularity == ScrollByPixel)
668 return ScrollAnimator::scroll(orientation, granularity, step, multiplier );
669
670 float currentPos = orientation == HorizontalScrollbar ? m_currentPosX : m_cu rrentPosY;
671 float newPos = std::max<float>(std::min<float>(currentPos + (step * multipli er), m_scrollableArea->maximumScrollPosition(orientation)), m_scrollableArea->mi nimumScrollPosition(orientation));
672 if (currentPos == newPos)
673 return false;
674
675 NSPoint newPoint;
676 if ([m_scrollAnimationHelper.get() _isAnimating]) {
677 NSPoint targetOrigin = [m_scrollAnimationHelper.get() targetOrigin];
678 newPoint = orientation == HorizontalScrollbar ? NSMakePoint(newPos, targ etOrigin.y) : NSMakePoint(targetOrigin.x, newPos);
679 } else
680 newPoint = orientation == HorizontalScrollbar ? NSMakePoint(newPos, m_cu rrentPosY) : NSMakePoint(m_currentPosX, newPos);
681
682 [m_scrollAnimationHelper.get() scrollToPoint:newPoint];
683 return true;
684 }
685
686 void ScrollAnimatorMac::scrollToOffsetWithoutAnimation(const FloatPoint& offset)
687 {
688 [m_scrollAnimationHelper.get() _stopRun];
689 immediateScrollTo(offset);
690 }
691
692 FloatPoint ScrollAnimatorMac::adjustScrollPositionIfNecessary(const FloatPoint& position) const
693 {
694 if (!m_scrollableArea->constrainsScrollingToContentEdge())
695 return position;
696
697 IntPoint minPos = m_scrollableArea->minimumScrollPosition();
698 IntPoint maxPos = m_scrollableArea->maximumScrollPosition();
699
700 float newX = max<float>(min<float>(position.x(), maxPos.x()), minPos.x());
701 float newY = max<float>(min<float>(position.y(), maxPos.y()), minPos.y());
702
703 return FloatPoint(newX, newY);
704 }
705
706 void ScrollAnimatorMac::immediateScrollTo(const FloatPoint& newPosition)
707 {
708 FloatPoint adjustedPosition = adjustScrollPositionIfNecessary(newPosition);
709
710 bool positionChanged = adjustedPosition.x() != m_currentPosX || adjustedPosi tion.y() != m_currentPosY;
711 if (!positionChanged && !scrollableArea()->scrollOriginChanged())
712 return;
713
714 FloatSize delta = FloatSize(adjustedPosition.x() - m_currentPosX, adjustedPo sition.y() - m_currentPosY);
715
716 m_currentPosX = adjustedPosition.x();
717 m_currentPosY = adjustedPosition.y();
718 notifyPositionChanged(delta);
719 }
720
721 bool ScrollAnimatorMac::isRubberBandInProgress() const
722 {
723 #if !USE(RUBBER_BANDING)
724 return false;
725 #else
726 return m_scrollElasticityController.isRubberBandInProgress();
727 #endif
728 }
729
730 void ScrollAnimatorMac::immediateScrollToPointForScrollAnimation(const FloatPoin t& newPosition)
731 {
732 ASSERT(m_scrollAnimationHelper);
733 immediateScrollTo(newPosition);
734 }
735
736 void ScrollAnimatorMac::notifyPositionChanged(const FloatSize& delta)
737 {
738 notifyContentAreaScrolled(delta);
739 ScrollAnimator::notifyPositionChanged(delta);
740 }
741
742 void ScrollAnimatorMac::contentAreaWillPaint() const
743 {
744 if (!scrollableArea()->scrollbarsCanBeActive())
745 return;
746 if (isScrollbarOverlayAPIAvailable())
747 [m_scrollbarPainterController.get() contentAreaWillDraw];
748 }
749
750 void ScrollAnimatorMac::mouseEnteredContentArea() const
751 {
752 if (!scrollableArea()->scrollbarsCanBeActive())
753 return;
754 if (isScrollbarOverlayAPIAvailable())
755 [m_scrollbarPainterController.get() mouseEnteredContentArea];
756 }
757
758 void ScrollAnimatorMac::mouseExitedContentArea() const
759 {
760 if (!scrollableArea()->scrollbarsCanBeActive())
761 return;
762 if (isScrollbarOverlayAPIAvailable())
763 [m_scrollbarPainterController.get() mouseExitedContentArea];
764 }
765
766 void ScrollAnimatorMac::mouseMovedInContentArea() const
767 {
768 if (!scrollableArea()->scrollbarsCanBeActive())
769 return;
770 if (isScrollbarOverlayAPIAvailable())
771 [m_scrollbarPainterController.get() mouseMovedInContentArea];
772 }
773
774 void ScrollAnimatorMac::mouseEnteredScrollbar(Scrollbar* scrollbar) const
775 {
776 // At this time, only legacy scrollbars needs to send notifications here.
777 if (recommendedScrollerStyle() != NSScrollerStyleLegacy)
778 return;
779
780 if (!scrollableArea()->scrollbarsCanBeActive())
781 return;
782
783 if (isScrollbarOverlayAPIAvailable()) {
784 if (!supportsUIStateTransitionProgress())
785 return;
786 if (ScrollbarPainter painter = scrollbarPainterForScrollbar(scrollbar))
787 [painter mouseEnteredScroller];
788 }
789 }
790
791 void ScrollAnimatorMac::mouseExitedScrollbar(Scrollbar* scrollbar) const
792 {
793 // At this time, only legacy scrollbars needs to send notifications here.
794 if (recommendedScrollerStyle() != NSScrollerStyleLegacy)
795 return;
796
797 if (!scrollableArea()->scrollbarsCanBeActive())
798 return;
799
800 if (isScrollbarOverlayAPIAvailable()) {
801 if (!supportsUIStateTransitionProgress())
802 return;
803 if (ScrollbarPainter painter = scrollbarPainterForScrollbar(scrollbar))
804 [painter mouseExitedScroller];
805 }
806 }
807
808 void ScrollAnimatorMac::willStartLiveResize()
809 {
810 if (!scrollableArea()->scrollbarsCanBeActive())
811 return;
812 if (isScrollbarOverlayAPIAvailable())
813 [m_scrollbarPainterController.get() startLiveResize];
814 }
815
816 void ScrollAnimatorMac::contentsResized() const
817 {
818 if (!scrollableArea()->scrollbarsCanBeActive())
819 return;
820 if (isScrollbarOverlayAPIAvailable())
821 [m_scrollbarPainterController.get() contentAreaDidResize];
822 }
823
824 void ScrollAnimatorMac::willEndLiveResize()
825 {
826 if (!scrollableArea()->scrollbarsCanBeActive())
827 return;
828 if (isScrollbarOverlayAPIAvailable())
829 [m_scrollbarPainterController.get() endLiveResize];
830 }
831
832 void ScrollAnimatorMac::contentAreaDidShow() const
833 {
834 if (!scrollableArea()->scrollbarsCanBeActive())
835 return;
836 if (isScrollbarOverlayAPIAvailable())
837 [m_scrollbarPainterController.get() windowOrderedIn];
838 }
839
840 void ScrollAnimatorMac::contentAreaDidHide() const
841 {
842 if (!scrollableArea()->scrollbarsCanBeActive())
843 return;
844 if (isScrollbarOverlayAPIAvailable())
845 [m_scrollbarPainterController.get() windowOrderedOut];
846 }
847
848 void ScrollAnimatorMac::didBeginScrollGesture() const
849 {
850 if (!scrollableArea()->scrollbarsCanBeActive())
851 return;
852 if (isScrollbarOverlayAPIAvailable())
853 [m_scrollbarPainterController.get() beginScrollGesture];
854 }
855
856 void ScrollAnimatorMac::didEndScrollGesture() const
857 {
858 if (!scrollableArea()->scrollbarsCanBeActive())
859 return;
860 if (isScrollbarOverlayAPIAvailable())
861 [m_scrollbarPainterController.get() endScrollGesture];
862 }
863
864 void ScrollAnimatorMac::mayBeginScrollGesture() const
865 {
866 if (!scrollableArea()->scrollbarsCanBeActive())
867 return;
868 if (!isScrollbarOverlayAPIAvailable())
869 return;
870
871 [m_scrollbarPainterController.get() beginScrollGesture];
872 [m_scrollbarPainterController.get() contentAreaScrolled];
873 }
874
875 void ScrollAnimatorMac::finishCurrentScrollAnimations()
876 {
877 if (isScrollbarOverlayAPIAvailable()) {
878 [m_scrollbarPainterController.get() hideOverlayScrollers];
879 }
880 }
881
882 void ScrollAnimatorMac::didAddVerticalScrollbar(Scrollbar* scrollbar)
883 {
884 if (!isScrollbarOverlayAPIAvailable())
885 return;
886
887 ScrollbarPainter painter = scrollbarPainterForScrollbar(scrollbar);
888 if (!painter)
889 return;
890
891 ASSERT(!m_verticalScrollbarPainterDelegate);
892 m_verticalScrollbarPainterDelegate.adoptNS([[WebScrollbarPainterDelegate all oc] initWithScrollbar:scrollbar]);
893
894 [painter setDelegate:m_verticalScrollbarPainterDelegate.get()];
895 [m_scrollbarPainterController.get() setVerticalScrollerImp:painter];
896 if (scrollableArea()->inLiveResize())
897 [painter setKnobAlpha:1];
898 }
899
900 void ScrollAnimatorMac::willRemoveVerticalScrollbar(Scrollbar* scrollbar)
901 {
902 if (!isScrollbarOverlayAPIAvailable())
903 return;
904
905 ScrollbarPainter painter = scrollbarPainterForScrollbar(scrollbar);
906 if (!painter)
907 return;
908
909 ASSERT(m_verticalScrollbarPainterDelegate);
910 [m_verticalScrollbarPainterDelegate.get() invalidate];
911 m_verticalScrollbarPainterDelegate = nullptr;
912
913 [painter setDelegate:nil];
914 [m_scrollbarPainterController.get() setVerticalScrollerImp:nil];
915 }
916
917 void ScrollAnimatorMac::didAddHorizontalScrollbar(Scrollbar* scrollbar)
918 {
919 if (!isScrollbarOverlayAPIAvailable())
920 return;
921
922 ScrollbarPainter painter = scrollbarPainterForScrollbar(scrollbar);
923 if (!painter)
924 return;
925
926 ASSERT(!m_horizontalScrollbarPainterDelegate);
927 m_horizontalScrollbarPainterDelegate.adoptNS([[WebScrollbarPainterDelegate a lloc] initWithScrollbar:scrollbar]);
928
929 [painter setDelegate:m_horizontalScrollbarPainterDelegate.get()];
930 [m_scrollbarPainterController.get() setHorizontalScrollerImp:painter];
931 if (scrollableArea()->inLiveResize())
932 [painter setKnobAlpha:1];
933 }
934
935 void ScrollAnimatorMac::willRemoveHorizontalScrollbar(Scrollbar* scrollbar)
936 {
937 if (!isScrollbarOverlayAPIAvailable())
938 return;
939
940 ScrollbarPainter painter = scrollbarPainterForScrollbar(scrollbar);
941 if (!painter)
942 return;
943
944 ASSERT(m_horizontalScrollbarPainterDelegate);
945 [m_horizontalScrollbarPainterDelegate.get() invalidate];
946 m_horizontalScrollbarPainterDelegate = nullptr;
947
948 [painter setDelegate:nil];
949 [m_scrollbarPainterController.get() setHorizontalScrollerImp:nil];
950 }
951
952 bool ScrollAnimatorMac::shouldScrollbarParticipateInHitTesting(Scrollbar* scroll bar)
953 {
954 // Non-overlay scrollbars should always participate in hit testing.
955 if (recommendedScrollerStyle() != NSScrollerStyleOverlay)
956 return true;
957
958 if (!isScrollbarOverlayAPIAvailable())
959 return true;
960
961 if (scrollbar->isAlphaLocked())
962 return true;
963
964 // Overlay scrollbars should participate in hit testing whenever they are at all visible.
965 ScrollbarPainter painter = scrollbarPainterForScrollbar(scrollbar);
966 if (!painter)
967 return false;
968 return [painter knobAlpha] > 0;
969 }
970
971 void ScrollAnimatorMac::notifyContentAreaScrolled(const FloatSize& delta)
972 {
973 if (!isScrollbarOverlayAPIAvailable())
974 return;
975
976 // This function is called when a page is going into the page cache, but the page
977 // isn't really scrolling in that case. We should only pass the message on t o the
978 // ScrollbarPainterController when we're really scrolling on an active page.
979 if (scrollableArea()->scrollbarsCanBeActive())
980 sendContentAreaScrolledSoon(delta);
981 }
982
983 void ScrollAnimatorMac::cancelAnimations()
984 {
985 m_haveScrolledSincePageLoad = false;
986
987 if (isScrollbarOverlayAPIAvailable()) {
988 if (scrollbarPaintTimerIsActive())
989 stopScrollbarPaintTimer();
990 [m_horizontalScrollbarPainterDelegate.get() cancelAnimations];
991 [m_verticalScrollbarPainterDelegate.get() cancelAnimations];
992 }
993 }
994
995 void ScrollAnimatorMac::handleWheelEventPhase(PlatformWheelEventPhase phase)
996 {
997 // This may not have been set to true yet if the wheel event was handled by the ScrollingTree,
998 // So set it to true here.
999 m_haveScrolledSincePageLoad = true;
1000
1001 if (phase == PlatformWheelEventPhaseBegan)
1002 didBeginScrollGesture();
1003 else if (phase == PlatformWheelEventPhaseEnded || phase == PlatformWheelEven tPhaseCancelled)
1004 didEndScrollGesture();
1005 else if (phase == PlatformWheelEventPhaseMayBegin)
1006 mayBeginScrollGesture();
1007 }
1008
1009 #if USE(RUBBER_BANDING)
1010 bool ScrollAnimatorMac::handleWheelEvent(const PlatformWheelEvent& wheelEvent)
1011 {
1012 m_haveScrolledSincePageLoad = true;
1013
1014 if (!wheelEvent.hasPreciseScrollingDeltas() || !rubberBandingEnabledForSyste m())
1015 return ScrollAnimator::handleWheelEvent(wheelEvent);
1016
1017 // FIXME: This is somewhat roundabout hack to allow forwarding wheel events
1018 // up to the parent scrollable area. It takes advantage of the fact that
1019 // the base class implementation of handleWheelEvent will not accept the
1020 // wheel event if there is nowhere to scroll.
1021 if (fabsf(wheelEvent.deltaY()) >= fabsf(wheelEvent.deltaX())) {
1022 if (!allowsVerticalStretching())
1023 return ScrollAnimator::handleWheelEvent(wheelEvent);
1024 } else {
1025 if (!allowsHorizontalStretching())
1026 return ScrollAnimator::handleWheelEvent(wheelEvent);
1027 }
1028
1029 bool didHandleEvent = m_scrollElasticityController.handleWheelEvent(wheelEve nt);
1030
1031 // The elasticity controller can return false on a phase end event if rubber banding wasn't in progress.
1032 // In this case, the wheel phase must still be handled so that that overlay scroll bars get hidden.
1033 if (didHandleEvent || wheelEvent.phase() == PlatformWheelEventPhaseEnded || wheelEvent.phase() == PlatformWheelEventPhaseCancelled)
1034 handleWheelEventPhase(wheelEvent.phase());
1035
1036 return didHandleEvent;
1037 }
1038
1039 bool ScrollAnimatorMac::pinnedInDirection(float deltaX, float deltaY)
1040 {
1041 FloatSize limitDelta;
1042 if (fabsf(deltaY) >= fabsf(deltaX)) {
1043 if (deltaY < 0) {
1044 // We are trying to scroll up. Make sure we are not pinned to the t op
1045 limitDelta.setHeight(m_scrollableArea->visibleContentRect().y() + + m_scrollableArea->scrollOrigin().y());
1046 } else {
1047 // We are trying to scroll down. Make sure we are not pinned to the bottom
1048 limitDelta.setHeight(m_scrollableArea->contentsSize().height() - (m_ scrollableArea->visibleContentRect().maxY() + m_scrollableArea->scrollOrigin().y ()));
1049 }
1050 } else if (deltaX != 0) {
1051 if (deltaX < 0) {
1052 // We are trying to scroll left. Make sure we are not pinned to the left
1053 limitDelta.setWidth(m_scrollableArea->visibleContentRect().x() + m_s crollableArea->scrollOrigin().x());
1054 } else {
1055 // We are trying to scroll right. Make sure we are not pinned to th e right
1056 limitDelta.setWidth(m_scrollableArea->contentsSize().width() - (m_sc rollableArea->visibleContentRect().maxX() + m_scrollableArea->scrollOrigin().x() ));
1057 }
1058 }
1059
1060 if ((deltaX != 0 || deltaY != 0) && (limitDelta.width() < 1 && limitDelta.he ight() < 1))
1061 return true;
1062 return false;
1063 }
1064
1065 bool ScrollAnimatorMac::allowsVerticalStretching()
1066 {
1067 switch (m_scrollableArea->verticalScrollElasticity()) {
1068 case ScrollElasticityAutomatic: {
1069 Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
1070 Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
1071 return (((vScroller && vScroller->enabled()) || (!hScroller || !hScrolle r->enabled())));
1072 }
1073 case ScrollElasticityNone:
1074 return false;
1075 case ScrollElasticityAllowed:
1076 return true;
1077 }
1078
1079 ASSERT_NOT_REACHED();
1080 return false;
1081 }
1082
1083 bool ScrollAnimatorMac::allowsHorizontalStretching()
1084 {
1085 switch (m_scrollableArea->horizontalScrollElasticity()) {
1086 case ScrollElasticityAutomatic: {
1087 Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
1088 Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
1089 return (((hScroller && hScroller->enabled()) || (!vScroller || !vScrolle r->enabled())));
1090 }
1091 case ScrollElasticityNone:
1092 return false;
1093 case ScrollElasticityAllowed:
1094 return true;
1095 }
1096
1097 ASSERT_NOT_REACHED();
1098 return false;
1099 }
1100
1101 IntSize ScrollAnimatorMac::stretchAmount()
1102 {
1103 return m_scrollableArea->overhangAmount();
1104 }
1105
1106 bool ScrollAnimatorMac::pinnedInDirection(const FloatSize& direction)
1107 {
1108 return pinnedInDirection(direction.width(), direction.height());
1109 }
1110
1111 bool ScrollAnimatorMac::canScrollHorizontally()
1112 {
1113 Scrollbar* scrollbar = m_scrollableArea->horizontalScrollbar();
1114 if (!scrollbar)
1115 return false;
1116 return scrollbar->enabled();
1117 }
1118
1119 bool ScrollAnimatorMac::canScrollVertically()
1120 {
1121 Scrollbar* scrollbar = m_scrollableArea->verticalScrollbar();
1122 if (!scrollbar)
1123 return false;
1124 return scrollbar->enabled();
1125 }
1126
1127 bool ScrollAnimatorMac::shouldRubberBandInDirection(ScrollDirection direction)
1128 {
1129 return m_scrollableArea->shouldRubberBandInDirection(direction);
1130 }
1131
1132 IntPoint ScrollAnimatorMac::absoluteScrollPosition()
1133 {
1134 return m_scrollableArea->visibleContentRect().location() + m_scrollableArea- >scrollOrigin();
1135 }
1136
1137 void ScrollAnimatorMac::immediateScrollByWithoutContentEdgeConstraints(const Flo atSize& delta)
1138 {
1139 m_scrollableArea->setConstrainsScrollingToContentEdge(false);
1140 immediateScrollBy(delta);
1141 m_scrollableArea->setConstrainsScrollingToContentEdge(true);
1142 }
1143
1144 void ScrollAnimatorMac::immediateScrollBy(const FloatSize& delta)
1145 {
1146 FloatPoint newPos = adjustScrollPositionIfNecessary(FloatPoint(m_currentPosX , m_currentPosY) + delta);
1147 if (newPos.x() == m_currentPosX && newPos.y() == m_currentPosY)
1148 return;
1149
1150 FloatSize adjustedDelta = FloatSize(newPos.x() - m_currentPosX, newPos.y() - m_currentPosY);
1151
1152 m_currentPosX = newPos.x();
1153 m_currentPosY = newPos.y();
1154 notifyPositionChanged(adjustedDelta);
1155 }
1156
1157 void ScrollAnimatorMac::startSnapRubberbandTimer()
1158 {
1159 m_snapRubberBandTimer.startRepeating(1.0 / 60.0);
1160 }
1161
1162 void ScrollAnimatorMac::stopSnapRubberbandTimer()
1163 {
1164 m_snapRubberBandTimer.stop();
1165 }
1166
1167 void ScrollAnimatorMac::snapRubberBandTimerFired(Timer<ScrollAnimatorMac>*)
1168 {
1169 m_scrollElasticityController.snapRubberBandTimerFired();
1170 }
1171 #endif
1172
1173 void ScrollAnimatorMac::setIsActive()
1174 {
1175 if (!isScrollbarOverlayAPIAvailable())
1176 return;
1177
1178 if (!m_needsScrollerStyleUpdate)
1179 return;
1180
1181 updateScrollerStyle();
1182 }
1183
1184 void ScrollAnimatorMac::updateScrollerStyle()
1185 {
1186 if (!isScrollbarOverlayAPIAvailable())
1187 return;
1188
1189 if (!scrollableArea()->scrollbarsCanBeActive()) {
1190 m_needsScrollerStyleUpdate = true;
1191 return;
1192 }
1193
1194 ScrollbarThemeMacOverlayAPI* macTheme = macOverlayScrollbarTheme();
1195 if (!macTheme) {
1196 m_needsScrollerStyleUpdate = false;
1197 return;
1198 }
1199
1200 NSScrollerStyle newStyle = [m_scrollbarPainterController.get() scrollerStyle ];
1201
1202 if (Scrollbar* verticalScrollbar = scrollableArea()->verticalScrollbar()) {
1203 verticalScrollbar->invalidate();
1204
1205 ScrollbarPainter oldVerticalPainter = [m_scrollbarPainterController.get( ) verticalScrollerImp];
1206 ScrollbarPainter newVerticalPainter = [NSClassFromString(@"NSScrollerImp ") scrollerImpWithStyle:newStyle
1207 controlSize:(NSControlSize)verticalScrollbar->controlSize()
1208 horizontal:NO
1209 replacingScrollerImp:oldVerticalPainter];
1210 [m_scrollbarPainterController.get() setVerticalScrollerImp:newVerticalPa inter];
1211 macTheme->setNewPainterForScrollbar(verticalScrollbar, newVerticalPainte r);
1212
1213 // The different scrollbar styles have different thicknesses, so we must re-set the
1214 // frameRect to the new thickness, and the re-layout below will ensure t he position
1215 // and length are properly updated.
1216 int thickness = macTheme->scrollbarThickness(verticalScrollbar->controlS ize());
1217 verticalScrollbar->setFrameRect(IntRect(0, 0, thickness, thickness));
1218 }
1219
1220 if (Scrollbar* horizontalScrollbar = scrollableArea()->horizontalScrollbar() ) {
1221 horizontalScrollbar->invalidate();
1222
1223 ScrollbarPainter oldHorizontalPainter = [m_scrollbarPainterController.ge t() horizontalScrollerImp];
1224 ScrollbarPainter newHorizontalPainter = [NSClassFromString(@"NSScrollerI mp") scrollerImpWithStyle:newStyle
1225 controlSize:(NSControlSize)horizontalScrollbar->controlSize()
1226 horizontal:YES
1227 replacingScrollerImp:oldHorizontalPainter];
1228 [m_scrollbarPainterController.get() setHorizontalScrollerImp:newHorizont alPainter];
1229 macTheme->setNewPainterForScrollbar(horizontalScrollbar, newHorizontalPa inter);
1230
1231 // The different scrollbar styles have different thicknesses, so we must re-set the
1232 // frameRect to the new thickness, and the re-layout below will ensure t he position
1233 // and length are properly updated.
1234 int thickness = macTheme->scrollbarThickness(horizontalScrollbar->contro lSize());
1235 horizontalScrollbar->setFrameRect(IntRect(0, 0, thickness, thickness));
1236 }
1237
1238 // If m_needsScrollerStyleUpdate is true, then the page is restoring from th e page cache, and
1239 // a relayout will happen on its own. Otherwise, we must initiate a re-layou t ourselves.
1240 scrollableArea()->scrollbarStyleChanged(newStyle, !m_needsScrollerStyleUpdat e);
1241
1242 m_needsScrollerStyleUpdate = false;
1243 }
1244
1245 void ScrollAnimatorMac::startScrollbarPaintTimer()
1246 {
1247 m_initialScrollbarPaintTimer.startOneShot(0.1);
1248 }
1249
1250 bool ScrollAnimatorMac::scrollbarPaintTimerIsActive() const
1251 {
1252 return m_initialScrollbarPaintTimer.isActive();
1253 }
1254
1255 void ScrollAnimatorMac::stopScrollbarPaintTimer()
1256 {
1257 m_initialScrollbarPaintTimer.stop();
1258 }
1259
1260 void ScrollAnimatorMac::initialScrollbarPaintTimerFired(Timer<ScrollAnimatorMac> *)
1261 {
1262 if (isScrollbarOverlayAPIAvailable()) {
1263 // To force the scrollbars to flash, we have to call hide first. Otherwi se, the ScrollbarPainterController
1264 // might think that the scrollbars are already showing and bail early.
1265 [m_scrollbarPainterController.get() hideOverlayScrollers];
1266 [m_scrollbarPainterController.get() flashScrollers];
1267 }
1268 }
1269
1270 void ScrollAnimatorMac::sendContentAreaScrolledSoon(const FloatSize& delta)
1271 {
1272 m_contentAreaScrolledTimerScrollDelta = delta;
1273
1274 if (!m_sendContentAreaScrolledTimer.isActive())
1275 m_sendContentAreaScrolledTimer.startOneShot(0);
1276 }
1277
1278 void ScrollAnimatorMac::sendContentAreaScrolledTimerFired(Timer<ScrollAnimatorMa c>*)
1279 {
1280 if (supportsContentAreaScrolledInDirection()) {
1281 [m_scrollbarPainterController.get() contentAreaScrolledInDirection:NSMak ePoint(m_contentAreaScrolledTimerScrollDelta.width(), m_contentAreaScrolledTimer ScrollDelta.height())];
1282 m_contentAreaScrolledTimerScrollDelta = FloatSize();
1283 } else
1284 [m_scrollbarPainterController.get() contentAreaScrolled];
1285 }
1286
1287 void ScrollAnimatorMac::setVisibleScrollerThumbRect(const IntRect& scrollerThumb )
1288 {
1289 IntRect rectInViewCoordinates = scrollerThumb;
1290 if (Scrollbar* verticalScrollbar = m_scrollableArea->verticalScrollbar())
1291 rectInViewCoordinates = verticalScrollbar->convertToContainingView(scrol lerThumb);
1292
1293 if (rectInViewCoordinates == m_visibleScrollerThumbRect)
1294 return;
1295
1296 m_visibleScrollerThumbRect = rectInViewCoordinates;
1297 }
1298
1299 bool ScrollAnimatorMac::canUseCoordinatedScrollbar() {
1300 return isScrollbarOverlayAPIAvailable();
1301 }
1302
1303 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/platform/mac/ScrollAnimatorMac.h ('k') | Source/core/platform/mac/ScrollElasticityController.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698