Changeset 245112 in webkit


Ignore:
Timestamp:
May 9, 2019 1:34:23 AM (5 years ago)
Author:
graouts@webkit.org
Message:

[iOS] Correctly handle overlapping regions for elements with a touch-action property
https://bugs.webkit.org/show_bug.cgi?id=194813
<rdar://problem/48194708>

Reviewed by Antti Koivisto.

Source/WebKit:

We now use WebKit::touchActionsForPoint() to determine the touch actions for a given touch using its location in -[WKContentViewInteraction
_handleTouchActionsForTouchEvent:]. We then record these touch actions for the touch's identifier on the RemoteScrollingCoordinatorProxy.

Then, as we interact with a UIScrollView, we get its gesture recognizer and get its active touch identifier through the new
-[WKContentViewInteraction activeTouchIdentifierForGestureRecognizer:] method, and query the RemoteScrollingCoordinatorProxy for the touch
actions matching that touch identifier.

Tests: pointerevents/ios/touch-action-none-overlap.html

pointerevents/ios/touch-action-pan-x-overlap.html
pointerevents/ios/touch-action-pan-y-overlap.html
pointerevents/ios/touch-action-pinch-zoom-overlap.html

  • UIProcess/PageClient.h:

(WebKit::PageClient::activeTouchIdentifierForGestureRecognizer):

  • UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.cpp: Maintain a touch identifier to touch actions map.

(WebKit::RemoteScrollingCoordinatorProxy::activeTouchActionsForTouchIdentifier const):
(WebKit::RemoteScrollingCoordinatorProxy::setTouchActionsForTouchIdentifier):
(WebKit::RemoteScrollingCoordinatorProxy::clearTouchActionsForTouchIdentifier):
(WebKit::RemoteScrollingCoordinatorProxy::touchActionDataAtPoint const): Deleted.
(WebKit::RemoteScrollingCoordinatorProxy::touchActionDataForScrollNodeID const): Deleted.
(WebKit::RemoteScrollingCoordinatorProxy::setTouchDataForTouchIdentifier): Deleted.
(WebKit::RemoteScrollingCoordinatorProxy::clearTouchDataForTouchIdentifier): Deleted.

  • UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h:
  • UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h:
  • UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm:

(-[WKScrollingNodeScrollViewDelegate scrollViewWillEndDragging:withVelocity:targetContentOffset:]):
(-[WKScrollingNodeScrollViewDelegate _scrollView:adjustedOffsetForOffset:translation:startPoint:locationInView:horizontalVelocity:verticalVelocity:]):
(WebKit::ScrollingTreeScrollingNodeDelegateIOS::activeTouchActionsForGestureRecognizer const):
(WebKit::ScrollingTreeScrollingNodeDelegateIOS::touchActionData const): Deleted.

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

(WebKit::PageClientImpl::activeTouchIdentifierForGestureRecognizer):

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

(-[WKContentView activeTouchIdentifierForGestureRecognizer:]):
(-[WKContentView _handleTouchActionsForTouchEvent:]):

LayoutTests:

Add new tests that check that an element overlapping another element with a "touch-action" property is not affected
by the property set on that underlying element.

  • pointerevents/ios/touch-action-none-overlap-expected.txt: Added.
  • pointerevents/ios/touch-action-none-overlap.html: Added.
  • pointerevents/ios/touch-action-pan-x-overlap-expected.txt: Added.
  • pointerevents/ios/touch-action-pan-x-overlap.html: Added.
  • pointerevents/ios/touch-action-pan-y-overlap-expected.txt: Added.
  • pointerevents/ios/touch-action-pan-y-overlap.html: Added.
  • pointerevents/ios/touch-action-pinch-zoom-overlap-expected.txt: Added.
  • pointerevents/ios/touch-action-pinch-zoom-overlap.html: Added.
Location:
trunk
Files:
8 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r245086 r245112  
     12019-05-08  Antoine Quint  <graouts@apple.com>
     2
     3        [iOS] Correctly handle overlapping regions for elements with a touch-action property
     4        https://bugs.webkit.org/show_bug.cgi?id=194813
     5        <rdar://problem/48194708>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        Add new tests that check that an element overlapping another element with a "touch-action" property is not affected
     10        by the property set on that underlying element.
     11
     12        * pointerevents/ios/touch-action-none-overlap-expected.txt: Added.
     13        * pointerevents/ios/touch-action-none-overlap.html: Added.
     14        * pointerevents/ios/touch-action-pan-x-overlap-expected.txt: Added.
     15        * pointerevents/ios/touch-action-pan-x-overlap.html: Added.
     16        * pointerevents/ios/touch-action-pan-y-overlap-expected.txt: Added.
     17        * pointerevents/ios/touch-action-pan-y-overlap.html: Added.
     18        * pointerevents/ios/touch-action-pinch-zoom-overlap-expected.txt: Added.
     19        * pointerevents/ios/touch-action-pinch-zoom-overlap.html: Added.
     20
    1212019-05-08  Chris Dumez  <cdumez@apple.com>
    222
  • trunk/Source/WebKit/ChangeLog

    r245079 r245112  
     12019-05-08  Antoine Quint  <graouts@apple.com>
     2
     3        [iOS] Correctly handle overlapping regions for elements with a touch-action property
     4        https://bugs.webkit.org/show_bug.cgi?id=194813
     5        <rdar://problem/48194708>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        We now use WebKit::touchActionsForPoint() to determine the touch actions for a given touch using its location in -[WKContentViewInteraction
     10        _handleTouchActionsForTouchEvent:]. We then record these touch actions for the touch's identifier on the RemoteScrollingCoordinatorProxy.
     11
     12        Then, as we interact with a UIScrollView, we get its gesture recognizer and get its active touch identifier through the new
     13        -[WKContentViewInteraction activeTouchIdentifierForGestureRecognizer:] method, and query the RemoteScrollingCoordinatorProxy for the touch
     14        actions matching that touch identifier.
     15
     16        Tests: pointerevents/ios/touch-action-none-overlap.html
     17               pointerevents/ios/touch-action-pan-x-overlap.html
     18               pointerevents/ios/touch-action-pan-y-overlap.html
     19               pointerevents/ios/touch-action-pinch-zoom-overlap.html
     20
     21        * UIProcess/PageClient.h:
     22        (WebKit::PageClient::activeTouchIdentifierForGestureRecognizer):
     23        * UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.cpp: Maintain a touch identifier to touch actions map.
     24        (WebKit::RemoteScrollingCoordinatorProxy::activeTouchActionsForTouchIdentifier const):
     25        (WebKit::RemoteScrollingCoordinatorProxy::setTouchActionsForTouchIdentifier):
     26        (WebKit::RemoteScrollingCoordinatorProxy::clearTouchActionsForTouchIdentifier):
     27        (WebKit::RemoteScrollingCoordinatorProxy::touchActionDataAtPoint const): Deleted.
     28        (WebKit::RemoteScrollingCoordinatorProxy::touchActionDataForScrollNodeID const): Deleted.
     29        (WebKit::RemoteScrollingCoordinatorProxy::setTouchDataForTouchIdentifier): Deleted.
     30        (WebKit::RemoteScrollingCoordinatorProxy::clearTouchDataForTouchIdentifier): Deleted.
     31        * UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h:
     32        * UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h:
     33        * UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm:
     34        (-[WKScrollingNodeScrollViewDelegate scrollViewWillEndDragging:withVelocity:targetContentOffset:]):
     35        (-[WKScrollingNodeScrollViewDelegate _scrollView:adjustedOffsetForOffset:translation:startPoint:locationInView:horizontalVelocity:verticalVelocity:]):
     36        (WebKit::ScrollingTreeScrollingNodeDelegateIOS::activeTouchActionsForGestureRecognizer const):
     37        (WebKit::ScrollingTreeScrollingNodeDelegateIOS::touchActionData const): Deleted.
     38        * UIProcess/ios/PageClientImplIOS.h:
     39        * UIProcess/ios/PageClientImplIOS.mm:
     40        (WebKit::PageClientImpl::activeTouchIdentifierForGestureRecognizer):
     41        * UIProcess/ios/WKContentViewInteraction.h:
     42        * UIProcess/ios/WKContentViewInteraction.mm:
     43        (-[WKContentView activeTouchIdentifierForGestureRecognizer:]):
     44        (-[WKContentView _handleTouchActionsForTouchEvent:]):
     45
    1462019-05-08  Megan Gardner  <megan_gardner@apple.com>
    247
  • trunk/Source/WebKit/UIProcess/PageClient.h

    r245072 r245112  
    502502#if ENABLE(POINTER_EVENTS)
    503503    virtual void cancelPointersForGestureRecognizer(UIGestureRecognizer*) { }
     504    virtual WTF::Optional<unsigned> activeTouchIdentifierForGestureRecognizer(UIGestureRecognizer*) { return WTF::nullopt; }
    504505#endif
    505506
  • trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.cpp

    r245006 r245112  
    248248
    249249#if ENABLE(POINTER_EVENTS)
    250 Optional<TouchActionData> RemoteScrollingCoordinatorProxy::touchActionDataAtPoint(const IntPoint p) const
    251 {
    252     return m_scrollingTree->touchActionDataAtPoint(p);
    253 }
    254 
    255 Optional<TouchActionData> RemoteScrollingCoordinatorProxy::touchActionDataForScrollNodeID(ScrollingNodeID scrollingNodeID) const
    256 {
    257     for (auto& touchActionData : m_touchActionDataByTouchIdentifier.values()) {
    258         if (touchActionData.scrollingNodeID == scrollingNodeID)
    259             return touchActionData;
    260     }
    261     return WTF::nullopt;
    262 }
    263 
    264 void RemoteScrollingCoordinatorProxy::setTouchDataForTouchIdentifier(TouchActionData touchActionData, unsigned touchIdentifier)
    265 {
    266     m_touchActionDataByTouchIdentifier.set(touchIdentifier, touchActionData);
    267 }
    268 
    269 void RemoteScrollingCoordinatorProxy::clearTouchDataForTouchIdentifier(unsigned touchIdentifier)
    270 {
    271     m_touchActionDataByTouchIdentifier.remove(touchIdentifier);
     250OptionSet<TouchAction> RemoteScrollingCoordinatorProxy::activeTouchActionsForTouchIdentifier(unsigned touchIdentifier) const
     251{
     252    auto iterator = m_touchActionsByTouchIdentifier.find(touchIdentifier);
     253    if (iterator == m_touchActionsByTouchIdentifier.end())
     254        return { };
     255    return iterator->value;
     256}
     257
     258void RemoteScrollingCoordinatorProxy::setTouchActionsForTouchIdentifier(OptionSet<TouchAction> touchActions, unsigned touchIdentifier)
     259{
     260    m_touchActionsByTouchIdentifier.set(touchIdentifier, touchActions);
     261}
     262
     263void RemoteScrollingCoordinatorProxy::clearTouchActionsForTouchIdentifier(unsigned touchIdentifier)
     264{
     265    m_touchActionsByTouchIdentifier.remove(touchIdentifier);
    272266}
    273267
  • trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h

    r245006 r245112  
    103103
    104104#if ENABLE(POINTER_EVENTS)
    105     Optional<WebCore::TouchActionData> touchActionDataAtPoint(const WebCore::IntPoint) const;
    106     Optional<WebCore::TouchActionData> touchActionDataForScrollNodeID(WebCore::ScrollingNodeID) const;
    107     void setTouchDataForTouchIdentifier(WebCore::TouchActionData, unsigned);
    108     void clearTouchDataForTouchIdentifier(unsigned);
     105    OptionSet<WebCore::TouchAction> activeTouchActionsForTouchIdentifier(unsigned touchIdentifier) const;
     106    void setTouchActionsForTouchIdentifier(OptionSet<WebCore::TouchAction>, unsigned);
     107    void clearTouchActionsForTouchIdentifier(unsigned);
    109108#endif
    110109
     
    121120    RefPtr<RemoteScrollingTree> m_scrollingTree;
    122121#if ENABLE(POINTER_EVENTS)
    123     HashMap<unsigned, WebCore::TouchActionData> m_touchActionDataByTouchIdentifier;
     122    HashMap<unsigned, OptionSet<WebCore::TouchAction>> m_touchActionsByTouchIdentifier;
    124123#endif
    125124    RequestedScrollInfo* m_requestedScrollInfo;
  • trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h

    r242356 r245112  
    6767
    6868#if ENABLE(POINTER_EVENTS)
    69     Optional<WebCore::TouchActionData> touchActionData() const;
     69    OptionSet<TouchAction> activeTouchActionsForGestureRecognizer(UIGestureRecognizer*) const;
    7070    void cancelPointersForGestureRecognizer(UIGestureRecognizer*);
    7171#endif
  • trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm

    r244955 r245112  
    8080#if ENABLE(POINTER_EVENTS)
    8181    if (![scrollView isZooming]) {
    82         if (auto touchActionData = _scrollingTreeNodeDelegate->touchActionData()) {
    83             auto touchActions = touchActionData->touchActions;
    84             if (touchActions != WebCore::TouchAction::Auto && touchActions != WebCore::TouchAction::Manipulation) {
    85                 bool canPanX = true;
    86                 bool canPanY = true;
    87                 if (!touchActions.contains(WebCore::TouchAction::PanX)) {
    88                     canPanX = false;
    89                     targetContentOffset->x = scrollView.contentOffset.x;
    90                 }
    91                 if (!touchActions.contains(WebCore::TouchAction::PanY)) {
    92                     canPanY = false;
    93                     targetContentOffset->y = scrollView.contentOffset.y;
    94                 }
     82        auto touchActions = _scrollingTreeNodeDelegate->activeTouchActionsForGestureRecognizer(scrollView.panGestureRecognizer);
     83        if (touchActions && !touchActions.containsAny({ WebCore::TouchAction::Auto, WebCore::TouchAction::Manipulation })) {
     84            bool canPanX = true;
     85            bool canPanY = true;
     86            if (!touchActions.contains(WebCore::TouchAction::PanX)) {
     87                canPanX = false;
     88                targetContentOffset->x = scrollView.contentOffset.x;
     89            }
     90            if (!touchActions.contains(WebCore::TouchAction::PanY)) {
     91                canPanY = false;
     92                targetContentOffset->y = scrollView.contentOffset.y;
    9593            }
    9694        }
     
    149147- (CGPoint)_scrollView:(UIScrollView *)scrollView adjustedOffsetForOffset:(CGPoint)offset translation:(CGPoint)translation startPoint:(CGPoint)start locationInView:(CGPoint)locationInView horizontalVelocity:(inout double *)hv verticalVelocity:(inout double *)vv
    150148{
    151     auto touchActionData = _scrollingTreeNodeDelegate->touchActionData();
    152     if (!touchActionData) {
    153         [self cancelPointersForGestureRecognizer:scrollView.panGestureRecognizer];
     149    auto* panGestureRecognizer = scrollView.panGestureRecognizer;
     150    auto touchActions = _scrollingTreeNodeDelegate->activeTouchActionsForGestureRecognizer(panGestureRecognizer);
     151    if (!touchActions) {
     152        [self cancelPointersForGestureRecognizer:panGestureRecognizer];
    154153        return offset;
    155154    }
    156155
    157     auto touchActions = touchActionData->touchActions;
    158     if (touchActions == WebCore::TouchAction::Auto || touchActions == WebCore::TouchAction::Manipulation)
     156    if (touchActions.containsAny({ WebCore::TouchAction::Auto, WebCore::TouchAction::Manipulation }))
    159157        return offset;
    160158
     
    339337
    340338#if ENABLE(POINTER_EVENTS)
    341 Optional<TouchActionData> ScrollingTreeScrollingNodeDelegateIOS::touchActionData() const
    342 {
    343     return downcast<RemoteScrollingTree>(scrollingTree()).scrollingCoordinatorProxy().touchActionDataForScrollNodeID(scrollingNode().scrollingNodeID());
     339OptionSet<TouchAction> ScrollingTreeScrollingNodeDelegateIOS::activeTouchActionsForGestureRecognizer(UIGestureRecognizer* gestureRecognizer) const
     340{
     341    auto& scrollingCoordinatorProxy = downcast<RemoteScrollingTree>(scrollingTree()).scrollingCoordinatorProxy();
     342    if (auto touchIdentifier = scrollingCoordinatorProxy.webPageProxy().pageClient().activeTouchIdentifierForGestureRecognizer(gestureRecognizer))
     343        return scrollingCoordinatorProxy.activeTouchActionsForTouchIdentifier(*touchIdentifier);
     344    return { };
    344345}
    345346
  • trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h

    r244559 r245112  
    252252#if ENABLE(POINTER_EVENTS)
    253253    void cancelPointersForGestureRecognizer(UIGestureRecognizer*) override;
     254    WTF::Optional<unsigned> activeTouchIdentifierForGestureRecognizer(UIGestureRecognizer*) override;
    254255#endif
    255256
  • trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm

    r244955 r245112  
    867867    [m_contentView cancelPointersForGestureRecognizer:gestureRecognizer];
    868868}
     869
     870WTF::Optional<unsigned> PageClientImpl::activeTouchIdentifierForGestureRecognizer(UIGestureRecognizer* gestureRecognizer)
     871{
     872    return [m_contentView activeTouchIdentifierForGestureRecognizer:gestureRecognizer];
     873}
    869874#endif
    870875
  • trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h

    r245079 r245112  
    410410#if ENABLE(POINTER_EVENTS)
    411411- (void)cancelPointersForGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer;
     412- (WTF::Optional<unsigned>)activeTouchIdentifierForGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer;
    412413#endif
    413414
  • trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm

    r245079 r245112  
    3838#import "NativeWebTouchEvent.h"
    3939#import "RemoteLayerTreeDrawingAreaProxy.h"
     40#import "RemoteLayerTreeViews.h"
    4041#import "SmartMagnificationController.h"
    4142#import "TextInputSPI.h"
     
    12581259#endif
    12591260}
     1261
     1262- (WTF::Optional<unsigned>)activeTouchIdentifierForGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
     1263{
     1264#if HAVE(UI_WEB_TOUCH_EVENTS_GESTURE_RECOGNIZER_WITH_ACTIVE_TOUCHES_BY_ID)
     1265    // FIXME: <rdar://problem/48035706>
     1266    NSMapTable<NSNumber *, UITouch *> *activeTouches = [_touchEventGestureRecognizer activeTouchesByIdentifier];
     1267    for (NSNumber *touchIdentifier in activeTouches) {
     1268        UITouch *touch = [activeTouches objectForKey:touchIdentifier];
     1269        if ([touch.gestureRecognizers containsObject:gestureRecognizer])
     1270            return [touchIdentifier unsignedIntValue];
     1271    }
     1272#endif
     1273    return WTF::nullopt;
     1274}
    12601275#endif
    12611276
     
    13191334        auto phase = touchPoint.phase();
    13201335        if (phase == WebKit::WebPlatformTouchPoint::TouchPressed) {
    1321             auto touchActionData = scrollingCoordinator->touchActionDataAtPoint(touchPoint.location());
    1322             if (!touchActionData || touchActionData->touchActions.contains(WebCore::TouchAction::Manipulation))
     1336            auto touchActions = WebKit::touchActionsForPoint(self, touchPoint.location());
     1337            if (!touchActions || touchActions.containsAny({ WebCore::TouchAction::Auto, WebCore::TouchAction::Manipulation }))
    13231338                continue;
    1324             if (auto scrollingNodeID = touchActionData->scrollingNodeID)
    1325                 scrollingCoordinator->setTouchDataForTouchIdentifier(*touchActionData, touchPoint.identifier());
    1326             else {
    1327                 if (!touchActionData->touchActions.contains(WebCore::TouchAction::PinchZoom))
    1328                     _webView.scrollView.pinchGestureRecognizer.enabled = NO;
    1329                 _preventsPanningInXAxis = !touchActionData->touchActions.contains(WebCore::TouchAction::PanX);
    1330                 _preventsPanningInYAxis = !touchActionData->touchActions.contains(WebCore::TouchAction::PanY);
    1331             }
     1339            scrollingCoordinator->setTouchActionsForTouchIdentifier(touchActions, touchPoint.identifier());
     1340
     1341            if (!touchActions.contains(WebCore::TouchAction::PinchZoom))
     1342                _webView.scrollView.pinchGestureRecognizer.enabled = NO;
     1343            _preventsPanningInXAxis = !touchActions.contains(WebCore::TouchAction::PanX);
     1344            _preventsPanningInYAxis = !touchActions.contains(WebCore::TouchAction::PanY);
     1345
    13321346        } else if (phase == WebKit::WebPlatformTouchPoint::TouchReleased || phase == WebKit::WebPlatformTouchPoint::TouchCancelled)
    1333             scrollingCoordinator->clearTouchDataForTouchIdentifier(touchPoint.identifier());
     1347            scrollingCoordinator->clearTouchActionsForTouchIdentifier(touchPoint.identifier());
    13341348    }
    13351349}
Note: See TracChangeset for help on using the changeset viewer.