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 |