Changeset 219310 in webkit


Ignore:
Timestamp:
Jul 10, 2017 3:08:38 PM (7 years ago)
Author:
Wenson Hsieh
Message:

[WK2] Ignore touch events that interrupt platform-driven momentum scrolling
https://bugs.webkit.org/show_bug.cgi?id=174300
<rdar://problem/33030639>

Reviewed by Simon Fraser.

Source/WebCore:

See Source/WebKit2/ChangeLog for more detail.

Tests: fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-mainframe.html

fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-overflow.html
fast/events/ios/touch-events-during-scroll-deceleration-in-overflow.html

  • page/scrolling/ScrollingTree.h:

(WebCore::ScrollingTree::scrollingTreeNodeDidEndPanGesture):

Source/WebKit2:

Adds support for immediately failing WKContentView's UIWebTouchEventsGestureRecognizer if any touch interrupts
scroll view deceleration. Covered by 3 new LayoutTests (see Source/WebCore/ChangeLog).

  • Platform/spi/ios/UIKitSPI.h:
  • UIProcess/API/Cocoa/WKWebView.mm:

(-[WKWebView scrollViewDidEndDragging:willDecelerate:]):
(-[WKWebView scrollViewDidEndZooming:withView:atScale:]):

  • UIProcess/PageClient.h:
  • UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h:
  • UIProcess/Scrolling/RemoteScrollingTree.cpp:

(WebKit::RemoteScrollingTree::scrollingTreeNodeDidEndPanGesture):

  • UIProcess/Scrolling/RemoteScrollingTree.h:
  • UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h:
  • UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm:

(-[WKOverflowScrollViewDelegate scrollViewDidEndDragging:willDecelerate:]):
(WebKit::ScrollingTreeOverflowScrollingNodeIOS::overflowScrollViewDidEndPanGesture):

Adds plumbing in the UI process to alert the WKContentView when scroll view dragging has ended in an overflow
momentum scrolling region (tracked by an overflow scrolling tree node). This parallels UI process plumbing for
ScrollingTreeOverflowScrollingNodeIOS::overflowScrollViewWillStartPanGesture.

  • UIProcess/WebPageProxy.h:
  • UIProcess/ios/PageClientImplIOS.h:
  • UIProcess/ios/PageClientImplIOS.mm:

(WebKit::PageClientImpl::overflowScrollViewDidEndPanGesture):

  • UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm:

(WebKit::RemoteScrollingCoordinatorProxy::scrollingTreeNodeDidEndPanGesture):

  • UIProcess/ios/WKContentViewInteraction.h:
  • UIProcess/ios/WKContentViewInteraction.mm:

(-[WKContentView scrollViewDidEndPanOrPinchGesture]):

When the dragging phase of a scroll gesture ends, ensure that _canSendTouchEventsAsynchronously is reset to NO.
When touches are not being prevented, this flag is set to YES in -scrollViewWillStartPanOrPinchGesture: and
normally reset to NO in -_webTouchEventsRecognized: after all touch points have been released. However, in the
case where we've prematurely failed the web touch events gesture recognizer after -touchesBegan:,
-_webTouchEventsRecognized: will not be called again in a state where all touches have been released. Thus, we
also need to bookend the place where we begin allowing async touch event dispatch in
-scrollViewWillStartPanOrPinchGesture by disallowing async touch event dispatch in
-scrollViewDidEndPanOrPinchGesture.

This has no impact in the normal case where the user scrolls without momentum, since
-scrollViewDidEndPanOrPinchGesture will fire after async touch events have already been disallowed in
-_webTouchEventsRecognized:, and in the case where the page prevents default on touches, scrolling doesn't
happen anyways, so neither scrollViewWillStartPanOrPinchGesture nor scrollViewDidEndPanOrPinchGesture will be
invoked.

(-[WKContentView gestureRecognizer:shouldIgnoreWebTouchWithEvent:]):

Implements a new SPI hook in UIKit. This serves an identical purpose as -shouldIgnoreWebTouch, but additionally
passes the triggering UIEvent, as well as the gesture recognizer itself (following standard convention for
Objective C delegate methods). Here, we return YES in the case where one or more of the touches recognized by
the gesture is currently interrupting scroll deceleration.

  • UIProcess/ios/WebPageProxyIOS.mm:

(WebKit::WebPageProxy::overflowScrollViewDidEndPanGesture):

LayoutTests:

Adds 3 new LayoutTests covering cases of touch event handling during scroll deceleration in mainframe and
overflow scrolling containers. See Source/WebKit2/ChangeLog for more detail.

  • fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-mainframe-expected.txt: Added.
  • fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-mainframe.html: Added.
  • fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-overflow-expected.txt: Added.
  • fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-overflow.html: Added.
  • fast/events/ios/touch-events-during-scroll-deceleration-in-overflow-expected.txt: Added.
  • fast/events/ios/touch-events-during-scroll-deceleration-in-overflow.html: Added.
Location:
trunk
Files:
6 added
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r219309 r219310  
     12017-07-10  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [WK2] Ignore touch events that interrupt platform-driven momentum scrolling
     4        https://bugs.webkit.org/show_bug.cgi?id=174300
     5        <rdar://problem/33030639>
     6
     7        Reviewed by Simon Fraser.
     8
     9        Adds 3 new LayoutTests covering cases of touch event handling during scroll deceleration in mainframe and
     10        overflow scrolling containers. See Source/WebKit2/ChangeLog for more detail.
     11
     12        * fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-mainframe-expected.txt: Added.
     13        * fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-mainframe.html: Added.
     14        * fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-overflow-expected.txt: Added.
     15        * fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-overflow.html: Added.
     16        * fast/events/ios/touch-events-during-scroll-deceleration-in-overflow-expected.txt: Added.
     17        * fast/events/ios/touch-events-during-scroll-deceleration-in-overflow.html: Added.
     18
    1192017-07-10  Matt Lewis  <jlewis3@apple.com>
    220
  • trunk/Source/WebCore/ChangeLog

    r219307 r219310  
     12017-07-10  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [WK2] Ignore touch events that interrupt platform-driven momentum scrolling
     4        https://bugs.webkit.org/show_bug.cgi?id=174300
     5        <rdar://problem/33030639>
     6
     7        Reviewed by Simon Fraser.
     8
     9        See Source/WebKit2/ChangeLog for more detail.
     10
     11        Tests: fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-mainframe.html
     12               fast/events/ios/no-touch-events-when-stopping-momentum-scroll-in-overflow.html
     13               fast/events/ios/touch-events-during-scroll-deceleration-in-overflow.html
     14
     15        * page/scrolling/ScrollingTree.h:
     16        (WebCore::ScrollingTree::scrollingTreeNodeDidEndPanGesture):
     17
    1182017-07-10  Jeremy Jones  <jeremyj@apple.com>
    219
  • trunk/Source/WebCore/page/scrolling/ScrollingTree.h

    r217737 r219310  
    102102    virtual FloatRect fixedPositionRect() = 0;
    103103    virtual void scrollingTreeNodeWillStartPanGesture() { }
     104    virtual void scrollingTreeNodeDidEndPanGesture() { }
    104105    virtual void scrollingTreeNodeWillStartScroll() { }
    105106    virtual void scrollingTreeNodeDidEndScroll() { }
  • trunk/Source/WebKit2/ChangeLog

    r219308 r219310  
     12017-07-10  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [WK2] Ignore touch events that interrupt platform-driven momentum scrolling
     4        https://bugs.webkit.org/show_bug.cgi?id=174300
     5        <rdar://problem/33030639>
     6
     7        Reviewed by Simon Fraser.
     8
     9        Adds support for immediately failing WKContentView's UIWebTouchEventsGestureRecognizer if any touch interrupts
     10        scroll view deceleration. Covered by 3 new LayoutTests (see Source/WebCore/ChangeLog).
     11
     12        * Platform/spi/ios/UIKitSPI.h:
     13        * UIProcess/API/Cocoa/WKWebView.mm:
     14        (-[WKWebView scrollViewDidEndDragging:willDecelerate:]):
     15        (-[WKWebView scrollViewDidEndZooming:withView:atScale:]):
     16        * UIProcess/PageClient.h:
     17        * UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h:
     18        * UIProcess/Scrolling/RemoteScrollingTree.cpp:
     19        (WebKit::RemoteScrollingTree::scrollingTreeNodeDidEndPanGesture):
     20        * UIProcess/Scrolling/RemoteScrollingTree.h:
     21        * UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h:
     22        * UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm:
     23        (-[WKOverflowScrollViewDelegate scrollViewDidEndDragging:willDecelerate:]):
     24        (WebKit::ScrollingTreeOverflowScrollingNodeIOS::overflowScrollViewDidEndPanGesture):
     25
     26        Adds plumbing in the UI process to alert the WKContentView when scroll view dragging has ended in an overflow
     27        momentum scrolling region (tracked by an overflow scrolling tree node). This parallels UI process plumbing for
     28        ScrollingTreeOverflowScrollingNodeIOS::overflowScrollViewWillStartPanGesture.
     29
     30        * UIProcess/WebPageProxy.h:
     31        * UIProcess/ios/PageClientImplIOS.h:
     32        * UIProcess/ios/PageClientImplIOS.mm:
     33        (WebKit::PageClientImpl::overflowScrollViewDidEndPanGesture):
     34        * UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm:
     35        (WebKit::RemoteScrollingCoordinatorProxy::scrollingTreeNodeDidEndPanGesture):
     36        * UIProcess/ios/WKContentViewInteraction.h:
     37        * UIProcess/ios/WKContentViewInteraction.mm:
     38        (-[WKContentView scrollViewDidEndPanOrPinchGesture]):
     39
     40        When the dragging phase of a scroll gesture ends, ensure that _canSendTouchEventsAsynchronously is reset to NO.
     41        When touches are not being prevented, this flag is set to YES in -scrollViewWillStartPanOrPinchGesture: and
     42        normally reset to NO in -_webTouchEventsRecognized: after all touch points have been released. However, in the
     43        case where we've prematurely failed the web touch events gesture recognizer after -touchesBegan:,
     44        -_webTouchEventsRecognized: will not be called again in a state where all touches have been released. Thus, we
     45        also need to bookend the place where we begin allowing async touch event dispatch in
     46        -scrollViewWillStartPanOrPinchGesture by disallowing async touch event dispatch in
     47        -scrollViewDidEndPanOrPinchGesture.
     48
     49        This has no impact in the normal case where the user scrolls without momentum, since
     50        -scrollViewDidEndPanOrPinchGesture will fire after async touch events have already been disallowed in
     51        -_webTouchEventsRecognized:, and in the case where the page prevents default on touches, scrolling doesn't
     52        happen anyways, so neither scrollViewWillStartPanOrPinchGesture nor scrollViewDidEndPanOrPinchGesture will be
     53        invoked.
     54
     55        (-[WKContentView gestureRecognizer:shouldIgnoreWebTouchWithEvent:]):
     56
     57        Implements a new SPI hook in UIKit. This serves an identical purpose as -shouldIgnoreWebTouch, but additionally
     58        passes the triggering UIEvent, as well as the gesture recognizer itself (following standard convention for
     59        Objective C delegate methods). Here, we return YES in the case where one or more of the touches recognized by
     60        the gesture is currently interrupting scroll deceleration.
     61
     62        * UIProcess/ios/WebPageProxyIOS.mm:
     63        (WebKit::WebPageProxy::overflowScrollViewDidEndPanGesture):
     64
    1652017-07-10  Brent Fulgham  <bfulgham@apple.com>
    266
  • trunk/Source/WebKit2/Platform/spi/ios/UIKitSPI.h

    r219225 r219310  
    690690};
    691691
    692 @protocol UIWebTouchEventsGestureRecognizerDelegate
     692@class UIWebTouchEventsGestureRecognizer;
     693
     694@protocol UIWebTouchEventsGestureRecognizerDelegate <NSObject>
    693695- (BOOL)isAnyTouchOverActiveArea:(NSSet *)touches;
    694 - (BOOL)shouldIgnoreWebTouch;
     696@optional
     697- (BOOL)gestureRecognizer:(UIWebTouchEventsGestureRecognizer *)gestureRecognizer shouldIgnoreWebTouchWithEvent:(UIEvent *)event;
    695698@end
    696699
  • trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm

    r219293 r219310  
    21512151    if (!decelerate)
    21522152        [self _didFinishScrolling];
     2153
     2154    if (scrollView.panGestureRecognizer.state == UIGestureRecognizerStateEnded)
     2155        [_contentView scrollViewDidEndPanOrPinchGesture];
    21532156}
    21542157
     
    21852188    [self _scheduleVisibleContentRectUpdateAfterScrollInView:scrollView];
    21862189    [_contentView didZoomToScale:scale];
     2190
     2191    if (scrollView.pinchGestureRecognizer.state == UIGestureRecognizerStateEnded)
     2192        [_contentView scrollViewDidEndPanOrPinchGesture];
    21872193}
    21882194
  • trunk/Source/WebKit2/UIProcess/PageClient.h

    r218837 r219310  
    309309    virtual WebCore::FloatRect documentRect() const = 0;
    310310    virtual void overflowScrollViewWillStartPanGesture() = 0;
     311    virtual void overflowScrollViewDidEndPanGesture() = 0;
    311312    virtual void overflowScrollViewDidScroll() = 0;
    312313    virtual void overflowScrollWillStartScroll() = 0;
  • trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h

    r208985 r219310  
    8787    WebCore::FloatRect customFixedPositionRect() const;
    8888    void scrollingTreeNodeWillStartPanGesture();
     89    void scrollingTreeNodeDidEndPanGesture();
    8990    void scrollingTreeNodeWillStartScroll();
    9091    void scrollingTreeNodeDidEndScroll();
  • trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingTree.cpp

    r211033 r219310  
    8888    m_scrollingCoordinatorProxy.scrollingTreeNodeWillStartPanGesture();
    8989}
     90
     91void RemoteScrollingTree::scrollingTreeNodeDidEndPanGesture()
     92{
     93    m_scrollingCoordinatorProxy.scrollingTreeNodeDidEndPanGesture();
     94}
    9095   
    9196void RemoteScrollingTree::scrollingTreeNodeWillStartScroll()
  • trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingTree.h

    r211033 r219310  
    6262    WebCore::FloatRect fixedPositionRect() override;
    6363    void scrollingTreeNodeWillStartPanGesture() override;
     64    void scrollingTreeNodeDidEndPanGesture() override;
    6465    void scrollingTreeNodeWillStartScroll() override;
    6566    void scrollingTreeNodeDidEndScroll() override;
  • trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h

    r208503 r219310  
    4545    void overflowScrollDidEnd();
    4646    void overflowScrollViewWillStartPanGesture();
     47    void overflowScrollViewDidEndPanGesture();
    4748    void scrollViewDidScroll(const WebCore::FloatPoint&, bool inUserInteration);
    4849    void currentSnapPointIndicesDidChange(unsigned horizontal, unsigned vertical);
  • trunk/Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm

    r219137 r219310  
    118118        _scrollingTreeNode->overflowScrollDidEnd();
    119119    }
     120
     121    if (scrollView.panGestureRecognizer.state == UIGestureRecognizerStateEnded)
     122        _scrollingTreeNode->overflowScrollViewDidEndPanGesture();
    120123}
    121124
     
    295298}
    296299
     300void ScrollingTreeOverflowScrollingNodeIOS::overflowScrollViewDidEndPanGesture()
     301{
     302    scrollingTree().scrollingTreeNodeDidEndPanGesture();
     303}
     304
    297305void ScrollingTreeOverflowScrollingNodeIOS::scrollViewDidScroll(const FloatPoint& scrollPosition, bool inUserInteration)
    298306{
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.h

    r219154 r219310  
    496496
    497497    void overflowScrollViewWillStartPanGesture();
     498    void overflowScrollViewDidEndPanGesture();
    498499    void overflowScrollViewDidScroll();
    499500    void overflowScrollWillStartScroll();
  • trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.h

    r218837 r219310  
    152152
    153153    void overflowScrollViewWillStartPanGesture() override;
     154    void overflowScrollViewDidEndPanGesture() override;
    154155    void overflowScrollViewDidScroll() override;
    155156    void overflowScrollWillStartScroll() override;
  • trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm

    r218837 r219310  
    672672}
    673673
     674void PageClientImpl::overflowScrollViewDidEndPanGesture()
     675{
     676    [m_contentView scrollViewDidEndPanOrPinchGesture];
     677}
     678
    674679void PageClientImpl::overflowScrollViewDidScroll()
    675680{
  • trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm

    r219137 r219310  
    105105}
    106106
     107void RemoteScrollingCoordinatorProxy::scrollingTreeNodeDidEndPanGesture()
     108{
     109    m_webPageProxy.overflowScrollViewDidEndPanGesture();
     110}
     111
    107112void RemoteScrollingCoordinatorProxy::scrollingTreeNodeWillStartScroll()
    108113{
  • trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h

    r219271 r219310  
    280280
    281281- (void)scrollViewWillStartPanOrPinchGesture;
     282- (void)scrollViewDidEndPanOrPinchGesture;
    282283
    283284- (BOOL)canBecomeFirstResponderForWebView;
  • trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm

    r219271 r219310  
    18441844
    18451845    _canSendTouchEventsAsynchronously = YES;
     1846}
     1847
     1848- (void)scrollViewDidEndPanOrPinchGesture
     1849{
     1850    _canSendTouchEventsAsynchronously = NO;
    18461851}
    18471852
     
    40514056#pragma mark - Implementation of UIWebTouchEventsGestureRecognizerDelegate.
    40524057
     4058// FIXME: Remove once -gestureRecognizer:shouldIgnoreWebTouchWithEvent: is in UIWebTouchEventsGestureRecognizer.h. Refer to <rdar://problem/33217525> for more details.
    40534059- (BOOL)shouldIgnoreWebTouch
    40544060{
    40554061    return NO;
     4062}
     4063
     4064- (BOOL)gestureRecognizer:(UIWebTouchEventsGestureRecognizer *)gestureRecognizer shouldIgnoreWebTouchWithEvent:(UIEvent *)event
     4065{
     4066    NSSet<UITouch *> *touches = [event touchesForGestureRecognizer:gestureRecognizer];
     4067    for (UITouch *touch in touches) {
     4068        if ([touch.view isKindOfClass:[UIScrollView class]] && [(UIScrollView *)touch.view _isInterruptingDeceleration])
     4069            return YES;
     4070    }
     4071    return self._scroller._isInterruptingDeceleration;
    40564072}
    40574073
  • trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm

    r218985 r219310  
    273273}
    274274
     275void WebPageProxy::overflowScrollViewDidEndPanGesture()
     276{
     277    m_pageClient.overflowScrollViewDidEndPanGesture();
     278}
     279
    275280void WebPageProxy::overflowScrollViewDidScroll()
    276281{
Note: See TracChangeset for help on using the changeset viewer.