Index: third_party/WebKit/Source/core/input/EventHandler.cpp |
diff --git a/third_party/WebKit/Source/core/input/EventHandler.cpp b/third_party/WebKit/Source/core/input/EventHandler.cpp |
index 762216c4c403531efb91c1f103f96da81ce4f2b9..57f4577d006af7968a2fafe51d970e616881287c 100644 |
--- a/third_party/WebKit/Source/core/input/EventHandler.cpp |
+++ b/third_party/WebKit/Source/core/input/EventHandler.cpp |
@@ -110,41 +110,6 @@ bool hasTouchHandlers(const EventHandlerRegistry& registry) |
|| registry.hasEventHandlers(EventHandlerRegistry::TouchEventPassive); |
} |
-WebInputEventResult mergeEventResult(WebInputEventResult responseA, WebInputEventResult responseB) |
-{ |
- // The ordering of the enumeration is specific. There are times that |
- // multiple events fire and we need to combine them into a single |
- // result code. The enumeration is based on the level of consumption that |
- // is most significant. The enumeration is ordered with smaller specified |
- // numbers first. Examples of merged results are: |
- // (HandledApplication, HandledSystem) -> HandledSystem |
- // (NotHandled, HandledApplication) -> HandledApplication |
- static_assert(static_cast<int>(WebInputEventResult::NotHandled) == 0, "WebInputEventResult not ordered"); |
- static_assert(static_cast<int>(WebInputEventResult::HandledSuppressed) < static_cast<int>(WebInputEventResult::HandledApplication), "WebInputEventResult not ordered"); |
- static_assert(static_cast<int>(WebInputEventResult::HandledApplication) < static_cast<int>(WebInputEventResult::HandledSystem), "WebInputEventResult not ordered"); |
- return static_cast<WebInputEventResult>(max(static_cast<int>(responseA), static_cast<int>(responseB))); |
-} |
- |
-WebInputEventResult eventToEventResult(PassRefPtrWillBeRawPtr<Event> event, bool res) |
-{ |
- if (event->defaultPrevented()) |
- return WebInputEventResult::HandledApplication; |
- if (event->defaultHandled()) |
- return WebInputEventResult::HandledSystem; |
- |
- // TODO(dtapuska): There are cases in the code where dispatchEvent |
- // returns false (indicated handled) but event is not marked |
- // as default handled or default prevented. crbug.com/560355 |
- if (!res) |
- return WebInputEventResult::HandledSuppressed; |
- return WebInputEventResult::NotHandled; |
-} |
- |
-bool isNodeInDocument(Node* n) |
-{ |
- return n && n->inDocument(); |
-} |
- |
const AtomicString& touchEventNameForTouchPointState(PlatformTouchPoint::State state) |
{ |
switch (state) { |
@@ -164,46 +129,6 @@ const AtomicString& touchEventNameForTouchPointState(PlatformTouchPoint::State s |
} |
} |
-const AtomicString& pointerEventNameForTouchPointState(PlatformTouchPoint::State state) |
-{ |
- switch (state) { |
- case PlatformTouchPoint::TouchReleased: |
- return EventTypeNames::pointerup; |
- case PlatformTouchPoint::TouchCancelled: |
- return EventTypeNames::pointercancel; |
- case PlatformTouchPoint::TouchPressed: |
- return EventTypeNames::pointerdown; |
- case PlatformTouchPoint::TouchMoved: |
- return EventTypeNames::pointermove; |
- case PlatformTouchPoint::TouchStationary: |
- // Fall through to default |
- default: |
- ASSERT_NOT_REACHED(); |
- return emptyAtom; |
- } |
-} |
- |
-const AtomicString& pointerEventNameForMouseEventName(const AtomicString& mouseEventName) |
-{ |
-#define RETURN_CORRESPONDING_PE_NAME(eventSuffix) \ |
- if (mouseEventName == EventTypeNames::mouse##eventSuffix) {\ |
- return EventTypeNames::pointer##eventSuffix;\ |
- } |
- |
- RETURN_CORRESPONDING_PE_NAME(down); |
- RETURN_CORRESPONDING_PE_NAME(enter); |
- RETURN_CORRESPONDING_PE_NAME(leave); |
- RETURN_CORRESPONDING_PE_NAME(move); |
- RETURN_CORRESPONDING_PE_NAME(out); |
- RETURN_CORRESPONDING_PE_NAME(over); |
- RETURN_CORRESPONDING_PE_NAME(up); |
- |
-#undef RETURN_CORRESPONDING_PE_NAME |
- |
- ASSERT_NOT_REACHED(); |
- return emptyAtom; |
-} |
- |
} // namespace |
using namespace HTMLNames; |
@@ -333,7 +258,6 @@ EventHandler::EventHandler(LocalFrame* frame) |
, m_mousePositionIsUnknown(true) |
, m_mouseDownTimestamp(0) |
, m_touchPressed(false) |
- , m_preventMouseEventForPointerTypeMouse(false) |
, m_inPointerCanceledState(false) |
, m_scrollGestureHandlingNode(nullptr) |
, m_lastGestureScrollOverWidget(false) |
@@ -370,6 +294,7 @@ DEFINE_TRACE(EventHandler) |
visitor->trace(m_previousGestureScrolledNode); |
visitor->trace(m_lastDeferredTapElement); |
visitor->trace(m_selectionController); |
+ visitor->trace(m_pointerEventManager); |
#endif |
} |
@@ -411,7 +336,6 @@ void EventHandler::clear() |
m_scrollbarHandlingScrollGesture = nullptr; |
m_touchPressed = false; |
m_pointerEventManager.clear(); |
- m_preventMouseEventForPointerTypeMouse = false; |
m_inPointerCanceledState = false; |
m_mouseDownMayStartDrag = false; |
m_lastShowPressTimestamp = 0; |
@@ -427,6 +351,38 @@ void EventHandler::clear() |
m_mouseDown = PlatformMouseEvent(); |
} |
+WebInputEventResult EventHandler::mergeEventResult( |
+ WebInputEventResult resultA, WebInputEventResult resultB) |
+{ |
+ // The ordering of the enumeration is specific. There are times that |
+ // multiple events fire and we need to combine them into a single |
+ // result code. The enumeration is based on the level of consumption that |
+ // is most significant. The enumeration is ordered with smaller specified |
+ // numbers first. Examples of merged results are: |
+ // (HandledApplication, HandledSystem) -> HandledSystem |
+ // (NotHandled, HandledApplication) -> HandledApplication |
+ static_assert(static_cast<int>(WebInputEventResult::NotHandled) == 0, "WebInputEventResult not ordered"); |
+ static_assert(static_cast<int>(WebInputEventResult::HandledSuppressed) < static_cast<int>(WebInputEventResult::HandledApplication), "WebInputEventResult not ordered"); |
+ static_assert(static_cast<int>(WebInputEventResult::HandledApplication) < static_cast<int>(WebInputEventResult::HandledSystem), "WebInputEventResult not ordered"); |
+ return static_cast<WebInputEventResult>(max(static_cast<int>(resultA), static_cast<int>(resultB))); |
+} |
+ |
+WebInputEventResult EventHandler::eventToEventResult( |
+ PassRefPtrWillBeRawPtr<Event> event, bool result) |
+{ |
+ if (event->defaultPrevented()) |
+ return WebInputEventResult::HandledApplication; |
+ if (event->defaultHandled()) |
+ return WebInputEventResult::HandledSystem; |
+ |
+ // TODO(dtapuska): There are cases in the code where dispatchEvent |
+ // returns false (indicated handled) but event is not marked |
+ // as default handled or default prevented. crbug.com/560355 |
+ if (!result) |
+ return WebInputEventResult::HandledSuppressed; |
+ return WebInputEventResult::NotHandled; |
+} |
+ |
void EventHandler::nodeWillBeRemoved(Node& nodeToBeRemoved) |
{ |
if (nodeToBeRemoved.containsIncludingShadowDOM(m_clickNode.get())) { |
@@ -1150,7 +1106,8 @@ WebInputEventResult EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& |
{ |
TRACE_EVENT0("blink", "EventHandler::handleMouseMoveEvent"); |
- conditionallyEnableMouseEventForPointerTypeMouse(event); |
+ m_pointerEventManager.conditionallyEnableMouseEventForPointerTypeMouse( |
+ event.modifiers()); |
RefPtrWillBeRawPtr<FrameView> protector(m_frame->view()); |
@@ -1179,7 +1136,8 @@ void EventHandler::handleMouseLeaveEvent(const PlatformMouseEvent& event) |
{ |
TRACE_EVENT0("blink", "EventHandler::handleMouseLeaveEvent"); |
- conditionallyEnableMouseEventForPointerTypeMouse(event); |
+ m_pointerEventManager.conditionallyEnableMouseEventForPointerTypeMouse( |
+ event.modifiers()); |
RefPtrWillBeRawPtr<FrameView> protector(m_frame->view()); |
handleMouseMoveOrLeaveEvent(event, 0, false, true); |
@@ -1363,7 +1321,8 @@ WebInputEventResult EventHandler::handleMouseReleaseEvent(const PlatformMouseEve |
WebInputEventResult eventResult = updatePointerTargetAndDispatchEvents(EventTypeNames::mouseup, mev.innerNode(), m_clickCount, mouseEvent); |
// TODO(crbug/545647): This state should reset with pointercancel too. |
- m_preventMouseEventForPointerTypeMouse = false; |
+ m_pointerEventManager.conditionallyEnableMouseEventForPointerTypeMouse( |
+ PlatformEvent::NoModifiers); |
bool contextMenuEvent = mouseEvent.button() == RightButton; |
#if OS(MACOSX) |
@@ -1649,108 +1608,8 @@ void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo |
m_lastScrollbarUnderMouse = nullptr; |
} |
- if (lastNodeUnderMouse != m_nodeUnderMouse) |
- sendNodeTransitionEvents(lastNodeUnderMouse.get(), m_nodeUnderMouse.get(), mouseEvent); |
-} |
- |
-WebInputEventResult EventHandler::dispatchPointerEvent(EventTarget* target, PassRefPtrWillBeRawPtr<PointerEvent> pointerEvent) |
-{ |
- if (!RuntimeEnabledFeatures::pointerEventEnabled()) |
- return WebInputEventResult::NotHandled; |
- |
- bool dispatchResult = target->dispatchEvent(pointerEvent.get()); |
- return eventToEventResult(pointerEvent, dispatchResult); |
-} |
- |
-void EventHandler::sendNodeTransitionEvents(Node* exitedNode, Node* enteredNode, |
- const PlatformMouseEvent& mouseEvent) |
-{ |
- ASSERT(exitedNode != enteredNode); |
- |
- // Dispatch pointerout/mouseout events |
- if (isNodeInDocument(exitedNode)) { |
- sendPointerAndMouseTransitionEvents(exitedNode, EventTypeNames::mouseout, mouseEvent, enteredNode, false); |
- } |
- |
- // 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. |
- |
- // Create lists of all exited/entered ancestors, locate the common ancestor & capturing listeners. |
- WillBeHeapVector<RefPtrWillBeMember<Node>, 32> exitedAncestors; |
- WillBeHeapVector<RefPtrWillBeMember<Node>, 32> enteredAncestors; |
- if (isNodeInDocument(exitedNode)) { |
- exitedNode->updateDistribution(); |
- for (Node* node = exitedNode; node; node = FlatTreeTraversal::parent(*node)) { |
- exitedAncestors.append(node); |
- } |
- } |
- if (isNodeInDocument(enteredNode)) { |
- enteredNode->updateDistribution(); |
- for (Node* node = enteredNode; node; node = FlatTreeTraversal::parent(*node)) { |
- enteredAncestors.append(node); |
- } |
- } |
- |
- size_t numExitedAncestors = exitedAncestors.size(); |
- size_t numEnteredAncestors = enteredAncestors.size(); |
- |
- size_t exitedAncestorIndex = numExitedAncestors; |
- size_t enteredAncestorIndex = numEnteredAncestors; |
- for (size_t j = 0; j < numExitedAncestors; j++) { |
- for (size_t i = 0; i < numEnteredAncestors; i++) { |
- if (exitedAncestors[j] == enteredAncestors[i]) { |
- exitedAncestorIndex = j; |
- enteredAncestorIndex = i; |
- break; |
- } |
- } |
- if (exitedAncestorIndex < numExitedAncestors) |
- break; |
- } |
- |
- bool exitedNodeHasCapturingAncestor = false; |
- for (size_t j = 0; j < numExitedAncestors; 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 < exitedAncestorIndex; j++) { |
- sendPointerAndMouseTransitionEvents(exitedAncestors[j].get(), EventTypeNames::mouseleave, mouseEvent, enteredNode, !exitedNodeHasCapturingAncestor); |
- } |
- |
- // Dispatch pointerover/mouseover. |
- if (isNodeInDocument(enteredNode)) { |
- sendPointerAndMouseTransitionEvents(enteredNode, EventTypeNames::mouseover, mouseEvent, exitedNode, false); |
- } |
- |
- // 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 < numEnteredAncestors; 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 = enteredAncestorIndex; i > 0; i--) { |
- sendPointerAndMouseTransitionEvents(enteredAncestors[i-1].get(), EventTypeNames::mouseenter, mouseEvent, exitedNode, !enteredNodeHasCapturingAncestor); |
- } |
+ m_pointerEventManager.sendNodeTransitionEvents(lastNodeUnderMouse, |
+ m_nodeUnderMouse, mouseEvent, m_frame->document()->domWindow()); |
} |
WebInputEventResult EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, int clickCount, const PlatformMouseEvent& mouseEvent) |
@@ -1764,38 +1623,6 @@ WebInputEventResult EventHandler::dispatchMouseEvent(const AtomicString& eventTy |
return eventToEventResult(event, dispatchResult); |
} |
-EventTarget* EventHandler::getEffectiveTargetForPointerEvent( |
- EventTarget* target, PassRefPtrWillBeRawPtr<PointerEvent> pointerEvent) |
-{ |
- EventTarget* capturingNode = m_pointerEventManager.getCapturingNode(pointerEvent.get()); |
- if (capturingNode) |
- target = capturingNode; |
- return target; |
-} |
- |
-void EventHandler::sendPointerAndMouseTransitionEvents(Node* target, const AtomicString& mouseEventType, |
- const PlatformMouseEvent& mouseEvent, Node* relatedTarget, bool checkForListener) |
-{ |
- ASSERT(mouseEventType == EventTypeNames::mouseenter |
- || mouseEventType == EventTypeNames::mouseleave |
- || mouseEventType == EventTypeNames::mouseover |
- || mouseEventType == EventTypeNames::mouseout); |
- |
- AtomicString pointerEventType = pointerEventNameForMouseEventName(mouseEventType); |
- RefPtrWillBeRawPtr<PointerEvent> pointerEvent = m_pointerEventManager.create(pointerEventType, |
- mouseEvent, relatedTarget, m_frame->document()->domWindow()); |
- |
- // Suppress these events if the target is not the capturing element |
- if (target != getEffectiveTargetForPointerEvent(target, pointerEvent)) |
- return; |
- |
- if (!checkForListener || target->hasEventListeners(pointerEventType)) |
- dispatchPointerEvent(target, pointerEvent); |
- |
- if (!checkForListener || target->hasEventListeners(mouseEventType)) |
- target->dispatchMouseEvent(mouseEvent, mouseEventType, 0, relatedTarget); |
-} |
- |
// TODO(mustaq): Make PE drive ME dispatch & bookkeeping in EventHandler. |
WebInputEventResult EventHandler::updatePointerTargetAndDispatchEvents(const AtomicString& mouseEventType, Node* targetNode, int clickCount, const PlatformMouseEvent& mouseEvent) |
{ |
@@ -1807,28 +1634,9 @@ WebInputEventResult EventHandler::updatePointerTargetAndDispatchEvents(const Ato |
if (!m_nodeUnderMouse) |
return WebInputEventResult::NotHandled; |
- AtomicString pointerEventType = pointerEventNameForMouseEventName(mouseEventType); |
- unsigned short pointerButtonsPressed = MouseEvent::platformModifiersToButtons(mouseEvent.modifiers()); |
- |
- // Make sure chorded buttons fire pointermove instead of pointerup/pointerdown. |
- if ((pointerEventType == EventTypeNames::pointerdown && (pointerButtonsPressed & ~MouseEvent::buttonToButtons(mouseEvent.button())) != 0) |
- || (pointerEventType == EventTypeNames::pointerup && pointerButtonsPressed != 0)) |
- pointerEventType = EventTypeNames::pointermove; |
- |
- RefPtrWillBeRawPtr<PointerEvent> pointerEvent = m_pointerEventManager.create(pointerEventType, |
- mouseEvent, nullptr, m_frame->document()->domWindow()); |
- |
- EventTarget* target = getEffectiveTargetForPointerEvent(m_nodeUnderMouse.get(), pointerEvent); |
- WebInputEventResult result = dispatchPointerEvent(target, pointerEvent); |
- |
- if (result != WebInputEventResult::NotHandled && pointerEventType == EventTypeNames::pointerdown) |
- m_preventMouseEventForPointerTypeMouse = true; |
- |
- if (!m_preventMouseEventForPointerTypeMouse) { |
- RefPtrWillBeRawPtr<MouseEvent> event = MouseEvent::create(mouseEventType, m_nodeUnderMouse->document().domWindow(), mouseEvent, clickCount, nullptr); |
- bool dispatchResult = target->dispatchEvent(event); |
- result = mergeEventResult(result, eventToEventResult(event, dispatchResult)); |
- } |
+ WebInputEventResult result = m_pointerEventManager.sendMousePointerEvent( |
+ m_nodeUnderMouse, mouseEventType, clickCount, mouseEvent, nullptr, |
+ m_frame->document()->domWindow()); |
return result; |
} |
@@ -3743,29 +3551,18 @@ void EventHandler::dispatchPointerEvents(const PlatformTouchEvent& event, |
for (unsigned i = 0; i < touchInfos.size(); ++i) { |
TouchInfo& touchInfo = touchInfos[i]; |
const PlatformTouchPoint& touchPoint = touchInfo.point; |
- const PlatformTouchPoint::State pointState = touchPoint.state(); |
- if (pointState == PlatformTouchPoint::TouchStationary || !touchInfo.knownTarget) |
+ if (touchPoint.state() == PlatformTouchPoint::TouchStationary |
+ || !touchInfo.knownTarget) |
continue; |
- bool pointerReleasedOrCancelled = pointState == PlatformTouchPoint::TouchReleased |
- || pointState == PlatformTouchPoint::TouchCancelled; |
- |
- RefPtrWillBeRawPtr<PointerEvent> pointerEvent = m_pointerEventManager.create( |
- pointerEventNameForTouchPointState(pointState), |
- touchPoint, event.modifiers(), |
+ WebInputEventResult result = |
+ m_pointerEventManager.sendTouchPointerEvent( |
+ touchInfo.touchTarget, touchPoint, event.modifiers(), |
touchInfo.adjustedRadius.width(), touchInfo.adjustedRadius.height(), |
touchInfo.adjustedPagePoint.x(), touchInfo.adjustedPagePoint.y()); |
- |
- // TODO(nzolghadr): crbug.com/579553 dealing with implicit touch capturing vs pointer event capturing |
- touchInfo.touchTarget->dispatchEvent(pointerEvent.get()); |
- |
- touchInfo.consumed = pointerEvent->defaultPrevented() || pointerEvent->defaultHandled(); |
- |
- // Remove the released/cancelled id at the end to correctly determine primary id above. |
- if (pointerReleasedOrCancelled) |
- m_pointerEventManager.remove(pointerEvent); |
+ touchInfo.consumed = result != WebInputEventResult::NotHandled; |
} |
} |
@@ -3783,12 +3580,9 @@ void EventHandler::sendPointerCancels(WillBeHeapVector<TouchInfo>& touchInfos) |
|| pointState == PlatformTouchPoint::TouchCancelled) |
continue; |
- RefPtrWillBeRawPtr<PointerEvent> pointerEvent = m_pointerEventManager.createPointerCancel(point); |
- |
- // TODO(nzolghadr): crbug.com/579553 dealing with implicit touch capturing vs pointer event capturing |
- touchInfo.touchTarget->dispatchEvent(pointerEvent.get()); |
- |
- m_pointerEventManager.remove(pointerEvent); |
+ m_pointerEventManager.sendTouchCancelPointerEvent( |
+ touchInfo.touchTarget, |
+ point); |
} |
} |
@@ -4116,12 +3910,6 @@ void EventHandler::setLastKnownMousePosition(const PlatformMouseEvent& event) |
m_lastKnownMouseGlobalPosition = event.globalPosition(); |
} |
-void EventHandler::conditionallyEnableMouseEventForPointerTypeMouse(const PlatformMouseEvent& event) |
-{ |
- if (event.button() == NoButton) |
- m_preventMouseEventForPointerTypeMouse = false; |
-} |
- |
WebInputEventResult EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, LocalFrame* subframe) |
{ |
selectionController().passMousePressEventToSubframe(mev); |