Changeset 253005 in webkit


Ignore:
Timestamp:
Dec 2, 2019 12:21:13 PM (4 years ago)
Author:
Wenson Hsieh
Message:

[iOS] Introduce a gesture recognizer that can be used to defer recognition of other gestures
https://bugs.webkit.org/show_bug.cgi?id=204748
<rdar://problem/38670692>

Reviewed by Tim Horton.

Introduces WKDeferringGestureRecognizer, which is similar to UIKit's _UIRelationshipGestureRecognizer. In a
future patch, this will be added to WKContentView to prevent platform gestures (pinching, panning, single/double
taps, etc.) from recognizing when dispatching a preventable touch event to the page.

Additionally renames a member variable on WKContentView, in preparation for making touch gesture recognition
asynchronous. No new tests, since there is no change in behavior yet.

  • SourcesCocoa.txt:

Add the new file.

  • UIProcess/ios/WKContentViewInteraction.h:

Add a couple of (currently unused) deferring gesture recognizers. These will be added to WKContentView in a
future patch. There are two deferring gestures here (one for "immediately resettable" gestures and another for
gestures for which the reset is "deferred" -- i.e., multi-tap gestures); this prevents a single deferring
gesture from connecting the entire gesture subgraph under WKWebView through failure dependencies. This would
result in various usability issues, such as being unable to perform a pan gesture to scroll WKScrollView if a
tap was recognized within the last 300 ms, since all gestures would need to wait until every double and triple-
tap gesture under WKWebView has failed.

  • UIProcess/ios/WKContentViewInteraction.mm:

(-[WKContentView setupInteraction]):
(-[WKContentView _webTouchEventsRecognized:]):

Rename _canSendTouchEventsAsynchronously to _touchEventsCanPreventNativeGestures in preparation for adding a
codepath for fully asynchronous touch event dispatch; we also flip the conditional in any places where
_canSendTouchEventsAsynchronously was previously set or read.

(-[WKContentView _webTouchEvent:preventsNativeGestures:]):
(-[WKContentView scrollViewWillStartPanOrPinchGesture]):
(-[WKContentView gestureRecognizer:shouldIgnoreWebTouchWithEvent:]):
(-[WKContentView gestureRecognizer:isInterruptingMomentumScrollingWithEvent:]):
(-[WKContentView deferringGestureRecognizer:shouldDeferGesturesWithEvent:]):
(-[WKContentView deferringGestureRecognizer:shouldDeferOtherGestureRecognizer:]):

Implement WKDeferringGestureRecognizerDelegate.

(-[WKContentView shouldIgnoreWebTouch]): Deleted.

Drive-by fix: remove this unnecessary method implementation, and the related FIXME.

  • UIProcess/ios/WKDeferringGestureRecognizer.h: Added.
  • UIProcess/ios/WKDeferringGestureRecognizer.mm: Added.

(-[WKDeferringGestureRecognizer initWithDeferringGestureDelegate:]):
(-[WKDeferringGestureRecognizer deferringGestureDelegate]):
(-[WKDeferringGestureRecognizer touchesBegan:withEvent:]):

Unless the touch is interrupts momentum scrolling, WKDeferringGestureRecognizer should transition to Possible
state when starting a touch. Later, -setDefaultPrevented: is invoked, which will either transition the deferring
gesture recognizer to Failed state (thereby allowing native gestures to begin), or Ended state (preventing other
native gestures).

(-[WKDeferringGestureRecognizer touchesCancelled:withEvent:]):
(-[WKDeferringGestureRecognizer setDefaultPrevented:]):
(-[WKDeferringGestureRecognizer canBePreventedByGestureRecognizer:]):

Return NO here to prevent certain platform gestures (e.g. scroll view panning) from causing the deferring
gesture to Failed state, when these gestures attempt to transition from Possible to Began state.

(-[WKDeferringGestureRecognizer shouldDeferGestureRecognizer:]):

  • WebKit.xcodeproj/project.pbxproj:
Location:
trunk/Source/WebKit
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r252984 r253005  
     12019-12-02  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [iOS] Introduce a gesture recognizer that can be used to defer recognition of other gestures
     4        https://bugs.webkit.org/show_bug.cgi?id=204748
     5        <rdar://problem/38670692>
     6
     7        Reviewed by Tim Horton.
     8
     9        Introduces WKDeferringGestureRecognizer, which is similar to UIKit's _UIRelationshipGestureRecognizer. In a
     10        future patch, this will be added to WKContentView to prevent platform gestures (pinching, panning, single/double
     11        taps, etc.) from recognizing when dispatching a preventable touch event to the page.
     12
     13        Additionally renames a member variable on WKContentView, in preparation for making touch gesture recognition
     14        asynchronous. No new tests, since there is no change in behavior yet.
     15
     16        * SourcesCocoa.txt:
     17
     18        Add the new file.
     19
     20        * UIProcess/ios/WKContentViewInteraction.h:
     21
     22        Add a couple of (currently unused) deferring gesture recognizers. These will be added to WKContentView in a
     23        future patch. There are two deferring gestures here (one for "immediately resettable" gestures and another for
     24        gestures for which the reset is "deferred" -- i.e., multi-tap gestures); this prevents a single deferring
     25        gesture from connecting the entire gesture subgraph under WKWebView through failure dependencies. This would
     26        result in various usability issues, such as being unable to perform a pan gesture to scroll WKScrollView if a
     27        tap was recognized within the last 300 ms, since all gestures would need to wait until every double and triple-
     28        tap gesture under WKWebView has failed.
     29
     30        * UIProcess/ios/WKContentViewInteraction.mm:
     31        (-[WKContentView setupInteraction]):
     32        (-[WKContentView _webTouchEventsRecognized:]):
     33
     34        Rename _canSendTouchEventsAsynchronously to _touchEventsCanPreventNativeGestures in preparation for adding a
     35        codepath for fully asynchronous touch event dispatch; we also flip the conditional in any places where
     36        _canSendTouchEventsAsynchronously was previously set or read.
     37
     38        (-[WKContentView _webTouchEvent:preventsNativeGestures:]):
     39        (-[WKContentView scrollViewWillStartPanOrPinchGesture]):
     40        (-[WKContentView gestureRecognizer:shouldIgnoreWebTouchWithEvent:]):
     41        (-[WKContentView gestureRecognizer:isInterruptingMomentumScrollingWithEvent:]):
     42        (-[WKContentView deferringGestureRecognizer:shouldDeferGesturesWithEvent:]):
     43        (-[WKContentView deferringGestureRecognizer:shouldDeferOtherGestureRecognizer:]):
     44
     45        Implement WKDeferringGestureRecognizerDelegate.
     46
     47        (-[WKContentView shouldIgnoreWebTouch]): Deleted.
     48
     49        Drive-by fix: remove this unnecessary method implementation, and the related FIXME.
     50
     51        * UIProcess/ios/WKDeferringGestureRecognizer.h: Added.
     52        * UIProcess/ios/WKDeferringGestureRecognizer.mm: Added.
     53        (-[WKDeferringGestureRecognizer initWithDeferringGestureDelegate:]):
     54        (-[WKDeferringGestureRecognizer deferringGestureDelegate]):
     55        (-[WKDeferringGestureRecognizer touchesBegan:withEvent:]):
     56
     57        Unless the touch is interrupts momentum scrolling, WKDeferringGestureRecognizer should transition to Possible
     58        state when starting a touch. Later, -setDefaultPrevented: is invoked, which will either transition the deferring
     59        gesture recognizer to Failed state (thereby allowing native gestures to begin), or Ended state (preventing other
     60        native gestures).
     61
     62        (-[WKDeferringGestureRecognizer touchesCancelled:withEvent:]):
     63        (-[WKDeferringGestureRecognizer setDefaultPrevented:]):
     64        (-[WKDeferringGestureRecognizer canBePreventedByGestureRecognizer:]):
     65
     66        Return NO here to prevent certain platform gestures (e.g. scroll view panning) from causing the deferring
     67        gesture to Failed state, when these gestures attempt to transition from Possible to Began state.
     68
     69        (-[WKDeferringGestureRecognizer shouldDeferGestureRecognizer:]):
     70        * WebKit.xcodeproj/project.pbxproj:
     71
    1722019-12-02  Yoshiaki Jitsukawa  <yoshiaki.jitsukawa@sony.com>
    273
  • trunk/Source/WebKit/SourcesCocoa.txt

    r252303 r253005  
    427427UIProcess/ios/WKContentView.mm @no-unify
    428428UIProcess/ios/WKContentViewInteraction.mm @no-unify
     429UIProcess/ios/WKDeferringGestureRecognizer.mm
    429430UIProcess/ios/WKDrawingCoordinator.mm
    430431UIProcess/ios/WKDrawingView.mm
  • trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h

    r252377 r253005  
    4343#import "WKActionSheetAssistant.h"
    4444#import "WKAirPlayRoutePicker.h"
     45#import "WKDeferringGestureRecognizer.h"
    4546#import "WKFileUploadPanel.h"
    4647#import "WKFormPeripheral.h"
     
    205206
    206207@interface WKContentView () {
     208    RetainPtr<WKDeferringGestureRecognizer> _deferringGestureRecognizerForImmediatelyResettableGestures;
     209    RetainPtr<WKDeferringGestureRecognizer> _deferringGestureRecognizerForDelayedResettableGestures;
    207210    RetainPtr<UIWebTouchEventsGestureRecognizer> _touchEventGestureRecognizer;
    208211
    209     BOOL _canSendTouchEventsAsynchronously;
     212    BOOL _touchEventsCanPreventNativeGestures;
    210213#if ENABLE(POINTER_EVENTS)
    211214    BOOL _preventsPanningInXAxis;
     
    399402@end
    400403
    401 @interface WKContentView (WKInteraction) <UIGestureRecognizerDelegate, UITextAutoscrolling, UITextInputMultiDocument, UITextInputPrivate, UIWebFormAccessoryDelegate, UIWebTouchEventsGestureRecognizerDelegate, UIWKInteractionViewProtocol, WKActionSheetAssistantDelegate, WKFileUploadPanelDelegate, WKKeyboardScrollViewAnimatorDelegate
     404@interface WKContentView (WKInteraction) <UIGestureRecognizerDelegate, UITextAutoscrolling, UITextInputMultiDocument, UITextInputPrivate, UIWebFormAccessoryDelegate, UIWebTouchEventsGestureRecognizerDelegate, UIWKInteractionViewProtocol, WKActionSheetAssistantDelegate, WKFileUploadPanelDelegate, WKKeyboardScrollViewAnimatorDelegate, WKDeferringGestureRecognizerDelegate
    402405#if !PLATFORM(WATCHOS) && !PLATFORM(APPLETV)
    403406    , WKShareSheetDelegate
  • trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm

    r252529 r253005  
    845845    [_actionSheetAssistant setDelegate:self];
    846846    _smartMagnificationController = makeUnique<WebKit::SmartMagnificationController>(self);
     847    _touchEventsCanPreventNativeGestures = YES;
    847848    _isExpectingFastSingleTapCommit = NO;
    848849    _potentialTapInProgress = NO;
     
    14111412#if ENABLE(TOUCH_EVENTS)
    14121413    WebKit::NativeWebTouchEvent nativeWebTouchEvent { lastTouchEvent, gestureRecognizerModifierFlags(gestureRecognizer) };
    1413     nativeWebTouchEvent.setCanPreventNativeGestures(!_canSendTouchEventsAsynchronously || [gestureRecognizer isDefaultPrevented]);
     1414    nativeWebTouchEvent.setCanPreventNativeGestures(_touchEventsCanPreventNativeGestures || [gestureRecognizer isDefaultPrevented]);
    14141415
    14151416#if ENABLE(POINTER_EVENTS)
     
    14171418#endif
    14181419
    1419     if (_canSendTouchEventsAsynchronously)
     1420    if (_touchEventsCanPreventNativeGestures)
     1421        _page->handleTouchEventSynchronously(nativeWebTouchEvent);
     1422    else
    14201423        _page->handleTouchEventAsynchronously(nativeWebTouchEvent);
    1421     else
    1422         _page->handleTouchEventSynchronously(nativeWebTouchEvent);
    14231424
    14241425    if (nativeWebTouchEvent.allTouchPointsAreReleased()) {
    1425         _canSendTouchEventsAsynchronously = NO;
     1426        _touchEventsCanPreventNativeGestures = YES;
    14261427
    14271428#if ENABLE(POINTER_EVENTS)
     
    15931594        _longPressCanClick = NO;
    15941595
    1595         _canSendTouchEventsAsynchronously = YES;
     1596        _touchEventsCanPreventNativeGestures = NO;
    15961597        [_touchEventGestureRecognizer setDefaultPrevented:YES];
    15971598    }
     
    27982799    [_keyboardScrollingAnimator willStartInteractiveScroll];
    27992800
    2800     _canSendTouchEventsAsynchronously = YES;
     2801    _touchEventsCanPreventNativeGestures = NO;
    28012802}
    28022803
     
    64596460#pragma mark - Implementation of UIWebTouchEventsGestureRecognizerDelegate.
    64606461
    6461 // FIXME: Remove once -gestureRecognizer:shouldIgnoreWebTouchWithEvent: is in UIWebTouchEventsGestureRecognizer.h. Refer to <rdar://problem/33217525> for more details.
    6462 - (BOOL)shouldIgnoreWebTouch
    6463 {
    6464     return NO;
    6465 }
    6466 
    64676462- (BOOL)gestureRecognizer:(UIWebTouchEventsGestureRecognizer *)gestureRecognizer shouldIgnoreWebTouchWithEvent:(UIEvent *)event
    64686463{
    6469     _canSendTouchEventsAsynchronously = NO;
    6470 
     6464    _touchEventsCanPreventNativeGestures = YES;
     6465
     6466    return [self gestureRecognizer:gestureRecognizer isInterruptingMomentumScrollingWithEvent:event];
     6467}
     6468
     6469- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer isInterruptingMomentumScrollingWithEvent:(UIEvent *)event
     6470{
    64716471    NSSet<UITouch *> *touches = [event touchesForGestureRecognizer:gestureRecognizer];
    64726472    for (UITouch *touch in touches) {
     
    66826682{
    66836683    [_contextMenuHintContainerView setHidden:YES];
     6684}
     6685
     6686#pragma mark - WKDeferringGestureRecognizerDelegate
     6687
     6688- (BOOL)deferringGestureRecognizer:(WKDeferringGestureRecognizer *)deferringGestureRecognizer shouldDeferGesturesWithEvent:(UIEvent *)event
     6689{
     6690    return ![self gestureRecognizer:deferringGestureRecognizer isInterruptingMomentumScrollingWithEvent:event];
     6691}
     6692
     6693- (BOOL)deferringGestureRecognizer:(WKDeferringGestureRecognizer *)deferringGestureRecognizer shouldDeferOtherGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
     6694{
     6695    auto isMultipleTapGesture = [](UIGestureRecognizer *gesture) {
     6696        return [gesture isKindOfClass:UITapGestureRecognizer.class] && [(UITapGestureRecognizer *)gesture numberOfTapsRequired] > 1;
     6697    };
     6698
     6699    if (deferringGestureRecognizer == _deferringGestureRecognizerForDelayedResettableGestures)
     6700        return gestureRecognizer != _touchEventGestureRecognizer && isMultipleTapGesture(gestureRecognizer);
     6701
     6702    if (deferringGestureRecognizer == _deferringGestureRecognizerForImmediatelyResettableGestures)
     6703        return gestureRecognizer != _touchEventGestureRecognizer && !isMultipleTapGesture(gestureRecognizer);
     6704
     6705    ASSERT_NOT_REACHED();
     6706    return NO;
    66846707}
    66856708
  • trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj

    r252759 r253005  
    17181718                F44291921FA591C9002CC93E /* _WKAttachment.h in Headers */ = {isa = PBXBuildFile; fileRef = F44291911FA59107002CC93E /* _WKAttachment.h */; settings = {ATTRIBUTES = (Private, ); }; };
    17191719                F44291961FA5942A002CC93E /* _WKAttachmentInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = F44291951FA5942A002CC93E /* _WKAttachmentInternal.h */; };
     1720                F44815642387820000982657 /* WKDeferringGestureRecognizer.h in Headers */ = {isa = PBXBuildFile; fileRef = F44815622387820000982657 /* WKDeferringGestureRecognizer.h */; };
    17201721                F44DFEB21E9E752F0038D196 /* WebIconUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = F44DFEB01E9E752F0038D196 /* WebIconUtilities.h */; };
    17211722                F48D2A8521583A7E00C6752B /* AppKitSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = F48D2A8421583A0200C6752B /* AppKitSPI.h */; };
     
    48094810                F44291931FA59311002CC93E /* _WKAttachment.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKAttachment.mm; sourceTree = "<group>"; };
    48104811                F44291951FA5942A002CC93E /* _WKAttachmentInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _WKAttachmentInternal.h; sourceTree = "<group>"; };
     4812                F44815622387820000982657 /* WKDeferringGestureRecognizer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WKDeferringGestureRecognizer.h; path = ios/WKDeferringGestureRecognizer.h; sourceTree = "<group>"; };
     4813                F44815632387820000982657 /* WKDeferringGestureRecognizer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = WKDeferringGestureRecognizer.mm; path = ios/WKDeferringGestureRecognizer.mm; sourceTree = "<group>"; };
    48114814                F44DFEB01E9E752F0038D196 /* WebIconUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebIconUtilities.h; path = ios/WebIconUtilities.h; sourceTree = "<group>"; };
    48124815                F44DFEB11E9E752F0038D196 /* WebIconUtilities.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = WebIconUtilities.mm; path = ios/WebIconUtilities.mm; sourceTree = "<group>"; };
     
    61526155                                0FCB4E6A18BBF26A000FCFC9 /* WKContentViewInteraction.h */,
    61536156                                0FCB4E6B18BBF26A000FCFC9 /* WKContentViewInteraction.mm */,
     6157                                F44815622387820000982657 /* WKDeferringGestureRecognizer.h */,
     6158                                F44815632387820000982657 /* WKDeferringGestureRecognizer.mm */,
    61546159                                2D21A45921DED49B002487E7 /* WKDrawingCoordinator.h */,
    61556160                                2D21A45821DED49B002487E7 /* WKDrawingCoordinator.mm */,
     
    98219826                                E18E690C169B563F009B6670 /* SecItemShimProxy.h in Headers */,
    98229827                                E18E6918169B667B009B6670 /* SecItemShimProxyMessages.h in Headers */,
    9823                                 7AA746D523593D8100095050 /* SecItemSPI.h in Headers */,
    98249828                                570AB8F320AE3BD700B8BE87 /* SecKeyProxyStore.h in Headers */,
    98259829                                514D9F5719119D35000063A7 /* ServicesController.h in Headers */,
     
    1022810232                                2E94FC1620351A6D00974BA0 /* WKDatePickerViewController.h in Headers */,
    1022910233                                377EAD4517E2C51A002D193D /* WKDeclarationSpecifiers.h in Headers */,
     10234                                F44815642387820000982657 /* WKDeferringGestureRecognizer.h in Headers */,
    1023010235                                5C359C0D2154739F009E7948 /* WKDeprecated.h in Headers */,
    1023110236                                8372DB2F1A677D4A00C697C5 /* WKDiagnosticLoggingResultType.h in Headers */,
Note: See TracChangeset for help on using the changeset viewer.