Changeset 246844 in webkit
- Timestamp:
- Jun 26, 2019 11:36:41 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r246840 r246844 1 2019-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 1 14 2019-06-26 Russell Epstein <russell_e@apple.com> 2 15 -
trunk/LayoutTests/imported/w3c/ChangeLog
r246753 r246844 1 2019-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 1 15 2019-06-24 Antoine Quint <graouts@apple.com> 2 16 -
trunk/LayoutTests/imported/w3c/web-platform-tests/pointerevents/pointerevent_boundary_events_at_implicit_release_hoverable_pointers-expected.txt
r246729 r246844 1 1 Pointer 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.4 2 5 3 When a captured pointer is implicitly released after a click, the boundary events should follow the lostpointercapture event. … … 7 5 Click on the black box with mouse and do not move the mouse after or during the click. 8 6 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" 7 PASS mouse Event sequence at implicit release on click 10 8 -
trunk/LayoutTests/imported/w3c/web-platform-tests/pointerevents/pointerevent_mouse_capture_change_hover-expected.txt
r246729 r246844 1 1 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" 2 PASS Mouse down and capture to green. 3 PASS Mouse down at green and capture to blue. 4 PASS Mouse down and capture to green, move to blue and release capture 5 5 -
trunk/LayoutTests/imported/w3c/web-platform-tests/pointerevents/pointerevent_setpointercapture_relatedtarget-expected.txt
r246729 r246844 17 17 The following pointer types were detected: mouse. 18 18 19 The following events were logged: pointerover@target1, gotpointercapture@target0, pointerover@target0, pointerover@target0, lostpointercapture@target0.19 The following events were logged: pointerover@target1, pointerover@target0, gotpointercapture@target0, lostpointercapture@target0. 20 20 21 21 Refresh the page to run the tests again with a different pointer type. 22 22 23 23 24 Harness Error (FAIL), message = 1 duplicate test name: "relatedTarget should not be null even when the capture is set."25 26 24 PASS pointerover shouldn't trigger for the purple rectangle while the black rectangle has capture 27 25 PASS relatedTarget should not be null even when the capture is set. 28 PASS relatedTarget should not be null even when the capture is set.29 26 -
trunk/LayoutTests/platform/mac-wk1/imported/w3c/web-platform-tests/pointerevents/pointerevent_boundary_events_at_implicit_release_hoverable_pointers-expected.txt
r246729 r246844 7 7 Click on the black box with mouse and do not move the mouse after or during the click. 8 8 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"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 "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" 10 10 -
trunk/LayoutTests/platform/mac-wk1/imported/w3c/web-platform-tests/pointerevents/pointerevent_setpointercapture_relatedtarget-expected.txt
r246729 r246844 17 17 The following pointer types were detected: mouse. 18 18 19 The following events were logged: pointerover@target1, gotpointercapture@target0, pointerover@target0, pointerover@target0, lostpointercapture@target0, pointerover@target0.19 The following events were logged: pointerover@target1, pointerover@target0, gotpointercapture@target0, lostpointercapture@target0, pointerover@target0. 20 20 21 21 Refresh the page to run the tests again with a different pointer type. 22 22 23 23 24 Harness Error (FAIL), message = 1 duplicate test name: "relatedTarget should not be null even when the capture is set."25 26 24 PASS pointerover shouldn't trigger for the purple rectangle while the black rectangle has capture 27 25 PASS relatedTarget should not be null even when the capture is set. 28 PASS relatedTarget should not be null even when the capture is set.29 26 -
trunk/Source/WebCore/ChangeLog
r246831 r246844 1 2019-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 1 53 2019-06-25 Fujii Hironori <Hironori.Fujii@sony.com> 2 54 -
trunk/Source/WebCore/dom/Document.cpp
r246729 r246844 321 321 #endif 322 322 323 #if ENABLE(POINTER_EVENTS) 324 #include "PointerCaptureController.h" 325 #endif 326 323 327 namespace WebCore { 324 328 … … 3733 3737 hitTest(request, result); 3734 3738 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 } 3737 3762 3738 3763 return MouseEventWithHitTestResults(event, result); … … 6738 6763 } 6739 6764 6740 void Document::updateHoverActiveState(const HitTestRequest& request, Element* innerElement )6765 void Document::updateHoverActiveState(const HitTestRequest& request, Element* innerElement, CaptureChange captureElementChanged) 6741 6766 { 6742 6767 ASSERT(!request.readOnly()); … … 6777 6802 // If the mouse is down and if this is a mouse move event, we want to restrict changes in 6778 6803 // :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; 6781 6806 6782 6807 RefPtr<Element> oldHoveredElement = WTFMove(m_hoveredElement); -
trunk/Source/WebCore/dom/Document.h
r246490 r246844 761 761 void elementInActiveChainDidDetach(Element&); 762 762 763 void updateHoverActiveState(const HitTestRequest&, Element*); 763 enum class CaptureChange : uint8_t { Yes, No }; 764 void updateHoverActiveState(const HitTestRequest&, Element*, CaptureChange = CaptureChange::No); 764 765 765 766 // Updates for :target (CSS3 selector). -
trunk/Source/WebCore/dom/PointerEvent.h
r246490 r246844 62 62 } 63 63 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) 65 65 { 66 66 Init initializer; 67 67 initializer.bubbles = true; 68 initializer.pointerId = pointer Event.pointerId();69 initializer.isPrimary = pointerEvent.isPrimary();70 initializer.pointerType = pointer Event.pointerType();68 initializer.pointerId = pointerId; 69 initializer.isPrimary = isPrimary; 70 initializer.pointerType = pointerType; 71 71 return adoptRef(*new PointerEvent(type, WTFMove(initializer))); 72 72 } -
trunk/Source/WebCore/page/EventHandler.cpp
r246729 r246844 128 128 #endif 129 129 130 #if ENABLE(POINTER_EVENTS) 131 #include "RuntimeEnabledFeatures.h" 132 #endif 133 130 134 namespace WebCore { 131 135 … … 2483 2487 } 2484 2488 2489 #if ENABLE(POINTER_EVENTS) 2490 void 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 2485 2502 MouseEventWithHitTestResults EventHandler::prepareMouseEvent(const HitTestRequest& request, const PlatformMouseEvent& mouseEvent) 2486 2503 { 2504 #if ENABLE(POINTER_EVENTS) 2505 m_lastPlatformMouseEvent = mouseEvent; 2506 #endif 2487 2507 Ref<Frame> protectedFrame(m_frame); 2488 2508 ASSERT(m_frame.document()); -
trunk/Source/WebCore/page/EventHandler.h
r246729 r246844 159 159 160 160 WEBCORE_EXPORT void setCapturingMouseEventsElement(Element*); 161 #if ENABLE(POINTER_EVENTS) 162 void pointerCaptureElementDidChange(Element*); 163 #endif 161 164 162 165 #if ENABLE(DRAG_SUPPORT) … … 593 596 WallTime m_mouseDownTimestamp; 594 597 PlatformMouseEvent m_mouseDown; 598 #if ENABLE(POINTER_EVENTS) 599 PlatformMouseEvent m_lastPlatformMouseEvent; 600 #endif 595 601 596 602 #if PLATFORM(COCOA) -
trunk/Source/WebCore/page/PointerCaptureController.cpp
r246752 r246844 49 49 } 50 50 51 Element* 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 51 62 ExceptionOr<void> PointerCaptureController::setPointerCapture(Element* capturingTarget, PointerID pointerId) 52 63 { … … 272 283 // https://w3c.github.io/pointerevents/#firing-events-using-the-pointerevent-interface 273 284 // 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()); 283 288 284 289 pointerEventWillBeDispatched(event, target); … … 341 346 if (event.type() == eventNames().pointerupEvent) { 342 347 capturingData.pendingTargetOverride = nullptr; 343 processPendingPointerCapture(event );348 processPendingPointerCapture(event.pointerId()); 344 349 } 345 350 … … 400 405 target->dispatchEvent(PointerEvent::create(eventNames().pointeroutEvent, pointerId, capturingData.pointerType, isPrimary)); 401 406 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 410 void PointerCaptureController::processPendingPointerCapture(PointerID pointerId) 411 { 412 if (m_processingPendingPointerCapture) 413 return; 414 415 m_processingPendingPointerCapture = true; 416 417 auto iterator = m_activePointerIdsToCapturingData.find(pointerId); 410 418 if (iterator == m_activePointerIdsToCapturingData.end()) 411 419 return; … … 416 424 auto pendingTargetOverride = capturingData.pendingTargetOverride; 417 425 426 // https://w3c.github.io/pointerevents/#process-pending-pointer-capture 418 427 // 1. If the pointer capture target override for this pointer is set and is not equal to the pending pointer capture target override, 419 428 // 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 } 422 436 423 437 // 2. If the pending pointer capture target override for this pointer is set and is not equal to the pointer capture target override, 424 438 // 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 } 427 446 428 447 // 3. Set the pointer capture target override to the pending pointer capture target override, if set. Otherwise, clear the pointer 429 448 // capture target override. 430 449 capturingData.targetOverride = pendingTargetOverride; 450 451 m_processingPendingPointerCapture = false; 431 452 } 432 453 -
trunk/Source/WebCore/page/PointerCaptureController.h
r246729 r246844 42 42 explicit PointerCaptureController(Page&); 43 43 44 Element* pointerCaptureElement(Document*, PointerID); 44 45 ExceptionOr<void> setPointerCapture(Element*, PointerID); 45 46 ExceptionOr<void> releasePointerCapture(Element*, PointerID); … … 61 62 void dispatchEvent(PointerEvent&, EventTarget*); 62 63 WEBCORE_EXPORT void cancelPointer(PointerID, const IntPoint&); 64 void processPendingPointerCapture(PointerID); 63 65 64 66 private: … … 76 78 void pointerEventWillBeDispatched(const PointerEvent&, EventTarget*); 77 79 void pointerEventWasDispatched(const PointerEvent&); 78 void processPendingPointerCapture(const PointerEvent&);79 80 80 81 Page& m_page; … … 83 84 using PointerIdToCapturingDataMap = HashMap<int64_t, CapturingData, WTF::IntHash<int64_t>, WTF::SignedWithZeroKeyHashTraits<int64_t>>; 84 85 PointerIdToCapturingDataMap m_activePointerIdsToCapturingData; 86 bool m_processingPendingPointerCapture; 85 87 }; 86 88
Note: See TracChangeset
for help on using the changeset viewer.