Wheel events' latching state is not reset when appropriate
authortonikitoo@webkit.org <tonikitoo@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 29 Mar 2016 22:17:04 +0000 (22:17 +0000)
committertonikitoo@webkit.org <tonikitoo@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 29 Mar 2016 22:17:04 +0000 (22:17 +0000)
commit7e34f2d249c3192f5d1d2f8dc554d6a5bbdfb28b
treeba6560115baa4bd4ff692f371a338b73a913de80
parent0cf16f6b1b12c0e145b3ae645847ab0e2f038127
Wheel events' latching state is not reset when appropriate
https://bugs.webkit.org/show_bug.cgi?id=155746

Reviewed by Simon Fraser.

Source/WebCore:

When one performs a two fingers scroll (with trackpad),
it might either trigger a kinetic scroll movement (by
flickering with both fingers in a given direction) or perform
a static scroll movement (without the flicker animation).

In case of the first scenario (kinetic), the container being
scrolled is "latched" during the scroll animation and properly unlatched
once the scroll ends. See the call to 'shouldResetLatching' in EventHandlerMac.mm.
When transitioning from non-momentum to momentum scroll, the following events are seen:
- 'phase PlatformWheelEventPhaseEnded' 'momentumPhase PlatformWheelEventPhaseNone' -> end of static scroll
- 'phase PlatformWheelEventPhaseNone' 'momentumPhase PlatformWheelEventPhaseBegan' -> start of momentum scroll

On the second scenario (static scroll), when the scroll movement ends,
the latched state is not reset. This might actually cause scrolling elsewhere on the page to scroll
the previously latched container.
Note that, only specific wheel event below is fired when static scroll ends:
- 'phase PlatformWheelEventPhaseEnded' 'momentumPhase PlatformWheelEventPhaseNone'

In order to fix this, patch installs a timer as soon as a non-momentum
wheel scroll event end fires. It works as follows:

- If the timer fires, the latched state is reset, preventing scrolling getting stuck to
a previously latched scrollable.
- If platform code starts sending momentum wheel scroll events before it times out, the timer is
stopped and the latched state remains untouched (this is a flick scroll case).
- If a new wheel scroll gesture starts, the latched state is manually reset
and the timer stopped.

Note that given that latched state logic applies primarily to main frames,
the timer only gets manipulated for main frame objects.

Test: tiled-drawing/scrolling/scroll-iframe-latched-selects.html

* page/EventHandler.cpp:
(WebCore::EventHandler::doOrScheduleClearLatchedStateIfNeeded):
* page/EventHandler.h:
* page/MainFrame.cpp:
(WebCore::MainFrame::MainFrame):
(WebCore::MainFrame::~MainFrame):
* page/MainFrame.h:
* page/mac/EventHandlerMac.mm:
(WebCore::scrollableAreaForContainerNode):
(WebCore::latchedToFrameOrBody):
(WebCore::areWheelEventsTransitioningToMomentumScrolling):
(WebCore::areWheelEventsEndingNonMomentumScrolling):
(WebCore::EventHandler::doOrScheduleClearLatchedStateIfNeeded):

LayoutTests:

* tiled-drawing/scrolling/resources/selects-iframe.html: Added.
* tiled-drawing/scrolling/scroll-iframe-latched-selects.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@198805 268f45cc-cd09-0410-ab3c-d52691b4dbfc
LayoutTests/ChangeLog
LayoutTests/tiled-drawing/scrolling/resources/selects-iframe.html [new file with mode: 0644]
LayoutTests/tiled-drawing/scrolling/scroll-iframe-latched-selects-expected.txt [new file with mode: 0644]
LayoutTests/tiled-drawing/scrolling/scroll-iframe-latched-selects.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/page/EventHandler.cpp
Source/WebCore/page/EventHandler.h
Source/WebCore/page/MainFrame.h
Source/WebCore/page/mac/EventHandlerMac.mm
Source/WebCore/platform/PlatformWheelEvent.h