OLD | NEW |
| (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 | |
OLD | NEW |