Changeset 134150 in webkit
- Timestamp:
- Nov 9, 2012 9:16:00 PM (11 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r134149 r134150 1 2012-11-09 Ojan Vafai <ojan@chromium.org> 2 3 Should only fire a single set of mouse events and update hover state once when scrolling is done 4 https://bugs.webkit.org/show_bug.cgi?id=99940 5 6 Reviewed by Levi Weintraub. 7 8 Tests basic throttling. I couldn't think of a good way to test changing 9 the delay that wouldn't make for a test that takes minutes to run. 10 11 * fast/scrolling/fake-mouse-event-throttling-expected.txt: Added. 12 * fast/scrolling/fake-mouse-event-throttling.html: Added. 13 1 14 2012-11-09 Rick Byers <rbyers@chromium.org> 2 15 -
trunk/LayoutTests/platform/mac/TestExpectations
r133884 r134150 1166 1166 platform/mac/tiled-drawing/ [ Skip ] 1167 1167 1168 # DRT is not firing fake mouse events. Safari fires them fine. Looks like a bug with Apple's Mac DRT. 1169 webkit.org/b/101808 fast/scrolling/fake-mouse-event-throttling.html [ Skip ] 1170 1168 1171 webkit.org/b/100846 inspector-protocol/debugger-pause-dedicated-worker.html [ Skip ] 1169 1172 webkit.org/b/100846 inspector-protocol/debugger-terminate-dedicated-worker-while-paused.html [ Skip ] -
trunk/Source/WebCore/ChangeLog
r134149 r134150 1 2012-11-09 Ojan Vafai <ojan@chromium.org> 2 3 Should only fire a single set of mouse events and update hover state once when scrolling is done 4 https://bugs.webkit.org/show_bug.cgi?id=99940 5 6 Reviewed by Levi Weintraub. 7 8 -Use a DeferrableOneShotTimer instead of a Timer. By resetting when the 9 timer is fired, we ensure the actual goal of not firing fake mouse events 10 until the scroll is completed. This is the core part of this change. 11 -Change our mouse event throttling to keep a running average of how long 12 mouse events take and adjust throttling appropriately. 13 Test: fast/scrolling/fake-mouse-event-throttling.html 14 -Maintain a minimum throttle of 100ms. 15 16 * page/EventHandler.cpp: 17 (WebCore): 18 (WebCore::RunningAverageDurationTracker::RunningAverageDurationTracker): 19 (WebCore::RunningAverageDurationTracker::~RunningAverageDurationTracker): 20 Keep track of a running average instead of max. This lets us adjust throttling 21 dynamically without punishing a page for having a single mouse event handler 22 that takes disproportionately long. 23 (RunningAverageDurationTracker): 24 (WebCore::EventHandler::EventHandler): 25 (WebCore::EventHandler::clear): 26 (WebCore::EventHandler::mouseMoved): 27 (WebCore::EventHandler::handleMouseMoveEvent): 28 (WebCore::EventHandler::dispatchFakeMouseMoveEventSoon): 29 (WebCore::EventHandler::fakeMouseMoveEventTimerFired): 30 * page/EventHandler.h: 31 (EventHandler): 32 * platform/Timer.h: 33 (WebCore::DeferrableOneShotTimer::setDelay): 34 (WebCore::DeferrableOneShotTimer::delay): 35 Add a way of adjusting the timer delay. 36 1 37 2012-11-09 Rick Byers <rbyers@chromium.org> 2 38 -
trunk/Source/WebCore/page/EventHandler.cpp
r134144 r134150 137 137 const double autoscrollInterval = 0.05; 138 138 139 // The amount of time to wait before sending a fake mouse event, triggered 140 // during a scroll. The short interval is used if the content responds to the mouse events quickly enough, 141 // otherwise the long interval is used. 142 const double fakeMouseMoveShortInterval = 0.1; 143 const double fakeMouseMoveLongInterval = 0.250; 139 // The amount of time to wait before sending a fake mouse event, triggered during a scroll. 140 const double fakeMouseMoveMinimumInterval = 0.1; 141 // Amount to increase the fake mouse event throttling when the running average exceeds the delay. 142 // Picked fairly arbitrarily. 143 const double fakeMouseMoveIntervalIncrease = 0.05; 144 const double fakeMouseMoveRunningAverageCount = 10; 145 // Decrease the fakeMouseMoveInterval when the current delay is >2x the running average, 146 // but only decrease to 3/4 the current delay to avoid too much thrashing. 147 // Not sure this distinction really matters in practice. 148 const double fakeMouseMoveIntervalReductionLimit = 0.5; 149 const double fakeMouseMoveIntervalReductionFraction = 0.75; 144 150 145 151 enum NoCursorChangeType { NoCursorChange }; … … 158 164 }; 159 165 160 class MaximumDurationTracker {166 class RunningAverageDurationTracker { 161 167 public: 162 explicit MaximumDurationTracker(double *maxDuration) 163 : m_maxDuration(maxDuration) 168 RunningAverageDurationTracker(double* average, unsigned numberOfRunsToTrack) 169 : m_average(average) 170 , m_numberOfRunsToTrack(numberOfRunsToTrack) 164 171 , m_start(monotonicallyIncreasingTime()) 165 172 { 166 173 } 167 174 168 ~ MaximumDurationTracker()175 ~RunningAverageDurationTracker() 169 176 { 170 *m_maxDuration = max(*m_maxDuration, monotonicallyIncreasingTime() - m_start); 177 double duration = monotonicallyIncreasingTime() - m_start; 178 if (!*m_average) { 179 *m_average = duration; 180 return; 181 } 182 *m_average = (*m_average * (m_numberOfRunsToTrack - 1) + (duration)) / m_numberOfRunsToTrack; 171 183 } 172 184 173 185 private: 174 double* m_maxDuration; 186 double* m_average; 187 unsigned m_numberOfRunsToTrack; 175 188 double m_start; 176 189 }; … … 317 330 , m_mouseDownMayStartAutoscroll(false) 318 331 , m_mouseDownWasInSubframe(false) 319 , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFired )332 , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFired, fakeMouseMoveMinimumInterval) 320 333 #if ENABLE(SVG) 321 334 , m_svgPan(false) … … 334 347 , m_touchPressed(false) 335 348 #endif 336 , m_m axMouseMovedDuration(0)349 , m_mouseMovedDurationRunningAverage(0) 337 350 , m_baseEventType(PlatformEvent::NoType) 338 351 { … … 386 399 m_scrollGestureHandlingNode = 0; 387 400 #endif 388 m_m axMouseMovedDuration= 0;401 m_mouseMovedDurationRunningAverage = 0; 389 402 m_baseEventType = PlatformEvent::NoType; 390 403 } … … 1733 1746 { 1734 1747 RefPtr<FrameView> protector(m_frame->view()); 1735 MaximumDurationTracker maxDurationTracker(&m_maxMouseMovedDuration);1748 RunningAverageDurationTracker durationTracker(&m_mouseMovedDurationRunningAverage, fakeMouseMoveRunningAverageCount); 1736 1749 1737 1750 … … 2864 2877 return; 2865 2878 2866 // If the content has ever taken longer than fakeMouseMoveShortInterval we 2867 // reschedule the timer and use a longer time. This will cause the content 2868 // to receive these moves only after the user is done scrolling, reducing 2869 // pauses during the scroll. 2870 if (m_maxMouseMovedDuration > fakeMouseMoveShortInterval) { 2871 if (m_fakeMouseMoveEventTimer.isActive()) 2872 m_fakeMouseMoveEventTimer.stop(); 2873 m_fakeMouseMoveEventTimer.startOneShot(fakeMouseMoveLongInterval); 2874 } else { 2875 if (!m_fakeMouseMoveEventTimer.isActive()) 2876 m_fakeMouseMoveEventTimer.startOneShot(fakeMouseMoveShortInterval); 2877 } 2879 // Adjust the mouse move throttling so that it's roughly around our running average of the duration of mousemove events. 2880 // This will cause the content to receive these moves only after the user is done scrolling, reducing pauses during the scroll. 2881 // This will only measure the duration of the mousemove event though (not for example layouts), 2882 // so maintain at least a minimum interval. 2883 if (m_mouseMovedDurationRunningAverage > m_fakeMouseMoveEventTimer.delay()) 2884 m_fakeMouseMoveEventTimer.setDelay(m_mouseMovedDurationRunningAverage + fakeMouseMoveIntervalIncrease); 2885 else if (m_mouseMovedDurationRunningAverage < fakeMouseMoveIntervalReductionLimit * m_fakeMouseMoveEventTimer.delay()) 2886 m_fakeMouseMoveEventTimer.setDelay(max(fakeMouseMoveMinimumInterval, fakeMouseMoveIntervalReductionFraction * m_fakeMouseMoveEventTimer.delay())); 2887 m_fakeMouseMoveEventTimer.restart(); 2878 2888 } 2879 2889 … … 2895 2905 } 2896 2906 2897 void EventHandler::fakeMouseMoveEventTimerFired( Timer<EventHandler>* timer)2907 void EventHandler::fakeMouseMoveEventTimerFired(DeferrableOneShotTimer<EventHandler>* timer) 2898 2908 { 2899 2909 ASSERT_UNUSED(timer, timer == &m_fakeMouseMoveEventTimer); -
trunk/Source/WebCore/page/EventHandler.h
r134144 r134150 283 283 static bool eventInvertsTabsToLinksClientCallResult(KeyboardEvent*); 284 284 285 void fakeMouseMoveEventTimerFired( Timer<EventHandler>*);285 void fakeMouseMoveEventTimerFired(DeferrableOneShotTimer<EventHandler>*); 286 286 void cancelFakeMouseMoveEvent(); 287 287 … … 406 406 bool m_mouseDownWasInSubframe; 407 407 408 Timer<EventHandler> m_fakeMouseMoveEventTimer;408 DeferrableOneShotTimer<EventHandler> m_fakeMouseMoveEventTimer; 409 409 410 410 #if ENABLE(SVG) … … 463 463 #endif 464 464 465 double m_m axMouseMovedDuration;465 double m_mouseMovedDurationRunningAverage; 466 466 PlatformEvent::Type m_baseEventType; 467 467 }; -
trunk/Source/WebCore/platform/Timer.h
r130720 r134150 141 141 } 142 142 143 void setDelay(double delay) 144 { 145 m_delay = delay; 146 if (isActive()) { 147 stop(); 148 restart(); 149 } 150 } 151 152 double delay() const { return m_delay; } 153 143 154 using TimerBase::stop; 144 155 using TimerBase::isActive;
Note: See TracChangeset
for help on using the changeset viewer.