Changeset 235865 in webkit
- Timestamp:
- Sep 10, 2018 2:54:14 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 6 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r235860 r235865 1 2018-09-07 Ryosuke Niwa <rniwa@webkit.org> 2 3 mouseenter and mouseleave events don't get dispatched even when there is a capturing event listener for a slot ancestor 4 https://bugs.webkit.org/show_bug.cgi?id=188561 5 6 Reviewed by Darin Adler. 7 8 Added tests for listening to mouseenter and mouseleave events using capturing and bubbling event listeners 9 across shadow boundaries. 10 11 * fast/shadow-dom/mouseenter-mouseleave-across-shadow-boundary-expected.txt: Added. 12 * fast/shadow-dom/mouseenter-mouseleave-across-shadow-boundary.html: Added. 13 * fast/shadow-dom/mouseenter-mouseleave-inside-shadow-tree-expected.txt: Added. 14 * fast/shadow-dom/mouseenter-mouseleave-inside-shadow-tree.html: Added. 15 * fast/shadow-dom/mouseenter-mouseleave-on-slot-parent-expected.txt: Added. 16 * fast/shadow-dom/mouseenter-mouseleave-on-slot-parent.html: Added. 17 * platform/ios/TestExpectations: Skip the new tests since mouse events aren't supported on iOS. 18 1 19 2018-09-10 Daniel Bates <dabates@apple.com> 2 20 -
trunk/LayoutTests/platform/ios/TestExpectations
r235806 r235865 684 684 fast/selectors/not-active-hover-strict.html [ Skip ] 685 685 fast/shapes/shape-outside-floats/shape-outside-clip-path-selection.html [ Skip ] 686 fast/shadow-dom/mouseenter-mouseleave-across-shadow-boundary.html [ Skip ] 687 fast/shadow-dom/mouseenter-mouseleave-inside-shadow-tree.html [ Skip ] 688 fast/shadow-dom/mouseenter-mouseleave-on-slot-parent.html [ Skip ] 686 689 fast/table/hittest-self-painting.html [ Skip ] 687 690 fast/text/atsui-pointtooffset-calls-cg.html [ Skip ] -
trunk/Source/WebCore/ChangeLog
r235864 r235865 1 2018-09-07 Ryosuke Niwa <rniwa@webkit.org> 2 3 mouseenter and mouseleave events don't get dispatched even when there is a capturing event listener for a slot ancestor 4 https://bugs.webkit.org/show_bug.cgi?id=188561 5 6 Reviewed by Darin Adler. 7 8 This patch makes mouseenter and mouseleave events to work with shadow trees and slots therein, and makes them uncomposed 9 as discussed in https://github.com/w3c/uievents/issues/208. 10 11 This patch also makes these events dispatched on DOM tree ancestors of the currently hovered element instead of 12 render tree's hover ancestors to be consistent with the check in hierarchyHasCapturingEventListeners and other browsers. 13 In particular, using hover ancestors is problematic when there is an element with display: contents such as slot elements, 14 which do not have a render object. 15 16 Tests: fast/shadow-dom/mouseenter-mouseleave-across-shadow-boundary.html 17 fast/shadow-dom/mouseenter-mouseleave-inside-shadow-tree.html 18 fast/shadow-dom/mouseenter-mouseleave-on-slot-parent.html 19 20 * dom/MouseEvent.cpp: 21 (WebCore::MouseEvent::create): 22 * page/EventHandler.cpp: 23 (WebCore::nearestCommonHoverAncestor): Deleted. 24 (WebCore::hierarchyHasCapturingEventListeners): Use parentInComposedTree. Else we would miss capturing event listeners 25 on inclusive ancestors of slots. 26 (WebCore::EventHandler::updateMouseEventTargetNode): Use the composed tree's ancestor chain to fire mouseenter and 27 mouseleave events. This is needed to dispatch mouseenter / mouseleave events on slot elements. Also removed comments 28 which just state what is self-evident from the code beneath them. 29 30 1 31 2018-09-08 Ryosuke Niwa <rniwa@webkit.org> 2 32 -
trunk/Source/WebCore/dom/MouseEvent.cpp
r235335 r235865 50 50 auto isCancelable = eventType != eventNames().mousemoveEvent && !isMouseEnterOrLeave ? IsCancelable::Yes : IsCancelable::No; 51 51 auto canBubble = !isMouseEnterOrLeave ? CanBubble::Yes : CanBubble::No; 52 53 return MouseEvent::create(eventType, canBubble, isCancelable, IsComposed::Yes, event.timestamp().approximateMonotonicTime(), WTFMove(view), detail, 52 auto isComposed = !isMouseEnterOrLeave ? IsComposed::Yes : IsComposed::No; 53 54 return MouseEvent::create(eventType, canBubble, isCancelable, isComposed, event.timestamp().approximateMonotonicTime(), WTFMove(view), detail, 54 55 event.globalPosition(), event.position(), 55 56 #if ENABLE(POINTER_LOCK) -
trunk/Source/WebCore/page/EventHandler.cpp
r235331 r235865 34 34 #include "Chrome.h" 35 35 #include "ChromeClient.h" 36 #include "ComposedTreeAncestorIterator.h" 36 37 #include "CursorList.h" 37 38 #include "DocumentMarkerController.h" … … 2445 2446 } 2446 2447 2447 static RenderElement* nearestCommonHoverAncestor(RenderElement* obj1, RenderElement* obj2)2448 {2449 if (!obj1 || !obj2)2450 return nullptr;2451 2452 for (RenderElement* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAncestor()) {2453 for (RenderElement* currObj2 = obj2; currObj2; currObj2 = currObj2->hoverAncestor()) {2454 if (currObj1 == currObj2)2455 return currObj1;2456 }2457 }2458 2459 return nullptr;2460 }2461 2462 2448 static bool hierarchyHasCapturingEventListeners(Element* element, const AtomicString& eventName) 2463 2449 { 2464 for (ContainerNode* curr = element; curr; curr = curr->parent OrShadowHostNode()) {2450 for (ContainerNode* curr = element; curr; curr = curr->parentInComposedTree()) { 2465 2451 if (curr->hasCapturingEventListeners(eventName)) 2466 2452 return true; … … 2536 2522 bool hasCapturingMouseLeaveListener = hierarchyHasCapturingEventListeners(m_lastElementUnderMouse.get(), eventNames().mouseleaveEvent); 2537 2523 2538 RenderElement* oldHoverRenderer = m_lastElementUnderMouse ? m_lastElementUnderMouse->renderer() : nullptr;2539 RenderElement* newHoverRenderer = m_elementUnderMouse ? m_elementUnderMouse->renderer() : nullptr;2540 RenderElement* ancestor = nearestCommonHoverAncestor(oldHoverRenderer, newHoverRenderer);2541 2542 2524 Vector<Ref<Element>, 32> leftElementsChain; 2543 if (oldHoverRenderer) { 2544 for (RenderElement* curr = oldHoverRenderer; curr && curr != ancestor; curr = curr->hoverAncestor()) { 2545 if (Element* element = curr->element()) 2546 leftElementsChain.append(*element); 2525 for (Element* element = m_lastElementUnderMouse.get(); element; element = element->parentElementInComposedTree()) 2526 leftElementsChain.append(*element); 2527 Vector<Ref<Element>, 32> enteredElementsChain; 2528 for (Element* element = m_elementUnderMouse.get(); element; element = element->parentElementInComposedTree()) 2529 enteredElementsChain.append(*element); 2530 2531 if (!leftElementsChain.isEmpty() && !enteredElementsChain.isEmpty() && leftElementsChain.last().ptr() == enteredElementsChain.last().ptr()) { 2532 size_t minHeight = std::min(leftElementsChain.size(), enteredElementsChain.size()); 2533 size_t i; 2534 for (i = 0; i < minHeight; ++i) { 2535 if (leftElementsChain[leftElementsChain.size() - i - 1].ptr() != enteredElementsChain[enteredElementsChain.size() - i - 1].ptr()) 2536 break; 2547 2537 } 2548 } else { 2549 // If the old hovered element is not null but it's renderer is, it was probably detached. 2550 // In this case, the old hovered element (and its ancestors) must be updated, to ensure it's normal style is re-applied. 2551 for (Element* element = m_lastElementUnderMouse.get(); element; element = element->parentElement()) 2552 leftElementsChain.append(*element); 2538 leftElementsChain.shrink(leftElementsChain.size() - i); 2539 enteredElementsChain.shrink(enteredElementsChain.size() - i); 2553 2540 } 2554 2541 2555 Vector<Ref<Element>, 32> enteredElementsChain;2556 const Element* ancestorElement = ancestor ? ancestor->element() : nullptr;2557 for (RenderElement* curr = newHoverRenderer; curr; curr = curr->hoverAncestor()) {2558 if (Element *element = curr->element()) {2559 if (element == ancestorElement)2560 break;2561 enteredElementsChain.append(*element);2562 }2563 }2564 2565 // Send mouseout event to the old node.2566 2542 if (m_lastElementUnderMouse) 2567 2543 m_lastElementUnderMouse->dispatchMouseEvent(platformMouseEvent, eventNames().mouseoutEvent, 0, m_elementUnderMouse.get()); 2568 2544 2569 // Send mouseleave to the node hierarchy no longer under the mouse.2570 2545 for (auto& chain : leftElementsChain) { 2571 2546 if (hasCapturingMouseLeaveListener || chain->hasEventListeners(eventNames().mouseleaveEvent)) … … 2573 2548 } 2574 2549 2575 // Send mouseover event to the new node.2576 2550 if (m_elementUnderMouse) 2577 2551 m_elementUnderMouse->dispatchMouseEvent(platformMouseEvent, eventNames().mouseoverEvent, 0, m_lastElementUnderMouse.get()); 2578 2552 2579 // Send mouseleave event to the nodes hierarchy under the mouse.2580 2553 for (auto& chain : enteredElementsChain) { 2581 2554 if (hasCapturingMouseEnterListener || chain->hasEventListeners(eventNames().mouseenterEvent))
Note: See TracChangeset
for help on using the changeset viewer.