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

Changeset 246074 in webkit


Ignore:
Timestamp:
Jun 4, 2019, 12:00:12 PM (7 years ago)
Author:
commit-queue@webkit.org
Message:

[Pointer Events] Only allow pointer capture if the pointer is in the active buttons state
https://bugs.webkit.org/show_bug.cgi?id=198479

Patch by Antoine Quint <Antoine Quint> on 2019-06-04
Reviewed by Dean Jackson.

LayoutTests/imported/w3c:

Mark WPT progression.

  • web-platform-tests/pointerevents/pointerevent_setpointercapture_inactive_button_mouse-expected.txt:

Source/WebCore:

The Pointer Events specification says that pointer capture can only be engaged provided the pointer is
in the active buttons state, which means that it has dispatched a "pointerdown" event more recently than
it has a "pointerup" event.

This is tested by web-platform-tests/pointerevents/pointerevent_setpointercapture_inactive_button_mouse.html.

That test showed a few issues that this patch addresses. First, we would update the pointerIsPressed state to
"true" only after a "pointerdown" event had been dispatched. This is incorrect since setPointerCapture() can,
and is likely to, be called during handling of a "pointerdown" event. So we now call pointerEventWillBeDispatched()
prior to dispatching a PointerEvent with a mouse type, which we only did previously for a PointerEvent with a
touch or pen type. If the event is "pointerdown", we set "pointerIsPressed" to true on the CapturingData object
matching the given pointer, and to false if the event is "pointerup".

Finally, we must also ensure that "pointerIsPressed" is set to true when creating CapturingData for a PointerEvent
with a touch or pen type since these types of pointer events implictly set capture.

  • page/PointerCaptureController.cpp:

(WebCore::PointerCaptureController::setPointerCapture):
(WebCore::PointerCaptureController::dispatchEvent):
(WebCore::PointerCaptureController::pointerEventWillBeDispatched):
(WebCore::PointerCaptureController::pointerEventWasDispatched):

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r246045 r246074  
     12019-06-04  Antoine Quint  <graouts@apple.com>
     2
     3        [Pointer Events] Only allow pointer capture if the pointer is in the active buttons state
     4        https://bugs.webkit.org/show_bug.cgi?id=198479
     5
     6        Reviewed by Dean Jackson.
     7
     8        Mark WPT progression.
     9
     10        * web-platform-tests/pointerevents/pointerevent_setpointercapture_inactive_button_mouse-expected.txt:
     11
    1122019-06-03  Rob Buis  <rbuis@igalia.com>
    213
  • trunk/LayoutTests/imported/w3c/web-platform-tests/pointerevents/pointerevent_setpointercapture_inactive_button_mouse-expected.txt

    r244393 r246074  
    1010
    1111
    12 FAIL pointer capture is not set while button state is inactive assert_false: pointer capture is not set while button state is inactive expected false got true
     12PASS pointer capture is not set while button state is inactive
    1313
  • trunk/Source/WebCore/ChangeLog

    r246072 r246074  
     12019-06-04  Antoine Quint  <graouts@apple.com>
     2
     3        [Pointer Events] Only allow pointer capture if the pointer is in the active buttons state
     4        https://bugs.webkit.org/show_bug.cgi?id=198479
     5
     6        Reviewed by Dean Jackson.
     7
     8        The Pointer Events specification says that pointer capture can only be engaged provided the pointer is
     9        in the active buttons state, which means that it has dispatched a "pointerdown" event more recently than
     10        it has a "pointerup" event.
     11
     12        This is tested by web-platform-tests/pointerevents/pointerevent_setpointercapture_inactive_button_mouse.html.
     13
     14        That test showed a few issues that this patch addresses. First, we would update the pointerIsPressed state to
     15        "true" only after a "pointerdown" event had been dispatched. This is incorrect since setPointerCapture() can,
     16        and is likely to, be called during handling of a "pointerdown" event. So we now call pointerEventWillBeDispatched()
     17        prior to dispatching a PointerEvent with a mouse type, which we only did previously for a PointerEvent with a
     18        touch or pen type. If the event is "pointerdown", we set "pointerIsPressed" to true on the CapturingData object
     19        matching the given pointer, and to false if the event is "pointerup".
     20
     21        Finally, we must also ensure that "pointerIsPressed" is set to true when creating CapturingData for a PointerEvent
     22        with a touch or pen type since these types of pointer events implictly set capture.
     23
     24        * page/PointerCaptureController.cpp:
     25        (WebCore::PointerCaptureController::setPointerCapture):
     26        (WebCore::PointerCaptureController::dispatchEvent):
     27        (WebCore::PointerCaptureController::pointerEventWillBeDispatched):
     28        (WebCore::PointerCaptureController::pointerEventWasDispatched):
     29
    1302019-06-04  Keith Rollin  <krollin@apple.com>
    231
  • trunk/Source/WebCore/page/PointerCaptureController.cpp

    r246072 r246074  
    7171
    7272    // 4. If the pointer is not in the active buttons state, then terminate these steps.
    73     // FIXME: implement when we support mouse events.
    74 
    7573    // 5. For the specified pointerId, set the pending pointer capture target override to the Element on which this method was invoked.
    76     iterator->value.pendingTargetOverride = capturingTarget;
     74    auto& capturingData = iterator->value;
     75    if (capturingData.pointerIsPressed)
     76        capturingData.pendingTargetOverride = capturingTarget;
    7777
    7878    return { };
     
    238238        auto& capturingData = iterator->value;
    239239        if (capturingData.pendingTargetOverride && capturingData.targetOverride)
    240             capturingData.targetOverride->dispatchEvent(event);
    241     }
    242 
    243     if (target && !event.target())
    244         target->dispatchEvent(event);
    245 
     240            target = capturingData.targetOverride.get();
     241    }
     242
     243    if (!target || event.target())
     244        return;
     245
     246    pointerEventWillBeDispatched(event, target);
     247    target->dispatchEvent(event);
    246248    pointerEventWasDispatched(event);
    247249}
     
    249251void PointerCaptureController::pointerEventWillBeDispatched(const PointerEvent& event, EventTarget* target)
    250252{
     253    if (!is<Element>(target))
     254        return;
     255
     256    bool isPointerdown = event.type() == eventNames().pointerdownEvent;
     257    bool isPointerup = event.type() == eventNames().pointerupEvent;
     258    if (!isPointerdown && !isPointerup)
     259        return;
     260
     261    auto pointerId = event.pointerId();
     262
     263    if (event.pointerType() == PointerEvent::mousePointerType()) {
     264        auto iterator = m_activePointerIdsToCapturingData.find(pointerId);
     265        if (iterator != m_activePointerIdsToCapturingData.end())
     266            iterator->value.pointerIsPressed = isPointerdown;
     267        return;
     268    }
     269
     270    if (!isPointerdown)
     271        return;
     272
    251273    // https://w3c.github.io/pointerevents/#implicit-pointer-capture
    252274
     
    261283    // to the target (as normal) indicating that capture is active.
    262284
    263     if (!is<Element>(target) || event.type() != eventNames().pointerdownEvent)
    264         return;
    265 
    266     auto pointerId = event.pointerId();
    267285    CapturingData capturingData;
    268286    capturingData.pointerType = event.pointerType();
     287    capturingData.pointerIsPressed = true;
    269288    m_activePointerIdsToCapturingData.set(pointerId, capturingData);
    270289    setPointerCapture(downcast<Element>(target), pointerId);
     
    282301        // Pointer Capture steps to fire lostpointercapture if necessary.
    283302        // https://w3c.github.io/pointerevents/#implicit-release-of-pointer-capture
    284         if (event.type() == eventNames().pointerupEvent) {
     303        if (event.type() == eventNames().pointerupEvent)
    285304            capturingData.pendingTargetOverride = nullptr;
    286             capturingData.pointerIsPressed = false;
    287         }
    288305
    289306        // If a mouse pointer has moved while it isn't pressed, make sure we reset the preventsCompatibilityMouseEvents flag since
     
    294311        // If the pointer event dispatched was pointerdown and the event was canceled, then set the PREVENT MOUSE EVENT flag for this pointerType.
    295312        // https://www.w3.org/TR/pointerevents/#mapping-for-devices-that-support-hover
    296         if (event.type() == eventNames().pointerdownEvent) {
     313        if (event.type() == eventNames().pointerdownEvent)
    297314            capturingData.preventsCompatibilityMouseEvents = event.defaultPrevented();
    298             capturingData.pointerIsPressed = true;
    299         }
    300315    }
    301316
Note: See TracChangeset for help on using the changeset viewer.