| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2011, Google Inc. All rights reserved. | 2 * Copyright (c) 2011, Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 #include "ScrollbarTheme.h" | 41 #include "ScrollbarTheme.h" |
| 42 #include "TraceEvent.h" | 42 #include "TraceEvent.h" |
| 43 #include <algorithm> | 43 #include <algorithm> |
| 44 #include <wtf/CurrentTime.h> | 44 #include <wtf/CurrentTime.h> |
| 45 #include <wtf/PassOwnPtr.h> | 45 #include <wtf/PassOwnPtr.h> |
| 46 | 46 |
| 47 using namespace std; | 47 using namespace std; |
| 48 | 48 |
| 49 namespace WebCore { | 49 namespace WebCore { |
| 50 | 50 |
| 51 static double kTickTime = .0166; | 51 static double kFrameRate = 60; |
| 52 | 52 static double kTickTime = 1 / kFrameRate; |
| 53 // This is used to set the timer delay - it needs to be slightly smaller than th
e tick count to leave some overhead. | 53 static double kMinimumTimerInterval = .001; |
| 54 static double kAnimationTimerDelay = 0.015; | |
| 55 | 54 |
| 56 PassOwnPtr<ScrollAnimator> ScrollAnimator::create(ScrollableArea* scrollableArea
) | 55 PassOwnPtr<ScrollAnimator> ScrollAnimator::create(ScrollableArea* scrollableArea
) |
| 57 { | 56 { |
| 58 if (scrollableArea && scrollableArea->scrollAnimatorEnabled()) | 57 if (scrollableArea && scrollableArea->scrollAnimatorEnabled()) |
| 59 return adoptPtr(new ScrollAnimatorNone(scrollableArea)); | 58 return adoptPtr(new ScrollAnimatorNone(scrollableArea)); |
| 60 return adoptPtr(new ScrollAnimator(scrollableArea)); | 59 return adoptPtr(new ScrollAnimator(scrollableArea)); |
| 61 } | 60 } |
| 62 | 61 |
| 63 ScrollAnimatorNone::Parameters::Parameters() | 62 ScrollAnimatorNone::Parameters::Parameters() |
| 64 : m_isEnabled(false) | 63 : m_isEnabled(false) |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 return t * t * 3; | 123 return t * t * 3; |
| 125 case Cubic: | 124 case Cubic: |
| 126 return t * t * t * 4; | 125 return t * t * t * 4; |
| 127 case Bounce: | 126 case Bounce: |
| 128 return t; | 127 return t; |
| 129 } | 128 } |
| 130 } | 129 } |
| 131 | 130 |
| 132 ScrollAnimatorNone::PerAxisData::PerAxisData(ScrollAnimatorNone* parent, float*
currentPosition) | 131 ScrollAnimatorNone::PerAxisData::PerAxisData(ScrollAnimatorNone* parent, float*
currentPosition) |
| 133 : m_currentPosition(currentPosition) | 132 : m_currentPosition(currentPosition) |
| 134 , m_animationTimer(parent, &ScrollAnimatorNone::animationTimerFired) | |
| 135 { | 133 { |
| 136 reset(); | 134 reset(); |
| 137 } | 135 } |
| 138 | 136 |
| 139 void ScrollAnimatorNone::PerAxisData::reset() | 137 void ScrollAnimatorNone::PerAxisData::reset() |
| 140 { | 138 { |
| 141 m_currentVelocity = 0; | 139 m_currentVelocity = 0; |
| 142 | 140 |
| 143 m_desiredPosition = 0; | 141 m_desiredPosition = 0; |
| 144 m_desiredVelocity = 0; | 142 m_desiredVelocity = 0; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 | 185 |
| 188 if (newPosition == m_desiredPosition) | 186 if (newPosition == m_desiredPosition) |
| 189 return false; | 187 return false; |
| 190 | 188 |
| 191 m_desiredPosition = newPosition; | 189 m_desiredPosition = newPosition; |
| 192 | 190 |
| 193 if (!m_startTime) { | 191 if (!m_startTime) { |
| 194 // FIXME: This should be the time from the event that got us here. | 192 // FIXME: This should be the time from the event that got us here. |
| 195 m_startTime = currentTime - kTickTime / 2; | 193 m_startTime = currentTime - kTickTime / 2; |
| 196 m_startPosition = *m_currentPosition; | 194 m_startPosition = *m_currentPosition; |
| 197 m_lastAnimationTime = currentTime; | 195 m_lastAnimationTime = m_startTime; |
| 198 } | 196 } |
| 199 m_startVelocity = m_currentVelocity; | 197 m_startVelocity = m_currentVelocity; |
| 200 | 198 |
| 201 double remainingDelta = m_desiredPosition - *m_currentPosition; | 199 double remainingDelta = m_desiredPosition - *m_currentPosition; |
| 202 | 200 |
| 203 double attackAreaLeft = 0; | 201 double attackAreaLeft = 0; |
| 204 | 202 |
| 205 double deltaTime = m_lastAnimationTime - m_startTime; | 203 double deltaTime = m_lastAnimationTime - m_startTime; |
| 206 double attackTimeLeft = max(0., m_attackTime - deltaTime); | 204 double attackTimeLeft = max(0., m_attackTime - deltaTime); |
| 207 double timeLeft = m_animationTime - deltaTime; | 205 double timeLeft = m_animationTime - deltaTime; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 233 double roundOff = m_releasePosition - ((attackAreaLeft ? m_attackPositio
n : *m_currentPosition) + m_desiredVelocity * sustainTimeLeft); | 231 double roundOff = m_releasePosition - ((attackAreaLeft ? m_attackPositio
n : *m_currentPosition) + m_desiredVelocity * sustainTimeLeft); |
| 234 m_desiredVelocity += roundOff / sustainTimeLeft; | 232 m_desiredVelocity += roundOff / sustainTimeLeft; |
| 235 } | 233 } |
| 236 | 234 |
| 237 return true; | 235 return true; |
| 238 } | 236 } |
| 239 | 237 |
| 240 // FIXME: Add in jank detection trace events into this function. | 238 // FIXME: Add in jank detection trace events into this function. |
| 241 bool ScrollAnimatorNone::PerAxisData::animateScroll(double currentTime) | 239 bool ScrollAnimatorNone::PerAxisData::animateScroll(double currentTime) |
| 242 { | 240 { |
| 243 // Get the current time; grabbing the current time once helps keep a consist
ent heartbeat. | |
| 244 double lastScrollInterval = currentTime - m_lastAnimationTime; | 241 double lastScrollInterval = currentTime - m_lastAnimationTime; |
| 242 if (lastScrollInterval < kMinimumTimerInterval) |
| 243 return true; |
| 244 |
| 245 m_lastAnimationTime = currentTime; | 245 m_lastAnimationTime = currentTime; |
| 246 | 246 |
| 247 double deltaTime = currentTime - m_startTime; | 247 double deltaTime = currentTime - m_startTime; |
| 248 double newPosition = *m_currentPosition; | 248 double newPosition = *m_currentPosition; |
| 249 | 249 |
| 250 if (deltaTime > m_animationTime) { | 250 if (deltaTime > m_animationTime) { |
| 251 *m_currentPosition = m_desiredPosition; | 251 *m_currentPosition = m_desiredPosition; |
| 252 reset(); | 252 reset(); |
| 253 return false; | 253 return false; |
| 254 } | 254 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 267 m_currentVelocity = (newPosition - *m_currentPosition) / lastScrollInter
val; | 267 m_currentVelocity = (newPosition - *m_currentPosition) / lastScrollInter
val; |
| 268 *m_currentPosition = newPosition; | 268 *m_currentPosition = newPosition; |
| 269 | 269 |
| 270 return true; | 270 return true; |
| 271 } | 271 } |
| 272 | 272 |
| 273 ScrollAnimatorNone::ScrollAnimatorNone(ScrollableArea* scrollableArea) | 273 ScrollAnimatorNone::ScrollAnimatorNone(ScrollableArea* scrollableArea) |
| 274 : ScrollAnimator(scrollableArea) | 274 : ScrollAnimator(scrollableArea) |
| 275 , m_horizontalData(this, &m_currentPosX) | 275 , m_horizontalData(this, &m_currentPosX) |
| 276 , m_verticalData(this, &m_currentPosY) | 276 , m_verticalData(this, &m_currentPosY) |
| 277 , m_animationTimer(this, &ScrollAnimatorNone::animationTimerFired) |
| 277 { | 278 { |
| 278 } | 279 } |
| 279 | 280 |
| 280 ScrollAnimatorNone::~ScrollAnimatorNone() | 281 ScrollAnimatorNone::~ScrollAnimatorNone() |
| 281 { | 282 { |
| 282 stopAnimationTimerIfNeeded(&m_horizontalData); | 283 stopAnimationTimerIfNeeded(); |
| 283 stopAnimationTimerIfNeeded(&m_verticalData); | |
| 284 } | 284 } |
| 285 | 285 |
| 286 bool ScrollAnimatorNone::scroll(ScrollbarOrientation orientation, ScrollGranular
ity granularity, float step, float multiplier) | 286 bool ScrollAnimatorNone::scroll(ScrollbarOrientation orientation, ScrollGranular
ity granularity, float step, float multiplier) |
| 287 { | 287 { |
| 288 if (!m_scrollableArea->scrollAnimatorEnabled()) | 288 if (!m_scrollableArea->scrollAnimatorEnabled()) |
| 289 return ScrollAnimator::scroll(orientation, granularity, step, multiplier
); | 289 return ScrollAnimator::scroll(orientation, granularity, step, multiplier
); |
| 290 | 290 |
| 291 // FIXME: get the type passed in. MouseWheel could also be by line, but shou
ld still have different | 291 // FIXME: get the type passed in. MouseWheel could also be by line, but shou
ld still have different |
| 292 // animation parameters than the keyboard. | 292 // animation parameters than the keyboard. |
| 293 Parameters parameters; | 293 Parameters parameters; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 304 parameters = Parameters(true, 11 * kTickTime, 2 * kTickTime, Quadratic,
3 * kTickTime, Quadratic, 3 * kTickTime); | 304 parameters = Parameters(true, 11 * kTickTime, 2 * kTickTime, Quadratic,
3 * kTickTime, Quadratic, 3 * kTickTime); |
| 305 break; | 305 break; |
| 306 default: | 306 default: |
| 307 break; | 307 break; |
| 308 } | 308 } |
| 309 | 309 |
| 310 // If the individual input setting is disabled, bail. | 310 // If the individual input setting is disabled, bail. |
| 311 if (!parameters.m_isEnabled) | 311 if (!parameters.m_isEnabled) |
| 312 return ScrollAnimator::scroll(orientation, granularity, step, multiplier
); | 312 return ScrollAnimator::scroll(orientation, granularity, step, multiplier
); |
| 313 | 313 |
| 314 // This is an animatable scroll. Calculate the scroll delta. | 314 // This is an animatable scroll. Set the animation in motion using the appro
priate parameters. |
| 315 PerAxisData* data = (orientation == VerticalScrollbar) ? &m_verticalData : &
m_horizontalData; | 315 float scrollableSize = static_cast<float>(m_scrollableArea->scrollSize(orien
tation)); |
| 316 | 316 |
| 317 float scrollableSize = static_cast<float>(m_scrollableArea->scrollSize(orien
tation)); | 317 PerAxisData& data = (orientation == VerticalScrollbar) ? m_verticalData : m_
horizontalData; |
| 318 bool result = data->updateDataFromParameters(orientation, step, multiplier,
scrollableSize, WTF::currentTime(), ¶meters); | 318 bool needToScroll = data.updateDataFromParameters(orientation, step, multipl
ier, scrollableSize, WTF::monotonicallyIncreasingTime(), ¶meters); |
| 319 if (!data->m_animationTimer.isActive()) { | 319 if (needToScroll && !m_animationTimer.isActive()) { |
| 320 result &= data->animateScroll(WTF::currentTime()); | 320 m_startTime = data.m_startTime; |
| 321 if (result) | 321 animationTimerFired(&m_animationTimer); |
| 322 data->m_animationTimer.startOneShot(kAnimationTimerDelay); | |
| 323 } | 322 } |
| 324 notityPositionChanged(); | 323 return needToScroll; |
| 325 return result; | |
| 326 } | 324 } |
| 327 | 325 |
| 328 void ScrollAnimatorNone::scrollToOffsetWithoutAnimation(const FloatPoint& offset
) | 326 void ScrollAnimatorNone::scrollToOffsetWithoutAnimation(const FloatPoint& offset
) |
| 329 { | 327 { |
| 330 stopAnimationTimerIfNeeded(&m_horizontalData); | 328 stopAnimationTimerIfNeeded(); |
| 331 stopAnimationTimerIfNeeded(&m_verticalData); | |
| 332 | 329 |
| 333 m_horizontalData.reset(); | 330 m_horizontalData.reset(); |
| 334 *m_horizontalData.m_currentPosition = offset.x(); | 331 *m_horizontalData.m_currentPosition = offset.x(); |
| 335 m_horizontalData.m_desiredPosition = offset.x(); | 332 m_horizontalData.m_desiredPosition = offset.x(); |
| 336 | 333 |
| 337 m_verticalData.reset(); | 334 m_verticalData.reset(); |
| 338 *m_verticalData.m_currentPosition = offset.y(); | 335 *m_verticalData.m_currentPosition = offset.y(); |
| 339 m_verticalData.m_desiredPosition = offset.y(); | 336 m_verticalData.m_desiredPosition = offset.y(); |
| 340 | 337 |
| 341 notityPositionChanged(); | 338 notityPositionChanged(); |
| 342 } | 339 } |
| 343 | 340 |
| 344 void ScrollAnimatorNone::animationTimerFired(Timer<ScrollAnimatorNone>* timer) | 341 void ScrollAnimatorNone::animationTimerFired(Timer<ScrollAnimatorNone>* timer) |
| 345 { | 342 { |
| 346 double currentTime = WTF::currentTime(); | 343 double currentTime = WTF::monotonicallyIncreasingTime(); |
| 347 if ((timer == &m_horizontalData.m_animationTimer) ? | 344 double deltaToNextFrame = ceil((currentTime - m_startTime) * kFrameRate) / k
FrameRate - (currentTime - m_startTime); |
| 348 m_horizontalData.animateScroll(currentTime) : | 345 |
| 349 m_verticalData.animateScroll(currentTime)) | 346 bool continueAnimation = false; |
| 350 { | 347 if (m_horizontalData.m_startTime && m_horizontalData.animateScroll(currentTi
me + deltaToNextFrame)) |
| 351 double delta = WTF::currentTime() - currentTime; | 348 continueAnimation = true; |
| 352 timer->startOneShot(kAnimationTimerDelay - delta); | 349 if (m_verticalData.m_startTime && m_verticalData.animateScroll(currentTime +
deltaToNextFrame)) |
| 350 continueAnimation = true; |
| 351 if (continueAnimation) { |
| 352 double nextTimerInterval = max(kMinimumTimerInterval, deltaToNextFrame); |
| 353 timer->startOneShot(nextTimerInterval); |
| 353 } | 354 } |
| 354 notityPositionChanged(); | 355 notityPositionChanged(); |
| 355 } | 356 } |
| 356 | 357 |
| 357 void ScrollAnimatorNone::stopAnimationTimerIfNeeded(PerAxisData* data) | 358 void ScrollAnimatorNone::stopAnimationTimerIfNeeded() |
| 358 { | 359 { |
| 359 if (data->m_animationTimer.isActive()) | 360 if (m_animationTimer.isActive()) |
| 360 data->m_animationTimer.stop(); | 361 m_animationTimer.stop(); |
| 361 } | 362 } |
| 362 | 363 |
| 363 } // namespace WebCore | 364 } // namespace WebCore |
| 364 | 365 |
| 365 #endif // ENABLE(SMOOTH_SCROLLING) | 366 #endif // ENABLE(SMOOTH_SCROLLING) |
| OLD | NEW |