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 898e7d53aeac75f92ae1735d289de4cfb5aceade..b56a0c0421ff4c2eae73ac5a5f62d95792904c15 100644 |
--- a/third_party/WebKit/Source/core/input/EventHandler.cpp |
+++ b/third_party/WebKit/Source/core/input/EventHandler.cpp |
@@ -42,6 +42,7 @@ |
#include "core/editing/SelectionController.h" |
#include "core/events/DragEvent.h" |
#include "core/events/EventPath.h" |
+#include "core/events/GestureEvent.h" |
#include "core/events/KeyboardEvent.h" |
#include "core/events/MouseEvent.h" |
#include "core/events/PointerEvent.h" |
@@ -103,6 +104,36 @@ namespace blink { |
namespace { |
+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(); |
@@ -400,7 +431,7 @@ void EventHandler::nodeWillBeRemoved(Node& nodeToBeRemoved) |
} |
} |
-bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& event) |
+WebInputEventResult EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& event) |
{ |
TRACE_EVENT0("blink", "EventHandler::handleMousePressEvent"); |
@@ -413,7 +444,7 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve |
if (FrameView* frameView = m_frame->view()) { |
if (frameView->isPointInScrollbarCorner(event.event().position())) |
- return false; |
+ return WebInputEventResult::NotHandled; |
} |
bool singleClick = event.event().clickCount() <= 1; |
@@ -428,7 +459,7 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve |
if (event.event().shiftKey() && singleClick) { |
m_svgPan = true; |
m_frame->document()->accessSVGExtensions().startPan(m_frame->view()->rootFrameToContents(event.event().position())); |
- return true; |
+ return WebInputEventResult::HandledSystem; |
} |
} |
@@ -455,10 +486,10 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve |
m_mouseDownMayStartAutoscroll = selectionController().mouseDownMayStartSelect() |
|| (m_mousePressNode && m_mousePressNode->layoutBox() && m_mousePressNode->layoutBox()->canBeProgramaticallyScrolled()); |
- return swallowEvent; |
+ return swallowEvent ? WebInputEventResult::HandledSystem : WebInputEventResult::NotHandled; |
} |
-bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& event) |
+WebInputEventResult EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& event) |
{ |
TRACE_EVENT0("blink", "EventHandler::handleMouseDraggedEvent"); |
@@ -480,24 +511,24 @@ bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e |
m_mousePressed = false; |
if (!m_mousePressed) |
- return false; |
+ return WebInputEventResult::NotHandled; |
if (handleDrag(event, DragInitiator::Mouse)) |
- return true; |
+ return WebInputEventResult::HandledSystem; |
Node* targetNode = event.innerNode(); |
if (!targetNode) |
- return false; |
+ return WebInputEventResult::NotHandled; |
LayoutObject* layoutObject = targetNode->layoutObject(); |
if (!layoutObject) { |
Node* parent = ComposedTreeTraversal::parent(*targetNode); |
if (!parent) |
- return false; |
+ return WebInputEventResult::NotHandled; |
layoutObject = parent->layoutObject(); |
if (!layoutObject || !layoutObject->isListBox()) |
- return false; |
+ return WebInputEventResult::NotHandled; |
} |
m_mouseDownMayStartDrag = false; |
@@ -510,7 +541,7 @@ bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e |
} |
selectionController().handleMouseDraggedEvent(event, m_mouseDownPos, m_dragStartPos, m_mousePressNode.get(), m_lastKnownMousePosition); |
- return true; |
+ return WebInputEventResult::HandledSystem; |
} |
void EventHandler::updateSelectionForMouseDrag() |
@@ -518,7 +549,7 @@ void EventHandler::updateSelectionForMouseDrag() |
selectionController().updateSelectionForMouseDrag(m_mousePressNode.get(), m_dragStartPos, m_lastKnownMousePosition); |
} |
-bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event) |
+WebInputEventResult EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event) |
{ |
AutoscrollController* controller = autoscrollController(); |
if (controller && controller->autoscrollInProgress()) |
@@ -531,7 +562,7 @@ bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e |
m_mouseDownMayStartDrag = false; |
m_mouseDownMayStartAutoscroll = false; |
- return selectionController().handleMouseReleaseEvent(event, m_dragStartPos); |
+ return selectionController().handleMouseReleaseEvent(event, m_dragStartPos) ? WebInputEventResult::HandledSystem : WebInputEventResult::NotHandled; |
} |
#if OS(WIN) |
@@ -948,7 +979,7 @@ static LayoutPoint contentPointFromRootFrame(LocalFrame* frame, const IntPoint& |
return view ? view->rootFrameToContents(pointInRootFrame) : pointInRootFrame; |
} |
-bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) |
+WebInputEventResult EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) |
{ |
TRACE_EVENT0("blink", "EventHandler::handleMousePressEvent"); |
@@ -971,7 +1002,7 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) |
m_mouseDownPos = view->rootFrameToContents(mouseEvent.position()); |
} else { |
invalidateClick(); |
- return false; |
+ return WebInputEventResult::NotHandled; |
} |
HitTestRequest request(HitTestRequest::Active); |
@@ -982,22 +1013,25 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) |
if (!mev.innerNode()) { |
invalidateClick(); |
- return false; |
+ return WebInputEventResult::NotHandled; |
} |
m_mousePressNode = mev.innerNode(); |
RefPtrWillBeRawPtr<LocalFrame> subframe = subframeForHitTestResult(mev); |
- if (subframe && passMousePressEventToSubframe(mev, subframe.get())) { |
+ if (subframe) { |
+ WebInputEventResult result = passMousePressEventToSubframe(mev, subframe.get()); |
// Start capturing future events for this frame. We only do this if we didn't clear |
// the m_mousePressed flag, which may happen if an AppKit widget entered a modal event loop. |
+ // The capturing should be done only when the result indicates it |
+ // has been handled. See crbug.com/269917 |
m_capturesDragging = subframe->eventHandler().capturesDragging(); |
if (m_mousePressed && m_capturesDragging) { |
m_capturingMouseEventsNode = mev.innerNode(); |
m_eventHandlerWillResetCapturingMouseEventsNode = true; |
} |
invalidateClick(); |
- return true; |
+ return result; |
} |
#if OS(WIN) |
@@ -1009,7 +1043,7 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) |
// We invalidate the click when exiting pan scrolling so that we don't inadvertently navigate |
// away from the current page (e.g. the click was on a hyperlink). See <rdar://problem/6095023>. |
invalidateClick(); |
- return true; |
+ return WebInputEventResult::HandledSuppressed; |
} |
#endif |
@@ -1024,13 +1058,13 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) |
m_resizeScrollableArea->setInResizeMode(true); |
m_offsetFromResizeCorner = LayoutSize(m_resizeScrollableArea->offsetFromResizeCorner(p)); |
invalidateClick(); |
- return true; |
+ return WebInputEventResult::HandledSuppressed; |
} |
} |
m_frame->selection().setCaretBlinkingSuspended(true); |
- bool swallowEvent = updatePointerTargetAndDispatchEvents(EventTypeNames::mousedown, mev.innerNode(), m_clickCount, mouseEvent); |
+ WebInputEventResult eventResult = updatePointerTargetAndDispatchEvents(EventTypeNames::mousedown, mev.innerNode(), m_clickCount, mouseEvent); |
// m_selectionInitiationState is initialized after dispatching mousedown |
// event in order not to keep the selection by DOM APIs Because we can't |
@@ -1041,8 +1075,9 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) |
HitTestResult hitTestResult = hitTestResultInFrame(m_frame, documentPoint, HitTestRequest::ReadOnly); |
InputDeviceCapabilities* sourceCapabilities = mouseEvent.syntheticEventType() == PlatformMouseEvent::FromTouch ? InputDeviceCapabilities::firesTouchEventsSourceCapabilities() : |
InputDeviceCapabilities::doesntFireTouchEventsSourceCapabilities(); |
- swallowEvent = swallowEvent || handleMouseFocus(MouseEventWithHitTestResults(mouseEvent, hitTestResult), sourceCapabilities); |
- m_capturesDragging = !swallowEvent || mev.scrollbar(); |
+ if (eventResult == WebInputEventResult::NotHandled) |
+ eventResult = handleMouseFocus(MouseEventWithHitTestResults(mouseEvent, hitTestResult), sourceCapabilities); |
+ m_capturesDragging = eventResult == WebInputEventResult::NotHandled || mev.scrollbar(); |
// If the hit testing originally determined the event was in a scrollbar, refetch the MouseEventWithHitTestResults |
// in case the scrollbar widget was destroyed when the mouse event was handled. |
@@ -1054,7 +1089,7 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) |
m_lastScrollbarUnderMouse = nullptr; |
} |
- if (swallowEvent) { |
+ if (eventResult != WebInputEventResult::NotHandled) { |
// scrollbars should get events anyway, even disabled controls might be scrollable |
passMousePressEventToScrollbar(mev); |
} else { |
@@ -1064,9 +1099,9 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) |
} |
if (passMousePressEventToScrollbar(mev)) |
- swallowEvent = true; |
+ eventResult = WebInputEventResult::HandledSystem; |
else |
- swallowEvent = handleMousePressEvent(mev); |
+ eventResult = handleMousePressEvent(mev); |
} |
if (mev.hitTestResult().innerNode() && mouseEvent.button() == LeftButton) { |
@@ -1076,7 +1111,7 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) |
m_frame->chromeClient().onMouseDown(result.innerNode()); |
} |
- return swallowEvent; |
+ return eventResult; |
} |
static PaintLayer* layerForNode(Node* node) |
@@ -1105,7 +1140,7 @@ ScrollableArea* EventHandler::associatedScrollableArea(const PaintLayer* layer) |
return nullptr; |
} |
-bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& event) |
+WebInputEventResult EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& event) |
{ |
TRACE_EVENT0("blink", "EventHandler::handleMouseMoveEvent"); |
@@ -1114,7 +1149,7 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& event) |
RefPtrWillBeRawPtr<FrameView> protector(m_frame->view()); |
HitTestResult hoveredNode = HitTestResult(); |
- bool result = handleMouseMoveOrLeaveEvent(event, &hoveredNode); |
+ WebInputEventResult result = handleMouseMoveOrLeaveEvent(event, &hoveredNode); |
Page* page = m_frame->page(); |
if (!page) |
@@ -1144,7 +1179,7 @@ void EventHandler::handleMouseLeaveEvent(const PlatformMouseEvent& event) |
handleMouseMoveOrLeaveEvent(event, 0, false, true); |
} |
-bool EventHandler::handleMouseMoveOrLeaveEvent(const PlatformMouseEvent& mouseEvent, HitTestResult* hoveredNode, bool onlyUpdateScrollbars, bool forceLeave) |
+WebInputEventResult EventHandler::handleMouseMoveOrLeaveEvent(const PlatformMouseEvent& mouseEvent, HitTestResult* hoveredNode, bool onlyUpdateScrollbars, bool forceLeave) |
{ |
ASSERT(m_frame); |
ASSERT(m_frame->view()); |
@@ -1160,7 +1195,7 @@ bool EventHandler::handleMouseMoveOrLeaveEvent(const PlatformMouseEvent& mouseEv |
if (m_svgPan) { |
m_frame->document()->accessSVGExtensions().updatePan(m_frame->view()->rootFrameToContents(m_lastKnownMousePosition)); |
- return true; |
+ return WebInputEventResult::HandledSuppressed; |
} |
if (m_frameSetBeingResized) |
@@ -1169,7 +1204,7 @@ bool EventHandler::handleMouseMoveOrLeaveEvent(const PlatformMouseEvent& mouseEv |
// Send events right to a scrollbar if the mouse is pressed. |
if (m_lastScrollbarUnderMouse && m_mousePressed) { |
m_lastScrollbarUnderMouse->mouseMoved(mouseEvent); |
- return true; |
+ return WebInputEventResult::HandledSystem; |
} |
// Mouse events simulated from touch should not hit-test again. |
@@ -1212,10 +1247,10 @@ bool EventHandler::handleMouseMoveOrLeaveEvent(const PlatformMouseEvent& mouseEv |
updateLastScrollbarUnderMouse(scrollbar, !m_mousePressed); |
if (onlyUpdateScrollbars) |
- return true; |
+ return WebInputEventResult::HandledSuppressed; |
} |
- bool swallowEvent = false; |
+ WebInputEventResult eventResult = WebInputEventResult::NotHandled; |
RefPtrWillBeRawPtr<LocalFrame> newSubframe = m_capturingMouseEventsNode.get() ? subframeForTargetNode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev); |
// We want mouseouts to happen first, from the inside out. First send a move event to the last subframe so that it will fire mouseouts. |
@@ -1229,7 +1264,7 @@ bool EventHandler::handleMouseMoveOrLeaveEvent(const PlatformMouseEvent& mouseEv |
// Event dispatch in updateMouseEventTargetNode may have caused the subframe of the target |
// node to be detached from its FrameView, in which case the event should not be passed. |
if (newSubframe->view()) |
- swallowEvent |= passMouseMoveEventToSubframe(mev, newSubframe.get(), hoveredNode); |
+ eventResult = passMouseMoveEventToSubframe(mev, newSubframe.get(), hoveredNode); |
} else { |
if (scrollbar && !m_mousePressed) |
scrollbar->mouseMoved(mouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering. |
@@ -1243,15 +1278,14 @@ bool EventHandler::handleMouseMoveOrLeaveEvent(const PlatformMouseEvent& mouseEv |
m_lastMouseMoveEventSubframe = newSubframe; |
- if (swallowEvent) |
- return true; |
- |
- swallowEvent = updatePointerTargetAndDispatchEvents(EventTypeNames::mousemove, mev.innerNode(), 0, mouseEvent); |
+ if (eventResult != WebInputEventResult::NotHandled) |
+ return eventResult; |
- if (!swallowEvent) |
- swallowEvent = handleMouseDraggedEvent(mev); |
+ eventResult = updatePointerTargetAndDispatchEvents(EventTypeNames::mousemove, mev.innerNode(), 0, mouseEvent); |
+ if (eventResult != WebInputEventResult::NotHandled) |
+ return eventResult; |
- return swallowEvent; |
+ return handleMouseDraggedEvent(mev); |
} |
void EventHandler::invalidateClick() |
@@ -1270,7 +1304,7 @@ static ContainerNode* parentForClickEvent(const Node& node) |
return ComposedTreeTraversal::parent(node); |
} |
-bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent) |
+WebInputEventResult EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent) |
{ |
TRACE_EVENT0("blink", "EventHandler::handleMouseReleaseEvent"); |
@@ -1296,7 +1330,7 @@ bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent) |
if (m_svgPan) { |
m_svgPan = false; |
m_frame->document()->accessSVGExtensions().updatePan(m_frame->view()->rootFrameToContents(m_lastKnownMousePosition)); |
- return true; |
+ return WebInputEventResult::HandledSuppressed; |
} |
if (m_frameSetBeingResized) |
@@ -1317,10 +1351,10 @@ bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent) |
LocalFrame* subframe = m_capturingMouseEventsNode.get() ? subframeForTargetNode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev); |
if (m_eventHandlerWillResetCapturingMouseEventsNode) |
m_capturingMouseEventsNode = nullptr; |
- if (subframe && passMouseReleaseEventToSubframe(mev, subframe)) |
- return true; |
+ if (subframe) |
+ return passMouseReleaseEventToSubframe(mev, subframe); |
- bool swallowUpEvent = updatePointerTargetAndDispatchEvents(EventTypeNames::mouseup, mev.innerNode(), m_clickCount, mouseEvent); |
+ WebInputEventResult eventResult = updatePointerTargetAndDispatchEvents(EventTypeNames::mouseup, mev.innerNode(), m_clickCount, mouseEvent); |
// TODO(crbug/545647): This state should reset with pointercancel too. |
m_preventMouseEventForPointerTypeMouse = false; |
@@ -1332,7 +1366,7 @@ bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent) |
contextMenuEvent = true; |
#endif |
- bool swallowClickEvent = false; |
+ WebInputEventResult clickEventResult = WebInputEventResult::NotHandled; |
if (m_clickCount > 0 && !contextMenuEvent && mev.innerNode() && m_clickNode && mev.innerNode()->canParticipateInComposedTree() && m_clickNode->canParticipateInComposedTree()) { |
// Updates distribution because a 'mouseup' event listener can make the |
// tree dirty at dispatchMouseEvent() invocation above. |
@@ -1347,8 +1381,10 @@ bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent) |
// because the mouseup dispatch above has already updated it |
// correctly. Moreover, clickTargetNode is different from |
// mev.innerNode at drag-release. |
- clickTargetNode->dispatchMouseEvent(mouseEvent, |
- EventTypeNames::click, m_clickCount); |
+ if (clickTargetNode->dispatchMouseEvent(mouseEvent, |
kotenkov
2016/01/12 20:55:00
There should be a negation here: |EventTarget::dis
dtapuska
2016/01/12 21:06:48
Thanks for the find; you are correct. This is in f
|
+ EventTypeNames::click, m_clickCount)) { |
+ clickEventResult = WebInputEventResult::HandledApplication; |
+ } |
} |
} |
@@ -1357,22 +1393,21 @@ bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent) |
m_resizeScrollableArea = nullptr; |
} |
- bool swallowMouseReleaseEvent = false; |
- if (!swallowUpEvent) |
- swallowMouseReleaseEvent = handleMouseReleaseEvent(mev); |
+ if (eventResult == WebInputEventResult::NotHandled) |
+ eventResult = handleMouseReleaseEvent(mev); |
invalidateClick(); |
- return swallowUpEvent || swallowClickEvent || swallowMouseReleaseEvent; |
+ return mergeEventResult(clickEventResult, eventResult); |
} |
-bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTarget, const PlatformMouseEvent& event, DataTransfer* dataTransfer) |
+WebInputEventResult EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTarget, const PlatformMouseEvent& event, DataTransfer* dataTransfer) |
{ |
FrameView* view = m_frame->view(); |
// FIXME: We might want to dispatch a dragleave even if the view is gone. |
if (!view) |
- return false; |
+ return WebInputEventResult::NotHandled; |
RefPtrWillBeRawPtr<DragEvent> me = DragEvent::create(eventType, |
true, true, m_frame->document()->domWindow(), |
@@ -1381,8 +1416,8 @@ bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTa |
event.modifiers(), |
0, MouseEvent::platformModifiersToButtons(event.modifiers()), nullptr, event.timestamp(), dataTransfer, event.syntheticEventType()); |
- dragTarget->dispatchEvent(me.get()); |
- return me->defaultPrevented(); |
+ bool dispatchResult = dragTarget->dispatchEvent(me.get()); |
+ return eventToEventResult(me, dispatchResult); |
} |
static bool targetIsFrame(Node* target, LocalFrame*& frame) |
@@ -1437,12 +1472,12 @@ static bool findDropZone(Node* target, DataTransfer* dataTransfer) |
return false; |
} |
-bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, DataTransfer* dataTransfer) |
+WebInputEventResult EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, DataTransfer* dataTransfer) |
{ |
- bool accept = false; |
+ WebInputEventResult eventResult = WebInputEventResult::NotHandled; |
if (!m_frame->view()) |
- return false; |
+ return eventResult; |
HitTestRequest request(HitTestRequest::ReadOnly); |
MouseEventWithHitTestResults mev = prepareMouseEvent(request, event); |
@@ -1464,21 +1499,21 @@ bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, DataTransf |
LocalFrame* targetFrame; |
if (targetIsFrame(newTarget.get(), targetFrame)) { |
if (targetFrame) |
- accept = targetFrame->eventHandler().updateDragAndDrop(event, dataTransfer); |
+ eventResult = targetFrame->eventHandler().updateDragAndDrop(event, dataTransfer); |
} else if (newTarget) { |
// As per section 7.9.4 of the HTML 5 spec., we must always fire a drag event before firing a dragenter, dragleave, or dragover event. |
if (dragState().m_dragSrc) { |
// for now we don't care if event handler cancels default behavior, since there is none |
dispatchDragSrcEvent(EventTypeNames::drag, event); |
} |
- accept = dispatchDragEvent(EventTypeNames::dragenter, newTarget.get(), event, dataTransfer); |
- if (!accept) |
- accept = findDropZone(newTarget.get(), dataTransfer); |
+ eventResult = dispatchDragEvent(EventTypeNames::dragenter, newTarget.get(), event, dataTransfer); |
+ if (eventResult == WebInputEventResult::NotHandled && findDropZone(newTarget.get(), dataTransfer)) |
+ eventResult = WebInputEventResult::HandledSystem; |
} |
if (targetIsFrame(m_dragTarget.get(), targetFrame)) { |
if (targetFrame) |
- accept = targetFrame->eventHandler().updateDragAndDrop(event, dataTransfer); |
+ eventResult = targetFrame->eventHandler().updateDragAndDrop(event, dataTransfer); |
} else if (m_dragTarget) { |
dispatchDragEvent(EventTypeNames::dragleave, m_dragTarget.get(), event, dataTransfer); |
} |
@@ -1492,22 +1527,22 @@ bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, DataTransf |
LocalFrame* targetFrame; |
if (targetIsFrame(newTarget.get(), targetFrame)) { |
if (targetFrame) |
- accept = targetFrame->eventHandler().updateDragAndDrop(event, dataTransfer); |
+ eventResult = targetFrame->eventHandler().updateDragAndDrop(event, dataTransfer); |
} else if (newTarget) { |
// Note, when dealing with sub-frames, we may need to fire only a dragover event as a drag event may have been fired earlier. |
if (!m_shouldOnlyFireDragOverEvent && dragState().m_dragSrc) { |
// for now we don't care if event handler cancels default behavior, since there is none |
dispatchDragSrcEvent(EventTypeNames::drag, event); |
} |
- accept = dispatchDragEvent(EventTypeNames::dragover, newTarget.get(), event, dataTransfer); |
- if (!accept) |
- accept = findDropZone(newTarget.get(), dataTransfer); |
+ eventResult = dispatchDragEvent(EventTypeNames::dragover, newTarget.get(), event, dataTransfer); |
+ if (eventResult == WebInputEventResult::NotHandled && findDropZone(newTarget.get(), dataTransfer)) |
+ eventResult = WebInputEventResult::HandledSystem; |
m_shouldOnlyFireDragOverEvent = false; |
} |
} |
m_dragTarget = newTarget; |
- return accept; |
+ return eventResult; |
} |
void EventHandler::cancelDragAndDrop(const PlatformMouseEvent& event, DataTransfer* dataTransfer) |
@@ -1524,18 +1559,18 @@ void EventHandler::cancelDragAndDrop(const PlatformMouseEvent& event, DataTransf |
clearDragState(); |
} |
-bool EventHandler::performDragAndDrop(const PlatformMouseEvent& event, DataTransfer* dataTransfer) |
+WebInputEventResult EventHandler::performDragAndDrop(const PlatformMouseEvent& event, DataTransfer* dataTransfer) |
{ |
LocalFrame* targetFrame; |
- bool preventedDefault = false; |
+ WebInputEventResult result = WebInputEventResult::NotHandled; |
if (targetIsFrame(m_dragTarget.get(), targetFrame)) { |
if (targetFrame) |
- preventedDefault = targetFrame->eventHandler().performDragAndDrop(event, dataTransfer); |
+ result = targetFrame->eventHandler().performDragAndDrop(event, dataTransfer); |
} else if (m_dragTarget.get()) { |
- preventedDefault = dispatchDragEvent(EventTypeNames::drop, m_dragTarget.get(), event, dataTransfer); |
+ result = dispatchDragEvent(EventTypeNames::drop, m_dragTarget.get(), event, dataTransfer); |
} |
clearDragState(); |
- return preventedDefault; |
+ return result; |
} |
void EventHandler::clearDragState() |
@@ -1612,16 +1647,17 @@ void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo |
sendMouseEventsForNodeTransition(lastNodeUnderMouse.get(), m_nodeUnderMouse.get(), mouseEvent); |
} |
-bool EventHandler::dispatchPointerEvent(Node* target, const AtomicString& eventType, |
+WebInputEventResult EventHandler::dispatchPointerEvent(Node* target, const AtomicString& eventType, |
const PlatformMouseEvent& mouseEvent, Node* relatedTarget) |
{ |
if (!RuntimeEnabledFeatures::pointerEventEnabled()) |
- return false; |
+ return WebInputEventResult::NotHandled; |
RefPtrWillBeRawPtr<PointerEvent> pointerEvent = PointerEvent::create(eventType, true, |
mouseEvent, relatedTarget, m_frame->document()->domWindow()); |
- target->dispatchEvent(pointerEvent.get()); |
- return pointerEvent->defaultPrevented() || pointerEvent->defaultHandled(); |
+ |
+ bool dispatchResult = target->dispatchEvent(pointerEvent.get()); |
+ return eventToEventResult(pointerEvent, dispatchResult); |
} |
void EventHandler::sendMouseEventsForNodeTransition(Node* exitedNode, Node* enteredNode, |
@@ -1727,14 +1763,19 @@ void EventHandler::sendMouseEventsForNodeTransition(Node* exitedNode, Node* ente |
} |
} |
-bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, int clickCount, const PlatformMouseEvent& mouseEvent) |
+WebInputEventResult EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, int clickCount, const PlatformMouseEvent& mouseEvent) |
{ |
updateMouseEventTargetNode(targetNode, mouseEvent); |
- return m_nodeUnderMouse && !m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, eventType, clickCount); |
+ if (!m_nodeUnderMouse) |
+ return WebInputEventResult::NotHandled; |
+ |
+ RefPtrWillBeRawPtr<MouseEvent> event = MouseEvent::create(eventType, m_nodeUnderMouse->document().domWindow(), mouseEvent, clickCount, nullptr); |
+ bool dispatchResult = m_nodeUnderMouse->dispatchEvent(event); |
+ return eventToEventResult(event, dispatchResult); |
} |
// TODO(mustaq): Make PE drive ME dispatch & bookkeeping in EventHandler. |
-bool EventHandler::updatePointerTargetAndDispatchEvents(const AtomicString& mouseEventType, Node* targetNode, int clickCount, const PlatformMouseEvent& mouseEvent) |
+WebInputEventResult EventHandler::updatePointerTargetAndDispatchEvents(const AtomicString& mouseEventType, Node* targetNode, int clickCount, const PlatformMouseEvent& mouseEvent) |
{ |
ASSERT(mouseEventType == EventTypeNames::mousedown |
|| mouseEventType == EventTypeNames::mousemove |
@@ -1742,29 +1783,31 @@ bool EventHandler::updatePointerTargetAndDispatchEvents(const AtomicString& mous |
updateMouseEventTargetNode(targetNode, mouseEvent); |
if (!m_nodeUnderMouse) |
- return false; |
+ return WebInputEventResult::NotHandled; |
- bool swallowEvent = dispatchPointerEvent(m_nodeUnderMouse.get(), |
+ WebInputEventResult result = dispatchPointerEvent(m_nodeUnderMouse.get(), |
pointerEventNameForMouseEventName(mouseEventType), |
mouseEvent); |
- if (swallowEvent && mouseEventType == EventTypeNames::mousedown) { |
+ if (result != WebInputEventResult::NotHandled && mouseEventType == EventTypeNames::mousedown) { |
m_preventMouseEventForPointerTypeMouse = true; |
} |
if (!m_preventMouseEventForPointerTypeMouse) { |
- swallowEvent |= !m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, mouseEventType, clickCount); |
+ RefPtrWillBeRawPtr<MouseEvent> event = MouseEvent::create(mouseEventType, m_nodeUnderMouse->document().domWindow(), mouseEvent, clickCount, nullptr); |
+ bool dispatchResult = m_nodeUnderMouse->dispatchEvent(event); |
+ result = mergeEventResult(result, eventToEventResult(event, dispatchResult)); |
} |
- return swallowEvent; |
+ return result; |
} |
-bool EventHandler::handleMouseFocus(const MouseEventWithHitTestResults& targetedEvent, InputDeviceCapabilities* sourceCapabilities) |
+WebInputEventResult EventHandler::handleMouseFocus(const MouseEventWithHitTestResults& targetedEvent, InputDeviceCapabilities* sourceCapabilities) |
{ |
// If clicking on a frame scrollbar, do not mess up with content focus. |
if (targetedEvent.hitTestResult().scrollbar() && m_frame->contentLayoutObject()) { |
if (targetedEvent.hitTestResult().scrollbar()->scrollableArea() == m_frame->contentLayoutObject()->scrollableArea()) |
- return false; |
+ return WebInputEventResult::NotHandled; |
} |
// The layout needs to be up to date to determine if an element is focusable. |
@@ -1775,7 +1818,7 @@ bool EventHandler::handleMouseFocus(const MouseEventWithHitTestResults& targeted |
element = m_nodeUnderMouse->isElementNode() ? toElement(m_nodeUnderMouse) : m_nodeUnderMouse->parentOrShadowHostElement(); |
for (; element; element = element->parentOrShadowHostElement()) { |
if (element->isFocusable() && element->isFocusedElementInDocument()) |
- return false; |
+ return WebInputEventResult::NotHandled; |
if (element->isMouseFocusable()) |
break; |
} |
@@ -1791,14 +1834,14 @@ bool EventHandler::handleMouseFocus(const MouseEventWithHitTestResults& targeted |
// |isNodeFullyContained()|. |
if (createRange(m_frame->selection().selection().toNormalizedEphemeralRange())->isNodeFullyContained(*element) |
&& element->isDescendantOf(m_frame->document()->focusedElement())) |
- return false; |
+ return WebInputEventResult::NotHandled; |
} |
// Only change the focus when clicking scrollbars if it can transfered to a |
// mouse focusable node. |
if (!element && targetedEvent.hitTestResult().scrollbar()) |
- return true; |
+ return WebInputEventResult::HandledSystem; |
if (Page* page = m_frame->page()) { |
// If focus shift is blocked, we eat the event. Note we should never |
@@ -1806,20 +1849,20 @@ bool EventHandler::handleMouseFocus(const MouseEventWithHitTestResults& targeted |
// default behavior). |
if (element) { |
if (slideFocusOnShadowHostIfNecessary(*element)) |
- return true; |
+ return WebInputEventResult::HandledSystem; |
if (!page->focusController().setFocusedElement(element, m_frame, FocusParams(SelectionBehaviorOnFocus::None, WebFocusTypeMouse, sourceCapabilities))) |
- return true; |
+ return WebInputEventResult::HandledSystem; |
} else { |
// We call setFocusedElement even with !element in order to blur |
// current focus element when a link is clicked; this is expected by |
// some sites that rely on onChange handlers running from form |
// fields before the button click is processed. |
if (!page->focusController().setFocusedElement(nullptr, m_frame, FocusParams(SelectionBehaviorOnFocus::None, WebFocusTypeNone, sourceCapabilities))) |
- return true; |
+ return WebInputEventResult::HandledSystem; |
} |
} |
- return false; |
+ return WebInputEventResult::NotHandled; |
} |
bool EventHandler::slideFocusOnShadowHostIfNecessary(const Element& element) |
@@ -1880,24 +1923,18 @@ ScrollResult scrollAreaWithWheelEvent(const PlatformWheelEvent& event, Scrollabl |
} // namespace |
-bool EventHandler::handleWheelEvent(const PlatformWheelEvent& event) |
+WebInputEventResult EventHandler::handleWheelEvent(const PlatformWheelEvent& event) |
{ |
-#define RETURN_WHEEL_EVENT_HANDLED() \ |
- { \ |
- setFrameWasScrolledByUser(); \ |
- return true; \ |
- } |
- |
Document* doc = m_frame->document(); |
if (!doc->layoutView()) |
- return false; |
+ return WebInputEventResult::NotHandled; |
RefPtrWillBeRawPtr<FrameView> protector(m_frame->view()); |
FrameView* view = m_frame->view(); |
if (!view) |
- return false; |
+ return WebInputEventResult::NotHandled; |
LayoutPoint vPoint = view->rootFrameToContents(event.position()); |
@@ -1920,33 +1957,41 @@ bool EventHandler::handleWheelEvent(const PlatformWheelEvent& event) |
LayoutObject* target = node->layoutObject(); |
if (isOverWidget && target && target->isLayoutPart()) { |
- Widget* widget = toLayoutPart(target)->widget(); |
- if (widget && passWheelEventToWidget(event, *widget)) |
- RETURN_WHEEL_EVENT_HANDLED(); |
+ if (Widget* widget = toLayoutPart(target)->widget()) { |
+ WebInputEventResult result = passWheelEventToWidget(event, *widget); |
+ if (result != WebInputEventResult::NotHandled) { |
+ setFrameWasScrolledByUser(); |
+ return result; |
+ } |
+ } |
} |
- if (node && !node->dispatchWheelEvent(event)) |
- RETURN_WHEEL_EVENT_HANDLED(); |
+ RefPtrWillBeRawPtr<Event> domEvent = WheelEvent::create(event, node->document().domWindow()); |
+ if (!node->dispatchEvent(domEvent)) { |
+ setFrameWasScrolledByUser(); |
+ return eventToEventResult(domEvent, false); |
+ } |
} |
// We do another check on the frame view because the event handler can run |
// JS which results in the frame getting destroyed. |
view = m_frame->view(); |
if (!view) |
- return false; |
+ return WebInputEventResult::NotHandled; |
// Wheel events which do not scroll are used to trigger zooming. |
if (!event.canScroll()) |
- return false; |
+ return WebInputEventResult::NotHandled; |
ScrollResult scrollResult = scrollAreaWithWheelEvent(event, *view->scrollableArea()); |
if (m_frame->settings() && m_frame->settings()->reportWheelOverscroll()) |
handleOverscroll(scrollResult); |
- if (scrollResult.didScroll()) |
- RETURN_WHEEL_EVENT_HANDLED(); |
+ if (scrollResult.didScroll()) { |
+ setFrameWasScrolledByUser(); |
+ return WebInputEventResult::HandledSystem; |
+ } |
- return false; |
-#undef RETURN_WHEEL_EVENT_HANDLED |
+ return WebInputEventResult::NotHandled; |
} |
void EventHandler::defaultWheelEventHandler(Node* startNode, WheelEvent* wheelEvent) |
@@ -1977,27 +2022,27 @@ void EventHandler::defaultWheelEventHandler(Node* startNode, WheelEvent* wheelEv |
m_previousWheelScrolledNode = stopNode; |
} |
-bool EventHandler::handleGestureShowPress() |
+WebInputEventResult EventHandler::handleGestureShowPress() |
{ |
m_lastShowPressTimestamp = WTF::monotonicallyIncreasingTime(); |
FrameView* view = m_frame->view(); |
if (!view) |
- return false; |
+ return WebInputEventResult::NotHandled; |
if (ScrollAnimatorBase* scrollAnimator = view->existingScrollAnimator()) |
scrollAnimator->cancelAnimations(); |
const FrameView::ScrollableAreaSet* areas = view->scrollableAreas(); |
if (!areas) |
- return false; |
+ return WebInputEventResult::NotHandled; |
for (const ScrollableArea* scrollableArea : *areas) { |
ScrollAnimatorBase* animator = scrollableArea->existingScrollAnimator(); |
if (animator) |
animator->cancelAnimations(); |
} |
- return false; |
+ return WebInputEventResult::NotHandled; |
} |
-bool EventHandler::handleGestureEvent(const PlatformGestureEvent& gestureEvent) |
+WebInputEventResult EventHandler::handleGestureEvent(const PlatformGestureEvent& gestureEvent) |
{ |
// Propagation to inner frames is handled below this function. |
ASSERT(m_frame == m_frame->localFrameRoot()); |
@@ -2014,7 +2059,7 @@ bool EventHandler::handleGestureEvent(const PlatformGestureEvent& gestureEvent) |
return handleGestureEvent(targetedEvent); |
} |
-bool EventHandler::handleGestureEvent(const GestureEventWithHitTestResults& targetedEvent) |
+WebInputEventResult EventHandler::handleGestureEvent(const GestureEventWithHitTestResults& targetedEvent) |
{ |
TRACE_EVENT0("input", "EventHandler::handleGestureEvent"); |
@@ -2037,7 +2082,7 @@ bool EventHandler::handleGestureEvent(const GestureEventWithHitTestResults& targ |
return handleGestureEventInFrame(targetedEvent); |
} |
-bool EventHandler::handleGestureEventInFrame(const GestureEventWithHitTestResults& targetedEvent) |
+WebInputEventResult EventHandler::handleGestureEventInFrame(const GestureEventWithHitTestResults& targetedEvent) |
{ |
ASSERT(!targetedEvent.event().isScrollEvent()); |
@@ -2050,11 +2095,16 @@ bool EventHandler::handleGestureEventInFrame(const GestureEventWithHitTestResult |
if (gestureEvent.type() == PlatformEvent::GestureTapDown && eventSwallowed) |
m_scrollbarHandlingScrollGesture = scrollbar; |
if (eventSwallowed) |
- return true; |
+ return WebInputEventResult::HandledSuppressed; |
} |
- if (eventTarget && eventTarget->dispatchGestureEvent(gestureEvent)) |
- return true; |
+ if (eventTarget) { |
+ RefPtrWillBeRawPtr<GestureEvent> gestureDomEvent = GestureEvent::create(eventTarget->document().domWindow(), gestureEvent); |
+ // TODO(dtapuska): dispatchEvent is inverted for Gesture Events |
+ // crbug.com/560357 |
+ if (gestureDomEvent.get() && eventTarget->dispatchEvent(gestureDomEvent)) |
+ return eventToEventResult(gestureDomEvent, false); |
+ } |
switch (gestureEvent.type()) { |
case PlatformEvent::GestureTap: |
@@ -2078,10 +2128,10 @@ bool EventHandler::handleGestureEventInFrame(const GestureEventWithHitTestResult |
ASSERT_NOT_REACHED(); |
} |
- return false; |
+ return WebInputEventResult::NotHandled; |
} |
-bool EventHandler::handleGestureScrollEvent(const PlatformGestureEvent& gestureEvent) |
+WebInputEventResult EventHandler::handleGestureScrollEvent(const PlatformGestureEvent& gestureEvent) |
{ |
TRACE_EVENT0("input", "EventHandler::handleGestureScrollEvent"); |
@@ -2095,7 +2145,7 @@ bool EventHandler::handleGestureScrollEvent(const PlatformGestureEvent& gestureE |
if (!eventTarget) { |
Document* document = m_frame->document(); |
if (!document->layoutView()) |
- return false; |
+ return WebInputEventResult::NotHandled; |
FrameView* view = m_frame->view(); |
LayoutPoint viewPoint = view->rootFrameToContents(gestureEvent.position()); |
@@ -2121,15 +2171,18 @@ bool EventHandler::handleGestureScrollEvent(const PlatformGestureEvent& gestureE |
m_scrollbarHandlingScrollGesture = nullptr; |
} |
if (eventSwallowed) |
- return true; |
+ return WebInputEventResult::HandledSuppressed; |
} |
if (eventTarget) { |
- bool eventSwallowed = handleScrollGestureOnResizer(eventTarget.get(), gestureEvent); |
- if (!eventSwallowed) |
- eventSwallowed = eventTarget->dispatchGestureEvent(gestureEvent); |
- if (eventSwallowed) |
- return true; |
+ if (handleScrollGestureOnResizer(eventTarget.get(), gestureEvent)) |
+ return WebInputEventResult::HandledSuppressed; |
+ |
+ RefPtrWillBeRawPtr<GestureEvent> gestureDomEvent = GestureEvent::create(eventTarget->document().domWindow(), gestureEvent); |
+ // TODO(dtapuska): dispatchEvent is inverted for Gesture Events |
+ // crbug.com/560357 |
+ if (gestureDomEvent.get() && eventTarget->dispatchEvent(gestureDomEvent)) |
+ return eventToEventResult(gestureDomEvent, false); |
} |
switch (gestureEvent.type()) { |
@@ -2143,14 +2196,14 @@ bool EventHandler::handleGestureScrollEvent(const PlatformGestureEvent& gestureE |
case PlatformEvent::GesturePinchBegin: |
case PlatformEvent::GesturePinchEnd: |
case PlatformEvent::GesturePinchUpdate: |
- return false; |
+ return WebInputEventResult::NotHandled; |
default: |
ASSERT_NOT_REACHED(); |
- return false; |
+ return WebInputEventResult::NotHandled; |
} |
} |
-bool EventHandler::handleGestureTap(const GestureEventWithHitTestResults& targetedEvent) |
+WebInputEventResult EventHandler::handleGestureTap(const GestureEventWithHitTestResults& targetedEvent) |
{ |
RefPtrWillBeRawPtr<FrameView> frameView(m_frame->view()); |
const PlatformGestureEvent& gestureEvent = targetedEvent.event(); |
@@ -2200,12 +2253,12 @@ bool EventHandler::handleGestureTap(const GestureEventWithHitTestResults& target |
LeftButton, PlatformEvent::MousePressed, gestureEvent.tapCount(), |
static_cast<PlatformEvent::Modifiers>(modifiers | PlatformEvent::LeftButtonDown), |
PlatformMouseEvent::FromTouch, gestureEvent.timestamp()); |
- bool swallowMouseDownEvent = dispatchMouseEvent(EventTypeNames::mousedown, currentHitTest.innerNode(), gestureEvent.tapCount(), fakeMouseDown); |
+ WebInputEventResult mouseDownEventResult = dispatchMouseEvent(EventTypeNames::mousedown, currentHitTest.innerNode(), gestureEvent.tapCount(), fakeMouseDown); |
selectionController().initializeSelectionState(); |
- if (!swallowMouseDownEvent) |
- swallowMouseDownEvent = handleMouseFocus(MouseEventWithHitTestResults(fakeMouseDown, currentHitTest), InputDeviceCapabilities::firesTouchEventsSourceCapabilities()); |
- if (!swallowMouseDownEvent) |
- swallowMouseDownEvent = handleMousePressEvent(MouseEventWithHitTestResults(fakeMouseDown, currentHitTest)); |
+ if (mouseDownEventResult == WebInputEventResult::NotHandled) |
+ mouseDownEventResult = handleMouseFocus(MouseEventWithHitTestResults(fakeMouseDown, currentHitTest), InputDeviceCapabilities::firesTouchEventsSourceCapabilities()); |
+ if (mouseDownEventResult == WebInputEventResult::NotHandled) |
+ mouseDownEventResult = handleMousePressEvent(MouseEventWithHitTestResults(fakeMouseDown, currentHitTest)); |
if (currentHitTest.innerNode()) { |
ASSERT(gestureEvent.type() == PlatformEvent::GestureTap); |
@@ -2226,9 +2279,9 @@ bool EventHandler::handleGestureTap(const GestureEventWithHitTestResults& target |
LeftButton, PlatformEvent::MouseReleased, gestureEvent.tapCount(), |
static_cast<PlatformEvent::Modifiers>(modifiers), |
PlatformMouseEvent::FromTouch, gestureEvent.timestamp()); |
- bool swallowMouseUpEvent = dispatchMouseEvent(EventTypeNames::mouseup, currentHitTest.innerNode(), gestureEvent.tapCount(), fakeMouseUp); |
+ WebInputEventResult mouseUpEventResult = dispatchMouseEvent(EventTypeNames::mouseup, currentHitTest.innerNode(), gestureEvent.tapCount(), fakeMouseUp); |
- bool swallowClickEvent = false; |
+ WebInputEventResult clickEventResult = WebInputEventResult::NotHandled; |
if (m_clickNode) { |
if (currentHitTest.innerNode()) { |
// Updates distribution because a mouseup (or mousedown) event listener can make the |
@@ -2238,26 +2291,26 @@ bool EventHandler::handleGestureTap(const GestureEventWithHitTestResults& target |
// because commonAncestor() will exit early if their documents are different. |
m_clickNode->updateDistribution(); |
Node* clickTargetNode = currentHitTest.innerNode()->commonAncestor(*m_clickNode, parentForClickEvent); |
- swallowClickEvent = dispatchMouseEvent(EventTypeNames::click, clickTargetNode, gestureEvent.tapCount(), fakeMouseUp); |
+ clickEventResult = dispatchMouseEvent(EventTypeNames::click, clickTargetNode, gestureEvent.tapCount(), fakeMouseUp); |
} |
m_clickNode = nullptr; |
} |
- if (!swallowMouseUpEvent) |
- swallowMouseUpEvent = handleMouseReleaseEvent(MouseEventWithHitTestResults(fakeMouseUp, currentHitTest)); |
+ if (mouseUpEventResult == WebInputEventResult::NotHandled) |
+ mouseUpEventResult = handleMouseReleaseEvent(MouseEventWithHitTestResults(fakeMouseUp, currentHitTest)); |
- bool swallowed = swallowMouseDownEvent | swallowMouseUpEvent | swallowClickEvent; |
- if (!swallowed && tappedNode && m_frame->page()) { |
+ WebInputEventResult eventResult = mergeEventResult(mergeEventResult(mouseDownEventResult, mouseUpEventResult), clickEventResult); |
+ if (eventResult == WebInputEventResult::NotHandled && tappedNode && m_frame->page()) { |
bool domTreeChanged = preDispatchDomTreeVersion != m_frame->document()->domTreeVersion(); |
bool styleChanged = preDispatchStyleVersion != m_frame->document()->styleVersion(); |
IntPoint tappedPositionInViewport = m_frame->page()->frameHost().visualViewport().rootFrameToViewport(tappedPosition); |
m_frame->chromeClient().showUnhandledTapUIIfNeeded(tappedPositionInViewport, tappedNode.get(), domTreeChanged || styleChanged); |
} |
- return swallowed; |
+ return eventResult; |
} |
-bool EventHandler::handleGestureLongPress(const GestureEventWithHitTestResults& targetedEvent) |
+WebInputEventResult EventHandler::handleGestureLongPress(const GestureEventWithHitTestResults& targetedEvent) |
{ |
const PlatformGestureEvent& gestureEvent = targetedEvent.event(); |
IntPoint adjustedPoint = gestureEvent.position(); |
@@ -2286,7 +2339,7 @@ bool EventHandler::handleGestureLongPress(const GestureEventWithHitTestResults& |
RefPtrWillBeRawPtr<FrameView> protector(m_frame->view()); |
if (handleDrag(mev, DragInitiator::Touch)) { |
m_longTapShouldInvokeContextMenu = true; |
- return true; |
+ return WebInputEventResult::HandledSystem; |
} |
} |
@@ -2295,13 +2348,13 @@ bool EventHandler::handleGestureLongPress(const GestureEventWithHitTestResults& |
RefPtrWillBeRawPtr<FrameView> protector(m_frame->view()); |
if (selectionController().handleGestureLongPress(gestureEvent, result)) { |
focusDocumentView(); |
- return true; |
+ return WebInputEventResult::HandledSystem; |
} |
return sendContextMenuEventForGesture(targetedEvent); |
} |
-bool EventHandler::handleGestureLongTap(const GestureEventWithHitTestResults& targetedEvent) |
+WebInputEventResult EventHandler::handleGestureLongTap(const GestureEventWithHitTestResults& targetedEvent) |
{ |
#if !OS(ANDROID) |
if (m_longTapShouldInvokeContextMenu) { |
@@ -2309,7 +2362,7 @@ bool EventHandler::handleGestureLongTap(const GestureEventWithHitTestResults& ta |
return sendContextMenuEventForGesture(targetedEvent); |
} |
#endif |
- return false; |
+ return WebInputEventResult::NotHandled; |
} |
bool EventHandler::handleScrollGestureOnResizer(Node* eventTarget, const PlatformGestureEvent& gestureEvent) |
@@ -2339,25 +2392,22 @@ bool EventHandler::handleScrollGestureOnResizer(Node* eventTarget, const Platfor |
return false; |
} |
-bool EventHandler::passScrollGestureEventToWidget(const PlatformGestureEvent& gestureEvent, LayoutObject* layoutObject) |
+WebInputEventResult EventHandler::passScrollGestureEventToWidget(const PlatformGestureEvent& gestureEvent, LayoutObject* layoutObject) |
{ |
ASSERT(gestureEvent.isScrollEvent()); |
- if (!m_lastGestureScrollOverWidget) |
- return false; |
- |
- if (!layoutObject || !layoutObject->isLayoutPart()) |
- return false; |
+ if (!m_lastGestureScrollOverWidget || !layoutObject || !layoutObject->isLayoutPart()) |
+ return WebInputEventResult::NotHandled; |
Widget* widget = toLayoutPart(layoutObject)->widget(); |
if (!widget || !widget->isFrameView()) |
- return false; |
+ return WebInputEventResult::NotHandled; |
return toFrameView(widget)->frame().eventHandler().handleGestureScrollEvent(gestureEvent); |
} |
-bool EventHandler::handleGestureScrollEnd(const PlatformGestureEvent& gestureEvent) |
+WebInputEventResult EventHandler::handleGestureScrollEnd(const PlatformGestureEvent& gestureEvent) |
{ |
RefPtrWillBeRawPtr<Node> node = m_scrollGestureHandlingNode; |
@@ -2372,18 +2422,18 @@ bool EventHandler::handleGestureScrollEnd(const PlatformGestureEvent& gestureEve |
} |
clearGestureScrollState(); |
- return false; |
+ return WebInputEventResult::NotHandled; |
} |
-bool EventHandler::handleGestureScrollBegin(const PlatformGestureEvent& gestureEvent) |
+WebInputEventResult EventHandler::handleGestureScrollBegin(const PlatformGestureEvent& gestureEvent) |
{ |
Document* document = m_frame->document(); |
if (!document->layoutView()) |
- return false; |
+ return WebInputEventResult::NotHandled; |
FrameView* view = m_frame->view(); |
if (!view) |
- return false; |
+ return WebInputEventResult::NotHandled; |
// If there's no layoutObject on the node, send the event to the nearest ancestor with a layoutObject. |
// Needed for <option> and <optgroup> elements so we can touch scroll <select>s |
@@ -2394,7 +2444,7 @@ bool EventHandler::handleGestureScrollBegin(const PlatformGestureEvent& gestureE |
if (RuntimeEnabledFeatures::scrollCustomizationEnabled()) |
m_scrollGestureHandlingNode = m_frame->document()->documentElement(); |
else |
- return false; |
+ return WebInputEventResult::NotHandled; |
} |
ASSERT(m_scrollGestureHandlingNode); |
@@ -2409,7 +2459,7 @@ bool EventHandler::handleGestureScrollBegin(const PlatformGestureEvent& gestureE |
if (m_frame->isMainFrame()) |
m_frame->host()->topControls().scrollBegin(); |
} |
- return true; |
+ return WebInputEventResult::HandledSystem; |
} |
void EventHandler::resetOverscroll(bool didScrollX, bool didScrollY) |
@@ -2441,26 +2491,27 @@ void EventHandler::handleOverscroll(const ScrollResult& scrollResult, const Floa |
} |
} |
-bool EventHandler::handleGestureScrollUpdate(const PlatformGestureEvent& gestureEvent) |
+WebInputEventResult EventHandler::handleGestureScrollUpdate(const PlatformGestureEvent& gestureEvent) |
{ |
ASSERT(gestureEvent.type() == PlatformEvent::GestureScrollUpdate); |
FloatSize delta(gestureEvent.deltaX(), gestureEvent.deltaY()); |
if (delta.isZero()) |
- return false; |
+ return WebInputEventResult::NotHandled; |
Node* node = m_scrollGestureHandlingNode.get(); |
if (node) { |
LayoutObject* layoutObject = node->layoutObject(); |
if (!layoutObject) |
- return false; |
+ return WebInputEventResult::NotHandled; |
RefPtrWillBeRawPtr<FrameView> protector(m_frame->view()); |
Node* stopNode = nullptr; |
// Try to send the event to the correct view. |
- if (passScrollGestureEventToWidget(gestureEvent, layoutObject)) { |
+ WebInputEventResult result = passScrollGestureEventToWidget(gestureEvent, layoutObject); |
+ if (result != WebInputEventResult::NotHandled) { |
if (gestureEvent.preventPropagation() |
&& !RuntimeEnabledFeatures::scrollCustomizationEnabled()) { |
// This is an optimization which doesn't apply with |
@@ -2470,7 +2521,7 @@ bool EventHandler::handleGestureScrollUpdate(const PlatformGestureEvent& gesture |
// FIXME: we should allow simultaneous scrolling of nested |
// iframes along perpendicular axes. See crbug.com/466991. |
m_deltaConsumedForScrollSequence = true; |
- return true; |
+ return result; |
} |
bool scrolled = false; |
@@ -2515,12 +2566,12 @@ bool EventHandler::handleGestureScrollUpdate(const PlatformGestureEvent& gesture |
} |
if (scrolled) { |
setFrameWasScrolledByUser(); |
- return true; |
+ return WebInputEventResult::HandledSystem; |
} |
} |
if (RuntimeEnabledFeatures::scrollCustomizationEnabled()) |
- return false; |
+ return WebInputEventResult::NotHandled; |
// Try to scroll the frame view. |
ScrollResult scrollResult = m_frame->applyScrollDelta(delta, false); |
@@ -2529,10 +2580,10 @@ bool EventHandler::handleGestureScrollUpdate(const PlatformGestureEvent& gesture |
handleOverscroll(scrollResult, position, velocity); |
if (scrollResult.didScroll()) { |
setFrameWasScrolledByUser(); |
- return true; |
+ return WebInputEventResult::HandledSystem; |
} |
- return false; |
+ return WebInputEventResult::NotHandled; |
} |
void EventHandler::clearGestureScrollState() |
@@ -2870,11 +2921,11 @@ void EventHandler::applyTouchAdjustment(PlatformGestureEvent* gestureEvent, HitT |
} |
} |
-bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event, Node* overrideTargetNode) |
+WebInputEventResult EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event, Node* overrideTargetNode) |
{ |
FrameView* v = m_frame->view(); |
if (!v) |
- return false; |
+ return WebInputEventResult::NotHandled; |
// Clear mouse press state to avoid initiating a drag while context menu is up. |
m_mousePressed = false; |
@@ -2888,15 +2939,15 @@ bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event, Node* o |
return dispatchMouseEvent(EventTypeNames::contextmenu, targetNode, 0, event); |
} |
-bool EventHandler::sendContextMenuEventForKey(Element* overrideTargetElement) |
+WebInputEventResult EventHandler::sendContextMenuEventForKey(Element* overrideTargetElement) |
{ |
FrameView* view = m_frame->view(); |
if (!view) |
- return false; |
+ return WebInputEventResult::NotHandled; |
Document* doc = m_frame->document(); |
if (!doc) |
- return false; |
+ return WebInputEventResult::NotHandled; |
// Clear mouse press state to avoid initiating a drag while context menu is up. |
m_mousePressed = false; |
@@ -2960,7 +3011,7 @@ bool EventHandler::sendContextMenuEventForKey(Element* overrideTargetElement) |
return sendContextMenuEvent(mouseEvent, overrideTargetElement); |
} |
-bool EventHandler::sendContextMenuEventForGesture(const GestureEventWithHitTestResults& targetedEvent) |
+WebInputEventResult EventHandler::sendContextMenuEventForGesture(const GestureEventWithHitTestResults& targetedEvent) |
{ |
const PlatformGestureEvent& gestureEvent = targetedEvent.event(); |
unsigned modifiers = gestureEvent.modifiers(); |
@@ -3148,7 +3199,7 @@ bool EventHandler::handleAccessKey(const PlatformKeyboardEvent& evt) |
return true; |
} |
-bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent) |
+WebInputEventResult EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent) |
{ |
RefPtrWillBeRawPtr<FrameView> protector(m_frame->view()); |
m_frame->chromeClient().setToolTip(String(), LTR); |
@@ -3163,7 +3214,7 @@ bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent) |
stopAutoscroll(); |
// If we were in panscroll mode, we swallow the key event |
- return true; |
+ return WebInputEventResult::HandledSuppressed; |
} |
#endif |
@@ -3171,7 +3222,7 @@ bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent) |
// from pressing return in the location bar. |
RefPtrWillBeRawPtr<Node> node = eventTargetNodeForDocument(m_frame->document()); |
if (!node) |
- return false; |
+ return WebInputEventResult::NotHandled; |
UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture); |
@@ -3185,8 +3236,12 @@ bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent) |
matchedAnAccessKey = handleAccessKey(initialKeyEvent); |
// FIXME: it would be fair to let an input method handle KeyUp events before DOM dispatch. |
- if (initialKeyEvent.type() == PlatformEvent::KeyUp || initialKeyEvent.type() == PlatformEvent::Char) |
- return !node->dispatchKeyEvent(initialKeyEvent); |
+ if (initialKeyEvent.type() == PlatformEvent::KeyUp || initialKeyEvent.type() == PlatformEvent::Char) { |
+ RefPtrWillBeRawPtr<KeyboardEvent> domEvent = KeyboardEvent::create(initialKeyEvent, m_frame->document()->domWindow()); |
+ |
+ bool dispatchResult = node->dispatchEvent(domEvent); |
+ return eventToEventResult(domEvent, dispatchResult); |
+ } |
PlatformKeyboardEvent keyDownEvent = initialKeyEvent; |
if (keyDownEvent.type() != PlatformEvent::RawKeyDown) |
@@ -3197,36 +3252,36 @@ bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent) |
keydown->setTarget(node); |
if (initialKeyEvent.type() == PlatformEvent::RawKeyDown) { |
- node->dispatchEvent(keydown); |
+ if (!node->dispatchEvent(keydown)) |
+ return eventToEventResult(keydown, false); |
// If frame changed as a result of keydown dispatch, then return true to avoid sending a subsequent keypress message to the new frame. |
bool changedFocusedFrame = m_frame->page() && m_frame != m_frame->page()->focusController().focusedOrMainFrame(); |
- return keydown->defaultHandled() || keydown->defaultPrevented() || changedFocusedFrame; |
+ if (changedFocusedFrame) |
+ return WebInputEventResult::HandledSystem; |
+ return WebInputEventResult::NotHandled; |
} |
- node->dispatchEvent(keydown); |
+ if (!node->dispatchEvent(keydown)) |
+ return eventToEventResult(keydown, false); |
// If frame changed as a result of keydown dispatch, then return early to avoid sending a subsequent keypress message to the new frame. |
bool changedFocusedFrame = m_frame->page() && m_frame != m_frame->page()->focusController().focusedOrMainFrame(); |
- bool keydownResult = keydown->defaultHandled() || keydown->defaultPrevented() || changedFocusedFrame; |
- if (keydownResult) |
- return keydownResult; |
+ if (changedFocusedFrame) |
+ return WebInputEventResult::HandledSystem; |
// Focus may have changed during keydown handling, so refetch node. |
// But if we are dispatching a fake backward compatibility keypress, then we pretend that the keypress happened on the original node. |
node = eventTargetNodeForDocument(m_frame->document()); |
if (!node) |
- return false; |
+ return WebInputEventResult::NotHandled; |
PlatformKeyboardEvent keyPressEvent = initialKeyEvent; |
keyPressEvent.disambiguateKeyDownEvent(PlatformEvent::Char); |
if (keyPressEvent.text().isEmpty()) |
- return keydownResult; |
+ return WebInputEventResult::NotHandled; |
RefPtrWillBeRawPtr<KeyboardEvent> keypress = KeyboardEvent::create(keyPressEvent, m_frame->document()->domWindow()); |
keypress->setTarget(node); |
- if (keydownResult) |
- keypress->setDefaultPrevented(true); |
- node->dispatchEvent(keypress); |
- |
- return keydownResult || keypress->defaultPrevented() || keypress->defaultHandled(); |
+ bool dispatchResult = node->dispatchEvent(keypress); |
+ return eventToEventResult(keypress, dispatchResult); |
} |
static WebFocusType focusDirectionForKey(const AtomicString& keyIdentifier) |
@@ -3344,7 +3399,7 @@ void EventHandler::updateDragStateAfterEditDragIfNeeded(Element* rootEditableEle |
} |
// returns if we should continue "default processing", i.e., whether eventhandler canceled |
-bool EventHandler::dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent& event) |
+WebInputEventResult EventHandler::dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent& event) |
{ |
return dispatchDragEvent(eventType, dragState().m_dragSrc.get(), event, dragState().m_dragDataTransfer.get()); |
} |
@@ -3433,7 +3488,7 @@ bool EventHandler::tryStartDrag(const MouseEventWithHitTestResults& event) |
// reset. Hence, need to check if this particular drag operation can |
// continue even if dispatchEvent() indicates no (direct) cancellation. |
// Do that by checking if m_dragSrc is still set. |
- m_mouseDownMayStartDrag = !dispatchDragSrcEvent(EventTypeNames::dragstart, m_mouseDown) |
+ m_mouseDownMayStartDrag = dispatchDragSrcEvent(EventTypeNames::dragstart, m_mouseDown) == WebInputEventResult::NotHandled |
&& !m_frame->selection().isInPasswordField() && dragState().m_dragSrc; |
// Invalidate clipboard here against anymore pasteboard writing for security. The drag |
@@ -3734,7 +3789,7 @@ public: |
} // namespace |
-bool EventHandler::dispatchTouchEvents(const PlatformTouchEvent& event, |
+WebInputEventResult EventHandler::dispatchTouchEvents(const PlatformTouchEvent& event, |
WillBeHeapVector<TouchInfo>& touchInfos, bool freshTouchEvents, bool allTouchReleased) |
{ |
// Build up the lists to use for the 'touches', 'targetTouches' and |
@@ -3806,7 +3861,7 @@ bool EventHandler::dispatchTouchEvents(const PlatformTouchEvent& event, |
m_touchSequenceUserGestureToken.clear(); |
} |
- bool swallowedEvent = false; |
+ WebInputEventResult eventResult = WebInputEventResult::NotHandled; |
// Now iterate through the changedTouches list and m_targets within it, sending |
// TouchEvents to the targets as required. |
@@ -3822,15 +3877,15 @@ bool EventHandler::dispatchTouchEvents(const PlatformTouchEvent& event, |
eventName, touchEventTarget->toNode()->document().domWindow(), |
event.modifiers(), event.cancelable(), event.causesScrollingIfUncanceled(), event.timestamp()); |
- touchEventTarget->dispatchEvent(touchEvent.get()); |
- swallowedEvent = swallowedEvent || touchEvent->defaultPrevented() || touchEvent->defaultHandled(); |
+ bool dispatchResult = touchEventTarget->dispatchEvent(touchEvent.get()); |
+ eventResult = mergeEventResult(eventResult, eventToEventResult(touchEvent, dispatchResult)); |
} |
} |
- return swallowedEvent; |
+ return eventResult; |
} |
-bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) |
+WebInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEvent& event) |
{ |
TRACE_EVENT0("blink", "EventHandler::handleTouchEvent"); |
@@ -3869,7 +3924,7 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) |
if (m_touchSequenceDocument && (!m_touchSequenceDocument->frame() || !m_touchSequenceDocument->frame()->view())) { |
// If the active touch document has no frame or view, it's probably being destroyed |
// so we can't dispatch events. |
- return false; |
+ return WebInputEventResult::NotHandled; |
} |
// First do hit tests for any new touch points. |
@@ -3932,7 +3987,7 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) |
m_touchSequenceDocument.clear(); |
m_touchSequenceUserGestureToken.clear(); |
} |
- return false; |
+ return WebInputEventResult::NotHandled; |
} |
// Compute and store the common info used by both PointerEvent and TouchEvent. |
@@ -4011,13 +4066,13 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) |
// scrolling starts because the scrolling would suppress upcoming PEs. This sudden "break" in TE |
// suppression can make the visible TEs inconsistent (e.g. touchmove without a touchstart). |
- bool swallowedTouchEvent = dispatchTouchEvents(event, touchInfos, freshTouchEvents, |
+ WebInputEventResult eventResult = dispatchTouchEvents(event, touchInfos, freshTouchEvents, |
allTouchReleased); |
if (!m_inPointerCanceledState) { |
// Check if we need to stop firing pointer events because of a touch action. |
// See: www.w3.org/TR/pointerevents/#declaring-candidate-regions-for-default-touch-behaviors |
- if (event.causesScrollingIfUncanceled() && !swallowedTouchEvent) { |
+ if (event.causesScrollingIfUncanceled() && eventResult == WebInputEventResult::NotHandled) { |
m_inPointerCanceledState = true; |
sendPointerCancels(touchInfos); |
} |
@@ -4025,7 +4080,7 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) |
m_inPointerCanceledState = false; |
} |
- return swallowedTouchEvent; |
+ return eventResult; |
} |
void EventHandler::setLastKnownMousePosition(const PlatformMouseEvent& event) |
@@ -4041,33 +4096,39 @@ void EventHandler::conditionallyEnableMouseEventForPointerTypeMouse(const Platfo |
m_preventMouseEventForPointerTypeMouse = false; |
} |
-bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, LocalFrame* subframe) |
+WebInputEventResult EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, LocalFrame* subframe) |
{ |
selectionController().passMousePressEventToSubframe(mev); |
- subframe->eventHandler().handleMousePressEvent(mev.event()); |
- return true; |
+ WebInputEventResult result = subframe->eventHandler().handleMousePressEvent(mev.event()); |
+ if (result != WebInputEventResult::NotHandled) |
+ return result; |
+ return WebInputEventResult::HandledSystem; |
} |
-bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& mev, LocalFrame* subframe, HitTestResult* hoveredNode) |
+WebInputEventResult EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& mev, LocalFrame* subframe, HitTestResult* hoveredNode) |
{ |
if (m_mouseDownMayStartDrag) |
- return false; |
- subframe->eventHandler().handleMouseMoveOrLeaveEvent(mev.event(), hoveredNode); |
- return true; |
+ return WebInputEventResult::NotHandled; |
+ WebInputEventResult result = subframe->eventHandler().handleMouseMoveOrLeaveEvent(mev.event(), hoveredNode); |
+ if (result != WebInputEventResult::NotHandled) |
+ return result; |
+ return WebInputEventResult::HandledSystem; |
} |
-bool EventHandler::passMouseReleaseEventToSubframe(MouseEventWithHitTestResults& mev, LocalFrame* subframe) |
+WebInputEventResult EventHandler::passMouseReleaseEventToSubframe(MouseEventWithHitTestResults& mev, LocalFrame* subframe) |
{ |
- subframe->eventHandler().handleMouseReleaseEvent(mev.event()); |
- return true; |
+ WebInputEventResult result = subframe->eventHandler().handleMouseReleaseEvent(mev.event()); |
+ if (result != WebInputEventResult::NotHandled) |
+ return result; |
+ return WebInputEventResult::HandledSystem; |
} |
-bool EventHandler::passWheelEventToWidget(const PlatformWheelEvent& wheelEvent, Widget& widget) |
+WebInputEventResult EventHandler::passWheelEventToWidget(const PlatformWheelEvent& wheelEvent, Widget& widget) |
{ |
// If not a FrameView, then probably a plugin widget. Those will receive |
// the event via an EventTargetNode dispatch when this returns false. |
if (!widget.isFrameView()) |
- return false; |
+ return WebInputEventResult::NotHandled; |
return toFrameView(&widget)->frame().eventHandler().handleWheelEvent(wheelEvent); |
} |