Chromium Code Reviews| Index: third_party/WebKit/Source/core/input/PointerEventManager.cpp |
| diff --git a/third_party/WebKit/Source/core/input/PointerEventManager.cpp b/third_party/WebKit/Source/core/input/PointerEventManager.cpp |
| index d258c2e85bba0711c5c58fad918864911fb5ecfa..cbdc697e462b5143005fb354b7ad977917bdac4e 100644 |
| --- a/third_party/WebKit/Source/core/input/PointerEventManager.cpp |
| +++ b/third_party/WebKit/Source/core/input/PointerEventManager.cpp |
| @@ -11,6 +11,8 @@ |
| #include "core/frame/UseCounter.h" |
| #include "core/html/HTMLCanvasElement.h" |
| #include "core/input/EventHandler.h" |
| +#include "core/input/EventHandlingUtil.h" |
| +#include "core/input/MouseEventManager.h" |
| #include "core/input/TouchActionUtil.h" |
| #include "core/page/ChromeClient.h" |
| #include "core/page/Page.h" |
| @@ -46,88 +48,49 @@ bool isInDocument(EventTarget* n) |
| return n && n->toNode() && n->toNode()->isConnected(); |
| } |
| -WebInputEventResult dispatchMouseEvent( |
| - EventTarget* target, |
| - const AtomicString& mouseEventType, |
| - const PlatformMouseEvent& mouseEvent, |
| - EventTarget* relatedTarget, |
| - int detail = 0, |
| - bool checkForListener = false) |
| -{ |
| - if (target && target->toNode() |
| - && (!checkForListener || target->hasEventListeners(mouseEventType))) { |
| - Node* targetNode = target->toNode(); |
| - MouseEvent* event = MouseEvent::create(mouseEventType, |
| - targetNode->document().domWindow(), mouseEvent, detail, |
| - relatedTarget ? relatedTarget->toNode() : nullptr); |
| - DispatchEventResult dispatchResult = target->dispatchEvent(event); |
| - return EventHandler::toWebInputEventResult(dispatchResult); |
| - } |
| - return WebInputEventResult::NotHandled; |
| +} // namespace |
| + |
| +PointerEventManager::PointerEventBoundaryEventDispatcher::PointerEventBoundaryEventDispatcher( |
| + PointerEventManager* pointerEventManager, |
| + PointerEvent* pointerEvent) |
| + : m_pointerEventManager(pointerEventManager) |
| + , m_pointerEvent(pointerEvent) |
| +{ |
| } |
| -PlatformMouseEvent mouseEventWithRegion(Node* node, const PlatformMouseEvent& mouseEvent) |
| +void PointerEventManager::PointerEventBoundaryEventDispatcher::dispatchOut( |
| + EventTarget* target, EventTarget* relatedTarget) |
| { |
| - if (!node->isElementNode()) |
| - return mouseEvent; |
| + dispatch(target, relatedTarget, EventTypeNames::pointerout, false); |
| +} |
| - Element* element = toElement(node); |
| - if (!element->isInCanvasSubtree()) |
| - return mouseEvent; |
| +void PointerEventManager::PointerEventBoundaryEventDispatcher::dispatchOver( |
| + EventTarget* target, EventTarget* relatedTarget) |
| +{ |
| + dispatch(target, relatedTarget, EventTypeNames::pointerover, false); |
| +} |
| - HTMLCanvasElement* canvas = Traversal<HTMLCanvasElement>::firstAncestorOrSelf(*element); |
| - // In this case, the event target is canvas and mouse rerouting doesn't happen. |
| - if (canvas == element) |
| - return mouseEvent; |
| - String region = canvas->getIdFromControl(element); |
| - PlatformMouseEvent newMouseEvent = mouseEvent; |
| - newMouseEvent.setRegion(region); |
| - return newMouseEvent; |
| +void PointerEventManager::PointerEventBoundaryEventDispatcher::dispatchLeave( |
| + EventTarget* target, EventTarget* relatedTarget, bool checkForListener) |
| +{ |
| + dispatch(target, relatedTarget, EventTypeNames::pointerleave, checkForListener); |
| } |
| -void buildAncestorChain( |
| - EventTarget* target, |
| - HeapVector<Member<Node>, 20>* ancestors) |
| +void PointerEventManager::PointerEventBoundaryEventDispatcher::dispatchEnter( |
| + EventTarget* target, EventTarget* relatedTarget, bool checkForListener) |
| { |
| - if (!isInDocument(target)) |
| - return; |
| - Node* targetNode = target->toNode(); |
| - DCHECK(targetNode); |
| - targetNode->updateDistribution(); |
| - // Index 0 element in the ancestors arrays will be the corresponding |
| - // target. So the root of their document will be their last element. |
| - for (Node* node = targetNode; node; node = FlatTreeTraversal::parent(*node)) |
| - ancestors->append(node); |
| -} |
| - |
| -void buildAncestorChainsAndFindCommonAncestors( |
| - EventTarget* exitedTarget, EventTarget* enteredTarget, |
| - HeapVector<Member<Node>, 20>* exitedAncestorsOut, |
| - HeapVector<Member<Node>, 20>* enteredAncestorsOut, |
| - size_t* exitedAncestorsCommonParentIndexOut, |
| - size_t* enteredAncestorsCommonParentIndexOut) |
| -{ |
| - DCHECK(exitedAncestorsOut); |
| - DCHECK(enteredAncestorsOut); |
| - DCHECK(exitedAncestorsCommonParentIndexOut); |
| - DCHECK(enteredAncestorsCommonParentIndexOut); |
| - |
| - buildAncestorChain(exitedTarget, exitedAncestorsOut); |
| - buildAncestorChain(enteredTarget, enteredAncestorsOut); |
| - |
| - *exitedAncestorsCommonParentIndexOut = exitedAncestorsOut->size(); |
| - *enteredAncestorsCommonParentIndexOut = enteredAncestorsOut->size(); |
| - while (*exitedAncestorsCommonParentIndexOut > 0 |
| - && *enteredAncestorsCommonParentIndexOut > 0) { |
| - if ((*exitedAncestorsOut)[(*exitedAncestorsCommonParentIndexOut)-1] |
| - != (*enteredAncestorsOut)[(*enteredAncestorsCommonParentIndexOut)-1]) |
| - break; |
| - (*exitedAncestorsCommonParentIndexOut)--; |
| - (*enteredAncestorsCommonParentIndexOut)--; |
| - } |
| + dispatch(target, relatedTarget, EventTypeNames::pointerenter, checkForListener); |
| } |
| -} // namespace |
| +void PointerEventManager::PointerEventBoundaryEventDispatcher::dispatch( |
| + EventTarget* target, EventTarget* relatedTarget, const AtomicString& type, |
| + bool checkForListener) |
| +{ |
| + m_pointerEventManager->dispatchPointerEvent(target, |
| + m_pointerEventManager->m_pointerEventFactory.createPointerBoundaryEvent( |
| + m_pointerEvent, type, relatedTarget), |
| + checkForListener); |
| +} |
| WebInputEventResult PointerEventManager::dispatchPointerEvent( |
| EventTarget* target, |
| @@ -160,7 +123,7 @@ WebInputEventResult PointerEventManager::dispatchPointerEvent( |
| UseCounter::count(m_frame->document(), UseCounter::PointerEventDispatchPointerDown); |
| DispatchEventResult dispatchResult = target->dispatchEvent(pointerEvent); |
| - return EventHandler::toWebInputEventResult(dispatchResult); |
| + return EventHandlingUtil::toWebInputEventResult(dispatchResult); |
| } |
| return WebInputEventResult::NotHandled; |
| } |
| @@ -204,109 +167,10 @@ void PointerEventManager::sendMouseAndPossiblyPointerBoundaryEvents( |
| void PointerEventManager::sendBoundaryEvents( |
| EventTarget* exitedTarget, |
| EventTarget* enteredTarget, |
| - PointerEvent* pointerEvent, |
| - const PlatformMouseEvent& mouseEvent, bool sendMouseEvent) |
| + PointerEvent* pointerEvent) |
| { |
| - if (exitedTarget == enteredTarget) |
| - return; |
| - |
| - // Dispatch pointerout/mouseout events |
| - if (isInDocument(exitedTarget)) { |
| - if (!sendMouseEvent) { |
| - dispatchPointerEvent(exitedTarget, m_pointerEventFactory.createPointerBoundaryEvent( |
| - pointerEvent, EventTypeNames::pointerout, enteredTarget)); |
| - } else { |
| - dispatchMouseEvent(exitedTarget, |
| - EventTypeNames::mouseout, |
| - mouseEventWithRegion(exitedTarget->toNode(), mouseEvent), |
| - enteredTarget); |
| - } |
| - } |
| - |
| - // Create lists of all exited/entered ancestors, locate the common ancestor |
| - // Based on httparchive, in more than 97% cases the depth of DOM is less |
| - // than 20. |
| - HeapVector<Member<Node>, 20> exitedAncestors; |
| - HeapVector<Member<Node>, 20> enteredAncestors; |
| - size_t exitedAncestorsCommonParentIndex = 0; |
| - size_t enteredAncestorsCommonParentIndex = 0; |
| - |
| - // A note on mouseenter and mouseleave: These are non-bubbling events, and they are dispatched if there |
| - // is a capturing event handler on an ancestor or a normal event handler on the element itself. This special |
| - // handling is necessary to avoid O(n^2) capturing event handler checks. |
| - // |
| - // Note, however, that this optimization can possibly cause some unanswered/missing/redundant mouseenter or |
| - // mouseleave events in certain contrived eventhandling scenarios, e.g., when: |
| - // - the mouseleave handler for a node sets the only capturing-mouseleave-listener in its ancestor, or |
| - // - DOM mods in any mouseenter/mouseleave handler changes the common ancestor of exited & entered nodes, etc. |
| - // We think the spec specifies a "frozen" state to avoid such corner cases (check the discussion on "candidate event |
| - // listeners" at http://www.w3.org/TR/uievents), but our code below preserves one such behavior from past only to |
| - // match Firefox and IE behavior. |
| - // |
| - // TODO(mustaq): Confirm spec conformance, double-check with other browsers. |
| - |
| - buildAncestorChainsAndFindCommonAncestors( |
| - exitedTarget, enteredTarget, |
| - &exitedAncestors, &enteredAncestors, |
| - &exitedAncestorsCommonParentIndex, &enteredAncestorsCommonParentIndex); |
| - |
| - bool exitedNodeHasCapturingAncestor = false; |
| - for (size_t j = 0; j < exitedAncestors.size(); j++) { |
| - if (exitedAncestors[j]->hasCapturingEventListeners(EventTypeNames::mouseleave) |
| - || (RuntimeEnabledFeatures::pointerEventEnabled() |
| - && exitedAncestors[j]->hasCapturingEventListeners(EventTypeNames::pointerleave))) |
| - exitedNodeHasCapturingAncestor = true; |
| - } |
| - |
| - // Dispatch pointerleave/mouseleave events, in child-to-parent order. |
| - for (size_t j = 0; j < exitedAncestorsCommonParentIndex; j++) { |
| - if (!sendMouseEvent) { |
| - dispatchPointerEvent(exitedAncestors[j].get(), |
| - m_pointerEventFactory.createPointerBoundaryEvent( |
| - pointerEvent, EventTypeNames::pointerleave, enteredTarget), |
| - !exitedNodeHasCapturingAncestor); |
| - } else { |
| - dispatchMouseEvent(exitedAncestors[j].get(), |
| - EventTypeNames::mouseleave, |
| - mouseEventWithRegion(exitedTarget->toNode(), mouseEvent), |
| - enteredTarget, 0, !exitedNodeHasCapturingAncestor); |
| - } |
| - } |
| - |
| - // Dispatch pointerover/mouseover. |
| - if (isInDocument(enteredTarget)) { |
| - if (!sendMouseEvent) { |
| - dispatchPointerEvent(enteredTarget, m_pointerEventFactory.createPointerBoundaryEvent( |
| - pointerEvent, EventTypeNames::pointerover, exitedTarget)); |
| - } else { |
| - dispatchMouseEvent(enteredTarget, |
| - EventTypeNames::mouseover, mouseEvent, exitedTarget); |
| - } |
| - } |
| - |
| - // Defer locating capturing pointeenter/mouseenter listener until /after/ dispatching the leave events because |
| - // the leave handlers might set a capturing enter handler. |
| - bool enteredNodeHasCapturingAncestor = false; |
| - for (size_t i = 0; i < enteredAncestors.size(); i++) { |
| - if (enteredAncestors[i]->hasCapturingEventListeners(EventTypeNames::mouseenter) |
| - || (RuntimeEnabledFeatures::pointerEventEnabled() |
| - && enteredAncestors[i]->hasCapturingEventListeners(EventTypeNames::pointerenter))) |
| - enteredNodeHasCapturingAncestor = true; |
| - } |
| - |
| - // Dispatch pointerenter/mouseenter events, in parent-to-child order. |
| - for (size_t i = enteredAncestorsCommonParentIndex; i > 0; i--) { |
| - if (!sendMouseEvent) { |
| - dispatchPointerEvent(enteredAncestors[i-1].get(), |
| - m_pointerEventFactory.createPointerBoundaryEvent( |
| - pointerEvent, EventTypeNames::pointerenter, exitedTarget), |
| - !enteredNodeHasCapturingAncestor); |
| - } else { |
| - dispatchMouseEvent(enteredAncestors[i-1].get(), |
| - EventTypeNames::mouseenter, mouseEvent, exitedTarget, |
| - 0, !enteredNodeHasCapturingAncestor); |
| - } |
| - } |
| + PointerEventBoundaryEventDispatcher boundaryEventDispatcher(this, pointerEvent); |
|
mustaq
2016/08/23 15:20:48
Creating a new instance of boundaryEventDispatcher
Navid Zolghadr
2016/08/24 16:07:28
I don't know how we should do this with a template
Navid Zolghadr
2016/08/30 18:46:26
I was looking into possibilities of creating this
|
| + EventHandlingUtil::sendBoundaryEvents(exitedTarget, enteredTarget, &boundaryEventDispatcher); |
| } |
| void PointerEventManager::setNodeUnderPointer( |
| @@ -576,9 +440,9 @@ WebInputEventResult PointerEventManager::sendMousePointerEvent( |
| } |
| } |
| } |
| - result = EventHandler::mergeEventResult(result, |
| - dispatchMouseEvent(mouseTarget, mouseEventType, mouseEvent, |
| - nullptr, clickCount)); |
| + result = EventHandlingUtil::mergeEventResult(result, |
| + m_mouseEventManager->dispatchMouseEvent(mouseTarget, mouseEventType, mouseEvent, |
| + nullptr, clickCount)); |
| } |
| if (pointerEvent->type() == EventTypeNames::pointerup |
| @@ -597,9 +461,11 @@ WebInputEventResult PointerEventManager::sendMousePointerEvent( |
| return result; |
| } |
| -PointerEventManager::PointerEventManager(LocalFrame* frame) |
| -: m_frame(frame) |
| -, m_touchEventManager(frame) |
| +PointerEventManager::PointerEventManager(LocalFrame* frame, |
| + MouseEventManager* mouseEventManager) |
| + : m_frame(frame) |
| + , m_touchEventManager(frame) |
| + , m_mouseEventManager(mouseEventManager) |
| { |
| clear(); |
| } |
| @@ -658,8 +524,8 @@ EventTarget* PointerEventManager::processCaptureAndPositionOfPointerEvent( |
| } |
| if (sendMouseEvent) { |
| // lastNodeUnderMouse is needed here because it is still stored in EventHandler. |
| - sendBoundaryEvents(lastNodeUnderMouse, hitTestTarget, |
| - pointerEvent, mouseEvent, true); |
| + m_mouseEventManager->sendBoundaryEvents(lastNodeUnderMouse, |
| + hitTestTarget, mouseEvent); |
| } |
| return hitTestTarget; |
| } |