⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 245639 in webkit


Ignore:
Timestamp:
May 22, 2019, 12:58:15 PM (7 years ago)
Author:
graouts@webkit.org
Message:

[iOS] Compatibility mouse events aren't prevented by calling preventDefault() on pointerdown
https://bugs.webkit.org/show_bug.cgi?id=198124
<rdar://problem/50410863>

Reviewed by Tim Horton.

LayoutTests/imported/w3c:

We add basic support to run a test that wasn't specifically designed for a touch-based interaction such that the test
at imported/w3c/web-platform-tests/pointerevents/pointerevent_suppress_compat_events_on_click.html may run on iOS. The
trick here is to add a pause after a touch ends to avoid the likelihood or two tap gestures triggering a double tap.

  • web-platform-tests/resources/testdriver-vendor.js:

Source/WebCore:

This fix builds atop the one made for wkb.ug/198072 which fixes this bug on macOS alone.

In order to correctly prevent "compatibility" mouse events from being dispatched when the initial "pointerdown" event had preventDefault()
called while handled, we need to pass the PointerID for the touch that triggered a tap gesture in the UI process down in the Web process
and into the resulting PlatformMouseEvent. This will allow upon dispatch of a PlatformMouseEvent to call into PointerCaptureController
to identify if the dispatch of mouse events is allowed for the event's PointerID.

To support this, some refactoring was required. The PointerID header is now under platform/ such that PlatformMouseEvent may safely use it.
Additionally, PointerEvent::defaultMousePointerIdentifier() is now a global mousePointerID defined in PointerID.h.

Finally, PointerCaptureController::touchEndedOrWasCancelledForIdentifier() has been renamed to PointerCaptureController::touchWithIdentifierWasRemoved() and
has WEBCORE_EXPORT such that it may be called from WebKit as the indication that a pointer is no longer active will now be initiated in WebKit
on the UI process side.

Testing is covered by the pre-existing imported/w3c/web-platform-tests/pointerevents/pointerevent_suppress_compat_events_on_click.html
which will now run on iOS through a change to WebKitAdditions.

  • Headers.cmake:
  • WebCore.xcodeproj/project.pbxproj:
  • dom/Element.cpp:

(WebCore::Element::dispatchMouseEvent): When dealing with a mouse event on iOS, check whether the mouse event's PointerID allows for compatibility
mouse events to be dispatched using PointerCaptureController::preventsCompatibilityMouseEventsForIdentifier(). The "click" event is not a compatibility
mouse event.

  • dom/PointerEvent.h:
  • page/PointerCaptureController.cpp:

(WebCore::PointerCaptureController::PointerCaptureController):
(WebCore::PointerCaptureController::touchWithIdentifierWasRemoved):
(WebCore::PointerCaptureController::touchEndedOrWasCancelledForIdentifier): Deleted.

  • page/PointerCaptureController.h:
  • platform/PlatformMouseEvent.h:

(WebCore::PlatformMouseEvent::PlatformMouseEvent):
(WebCore::PlatformMouseEvent::pointerId const):

  • platform/PointerID.h: Renamed from Source/WebCore/dom/PointerID.h.

(WebCore::mousePointerID):

Source/WebKit:

In order to correctly prevent "compatibility" mouse events from being dispatched when the initial "pointerdown" event had preventDefault()
called while handled, we need to pass the PointerID for the touch that triggered a tap gesture in the UI process down in the Web process
and into the resulting PlatformMouseEvent.

This means we need to identify the touch identifier, which is the same as the PointerID used for Pointer Events, in the single tap gesture
recognizer, an instance of WKSyntheticTapGestureRecognizer. To do this, we subclass the -[UIResponder touchesEnded:withEvent:] method and
track the touch identifier as the lastActiveTouchIdentifier, a new public property of WKSyntheticTapGestureRecognizer. To allow for this,
we need the support of the content view's UIWebTouchEventsGestureRecognizer which is exposed to the WKSyntheticTapGestureRecognizer as its
supportingWebTouchEventsGestureRecognizer property. This lastActiveTouchIdentifier property is cleared as the gesture recognizer is reset.

This allows the content view to pass the PointerID down to the Web process starting from -[WKContentView _singleTapRecognized:], going
through WebPageProxy::commitPotentialTap() and eventually WebPage::completeSyntheticClick().

While we used to tell the PointerCaptureController that a PointerID was no longer active when a given touch ended or was canceled (in
WebKitAdditions code), we can no longer do this as the dispatch of a synthetic tap is performed asynchronously and will happen past the
dispatch of "pointerup" and "pointercancel" Pointer Events. To clear inactive PointerIDs from the PointerCaptureController, we add a new
touchWithIdentifierWasRemoved() method on the WebPage and its proxy. When the WKSyntheticTapGestureRecognizer resets and -[WKContentView _singleTapDidReset:]
is called, we call that method which allows for only active PointerIDs to be tracked by the PointerCaptureController.

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

(-[WKContentView setupInteraction]):
(-[WKContentView cleanupInteraction]):
(-[WKContentView _singleTapDidReset:]):
(-[WKContentView _singleTapRecognized:]):

  • UIProcess/ios/WKSyntheticTapGestureRecognizer.h:
  • UIProcess/ios/WKSyntheticTapGestureRecognizer.m:

(-[WKSyntheticTapGestureRecognizer reset]):
(-[WKSyntheticTapGestureRecognizer touchesEnded:withEvent:]):

  • UIProcess/ios/WebPageProxyIOS.mm:

(WebKit::WebPageProxy::touchWithIdentifierWasRemoved):
(WebKit::WebPageProxy::commitPotentialTap):

  • WebProcess/WebPage/WebPage.h:
  • WebProcess/WebPage/WebPage.messages.in:
  • WebProcess/WebPage/ios/WebPageIOS.mm:

(WebKit::dispatchSyntheticMouseMove):
(WebKit::WebPage::handleSyntheticClick):
(WebKit::WebPage::completePendingSyntheticClickForContentChangeObserver):
(WebKit::WebPage::completeSyntheticClick):
(WebKit::WebPage::commitPotentialTap):
(WebKit::WebPage::touchWithIdentifierWasRemoved):

LayoutTests:

We're adding an iOS-specific expectation since this test prints out the pointer type detected while it runs, which is "touch"
on iOS and "mouse" in the expectation that already exists for macOS.

  • platform/ios/imported/w3c/web-platform-tests/pointerevents/pointerevent_suppress_compat_events_on_click-expected.txt: Added.
Location:
trunk
Files:
2 added
20 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r245638 r245639  
     12019-05-22  Antoine Quint  <graouts@apple.com>
     2
     3        [iOS] Compatibility mouse events aren't prevented by calling preventDefault() on pointerdown
     4        https://bugs.webkit.org/show_bug.cgi?id=198124
     5        <rdar://problem/50410863>
     6
     7        Reviewed by Tim Horton.
     8
     9        We're adding an iOS-specific expectation since this test prints out the pointer type detected while it runs, which is "touch"
     10        on iOS and "mouse" in the expectation that already exists for macOS.
     11
     12        * platform/ios/imported/w3c/web-platform-tests/pointerevents/pointerevent_suppress_compat_events_on_click-expected.txt: Added.
     13
    1142019-05-22  Jiewen Tan  <jiewen_tan@apple.com>
    215
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r245625 r245639  
     12019-05-22  Antoine Quint  <graouts@apple.com>
     2
     3        [iOS] Compatibility mouse events aren't prevented by calling preventDefault() on pointerdown
     4        https://bugs.webkit.org/show_bug.cgi?id=198124
     5        <rdar://problem/50410863>
     6
     7        Reviewed by Tim Horton.
     8
     9        We add basic support to run a test that wasn't specifically designed for a touch-based interaction such that the test
     10        at imported/w3c/web-platform-tests/pointerevents/pointerevent_suppress_compat_events_on_click.html may run on iOS. The
     11        trick here is to add a pause after a touch ends to avoid the likelihood or two tap gestures triggering a double tap.
     12
     13        * web-platform-tests/resources/testdriver-vendor.js:
     14
    1152019-05-22  Youenn Fablet  <youenn@apple.com>
    216
  • trunk/LayoutTests/imported/w3c/web-platform-tests/resources/testdriver-vendor.js

    r245584 r245639  
    4747}
    4848
    49 function dispatchTouchActions(actions)
     49function dispatchTouchActions(actions, options = { insertPauseAfterPointerUp: false })
    5050{
    5151    if (!window.testRunner || typeof window.testRunner.runUIScript !== "function")
     
    100100            touch.y = y;
    101101            id++;
     102            // We need to add a pause after a pointer up to ensure that a subsequent tap may be recognized as such.
     103            if (options.insertPauseAfterPointerUp)
     104                timeOffsetIncrease = 0.5;
    102105            break;
    103106        case "pause":
     
    174177    logDebug(() => JSON.stringify(pointerSource));
    175178
     179    if (pointerType === "touch")
     180        return dispatchTouchActions(pointerSource.actions);
     181    if ("createTouch" in document)
     182        return dispatchTouchActions(pointerSource.actions, { insertPauseAfterPointerUp: true });
    176183    if (pointerType === "mouse")
    177184        return dispatchMouseActions(pointerSource.actions);
    178     if (pointerType === "touch")
    179         return dispatchTouchActions(pointerSource.actions);
    180185};
  • trunk/Source/WebCore/ChangeLog

    r245638 r245639  
     12019-05-22  Antoine Quint  <graouts@apple.com>
     2
     3        [iOS] Compatibility mouse events aren't prevented by calling preventDefault() on pointerdown
     4        https://bugs.webkit.org/show_bug.cgi?id=198124
     5        <rdar://problem/50410863>
     6
     7        Reviewed by Tim Horton.
     8
     9        This fix builds atop the one made for wkb.ug/198072 which fixes this bug on macOS alone.
     10
     11        In order to correctly prevent "compatibility" mouse events from being dispatched when the initial "pointerdown" event had preventDefault()
     12        called while handled, we need to pass the PointerID for the touch that triggered a tap gesture in the UI process down in the Web process
     13        and into the resulting PlatformMouseEvent. This will allow upon dispatch of a PlatformMouseEvent to call into PointerCaptureController
     14        to identify if the dispatch of mouse events is allowed for the event's PointerID.
     15
     16        To support this, some refactoring was required. The PointerID header is now under platform/ such that PlatformMouseEvent may safely use it.
     17        Additionally, PointerEvent::defaultMousePointerIdentifier() is now a global mousePointerID defined in PointerID.h.
     18
     19        Finally, PointerCaptureController::touchEndedOrWasCancelledForIdentifier() has been renamed to PointerCaptureController::touchWithIdentifierWasRemoved() and
     20        has WEBCORE_EXPORT such that it may be called from WebKit as the indication that a pointer is no longer active will now be initiated in WebKit
     21        on the UI process side.
     22
     23        Testing is covered by the pre-existing imported/w3c/web-platform-tests/pointerevents/pointerevent_suppress_compat_events_on_click.html
     24        which will now run on iOS through a change to WebKitAdditions.
     25
     26        * Headers.cmake:
     27        * WebCore.xcodeproj/project.pbxproj:
     28        * dom/Element.cpp:
     29        (WebCore::Element::dispatchMouseEvent): When dealing with a mouse event on iOS, check whether the mouse event's PointerID allows for compatibility
     30        mouse events to be dispatched using PointerCaptureController::preventsCompatibilityMouseEventsForIdentifier(). The "click" event is not a compatibility
     31        mouse event.
     32        * dom/PointerEvent.h:
     33        * page/PointerCaptureController.cpp:
     34        (WebCore::PointerCaptureController::PointerCaptureController):
     35        (WebCore::PointerCaptureController::touchWithIdentifierWasRemoved):
     36        (WebCore::PointerCaptureController::touchEndedOrWasCancelledForIdentifier): Deleted.
     37        * page/PointerCaptureController.h:
     38        * platform/PlatformMouseEvent.h:
     39        (WebCore::PlatformMouseEvent::PlatformMouseEvent):
     40        (WebCore::PlatformMouseEvent::pointerId const):
     41        * platform/PointerID.h: Renamed from Source/WebCore/dom/PointerID.h.
     42        (WebCore::mousePointerID):
     43
    1442019-05-22  Jiewen Tan  <jiewen_tan@apple.com>
    245
  • trunk/Source/WebCore/Headers.cmake

    r245638 r245639  
    421421    dom/NodeTraversal.h
    422422    dom/OverflowEvent.h
    423     dom/PointerID.h
    424423    dom/Position.h
    425424    dom/ProcessingInstruction.h
     
    929928    platform/PlatformTouchPoint.h
    930929    platform/PlatformWheelEvent.h
     930    platform/PointerID.h
    931931    platform/PopupMenu.h
    932932    platform/PopupMenuClient.h
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r245638 r245639  
    932932                316FE11A0E6E1DA700BF6088 /* KeyframeAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 316FE1100E6E1DA700BF6088 /* KeyframeAnimation.h */; };
    933933                31741AAD16636609008A5B7E /* SimulatedClickOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 31741AAB16635E45008A5B7E /* SimulatedClickOptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
    934                 317D3FF3215599F40034E3B9 /* PointerEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 317D3FF2215599E30034E3B9 /* PointerEvent.h */; };
     934                317D3FF3215599F40034E3B9 /* PointerEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 317D3FF2215599E30034E3B9 /* PointerEvent.h */; settings = {ATTRIBUTES = (Private, ); }; };
    935935                31815A311F9A6C8F00FCBF89 /* ImageBitmap.h in Headers */ = {isa = PBXBuildFile; fileRef = 31D26BBF1F86D189008FF255 /* ImageBitmap.h */; settings = {ATTRIBUTES = (Private, ); }; };
    936936                318436DE21B9DAAF00ED383E /* WebGPULayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 318436DB21B9DAA000ED383E /* WebGPULayer.h */; };
     
    1701017010                        isa = PBXGroup;
    1701117011                        children = (
    17012                                 5215862C229377B7005925EF /* WHLSLAST.h */,
    1701317012                                1C840B9021EC30F900D0500D /* WHLSLAddressSpace.h */,
    1701417013                                C21BF72521CD89E200227979 /* WHLSLArrayReferenceType.h */,
    1701517014                                C21BF70921CD89CA00227979 /* WHLSLArrayType.h */,
    1701617015                                C21BF73021CD89ED00227979 /* WHLSLAssignmentExpression.h */,
     17016                                5215862C229377B7005925EF /* WHLSLAST.h */,
    1701717017                                C21BF70A21CD89CB00227979 /* WHLSLBaseFunctionAttribute.h */,
    1701817018                                C21BF6FA21CD89BE00227979 /* WHLSLBaseSemantic.h */,
     
    2531525315                                BCBB8AB613F1AFB000734DF0 /* PODIntervalTree.h */,
    2531625316                                BCBB8AB713F1AFB000734DF0 /* PODRedBlackTree.h */,
     25317                                71EADCD622087E6D0065A45F /* PointerID.h */,
    2531725318                                0668E1890ADD9624004128E0 /* PopupMenu.h */,
    2531825319                                ABC128760B33AA6D00C693D5 /* PopupMenuClient.h */,
     
    2747627477                                317D3FF2215599E30034E3B9 /* PointerEvent.h */,
    2747727478                                317D3FEF215599E10034E3B9 /* PointerEvent.idl */,
    27478                                 71EADCD622087E6D0065A45F /* PointerID.h */,
    2747927479                                5189F0DD10B46B0E00F3C739 /* PopStateEvent.cpp */,
    2748027480                                5174E20810A1F44F00F95E6F /* PopStateEvent.h */,
  • trunk/Source/WebCore/dom/Element.cpp

    r245585 r245639  
    304304    bool didNotSwallowEvent = true;
    305305
    306 #if ENABLE(POINTER_EVENTS) && !ENABLE(TOUCH_EVENTS)
     306#if ENABLE(POINTER_EVENTS)
    307307    if (RuntimeEnabledFeatures::sharedFeatures().pointerEventsEnabled()) {
     308#if ENABLE(TOUCH_EVENTS)
     309        if (auto* page = document().page()) {
     310            if (mouseEvent->type() != eventNames().clickEvent && page->pointerCaptureController().preventsCompatibilityMouseEventsForIdentifier(platformEvent.pointerId()))
     311                return false;
     312        }
     313#else
    308314        if (auto pointerEvent = PointerEvent::create(mouseEvent)) {
    309315            if (auto* page = document().page()) {
     
    318324            }
    319325        }
     326#endif
    320327    }
    321328#endif
  • trunk/Source/WebCore/dom/PointerEvent.h

    r245020 r245639  
    4141public:
    4242    struct Init : MouseEventInit {
    43         PointerID pointerId { PointerEvent::defaultMousePointerIdentifier() };
     43        PointerID pointerId { mousePointerID };
    4444        double width { 1 };
    4545        double height { 1 };
     
    8686    static const String& penPointerType();
    8787    static const String& touchPointerType();
    88     static PointerID defaultMousePointerIdentifier() { return 1; }
    8988
    9089    virtual ~PointerEvent();
     
    114113#endif
    115114
    116     PointerID m_pointerId { PointerEvent::defaultMousePointerIdentifier() };
     115    PointerID m_pointerId { mousePointerID };
    117116    double m_width { 1 };
    118117    double m_height { 1 };
  • trunk/Source/WebCore/page/PointerCaptureController.cpp

    r245585 r245639  
    4848    CapturingData capturingData;
    4949    capturingData.pointerType = PointerEvent::mousePointerType();
    50     m_activePointerIdsToCapturingData.set(PointerEvent::defaultMousePointerIdentifier(), capturingData);
     50    m_activePointerIdsToCapturingData.set(mousePointerID, capturingData);
    5151#endif
    5252}
     
    147147}
    148148
    149 void PointerCaptureController::touchEndedOrWasCancelledForIdentifier(PointerID pointerId)
     149void PointerCaptureController::touchWithIdentifierWasRemoved(PointerID pointerId)
    150150{
    151151    m_activePointerIdsToCapturingData.remove(pointerId);
  • trunk/Source/WebCore/page/PointerCaptureController.h

    r245585 r245639  
    5353#endif
    5454
    55     void touchEndedOrWasCancelledForIdentifier(PointerID);
     55    WEBCORE_EXPORT void touchWithIdentifierWasRemoved(PointerID);
    5656    bool hasCancelledPointerEventForIdentifier(PointerID);
    5757    bool preventsCompatibilityMouseEventsForIdentifier(PointerID);
  • trunk/Source/WebCore/platform/PlatformMouseEvent.h

    r223264 r245639  
    2929#include "IntPoint.h"
    3030#include "PlatformEvent.h"
     31#include "PointerID.h"
    3132#include <wtf/WindowsExtras.h>
    3233
     
    6263
    6364        PlatformMouseEvent(const IntPoint& position, const IntPoint& globalPosition, MouseButton button, PlatformEvent::Type type,
    64                            int clickCount, bool shiftKey, bool ctrlKey, bool altKey, bool metaKey, WallTime timestamp, double force, SyntheticClickType syntheticClickType)
     65                           int clickCount, bool shiftKey, bool ctrlKey, bool altKey, bool metaKey, WallTime timestamp, double force, SyntheticClickType syntheticClickType, PointerID pointerId = mousePointerID)
    6566            : PlatformEvent(type, shiftKey, ctrlKey, altKey, metaKey, timestamp)
    6667            , m_position(position)
     
    7172            , m_force(force)
    7273            , m_syntheticClickType(syntheticClickType)
     74            , m_pointerId(pointerId)
    7375#if PLATFORM(MAC)
    7476            , m_eventNumber(0)
     
    9294        double force() const { return m_force; }
    9395        SyntheticClickType syntheticClickType() const { return m_syntheticClickType; }
     96        PointerID pointerId() const { return m_pointerId; }
    9497
    9598#if PLATFORM(GTK)
     
    122125        double m_force { 0 };
    123126        SyntheticClickType m_syntheticClickType { NoTap };
     127        PointerID m_pointerId { mousePointerID };
    124128
    125129#if PLATFORM(MAC)
  • trunk/Source/WebCore/platform/PointerID.h

    r245638 r245639  
    2626#pragma once
    2727
    28 #if ENABLE(POINTER_EVENTS)
    29 
    3028namespace WebCore {
    3129
    3230using PointerID = int32_t;
    3331
     32static PointerID mousePointerID = 1;
     33
    3434}
    35 
    36 #endif // ENABLE(POINTER_EVENTS)
  • trunk/Source/WebKit/ChangeLog

    r245638 r245639  
     12019-05-22  Antoine Quint  <graouts@apple.com>
     2
     3        [iOS] Compatibility mouse events aren't prevented by calling preventDefault() on pointerdown
     4        https://bugs.webkit.org/show_bug.cgi?id=198124
     5        <rdar://problem/50410863>
     6
     7        Reviewed by Tim Horton.
     8
     9        In order to correctly prevent "compatibility" mouse events from being dispatched when the initial "pointerdown" event had preventDefault()
     10        called while handled, we need to pass the PointerID for the touch that triggered a tap gesture in the UI process down in the Web process
     11        and into the resulting PlatformMouseEvent.
     12
     13        This means we need to identify the touch identifier, which is the same as the PointerID used for Pointer Events, in the single tap gesture
     14        recognizer, an instance of WKSyntheticTapGestureRecognizer. To do this, we subclass the -[UIResponder touchesEnded:withEvent:] method and
     15        track the touch identifier as the lastActiveTouchIdentifier, a new public property of WKSyntheticTapGestureRecognizer. To allow for this,
     16        we need the support of the content view's UIWebTouchEventsGestureRecognizer which is exposed to the WKSyntheticTapGestureRecognizer as its
     17        supportingWebTouchEventsGestureRecognizer property. This lastActiveTouchIdentifier property is cleared as the gesture recognizer is reset.
     18
     19        This allows the content view to pass the PointerID down to the Web process starting from -[WKContentView _singleTapRecognized:], going
     20        through WebPageProxy::commitPotentialTap() and eventually WebPage::completeSyntheticClick().
     21
     22        While we used to tell the PointerCaptureController that a PointerID was no longer active when a given touch ended or was canceled (in
     23        WebKitAdditions code), we can no longer do this as the dispatch of a synthetic tap is performed asynchronously and will happen past the
     24        dispatch of "pointerup" and "pointercancel" Pointer Events. To clear inactive PointerIDs from the PointerCaptureController, we add a new
     25        touchWithIdentifierWasRemoved() method on the WebPage and its proxy. When the WKSyntheticTapGestureRecognizer resets and -[WKContentView _singleTapDidReset:]
     26        is called, we call that method which allows for only active PointerIDs to be tracked by the PointerCaptureController.
     27
     28        * UIProcess/WebPageProxy.h:
     29        * UIProcess/ios/WKContentViewInteraction.mm:
     30        (-[WKContentView setupInteraction]):
     31        (-[WKContentView cleanupInteraction]):
     32        (-[WKContentView _singleTapDidReset:]):
     33        (-[WKContentView _singleTapRecognized:]):
     34        * UIProcess/ios/WKSyntheticTapGestureRecognizer.h:
     35        * UIProcess/ios/WKSyntheticTapGestureRecognizer.m:
     36        (-[WKSyntheticTapGestureRecognizer reset]):
     37        (-[WKSyntheticTapGestureRecognizer touchesEnded:withEvent:]):
     38        * UIProcess/ios/WebPageProxyIOS.mm:
     39        (WebKit::WebPageProxy::touchWithIdentifierWasRemoved):
     40        (WebKit::WebPageProxy::commitPotentialTap):
     41        * WebProcess/WebPage/WebPage.h:
     42        * WebProcess/WebPage/WebPage.messages.in:
     43        * WebProcess/WebPage/ios/WebPageIOS.mm:
     44        (WebKit::dispatchSyntheticMouseMove):
     45        (WebKit::WebPage::handleSyntheticClick):
     46        (WebKit::WebPage::completePendingSyntheticClickForContentChangeObserver):
     47        (WebKit::WebPage::completeSyntheticClick):
     48        (WebKit::WebPage::commitPotentialTap):
     49        (WebKit::WebPage::touchWithIdentifierWasRemoved):
     50
    1512019-05-22  Jiewen Tan  <jiewen_tan@apple.com>
    252
  • trunk/Source/WebKit/UIProcess/WebPageProxy.h

    r245595 r245639  
    12131213    void willStartUserTriggeredZooming();
    12141214
     1215#if ENABLE(POINTER_EVENTS)
     1216    void touchWithIdentifierWasRemoved(WebCore::PointerID);
     1217#endif
     1218
    12151219    void potentialTapAtPosition(const WebCore::FloatPoint&, bool shouldRequestMagnificationInformation, uint64_t& requestID);
    1216     void commitPotentialTap(OptionSet<WebKit::WebEvent::Modifier>, uint64_t layerTreeTransactionIdAtLastTouchStart);
     1220    void commitPotentialTap(OptionSet<WebKit::WebEvent::Modifier>, uint64_t layerTreeTransactionIdAtLastTouchStart, WebCore::PointerID);
    12171221    void cancelPotentialTap();
    12181222    void tapHighlightAtPosition(const WebCore::FloatPoint&, uint64_t& requestID);
  • trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm

    r245597 r245639  
    728728    [_singleTapGestureRecognizer setGestureIdentifiedTarget:self action:@selector(_singleTapIdentified:)];
    729729    [_singleTapGestureRecognizer setResetTarget:self action:@selector(_singleTapDidReset:)];
     730#if ENABLE(POINTER_EVENTS)
     731    [_singleTapGestureRecognizer setSupportingWebTouchEventsGestureRecognizer:_touchEventGestureRecognizer.get()];
     732#endif
    730733    [self addGestureRecognizer:_singleTapGestureRecognizer.get()];
    731734
     
    865868    [_singleTapGestureRecognizer setGestureIdentifiedTarget:nil action:nil];
    866869    [_singleTapGestureRecognizer setResetTarget:nil action:nil];
     870#if ENABLE(POINTER_EVENTS)
     871    [_singleTapGestureRecognizer setSupportingWebTouchEventsGestureRecognizer:nil];
     872#endif
    867873    [self removeGestureRecognizer:_singleTapGestureRecognizer.get()];
    868874
     
    23132319    ASSERT(gestureRecognizer == _singleTapGestureRecognizer);
    23142320    cancelPotentialTapIfNecessary(self);
     2321#if ENABLE(POINTER_EVENTS)
     2322    if (auto* singleTapTouchIdentifier = [_singleTapGestureRecognizer lastActiveTouchIdentifier])
     2323        _page->touchWithIdentifierWasRemoved([singleTapTouchIdentifier unsignedIntValue]);
     2324#endif
    23152325}
    23162326
     
    23762386    RELEASE_LOG(ViewGestures, "Single tap recognized - commit potential tap (%p)", self);
    23772387
    2378     _page->commitPotentialTap(WebKit::webEventModifierFlags(gestureRecognizerModifierFlags(gestureRecognizer)), _layerTreeTransactionIdAtLastTouchStart);
     2388    WebCore::PointerID pointerId = WebCore::mousePointerID;
     2389#if ENABLE(POINTER_EVENTS)
     2390    if (auto* singleTapTouchIdentifier = [_singleTapGestureRecognizer lastActiveTouchIdentifier])
     2391        pointerId = [singleTapTouchIdentifier unsignedIntValue];
     2392#endif
     2393    _page->commitPotentialTap(WebKit::webEventModifierFlags(gestureRecognizerModifierFlags(gestureRecognizer)), _layerTreeTransactionIdAtLastTouchStart, pointerId);
    23792394
    23802395    if (!_isExpectingFastSingleTapCommit)
  • trunk/Source/WebKit/UIProcess/ios/WKSyntheticTapGestureRecognizer.h

    r244955 r245639  
    3636- (void)setGestureFailedTarget:(id)target action:(SEL)action;
    3737- (void)setResetTarget:(id)target action:(SEL)action;
     38#if ENABLE(POINTER_EVENTS)
     39@property (nonatomic, weak) UIWebTouchEventsGestureRecognizer *supportingWebTouchEventsGestureRecognizer;
     40@property (nonatomic, readonly) NSNumber *lastActiveTouchIdentifier;
     41#endif
    3842@end
    3943
  • trunk/Source/WebKit/UIProcess/ios/WKSyntheticTapGestureRecognizer.m

    r242757 r245639  
    7171    [super reset];
    7272    [_resetTarget performSelector:_resetAction withObject:self];
     73    _lastActiveTouchIdentifier = nil;
     74}
     75
     76- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
     77{
     78    [super touchesEnded:touches withEvent:event];
     79    if (!_supportingWebTouchEventsGestureRecognizer)
     80        return;
     81
     82#if ENABLE(POINTER_EVENTS) && HAVE(UI_WEB_TOUCH_EVENTS_GESTURE_RECOGNIZER_WITH_ACTIVE_TOUCHES_BY_ID)
     83    // FIXME: <rdar://problem/48035706>
     84    NSMapTable<NSNumber *, UITouch *> *activeTouches = [_supportingWebTouchEventsGestureRecognizer activeTouchesByIdentifier];
     85    for (NSNumber *touchIdentifier in activeTouches) {
     86        UITouch *touch = [activeTouches objectForKey:touchIdentifier];
     87        if ([touch.gestureRecognizers containsObject:self]) {
     88            _lastActiveTouchIdentifier = touchIdentifier;
     89            break;
     90        }
     91    }
     92#endif
    7393}
    7494
  • trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm

    r245079 r245639  
    837837}
    838838
     839#if ENABLE(POINTER_EVENTS)
     840void WebPageProxy::touchWithIdentifierWasRemoved(WebCore::PointerID pointerId)
     841{
     842    process().send(Messages::WebPage::TouchWithIdentifierWasRemoved(pointerId), m_pageID);
     843}
     844#endif
     845
    839846void WebPageProxy::potentialTapAtPosition(const WebCore::FloatPoint& position, bool shouldRequestMagnificationInformation, uint64_t& requestID)
    840847{
     
    843850}
    844851
    845 void WebPageProxy::commitPotentialTap(OptionSet<WebEvent::Modifier> modifiers, uint64_t layerTreeTransactionIdAtLastTouchStart)
    846 {
    847     process().send(Messages::WebPage::CommitPotentialTap(modifiers, layerTreeTransactionIdAtLastTouchStart), m_pageID);
     852void WebPageProxy::commitPotentialTap(OptionSet<WebEvent::Modifier> modifiers, uint64_t layerTreeTransactionIdAtLastTouchStart, WebCore::PointerID pointerId)
     853{
     854    process().send(Messages::WebPage::CommitPotentialTap(modifiers, layerTreeTransactionIdAtLastTouchStart, pointerId), m_pageID);
    848855}
    849856
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.h

    r245595 r245639  
    623623    bool hasStablePageScaleFactor() const { return m_hasStablePageScaleFactor; }
    624624
     625#if ENABLE(POINTER_EVENTS)
     626    void touchWithIdentifierWasRemoved(WebCore::PointerID);
     627#endif
     628
    625629    void handleTap(const WebCore::IntPoint&, OptionSet<WebKit::WebEvent::Modifier>, uint64_t lastLayerTreeTransactionId);
    626630    void potentialTapAtPosition(uint64_t requestID, const WebCore::FloatPoint&, bool shouldRequestMagnificationInformation);
    627     void commitPotentialTap(OptionSet<WebKit::WebEvent::Modifier>, uint64_t lastLayerTreeTransactionId);
     631    void commitPotentialTap(OptionSet<WebKit::WebEvent::Modifier>, uint64_t lastLayerTreeTransactionId, WebCore::PointerID);
    628632    void commitPotentialTapFailed();
    629633    void cancelPotentialTap();
     
    12351239    void platformInitializeAccessibility();
    12361240    void generateSyntheticEditingCommand(SyntheticEditingCommandType);
    1237     void handleSyntheticClick(WebCore::Node& nodeRespondingToClick, const WebCore::FloatPoint& location, OptionSet<WebKit::WebEvent::Modifier>);
    1238     void completeSyntheticClick(WebCore::Node& nodeRespondingToClick, const WebCore::FloatPoint& location, OptionSet<WebKit::WebEvent::Modifier>, WebCore::SyntheticClickType);
     1241    void handleSyntheticClick(WebCore::Node& nodeRespondingToClick, const WebCore::FloatPoint& location, OptionSet<WebKit::WebEvent::Modifier>, WebCore::PointerID = WebCore::mousePointerID);
     1242    void completeSyntheticClick(WebCore::Node& nodeRespondingToClick, const WebCore::FloatPoint& location, OptionSet<WebKit::WebEvent::Modifier>, WebCore::SyntheticClickType, WebCore::PointerID = WebCore::mousePointerID);
    12391243    void sendTapHighlightForNodeIfNecessary(uint64_t requestID, WebCore::Node*);
    12401244    void resetTextAutosizing();
     
    18451849    WebCore::FloatRect m_previousExposedContentRect;
    18461850    OptionSet<WebKit::WebEvent::Modifier> m_pendingSyntheticClickModifiers;
     1851    WebCore::PointerID m_pendingSyntheticClickPointerId { 0 };
    18471852    FocusedElementIdentifier m_currentFocusedElementIdentifier { 0 };
    18481853    Optional<DynamicViewportSizeUpdateID> m_pendingDynamicViewportSizeUpdateID;
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in

    r245595 r245639  
    5252    DynamicViewportSizeUpdate(WebCore::FloatSize viewLayoutSize, WebCore::FloatSize maximumUnobscuredSize, WebCore::FloatRect targetExposedContentRect, WebCore::FloatRect targetUnobscuredRect, WebCore::FloatRect targetUnobscuredRectInScrollViewCoordinates, WebCore::RectEdges<float> targetUnobscuredSafeAreaInsets, double scale, int32_t deviceOrientation, uint64_t dynamicViewportSizeUpdateID)
    5353
     54    TouchWithIdentifierWasRemoved(WebCore::PointerID pointerId)
    5455    HandleTap(WebCore::IntPoint point, OptionSet<WebKit::WebEvent::Modifier> modifiers, uint64_t lastLayerTreeTransactionId)
    5556    PotentialTapAtPosition(uint64_t requestID, WebCore::FloatPoint point, bool shouldRequestMagnificationInformation)
    56     CommitPotentialTap(OptionSet<WebKit::WebEvent::Modifier> modifiers, uint64_t lastLayerTreeTransactionId)
     57    CommitPotentialTap(OptionSet<WebKit::WebEvent::Modifier> modifiers, uint64_t lastLayerTreeTransactionId, WebCore::PointerID pointerId)
    5758    CancelPotentialTap()
    5859    TapHighlightAtPosition(uint64_t requestID, WebCore::FloatPoint point)
  • trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm

    r245561 r245639  
    109109#import <WebCore/PlatformKeyboardEvent.h>
    110110#import <WebCore/PlatformMouseEvent.h>
     111#import <WebCore/PointerCaptureController.h>
    111112#import <WebCore/Quirks.h>
    112113#import <WebCore/RenderBlock.h>
     
    564565}
    565566
    566 static void dispatchSyntheticMouseMove(Frame& mainFrame, const WebCore::FloatPoint& location, OptionSet<WebEvent::Modifier> modifiers)
     567static void dispatchSyntheticMouseMove(Frame& mainFrame, const WebCore::FloatPoint& location, OptionSet<WebEvent::Modifier> modifiers, WebCore::PointerID pointerId = WebCore::mousePointerID)
    567568{
    568569    IntPoint roundedAdjustedPoint = roundedIntPoint(location);
     
    571572    auto altKey = modifiers.contains(WebEvent::Modifier::AltKey);
    572573    auto metaKey = modifiers.contains(WebEvent::Modifier::MetaKey);
    573     auto mouseEvent = PlatformMouseEvent(roundedAdjustedPoint, roundedAdjustedPoint, NoButton, PlatformEvent::MouseMoved, 0, shiftKey, ctrlKey, altKey, metaKey, WallTime::now(), WebCore::ForceAtClick, WebCore::NoTap);
     574    auto mouseEvent = PlatformMouseEvent(roundedAdjustedPoint, roundedAdjustedPoint, NoButton, PlatformEvent::MouseMoved, 0, shiftKey, ctrlKey, altKey, metaKey, WallTime::now(), WebCore::ForceAtClick, WebCore::NoTap, pointerId);
    574575    // FIXME: Pass caps lock state.
    575576    mainFrame.eventHandler().dispatchSyntheticMouseMove(mouseEvent);
     
    628629}
    629630
    630 void WebPage::handleSyntheticClick(Node& nodeRespondingToClick, const WebCore::FloatPoint& location, OptionSet<WebEvent::Modifier> modifiers)
     631void WebPage::handleSyntheticClick(Node& nodeRespondingToClick, const WebCore::FloatPoint& location, OptionSet<WebEvent::Modifier> modifiers, WebCore::PointerID pointerId)
    631632{
    632633    if (!nodeRespondingToClick.document().settings().contentChangeObserverEnabled()) {
    633         completeSyntheticClick(nodeRespondingToClick, location, modifiers, WebCore::OneFingerTap);
     634        completeSyntheticClick(nodeRespondingToClick, location, modifiers, WebCore::OneFingerTap, pointerId);
    634635        return;
    635636    }
     
    640641        ContentChangeObserver::MouseMovedScope observingScope(respondingDocument);
    641642        auto& mainFrame = m_page->mainFrame();
    642         dispatchSyntheticMouseMove(mainFrame, location, modifiers);
     643        dispatchSyntheticMouseMove(mainFrame, location, modifiers, pointerId);
    643644        mainFrame.document()->updateStyleIfNeeded();
    644645    }
     
    660661        m_pendingSyntheticClickLocation = location;
    661662        m_pendingSyntheticClickModifiers = modifiers;
    662         return;
    663     }
    664 
    665     callOnMainThread([protectedThis = makeRefPtr(this), targetNode = Ref<Node>(nodeRespondingToClick), location, modifiers, observedContentChange, targetNodeTriggersClick] {
     663        m_pendingSyntheticClickPointerId = pointerId;
     664        return;
     665    }
     666
     667    callOnMainThread([protectedThis = makeRefPtr(this), targetNode = Ref<Node>(nodeRespondingToClick), location, modifiers, observedContentChange, targetNodeTriggersClick, pointerId] {
    666668        if (protectedThis->m_isClosed || !protectedThis->corePage())
    667669            return;
     
    670672        if (shouldStayAtHoverState) {
    671673            // The move event caused new contents to appear. Don't send synthetic click event, but just ensure that the mouse is on the most recent content.
    672             dispatchSyntheticMouseMove(protectedThis->corePage()->mainFrame(), location, modifiers);
     674            dispatchSyntheticMouseMove(protectedThis->corePage()->mainFrame(), location, modifiers, pointerId);
    673675            LOG(ContentObservation, "handleSyntheticClick: Observed meaningful visible change -> hover.");
    674676            return;
    675677        }
    676678        LOG(ContentObservation, "handleSyntheticClick: calling completeSyntheticClick -> click.");
    677         protectedThis->completeSyntheticClick(targetNode, location, modifiers, WebCore::OneFingerTap);
     679        protectedThis->completeSyntheticClick(targetNode, location, modifiers, WebCore::OneFingerTap, pointerId);
    678680    });
    679681}
     
    688690    if (observedContentChange == WKContentNoChange) {
    689691        LOG(ContentObservation, "No chage was observed -> click.");
    690         completeSyntheticClick(*m_pendingSyntheticClickNode, m_pendingSyntheticClickLocation, m_pendingSyntheticClickModifiers, WebCore::OneFingerTap);
     692        completeSyntheticClick(*m_pendingSyntheticClickNode, m_pendingSyntheticClickLocation, m_pendingSyntheticClickModifiers, WebCore::OneFingerTap, m_pendingSyntheticClickPointerId);
    691693    } else {
    692694        // Ensure that the mouse is on the most recent content.
    693         dispatchSyntheticMouseMove(m_page->mainFrame(), m_pendingSyntheticClickLocation, m_pendingSyntheticClickModifiers);
     695        dispatchSyntheticMouseMove(m_page->mainFrame(), m_pendingSyntheticClickLocation, m_pendingSyntheticClickModifiers, m_pendingSyntheticClickPointerId);
    694696        LOG(ContentObservation, "Observed meaningful visible change -> hover.");
    695697    }
     
    698700    m_pendingSyntheticClickLocation = FloatPoint();
    699701    m_pendingSyntheticClickModifiers = { };
    700 }
    701 
    702 void WebPage::completeSyntheticClick(Node& nodeRespondingToClick, const WebCore::FloatPoint& location, OptionSet<WebEvent::Modifier> modifiers, SyntheticClickType syntheticClickType)
     702    m_pendingSyntheticClickPointerId = 0;
     703}
     704
     705void WebPage::completeSyntheticClick(Node& nodeRespondingToClick, const WebCore::FloatPoint& location, OptionSet<WebEvent::Modifier> modifiers, SyntheticClickType syntheticClickType, WebCore::PointerID pointerId)
    703706{
    704707    IntPoint roundedAdjustedPoint = roundedIntPoint(location);
     
    719722    bool metaKey = modifiers.contains(WebEvent::Modifier::MetaKey);
    720723
    721     tapWasHandled |= mainframe.eventHandler().handleMousePressEvent(PlatformMouseEvent(roundedAdjustedPoint, roundedAdjustedPoint, LeftButton, PlatformEvent::MousePressed, 1, shiftKey, ctrlKey, altKey, metaKey, WallTime::now(), WebCore::ForceAtClick, syntheticClickType));
     724    tapWasHandled |= mainframe.eventHandler().handleMousePressEvent(PlatformMouseEvent(roundedAdjustedPoint, roundedAdjustedPoint, LeftButton, PlatformEvent::MousePressed, 1, shiftKey, ctrlKey, altKey, metaKey, WallTime::now(), WebCore::ForceAtClick, syntheticClickType, pointerId));
    722725    if (m_isClosed)
    723726        return;
    724727
    725     tapWasHandled |= mainframe.eventHandler().handleMouseReleaseEvent(PlatformMouseEvent(roundedAdjustedPoint, roundedAdjustedPoint, LeftButton, PlatformEvent::MouseReleased, 1, shiftKey, ctrlKey, altKey, metaKey, WallTime::now(), WebCore::ForceAtClick, syntheticClickType));
     728    tapWasHandled |= mainframe.eventHandler().handleMouseReleaseEvent(PlatformMouseEvent(roundedAdjustedPoint, roundedAdjustedPoint, LeftButton, PlatformEvent::MouseReleased, 1, shiftKey, ctrlKey, altKey, metaKey, WallTime::now(), WebCore::ForceAtClick, syntheticClickType, pointerId));
    726729    if (m_isClosed)
    727730        return;
     
    739742    // Only send a synthetic mouse out event if synthetic mouse move events were sent; this is true when ContentChangeObserver is enabled.
    740743    if (nodeRespondingToClick.document().settings().contentChangeObserverEnabled() && !tapWasHandled && nodeRespondingToClick.document().frame())
    741         nodeRespondingToClick.document().frame()->eventHandler().dispatchSyntheticMouseOut(PlatformMouseEvent(roundedAdjustedPoint, roundedAdjustedPoint, LeftButton, PlatformEvent::NoType, 0, shiftKey, ctrlKey, altKey, metaKey, WallTime::now(), 0, WebCore::NoTap));
     744        nodeRespondingToClick.document().frame()->eventHandler().dispatchSyntheticMouseOut(PlatformMouseEvent(roundedAdjustedPoint, roundedAdjustedPoint, LeftButton, PlatformEvent::NoType, 0, shiftKey, ctrlKey, altKey, metaKey, WallTime::now(), 0, WebCore::NoTap, pointerId));
    742745
    743746    if (m_isClosed)
     
    960963}
    961964
    962 void WebPage::commitPotentialTap(OptionSet<WebEvent::Modifier> modifiers, uint64_t lastLayerTreeTransactionId)
     965void WebPage::commitPotentialTap(OptionSet<WebEvent::Modifier> modifiers, uint64_t lastLayerTreeTransactionId, WebCore::PointerID pointerId)
    963966{
    964967    if (!m_potentialTapNode || (!m_potentialTapNode->renderer() && !is<HTMLAreaElement>(m_potentialTapNode.get()))) {
     
    984987        } else
    985988#endif
    986             handleSyntheticClick(*nodeRespondingToClick, adjustedPoint, modifiers);
     989            handleSyntheticClick(*nodeRespondingToClick, adjustedPoint, modifiers, pointerId);
    987990    } else
    988991        commitPotentialTapFailed();
     
    10331036    sendTapHighlightForNodeIfNecessary(requestID, mainframe.nodeRespondingToClickEvents(position, adjustedPoint));
    10341037}
     1038
     1039#if ENABLE(POINTER_EVENTS)
     1040void WebPage::touchWithIdentifierWasRemoved(WebCore::PointerID pointerId)
     1041{
     1042    m_page->pointerCaptureController().touchWithIdentifierWasRemoved(pointerId);
     1043}
     1044#endif
    10351045
    10361046void WebPage::inspectorNodeSearchMovedToPosition(const FloatPoint& position)
Note: See TracChangeset for help on using the changeset viewer.