Changeset 246844 in webkit


Ignore:
Timestamp:
Jun 26, 2019 11:36:41 AM (5 years ago)
Author:
graouts@webkit.org
Message:

[Pointer Events] Respect pointer capture when dispatching mouse boundary events and updating :hover
https://bugs.webkit.org/show_bug.cgi?id=198999
<rdar://problem/51979477>

Reviewed by Dean Jackson.

LayoutTests/imported/w3c:

Mark the progressions in 3 WPT tests.

  • web-platform-tests/pointerevents/pointerevent_boundary_events_at_implicit_release_hoverable_pointers-expected.txt:
  • web-platform-tests/pointerevents/pointerevent_mouse_capture_change_hover-expected.txt:
  • web-platform-tests/pointerevents/pointerevent_setpointercapture_relatedtarget-expected.txt:

Source/WebCore:

Up until now, we would not account for pointer capture (see ​https://w3c.github.io/pointerevents/#pointer-capture) when dispatching
mouse boundary events (mouseover, mouseout, mouseenter, mouseleave) and their counterpart pointer events. We would also not account
for it when updating :hover styles.

Now, when pointer capture changes for an element, we call setCapturingMouseEventsElement() on the EventHandler such that the element
that would naturally hit-test is overridden by the pointer capture element when identifying which target to use for the dispatch of
boundary mouse events. Additionally, when calling Document::prepareMouseEvent(), we also use the pointer capture element to
pass down to Document::updateHoverActiveState() such that :hover styles are applied to the correct element.

  • dom/Document.cpp:

(WebCore::Document::prepareMouseEvent): When a new event is going to be dispatched, we must run the Process Pending Capture Element
steps as mandated by the Pointer Events spec. Calling this will dispatch the appropriate pointer capture change events and also
required boundary events since EventHandler::setCapturingMouseEventsElement() calls into EventHandler::updateMouseEventTargetNode().
Since this may update the capturing mouse events element, we ensure that we call updateHoverActiveState() with a flag that indicates that.
Finally, we use the capturing mouse events element instead of the hit-testing element to pass to updateHoverActiveState() to ensure
that is has :hover styles applied.
(WebCore::Document::updateHoverActiveState): Account for the new CaptureChange flag to force the invalidation of the :hover and :active
elements chain at all times when the capturing mouse events element changed.

  • dom/Document.h:
  • dom/PointerEvent.h: Update PointerEvent::createForPointerCapture() to take specific parameters rather than a single PointerEvent to

set the pointerId, isPrimary and pointerType properties of the generated event. This is required to call processPendingPointerCapture()
outside of PointerEvent dispatch logic since we now call it from Document::prepareMouseEvent() where we haven't yet generated such an
event.

  • page/EventHandler.cpp:

(WebCore::EventHandler::pointerCaptureElementDidChange): When a new pointer capture element is set, call updateMouseEventTargetNode()
to ensure that boundary events are fired to indicate the pointer capture state change.
(WebCore::EventHandler::prepareMouseEvent): Keep track of the last PlatformMouseEvent used to prepare a mouse event so that we can use
it when setCapturingMouseEventsElement() is called.

  • page/EventHandler.h:
  • page/PointerCaptureController.cpp:

(WebCore::PointerCaptureController::pointerCaptureElement): Since Document::prepareMouseEvent() needs to know the current pointer capture
element, add a new public method that indicates the pointer capture element if that element is contained in the provided document. We need
to provide the document since PointerCaptureController is owned by the Page and may manage several documents.
(WebCore::PointerCaptureController::dispatchEvent): Only run the Process Pending Capture Element steps when dealing with a touch or pen
event since those steps are already ran for mouse events in Document::prepareMouseEvent(). Additionally, since the element target is already
set to be the pointer capture element with the changes made to processPendingPointerCapture(), and because on iOS pointer capture is always
active, we can remove the code that would retarget the event to the pointer capture element.
(WebCore::PointerCaptureController::pointerEventWasDispatched):
(WebCore::PointerCaptureController::cancelPointer):
(WebCore::PointerCaptureController::processPendingPointerCapture): We now call into EventHandler::setCapturingMouseEventsElement() when the
capture target element changes. We must be careful to call this method prior to dispatching the "gotpointercapture" event and after dispatching
the "lostpointercapture" event so that boundary events are fired at the right time.

  • page/PointerCaptureController.h:

LayoutTests:

Update some WK1-specific expectations.

  • platform/mac-wk1/imported/w3c/web-platform-tests/pointerevents/pointerevent_boundary_events_at_implicit_release_hoverable_pointers-expected.txt:
  • platform/mac-wk1/imported/w3c/web-platform-tests/pointerevents/pointerevent_setpointercapture_relatedtarget-expected.txt:
Location:
trunk
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r246840 r246844  
     12019-06-26  Antoine Quint  <graouts@apple.com>
     2
     3        [Pointer Events] Respect pointer capture when dispatching mouse boundary events and updating :hover
     4        https://bugs.webkit.org/show_bug.cgi?id=198999
     5        <rdar://problem/51979477>
     6
     7        Reviewed by Dean Jackson.
     8
     9        Update some WK1-specific expectations.
     10
     11        * platform/mac-wk1/imported/w3c/web-platform-tests/pointerevents/pointerevent_boundary_events_at_implicit_release_hoverable_pointers-expected.txt:
     12        * platform/mac-wk1/imported/w3c/web-platform-tests/pointerevents/pointerevent_setpointercapture_relatedtarget-expected.txt:
     13
    1142019-06-26  Russell Epstein  <russell_e@apple.com>
    215
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r246753 r246844  
     12019-06-26  Antoine Quint  <graouts@apple.com>
     2
     3        [Pointer Events] Respect pointer capture when dispatching mouse boundary events and updating :hover
     4        https://bugs.webkit.org/show_bug.cgi?id=198999
     5        <rdar://problem/51979477>
     6
     7        Reviewed by Dean Jackson.
     8
     9        Mark the progressions in 3 WPT tests.
     10
     11        * web-platform-tests/pointerevents/pointerevent_boundary_events_at_implicit_release_hoverable_pointers-expected.txt:
     12        * web-platform-tests/pointerevents/pointerevent_mouse_capture_change_hover-expected.txt:
     13        * web-platform-tests/pointerevents/pointerevent_setpointercapture_relatedtarget-expected.txt:
     14
    1152019-06-24  Antoine Quint  <graouts@apple.com>
    216
  • trunk/LayoutTests/imported/w3c/web-platform-tests/pointerevents/pointerevent_boundary_events_at_implicit_release_hoverable_pointers-expected.txt

    r246729 r246844  
    11Pointer Event: Boundary event sequence at implicit capture release
    2 
    3 Follow the test instructions with mouse. If you don't have the device skip it.
    42
    53When a captured pointer is implicitly released after a click, the boundary events should follow the lostpointercapture event.
     
    75Click on the black box with mouse and do not move the mouse after or during the click.
    86
    9 FAIL mouse Event sequence at implicit release on click assert_equals: expected "pointerout@target, pointerleave@target, pointerover@capture-target, pointerenter@capture-target, gotpointercapture@capture-target, pointerup@capture-target, lostpointercapture@capture-target, pointerout@capture-target, pointerleave@capture-target, pointerover@target, pointerenter@target" but got "gotpointercapture@capture-target, pointerup@capture-target, lostpointercapture@capture-target"
     7PASS mouse Event sequence at implicit release on click
    108
  • trunk/LayoutTests/imported/w3c/web-platform-tests/pointerevents/pointerevent_mouse_capture_change_hover-expected.txt

    r246729 r246844  
    11
    2 FAIL Mouse down and capture to green. assert_array_equals: Received events: green received pointerover,green received pointerenter,green received pointermove,green received pointerdown,green received gotpointercapture,green received pointermove,green received pointerout,green received pointerleave,green received pointerover,green received pointerenter,green received pointermove lengths differ, expected 7 got 11
    3 FAIL Mouse down at green and capture to blue. assert_array_equals: Received events: green received pointerout,green received pointerover,green received pointerenter,green received pointermove,green received pointermove,green received pointermove,green received pointermove lengths differ, expected 11 got 7
    4 FAIL Mouse down and capture to green, move to blue and release capture assert_array_equals: Received events: green received pointerout,green received pointerover,green received pointerenter,green received pointermove,green received lostpointercapture,green received pointermove,green received pointerout,green received pointerleave,blue received pointerover,blue received pointerenter,blue received pointermove,blue received pointermove property 0, expected "green received pointerover" but got "green received pointerout"
     2PASS Mouse down and capture to green.
     3PASS Mouse down at green and capture to blue.
     4PASS Mouse down and capture to green, move to blue and release capture
    55
  • trunk/LayoutTests/imported/w3c/web-platform-tests/pointerevents/pointerevent_setpointercapture_relatedtarget-expected.txt

    r246729 r246844  
    1717The following pointer types were detected: mouse.
    1818
    19 The following events were logged: pointerover@target1, gotpointercapture@target0, pointerover@target0, pointerover@target0, lostpointercapture@target0.
     19The following events were logged: pointerover@target1, pointerover@target0, gotpointercapture@target0, lostpointercapture@target0.
    2020
    2121Refresh the page to run the tests again with a different pointer type.
    2222
    2323
    24 Harness Error (FAIL), message = 1 duplicate test name: "relatedTarget should not be null even when the capture is set."
    25 
    2624PASS pointerover shouldn't trigger for the purple rectangle while the black rectangle has capture
    2725PASS relatedTarget should not be null even when the capture is set.
    28 PASS relatedTarget should not be null even when the capture is set.
    2926
  • trunk/LayoutTests/platform/mac-wk1/imported/w3c/web-platform-tests/pointerevents/pointerevent_boundary_events_at_implicit_release_hoverable_pointers-expected.txt

    r246729 r246844  
    77Click on the black box with mouse and do not move the mouse after or during the click.
    88
    9 FAIL mouse Event sequence at implicit release on click assert_equals: expected "pointerout@target, pointerleave@target, pointerover@capture-target, pointerenter@capture-target, gotpointercapture@capture-target, pointerup@capture-target, lostpointercapture@capture-target, pointerout@capture-target, pointerleave@capture-target, pointerover@target, pointerenter@target" but got "gotpointercapture@capture-target, pointerup@capture-target, lostpointercapture@capture-target, pointermove@target"
     9FAIL mouse Event sequence at implicit release on click assert_equals: expected "pointerout@target, pointerleave@target, pointerover@capture-target, pointerenter@capture-target, gotpointercapture@capture-target, pointerup@capture-target, lostpointercapture@capture-target, pointerout@capture-target, pointerleave@capture-target, pointerover@target, pointerenter@target" but got "pointerout@target, pointerleave@target, pointerover@capture-target, pointerenter@capture-target, gotpointercapture@capture-target, pointerup@capture-target, lostpointercapture@capture-target, pointerout@capture-target, pointerleave@capture-target, pointerover@target, pointerenter@target, pointermove@target"
    1010
  • trunk/LayoutTests/platform/mac-wk1/imported/w3c/web-platform-tests/pointerevents/pointerevent_setpointercapture_relatedtarget-expected.txt

    r246729 r246844  
    1717The following pointer types were detected: mouse.
    1818
    19 The following events were logged: pointerover@target1, gotpointercapture@target0, pointerover@target0, pointerover@target0, lostpointercapture@target0, pointerover@target0.
     19The following events were logged: pointerover@target1, pointerover@target0, gotpointercapture@target0, lostpointercapture@target0, pointerover@target0.
    2020
    2121Refresh the page to run the tests again with a different pointer type.
    2222
    2323
    24 Harness Error (FAIL), message = 1 duplicate test name: "relatedTarget should not be null even when the capture is set."
    25 
    2624PASS pointerover shouldn't trigger for the purple rectangle while the black rectangle has capture
    2725PASS relatedTarget should not be null even when the capture is set.
    28 PASS relatedTarget should not be null even when the capture is set.
    2926
  • trunk/Source/WebCore/ChangeLog

    r246831 r246844  
     12019-06-26  Antoine Quint  <graouts@apple.com>
     2
     3        [Pointer Events] Respect pointer capture when dispatching mouse boundary events and updating :hover
     4        https://bugs.webkit.org/show_bug.cgi?id=198999
     5        <rdar://problem/51979477>
     6
     7        Reviewed by Dean Jackson.
     8
     9        Up until now, we would not account for pointer capture (see ​https://w3c.github.io/pointerevents/#pointer-capture) when dispatching
     10        mouse boundary events (mouseover, mouseout, mouseenter, mouseleave) and their counterpart pointer events. We would also not account
     11        for it when updating :hover styles.
     12
     13        Now, when pointer capture changes for an element, we call setCapturingMouseEventsElement() on the EventHandler such that the element
     14        that would naturally hit-test is overridden by the pointer capture element when identifying which target to use for the dispatch of
     15        boundary mouse events. Additionally, when calling Document::prepareMouseEvent(), we also use the pointer capture element to
     16        pass down to Document::updateHoverActiveState() such that :hover styles are applied to the correct element.
     17
     18        * dom/Document.cpp:
     19        (WebCore::Document::prepareMouseEvent): When a new event is going to be dispatched, we must run the Process Pending Capture Element
     20        steps as mandated by the Pointer Events spec. Calling this will dispatch the appropriate pointer capture change events and also
     21        required boundary events since EventHandler::setCapturingMouseEventsElement() calls into EventHandler::updateMouseEventTargetNode().
     22        Since this may update the capturing mouse events element, we ensure that we call updateHoverActiveState() with a flag that indicates that.
     23        Finally, we use the capturing mouse events element instead of the hit-testing element to pass to updateHoverActiveState() to ensure
     24        that is has :hover styles applied.
     25        (WebCore::Document::updateHoverActiveState): Account for the new CaptureChange flag to force the invalidation of the :hover and :active
     26        elements chain at all times when the capturing mouse events element changed.
     27        * dom/Document.h:
     28        * dom/PointerEvent.h: Update PointerEvent::createForPointerCapture() to take specific parameters rather than a single PointerEvent to
     29        set the pointerId, isPrimary and pointerType properties of the generated event. This is required to call processPendingPointerCapture()
     30        outside of PointerEvent dispatch logic since we now call it from Document::prepareMouseEvent() where we haven't yet generated such an
     31        event.
     32        * page/EventHandler.cpp:
     33        (WebCore::EventHandler::pointerCaptureElementDidChange): When a new pointer capture element is set, call updateMouseEventTargetNode()
     34        to ensure that boundary events are fired to indicate the pointer capture state change.
     35        (WebCore::EventHandler::prepareMouseEvent): Keep track of the last PlatformMouseEvent used to prepare a mouse event so that we can use
     36        it when setCapturingMouseEventsElement() is called.
     37        * page/EventHandler.h:
     38        * page/PointerCaptureController.cpp:
     39        (WebCore::PointerCaptureController::pointerCaptureElement): Since Document::prepareMouseEvent() needs to know the current pointer capture
     40        element, add a new public method that indicates the pointer capture element if that element is contained in the provided document. We need
     41        to provide the document since PointerCaptureController is owned by the Page and may manage several documents.
     42        (WebCore::PointerCaptureController::dispatchEvent): Only run the Process Pending Capture Element steps when dealing with a touch or pen
     43        event since those steps are already ran for mouse events in Document::prepareMouseEvent(). Additionally, since the element target is already
     44        set to be the pointer capture element with the changes made to processPendingPointerCapture(), and because on iOS pointer capture is always
     45        active, we can remove the code that would retarget the event to the pointer capture element.
     46        (WebCore::PointerCaptureController::pointerEventWasDispatched):
     47        (WebCore::PointerCaptureController::cancelPointer):
     48        (WebCore::PointerCaptureController::processPendingPointerCapture): We now call into EventHandler::setCapturingMouseEventsElement() when the
     49        capture target element changes. We must be careful to call this method prior to dispatching the "gotpointercapture" event and after dispatching
     50        the "lostpointercapture" event so that boundary events are fired at the right time.
     51        * page/PointerCaptureController.h:
     52
    1532019-06-25  Fujii Hironori  <Hironori.Fujii@sony.com>
    254
  • trunk/Source/WebCore/dom/Document.cpp

    r246729 r246844  
    321321#endif
    322322
     323#if ENABLE(POINTER_EVENTS)
     324#include "PointerCaptureController.h"
     325#endif
     326
    323327namespace WebCore {
    324328
     
    37333737    hitTest(request, result);
    37343738
    3735     if (!request.readOnly())
    3736         updateHoverActiveState(request, result.targetElement());
     3739    auto captureElementChanged = CaptureChange::No;
     3740    if (!request.readOnly()) {
     3741        auto targetElement = makeRefPtr(result.targetElement());
     3742#if ENABLE(POINTER_EVENTS)
     3743        if (auto* page = this->page()) {
     3744            // Before we dispatch a new mouse event, we must run the Process Pending Capture Element steps as defined
     3745            // in https://w3c.github.io/pointerevents/#process-pending-pointer-capture.
     3746            auto& pointerCaptureController = page->pointerCaptureController();
     3747            auto* previousCaptureElement = pointerCaptureController.pointerCaptureElement(this, event.pointerId());
     3748            pointerCaptureController.processPendingPointerCapture(event.pointerId());
     3749            auto* captureElement = pointerCaptureController.pointerCaptureElement(this, event.pointerId());
     3750            // If the capture element has changed while running the Process Pending Capture Element steps then
     3751            // we need to indicate that when calling updateHoverActiveState to be sure that the :active and :hover
     3752            // element chains are updated.
     3753            if (previousCaptureElement != captureElement)
     3754                captureElementChanged = CaptureChange::Yes;
     3755            // If we have a capture element, we must target it instead of what would normally hit-test for this event.
     3756            if (captureElement)
     3757                targetElement = captureElement;
     3758        }
     3759#endif
     3760        updateHoverActiveState(request, targetElement.get(), captureElementChanged);
     3761    }
    37373762
    37383763    return MouseEventWithHitTestResults(event, result);
     
    67386763}
    67396764
    6740 void Document::updateHoverActiveState(const HitTestRequest& request, Element* innerElement)
     6765void Document::updateHoverActiveState(const HitTestRequest& request, Element* innerElement, CaptureChange captureElementChanged)
    67416766{
    67426767    ASSERT(!request.readOnly());
     
    67776802    // If the mouse is down and if this is a mouse move event, we want to restrict changes in
    67786803    // :hover/:active to only apply to elements that are in the :active chain that we froze
    6779     // at the time the mouse went down.
    6780     bool mustBeInActiveChain = request.active() && request.move();
     6804    // at the time the mouse went down, unless the capture element changed.
     6805    bool mustBeInActiveChain = request.active() && request.move() && captureElementChanged == CaptureChange::No;
    67816806
    67826807    RefPtr<Element> oldHoveredElement = WTFMove(m_hoveredElement);
  • trunk/Source/WebCore/dom/Document.h

    r246490 r246844  
    761761    void elementInActiveChainDidDetach(Element&);
    762762
    763     void updateHoverActiveState(const HitTestRequest&, Element*);
     763    enum class CaptureChange : uint8_t { Yes, No };
     764    void updateHoverActiveState(const HitTestRequest&, Element*, CaptureChange = CaptureChange::No);
    764765
    765766    // Updates for :target (CSS3 selector).
  • trunk/Source/WebCore/dom/PointerEvent.h

    r246490 r246844  
    6262    }
    6363
    64     static Ref<PointerEvent> createForPointerCapture(const AtomString& type, const PointerEvent& pointerEvent)
     64    static Ref<PointerEvent> createForPointerCapture(const AtomString& type, PointerID pointerId, bool isPrimary, String pointerType)
    6565    {
    6666        Init initializer;
    6767        initializer.bubbles = true;
    68         initializer.pointerId = pointerEvent.pointerId();
    69         initializer.isPrimary = pointerEvent.isPrimary();
    70         initializer.pointerType = pointerEvent.pointerType();
     68        initializer.pointerId = pointerId;
     69        initializer.isPrimary = isPrimary;
     70        initializer.pointerType = pointerType;
    7171        return adoptRef(*new PointerEvent(type, WTFMove(initializer)));
    7272    }
  • trunk/Source/WebCore/page/EventHandler.cpp

    r246729 r246844  
    128128#endif
    129129
     130#if ENABLE(POINTER_EVENTS)
     131#include "RuntimeEnabledFeatures.h"
     132#endif
     133
    130134namespace WebCore {
    131135
     
    24832487}
    24842488
     2489#if ENABLE(POINTER_EVENTS)
     2490void EventHandler::pointerCaptureElementDidChange(Element* element)
     2491{
     2492    if (m_capturingMouseEventsElement == element)
     2493        return;
     2494
     2495    setCapturingMouseEventsElement(element);
     2496
     2497    // Now that we have a new capture element, we need to dispatch boundary mouse events.
     2498    updateMouseEventTargetNode(element, m_lastPlatformMouseEvent, FireMouseOverOut::Yes);
     2499}
     2500#endif
     2501
    24852502MouseEventWithHitTestResults EventHandler::prepareMouseEvent(const HitTestRequest& request, const PlatformMouseEvent& mouseEvent)
    24862503{
     2504#if ENABLE(POINTER_EVENTS)
     2505    m_lastPlatformMouseEvent = mouseEvent;
     2506#endif
    24872507    Ref<Frame> protectedFrame(m_frame);
    24882508    ASSERT(m_frame.document());
  • trunk/Source/WebCore/page/EventHandler.h

    r246729 r246844  
    159159
    160160    WEBCORE_EXPORT void setCapturingMouseEventsElement(Element*);
     161#if ENABLE(POINTER_EVENTS)
     162    void pointerCaptureElementDidChange(Element*);
     163#endif
    161164
    162165#if ENABLE(DRAG_SUPPORT)
     
    593596    WallTime m_mouseDownTimestamp;
    594597    PlatformMouseEvent m_mouseDown;
     598#if ENABLE(POINTER_EVENTS)
     599    PlatformMouseEvent m_lastPlatformMouseEvent;
     600#endif
    595601
    596602#if PLATFORM(COCOA)
  • trunk/Source/WebCore/page/PointerCaptureController.cpp

    r246752 r246844  
    4949}
    5050
     51Element* PointerCaptureController::pointerCaptureElement(Document* document, PointerID pointerId)
     52{
     53    auto iterator = m_activePointerIdsToCapturingData.find(pointerId);
     54    if (iterator != m_activePointerIdsToCapturingData.end()) {
     55        auto pointerCaptureElement = iterator->value.targetOverride;
     56        if (pointerCaptureElement && &pointerCaptureElement->document() == document)
     57            return pointerCaptureElement.get();
     58    }
     59    return nullptr;
     60}
     61
    5162ExceptionOr<void> PointerCaptureController::setPointerCapture(Element* capturingTarget, PointerID pointerId)
    5263{
     
    272283    // https://w3c.github.io/pointerevents/#firing-events-using-the-pointerevent-interface
    273284    // If the event is not gotpointercapture or lostpointercapture, run Process Pending Pointer Capture steps for this PointerEvent.
    274     processPendingPointerCapture(event);
    275 
    276     // If the pointer capture target override has been set for the pointer, set the target to pointer capture target override object.
    277     auto iterator = m_activePointerIdsToCapturingData.find(event.pointerId());
    278     if (iterator != m_activePointerIdsToCapturingData.end()) {
    279         auto& capturingData = iterator->value;
    280         if (capturingData.targetOverride)
    281             target = capturingData.targetOverride.get();
    282     }
     285    // We only need to do this for non-mouse type since for mouse events this method will be called in Document::prepareMouseEvent().
     286    if (event.pointerType() != PointerEvent::mousePointerType())
     287        processPendingPointerCapture(event.pointerId());
    283288
    284289    pointerEventWillBeDispatched(event, target);
     
    341346        if (event.type() == eventNames().pointerupEvent) {
    342347            capturingData.pendingTargetOverride = nullptr;
    343             processPendingPointerCapture(event);
     348            processPendingPointerCapture(event.pointerId());
    344349        }
    345350
     
    400405    target->dispatchEvent(PointerEvent::create(eventNames().pointeroutEvent, pointerId, capturingData.pointerType, isPrimary));
    401406    target->dispatchEvent(PointerEvent::create(eventNames().pointerleaveEvent, pointerId, capturingData.pointerType, isPrimary));
    402     processPendingPointerCapture(WTFMove(cancelEvent));
    403 }
    404 
    405 void PointerCaptureController::processPendingPointerCapture(const PointerEvent& event)
    406 {
    407     // https://w3c.github.io/pointerevents/#process-pending-pointer-capture
    408 
    409     auto iterator = m_activePointerIdsToCapturingData.find(event.pointerId());
     407    processPendingPointerCapture(pointerId);
     408}
     409
     410void PointerCaptureController::processPendingPointerCapture(PointerID pointerId)
     411{
     412    if (m_processingPendingPointerCapture)
     413        return;
     414
     415    m_processingPendingPointerCapture = true;
     416
     417    auto iterator = m_activePointerIdsToCapturingData.find(pointerId);
    410418    if (iterator == m_activePointerIdsToCapturingData.end())
    411419        return;
     
    416424    auto pendingTargetOverride = capturingData.pendingTargetOverride;
    417425
     426    // https://w3c.github.io/pointerevents/#process-pending-pointer-capture
    418427    // 1. If the pointer capture target override for this pointer is set and is not equal to the pending pointer capture target override,
    419428    // then fire a pointer event named lostpointercapture at the pointer capture target override node.
    420     if (capturingData.targetOverride && capturingData.targetOverride->isConnected() && capturingData.targetOverride != pendingTargetOverride)
    421         capturingData.targetOverride->dispatchEvent(PointerEvent::createForPointerCapture(eventNames().lostpointercaptureEvent, event));
     429    if (capturingData.targetOverride && capturingData.targetOverride->isConnected() && capturingData.targetOverride != pendingTargetOverride) {
     430        capturingData.targetOverride->dispatchEvent(PointerEvent::createForPointerCapture(eventNames().lostpointercaptureEvent, pointerId, capturingData.isPrimary, capturingData.pointerType));
     431        if (capturingData.pointerType == PointerEvent::mousePointerType()) {
     432            if (auto* frame = capturingData.targetOverride->document().frame())
     433                frame->eventHandler().pointerCaptureElementDidChange(nullptr);
     434        }
     435    }
    422436
    423437    // 2. If the pending pointer capture target override for this pointer is set and is not equal to the pointer capture target override,
    424438    // then fire a pointer event named gotpointercapture at the pending pointer capture target override.
    425     if (capturingData.pendingTargetOverride && capturingData.targetOverride != pendingTargetOverride)
    426         pendingTargetOverride->dispatchEvent(PointerEvent::createForPointerCapture(eventNames().gotpointercaptureEvent, event));
     439    if (capturingData.pendingTargetOverride && capturingData.targetOverride != pendingTargetOverride) {
     440        if (capturingData.pointerType == PointerEvent::mousePointerType()) {
     441            if (auto* frame = pendingTargetOverride->document().frame())
     442                frame->eventHandler().pointerCaptureElementDidChange(pendingTargetOverride.get());
     443        }
     444        pendingTargetOverride->dispatchEvent(PointerEvent::createForPointerCapture(eventNames().gotpointercaptureEvent, pointerId, capturingData.isPrimary, capturingData.pointerType));
     445    }
    427446
    428447    // 3. Set the pointer capture target override to the pending pointer capture target override, if set. Otherwise, clear the pointer
    429448    // capture target override.
    430449    capturingData.targetOverride = pendingTargetOverride;
     450
     451    m_processingPendingPointerCapture = false;
    431452}
    432453
  • trunk/Source/WebCore/page/PointerCaptureController.h

    r246729 r246844  
    4242    explicit PointerCaptureController(Page&);
    4343
     44    Element* pointerCaptureElement(Document*, PointerID);
    4445    ExceptionOr<void> setPointerCapture(Element*, PointerID);
    4546    ExceptionOr<void> releasePointerCapture(Element*, PointerID);
     
    6162    void dispatchEvent(PointerEvent&, EventTarget*);
    6263    WEBCORE_EXPORT void cancelPointer(PointerID, const IntPoint&);
     64    void processPendingPointerCapture(PointerID);
    6365
    6466private:
     
    7678    void pointerEventWillBeDispatched(const PointerEvent&, EventTarget*);
    7779    void pointerEventWasDispatched(const PointerEvent&);
    78     void processPendingPointerCapture(const PointerEvent&);
    7980
    8081    Page& m_page;
     
    8384    using PointerIdToCapturingDataMap = HashMap<int64_t, CapturingData, WTF::IntHash<int64_t>, WTF::SignedWithZeroKeyHashTraits<int64_t>>;
    8485    PointerIdToCapturingDataMap m_activePointerIdsToCapturingData;
     86    bool m_processingPendingPointerCapture;
    8587};
    8688
Note: See TracChangeset for help on using the changeset viewer.