Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(497)

Unified Diff: third_party/WebKit/Source/core/input/EventHandler.cpp

Issue 2350433002: Extract more of the mouse logic from EventHandler (Closed)
Patch Set: Yet another rebase because of a presubmit rule bug Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 2e2be2433344603ac8b1104442e0e56189eded89..f32b2e5c1447fe18039179e4804d493656f8d1c6 100644
--- a/third_party/WebKit/Source/core/input/EventHandler.cpp
+++ b/third_party/WebKit/Source/core/input/EventHandler.cpp
@@ -30,7 +30,6 @@
#include "bindings/core/v8/ExceptionStatePlaceholder.h"
#include "core/HTMLNames.h"
#include "core/InputTypeNames.h"
-#include "core/clipboard/DataObject.h"
#include "core/clipboard/DataTransfer.h"
#include "core/dom/DOMNodeIds.h"
#include "core/dom/Document.h"
@@ -41,7 +40,6 @@
#include "core/editing/Editor.h"
#include "core/editing/FrameSelection.h"
#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"
@@ -77,7 +75,6 @@
#include "core/loader/FrameLoaderClient.h"
#include "core/page/AutoscrollController.h"
#include "core/page/ChromeClient.h"
-#include "core/page/DragController.h"
#include "core/page/DragState.h"
#include "core/page/FocusController.h"
#include "core/page/FrameTree.h"
@@ -126,18 +123,6 @@ bool shouldRefetchEventTarget(const MouseEventWithHitTestResults& mev) {
using namespace HTMLNames;
-// The link drag hysteresis is much larger than the others because there
-// needs to be enough space to cancel the link press without starting a link drag,
-// and because dragging links is rare.
-static const int LinkDragHysteresis = 40;
-static const int ImageDragHysteresis = 5;
-static const int TextDragHysteresis = 3;
-static const int GeneralDragHysteresis = 3;
-
-// The amount of time to wait before sending a fake mouse event triggered
-// during a scroll.
-static const double fakeMouseMoveInterval = 0.1;
-
// The amount of time to wait for a cursor update on style and layout changes
// Set to 50Hz, no need to be faster than common screen refresh rate
static const double cursorUpdateInterval = 0.02;
@@ -153,16 +138,8 @@ static const double minimumCursorScale = 0.001;
// This is roughly 9 frames, which should be long enough to be noticeable.
static const double minimumActiveInterval = 0.15;
-#if OS(MACOSX)
-static const double TextDragDelay = 0.15;
-#else
-static const double TextDragDelay = 0.0;
-#endif
-
enum NoCursorChangeType { NoCursorChange };
-enum class DragInitiator { Mouse, Touch };
-
class OptionalCursor {
public:
OptionalCursor(NoCursorChangeType) : m_isCursorChange(false) {}
@@ -182,45 +159,29 @@ class OptionalCursor {
EventHandler::EventHandler(LocalFrame* frame)
: m_frame(frame),
- m_mousePressed(false),
- m_capturesDragging(false),
- m_mouseDownMayStartDrag(false),
m_selectionController(SelectionController::create(*frame)),
m_hoverTimer(this, &EventHandler::hoverTimerFired),
m_cursorUpdateTimer(this, &EventHandler::cursorUpdateTimerFired),
- m_mouseDownMayStartAutoscroll(false),
- m_fakeMouseMoveEventTimer(this,
- &EventHandler::fakeMouseMoveEventTimerFired),
- m_svgPan(false),
m_eventHandlerWillResetCapturingMouseEventsNode(0),
- m_clickCount(0),
m_shouldOnlyFireDragOverEvent(false),
- m_mousePositionIsUnknown(true),
- m_mouseDownTimestamp(0),
m_scrollManager(new ScrollManager(frame)),
- m_mouseEventManager(new MouseEventManager(frame)),
+ m_mouseEventManager(new MouseEventManager(frame, m_scrollManager)),
m_keyboardEventManager(new KeyboardEventManager(frame, m_scrollManager)),
m_pointerEventManager(
new PointerEventManager(frame, m_mouseEventManager)),
m_gestureManager(new GestureManager(frame,
m_scrollManager,
+ m_mouseEventManager,
m_pointerEventManager,
m_selectionController)),
m_activeIntervalTimer(this, &EventHandler::activeIntervalTimerFired) {}
-EventHandler::~EventHandler() {
- ASSERT(!m_fakeMouseMoveEventTimer.isActive());
-}
-
DEFINE_TRACE(EventHandler) {
visitor->trace(m_frame);
- visitor->trace(m_mousePressNode);
visitor->trace(m_selectionController);
visitor->trace(m_capturingMouseEventsNode);
- visitor->trace(m_nodeUnderMouse);
visitor->trace(m_lastMouseMoveEventSubframe);
visitor->trace(m_lastScrollbarUnderMouse);
- visitor->trace(m_clickNode);
visitor->trace(m_dragTarget);
visitor->trace(m_frameSetBeingResized);
visitor->trace(m_scrollManager);
@@ -231,198 +192,31 @@ DEFINE_TRACE(EventHandler) {
visitor->trace(m_lastDeferredTapElement);
}
-DragState& EventHandler::dragState() {
- DEFINE_STATIC_LOCAL(DragState, state, (new DragState));
- return state;
-}
-
void EventHandler::clear() {
m_hoverTimer.stop();
m_cursorUpdateTimer.stop();
- m_fakeMouseMoveEventTimer.stop();
m_activeIntervalTimer.stop();
- m_nodeUnderMouse = nullptr;
m_lastMouseMoveEventSubframe = nullptr;
m_lastScrollbarUnderMouse = nullptr;
- m_clickCount = 0;
- m_clickNode = nullptr;
m_frameSetBeingResized = nullptr;
m_dragTarget = nullptr;
m_shouldOnlyFireDragOverEvent = false;
- m_mousePositionIsUnknown = true;
- m_lastKnownMousePosition = IntPoint();
- m_lastKnownMouseGlobalPosition = IntPoint();
m_lastMouseDownUserGestureToken.clear();
- m_mousePressNode = nullptr;
- m_mousePressed = false;
- m_capturesDragging = false;
m_capturingMouseEventsNode = nullptr;
m_pointerEventManager->clear();
m_scrollManager->clear();
m_gestureManager->clear();
m_mouseEventManager->clear();
- m_mouseDownMayStartDrag = false;
m_lastDeferredTapElement = nullptr;
m_eventHandlerWillResetCapturingMouseEventsNode = false;
- m_mouseDownMayStartAutoscroll = false;
- m_svgPan = false;
- m_mouseDownPos = IntPoint();
- m_mouseDownTimestamp = 0;
- m_dragStartPos = LayoutPoint();
- m_mouseDown = PlatformMouseEvent();
}
void EventHandler::nodeWillBeRemoved(Node& nodeToBeRemoved) {
- if (nodeToBeRemoved.isShadowIncludingInclusiveAncestorOf(m_clickNode.get())) {
- // We don't dispatch click events if the mousedown node is removed
- // before a mouseup event. It is compatible with IE and Firefox.
- m_clickNode = nullptr;
- }
-}
-
-WebInputEventResult EventHandler::handleMousePressEvent(
- const MouseEventWithHitTestResults& event) {
- TRACE_EVENT0("blink", "EventHandler::handleMousePressEvent");
-
- // Reset drag state.
- dragState().m_dragSrc = nullptr;
-
- cancelFakeMouseMoveEvent();
-
- m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets();
-
- if (FrameView* frameView = m_frame->view()) {
- if (frameView->isPointInScrollbarCorner(event.event().position()))
- return WebInputEventResult::NotHandled;
- }
-
- bool singleClick = event.event().clickCount() <= 1;
-
- m_mouseDownMayStartDrag =
- singleClick && !isLinkSelection(event) && !isExtendingSelection(event);
-
- selectionController().handleMousePressEvent(event);
-
- m_mouseDown = event.event();
-
- if (m_frame->document()->isSVGDocument() &&
- m_frame->document()->accessSVGExtensions().zoomAndPanEnabled()) {
- if (event.event().shiftKey() && singleClick) {
- m_svgPan = true;
- m_frame->document()->accessSVGExtensions().startPan(
- m_frame->view()->rootFrameToContents(event.event().position()));
- return WebInputEventResult::HandledSystem;
- }
- }
-
- // We don't do this at the start of mouse down handling,
- // because we don't want to do it until we know we didn't hit a widget.
- if (singleClick)
- focusDocumentView();
-
- Node* innerNode = event.innerNode();
-
- m_mousePressNode = innerNode;
- m_frame->document()->setSequentialFocusNavigationStartingPoint(innerNode);
- m_dragStartPos = event.event().position();
-
- bool swallowEvent = false;
- m_mousePressed = true;
-
- if (event.event().clickCount() == 2)
- swallowEvent =
- selectionController().handleMousePressEventDoubleClick(event);
- else if (event.event().clickCount() >= 3)
- swallowEvent =
- selectionController().handleMousePressEventTripleClick(event);
- else
- swallowEvent =
- selectionController().handleMousePressEventSingleClick(event);
-
- m_mouseDownMayStartAutoscroll =
- selectionController().mouseDownMayStartSelect() ||
- (m_mousePressNode && m_mousePressNode->layoutBox() &&
- m_mousePressNode->layoutBox()->canBeProgramaticallyScrolled());
-
- return swallowEvent ? WebInputEventResult::HandledSystem
- : WebInputEventResult::NotHandled;
-}
-
-WebInputEventResult EventHandler::handleMouseDraggedEvent(
- const MouseEventWithHitTestResults& event) {
- TRACE_EVENT0("blink", "EventHandler::handleMouseDraggedEvent");
-
- // While resetting m_mousePressed here may seem out of place, it turns out
- // to be needed to handle some bugs^Wfeatures in Blink mouse event handling:
- // 1. Certain elements, such as <embed>, capture mouse events. They do not
- // bubble back up. One way for a <embed> to start capturing mouse events
- // is on a mouse press. The problem is the <embed> node only starts
- // capturing mouse events *after* m_mousePressed for the containing frame
- // has already been set to true. As a result, the frame's EventHandler
- // never sees the mouse release event, which is supposed to reset
- // m_mousePressed... so m_mousePressed ends up remaining true until the
- // event handler finally gets another mouse released event. Oops.
- // 2. Dragging doesn't start until after a mouse press event, but a drag
- // that ends as a result of a mouse release does not send a mouse release
- // event. As a result, m_mousePressed also ends up remaining true until
- // the next mouse release event seen by the EventHandler.
- if (event.event().pointerProperties().button !=
- WebPointerProperties::Button::Left)
- m_mousePressed = false;
-
- if (!m_mousePressed)
- return WebInputEventResult::NotHandled;
-
- if (handleDrag(event, DragInitiator::Mouse))
- return WebInputEventResult::HandledSystem;
-
- Node* targetNode = event.innerNode();
- if (!targetNode)
- return WebInputEventResult::NotHandled;
-
- LayoutObject* layoutObject = targetNode->layoutObject();
- if (!layoutObject) {
- Node* parent = FlatTreeTraversal::parent(*targetNode);
- if (!parent)
- return WebInputEventResult::NotHandled;
-
- layoutObject = parent->layoutObject();
- if (!layoutObject || !layoutObject->isListBox())
- return WebInputEventResult::NotHandled;
- }
-
- m_mouseDownMayStartDrag = false;
-
- if (m_mouseDownMayStartAutoscroll &&
- !m_scrollManager->middleClickAutoscrollInProgress()) {
- if (AutoscrollController* controller =
- m_scrollManager->autoscrollController()) {
- controller->startAutoscrollForSelection(layoutObject);
- m_mouseDownMayStartAutoscroll = false;
- }
- }
-
- selectionController().handleMouseDraggedEvent(
- event, m_mouseDownPos, m_dragStartPos, m_mousePressNode.get(),
- m_lastKnownMousePosition);
- return WebInputEventResult::HandledSystem;
+ m_mouseEventManager->nodeWillBeRemoved(nodeToBeRemoved);
}
void EventHandler::updateSelectionForMouseDrag() {
- selectionController().updateSelectionForMouseDrag(
- m_mousePressNode.get(), m_dragStartPos, m_lastKnownMousePosition);
-}
-
-// TODO(nzolghadr): Refactor the mouse related functions to MouseEventManager.
-WebInputEventResult EventHandler::handleMouseReleaseEvent(
- const MouseEventWithHitTestResults& event) {
- AutoscrollController* controller = m_scrollManager->autoscrollController();
- if (controller && controller->autoscrollInProgress())
- m_scrollManager->stopAutoscroll();
-
- return selectionController().handleMouseReleaseEvent(event, m_dragStartPos)
- ? WebInputEventResult::HandledSystem
- : WebInputEventResult::NotHandled;
+ m_mouseEventManager->updateSelectionForMouseDrag();
}
void EventHandler::startMiddleClickAutoscroll(LayoutObject* layoutObject) {
@@ -432,9 +226,9 @@ void EventHandler::startMiddleClickAutoscroll(LayoutObject* layoutObject) {
AutoscrollController* controller = m_scrollManager->autoscrollController();
if (!controller)
return;
- controller->startMiddleClickAutoscroll(toLayoutBox(layoutObject),
- lastKnownMousePosition());
- invalidateClick();
+ controller->startMiddleClickAutoscroll(
+ toLayoutBox(layoutObject), m_mouseEventManager->lastKnownMousePosition());
+ m_mouseEventManager->invalidateClick();
}
HitTestResult EventHandler::hitTestResultAtPoint(
@@ -473,7 +267,7 @@ HitTestResult EventHandler::hitTestResultAtPoint(
// have intentionally clicked on something belonging to this page. Furthermore,
// mousemove events before the first layout should not lead to a premature layout()
// happening, which could show a flash of white.
- // See also the similar code in Document::prepareMouseEvent.
+ // See also the similar code in Document::performMouseEventHitTest.
if (m_frame->contentLayoutItem().isNull() || !m_frame->view() ||
!m_frame->view()->didFirstLayout())
return result;
@@ -495,16 +289,16 @@ bool EventHandler::bubblingScroll(ScrollDirection direction,
ScrollGranularity granularity,
Node* startingNode) {
return m_scrollManager->bubblingScroll(direction, granularity, startingNode,
- m_mousePressNode);
+ m_mouseEventManager->mousePressNode());
}
IntPoint EventHandler::lastKnownMousePosition() const {
- return m_lastKnownMousePosition;
+ return m_mouseEventManager->lastKnownMousePosition();
}
IntPoint EventHandler::dragDataTransferLocationForTesting() {
- if (dragState().m_dragDataTransfer)
- return dragState().m_dragDataTransfer->dragLocation();
+ if (m_mouseEventManager->dragState().m_dragDataTransfer)
+ return m_mouseEventManager->dragState().m_dragDataTransfer->dragLocation();
return IntPoint();
}
@@ -557,7 +351,7 @@ void EventHandler::updateCursor() {
// update could be occluded by a different frame.
ASSERT(m_frame == m_frame->localFrameRoot());
- if (m_mousePositionIsUnknown)
+ if (m_mouseEventManager->isMousePositionUnknown())
return;
FrameView* view = m_frame->view();
@@ -572,8 +366,9 @@ void EventHandler::updateCursor() {
HitTestRequest request(HitTestRequest::ReadOnly |
HitTestRequest::AllowChildFrameContent);
- HitTestResult result(request,
- view->rootFrameToContents(m_lastKnownMousePosition));
+ HitTestResult result(
+ request,
+ view->rootFrameToContents(m_mouseEventManager->lastKnownMousePosition()));
layoutViewItem.hitTest(result);
if (LocalFrame* frame = result.innerNodeFrame()) {
@@ -747,9 +542,10 @@ OptionalCursor EventHandler::selectAutoCursor(const HitTestResult& result,
// During selection, use an I-beam no matter what we're over.
// If a drag may be starting or we're capturing mouse events for a particular node, don't treat this as a selection.
- if (m_mousePressed && selectionController().mouseDownMayStartSelect() &&
- !m_mouseDownMayStartDrag && !m_frame->selection().isNone() &&
- !m_capturingMouseEventsNode) {
+ if (m_mouseEventManager->mousePressed() &&
+ selectionController().mouseDownMayStartSelect() &&
+ !m_mouseEventManager->mouseDownMayStartDrag() &&
+ !m_frame->selection().isNone() && !m_capturingMouseEventsNode) {
return iBeam;
}
@@ -760,14 +556,6 @@ OptionalCursor EventHandler::selectAutoCursor(const HitTestResult& result,
return pointerCursor();
}
-static LayoutPoint contentPointFromRootFrame(LocalFrame* frame,
- const IntPoint& pointInRootFrame) {
- FrameView* view = frame->view();
- // FIXME: Is it really OK to use the wrong coordinates here when view is 0?
- // Historically the code would just crash; this is clearly no worse than that.
- return view ? view->rootFrameToContents(pointInRootFrame) : pointInRootFrame;
-}
-
WebInputEventResult EventHandler::handleMousePressEvent(
const PlatformMouseEvent& mouseEvent) {
TRACE_EVENT0("blink", "EventHandler::handleMousePressEvent");
@@ -783,37 +571,28 @@ WebInputEventResult EventHandler::handleMousePressEvent(
m_frame->localFrameRoot()->eventHandler().m_lastMouseDownUserGestureToken =
UserGestureIndicator::currentToken();
- cancelFakeMouseMoveEvent();
if (m_eventHandlerWillResetCapturingMouseEventsNode)
m_capturingMouseEventsNode = nullptr;
- m_mousePressed = true;
- m_capturesDragging = true;
- setLastKnownMousePosition(mouseEvent);
- m_mouseDownTimestamp = mouseEvent.timestamp();
- m_mouseDownMayStartDrag = false;
+ m_mouseEventManager->handleMousePressEventUpdateStates(mouseEvent);
selectionController().setMouseDownMayStartSelect(false);
- m_mouseDownMayStartAutoscroll = false;
- if (FrameView* view = m_frame->view()) {
- m_mouseDownPos = view->rootFrameToContents(mouseEvent.position());
- } else {
- invalidateClick();
+ if (!m_frame->view())
return WebInputEventResult::NotHandled;
- }
HitTestRequest request(HitTestRequest::Active);
// Save the document point we generate in case the window coordinate is invalidated by what happens
// when we dispatch the event.
LayoutPoint documentPoint =
- contentPointFromRootFrame(m_frame, mouseEvent.position());
- MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(
- request, documentPoint, mouseEvent);
+ m_frame->view()->rootFrameToContents(mouseEvent.position());
+ MouseEventWithHitTestResults mev =
+ m_frame->document()->performMouseEventHitTest(request, documentPoint,
+ mouseEvent);
if (!mev.innerNode()) {
- invalidateClick();
+ m_mouseEventManager->invalidateClick();
return WebInputEventResult::NotHandled;
}
- m_mousePressNode = mev.innerNode();
+ m_mouseEventManager->setMousePressNode(mev.innerNode());
m_frame->document()->setSequentialFocusNavigationStartingPoint(
mev.innerNode());
@@ -824,12 +603,14 @@ WebInputEventResult EventHandler::handleMousePressEvent(
// 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_mouseEventManager->setCapturesDragging(
+ subframe->eventHandler().m_mouseEventManager->capturesDragging());
+ if (m_mouseEventManager->mousePressed() &&
+ m_mouseEventManager->capturesDragging()) {
m_capturingMouseEventsNode = mev.innerNode();
m_eventHandlerWillResetCapturingMouseEventsNode = true;
}
- invalidateClick();
+ m_mouseEventManager->invalidateClick();
return result;
}
@@ -842,21 +623,22 @@ WebInputEventResult EventHandler::handleMousePressEvent(
if (isMiddleClickAutoscrollInProgress) {
// We invalidate the click when exiting middle click auto scroll 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();
+ m_mouseEventManager->invalidateClick();
return WebInputEventResult::HandledSuppressed;
}
}
- m_clickCount = mouseEvent.clickCount();
- m_clickNode = mev.innerNode()->isTextNode()
- ? FlatTreeTraversal::parent(*mev.innerNode())
- : mev.innerNode();
+ m_mouseEventManager->setClickCount(mouseEvent.clickCount());
+ m_mouseEventManager->setClickNode(
+ mev.innerNode()->isTextNode()
+ ? FlatTreeTraversal::parent(*mev.innerNode())
+ : mev.innerNode());
if (!mouseEvent.fromTouch())
m_frame->selection().setCaretBlinkingSuspended(true);
WebInputEventResult eventResult = updatePointerTargetAndDispatchEvents(
- EventTypeNames::mousedown, mev.innerNode(), m_clickCount, mev.event());
+ EventTypeNames::mousedown, mev.innerNode(), mev.event());
if (eventResult == WebInputEventResult::NotHandled && m_frame->view()) {
FrameView* view = m_frame->view();
@@ -884,10 +666,12 @@ WebInputEventResult EventHandler::handleMousePressEvent(
mouseEvent.getSyntheticEventType() == PlatformMouseEvent::FromTouch
? InputDeviceCapabilities::firesTouchEventsSourceCapabilities()
: InputDeviceCapabilities::doesntFireTouchEventsSourceCapabilities();
- if (eventResult == WebInputEventResult::NotHandled)
- eventResult = handleMouseFocus(hitTestResult, sourceCapabilities);
- m_capturesDragging =
- eventResult == WebInputEventResult::NotHandled || mev.scrollbar();
+ if (eventResult == WebInputEventResult::NotHandled) {
+ eventResult = m_mouseEventManager->handleMouseFocus(hitTestResult,
+ sourceCapabilities);
+ }
+ m_mouseEventManager->setCapturesDragging(
+ 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.
@@ -895,8 +679,8 @@ WebInputEventResult EventHandler::handleMousePressEvent(
const bool wasLastScrollBar =
mev.scrollbar() == m_lastScrollbarUnderMouse.get();
HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
- mev = m_frame->document()->prepareMouseEvent(request, documentPoint,
- mouseEvent);
+ mev = m_frame->document()->performMouseEventHitTest(request, documentPoint,
+ mouseEvent);
if (wasLastScrollBar && mev.scrollbar() != m_lastScrollbarUnderMouse.get())
m_lastScrollbarUnderMouse = nullptr;
}
@@ -907,14 +691,14 @@ WebInputEventResult EventHandler::handleMousePressEvent(
} else {
if (shouldRefetchEventTarget(mev)) {
HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
- mev = m_frame->document()->prepareMouseEvent(request, documentPoint,
- mouseEvent);
+ mev = m_frame->document()->performMouseEventHitTest(
+ request, documentPoint, mouseEvent);
}
if (passMousePressEventToScrollbar(mev))
eventResult = WebInputEventResult::HandledSystem;
else
- eventResult = handleMousePressEvent(mev);
+ eventResult = m_mouseEventManager->handleMousePressEvent(mev);
}
if (mev.hitTestResult().innerNode() &&
@@ -929,31 +713,6 @@ WebInputEventResult EventHandler::handleMousePressEvent(
return eventResult;
}
-static PaintLayer* layerForNode(Node* node) {
- if (!node)
- return nullptr;
-
- LayoutObject* layoutObject = node->layoutObject();
- if (!layoutObject)
- return nullptr;
-
- PaintLayer* layer = layoutObject->enclosingLayer();
- if (!layer)
- return nullptr;
-
- return layer;
-}
-
-ScrollableArea* EventHandler::associatedScrollableArea(
- const PaintLayer* layer) const {
- if (PaintLayerScrollableArea* scrollableArea = layer->getScrollableArea()) {
- if (scrollableArea->scrollsOverflow())
- return scrollableArea;
- }
-
- return nullptr;
-}
-
WebInputEventResult EventHandler::handleMouseMoveEvent(
const PlatformMouseEvent& event) {
TRACE_EVENT0("blink", "EventHandler::handleMouseMoveEvent");
@@ -965,8 +724,10 @@ WebInputEventResult EventHandler::handleMouseMoveEvent(
if (!page)
return result;
- if (PaintLayer* layer = layerForNode(hoveredNode.innerNode())) {
- if (ScrollableArea* layerScrollableArea = associatedScrollableArea(layer))
+ if (PaintLayer* layer =
+ EventHandlingUtil::layerForNode(hoveredNode.innerNode())) {
+ if (ScrollableArea* layerScrollableArea =
+ EventHandlingUtil::associatedScrollableArea(layer))
layerScrollableArea->mouseMovedInContentArea();
}
@@ -993,27 +754,24 @@ WebInputEventResult EventHandler::handleMouseMoveOrLeaveEvent(
ASSERT(m_frame);
ASSERT(m_frame->view());
- setLastKnownMousePosition(mouseEvent);
+ m_mouseEventManager->setLastKnownMousePosition(mouseEvent);
if (m_hoverTimer.isActive())
m_hoverTimer.stop();
m_cursorUpdateTimer.stop();
- cancelFakeMouseMoveEvent();
+ m_mouseEventManager->cancelFakeMouseMoveEvent();
- if (m_svgPan) {
- m_frame->document()->accessSVGExtensions().updatePan(
- m_frame->view()->rootFrameToContents(m_lastKnownMousePosition));
- return WebInputEventResult::HandledSuppressed;
- }
+ m_mouseEventManager->handleSvgPanIfNeeded(false);
- if (m_frameSetBeingResized)
+ if (m_frameSetBeingResized) {
return updatePointerTargetAndDispatchEvents(
- EventTypeNames::mousemove, m_frameSetBeingResized.get(), 0, mouseEvent);
+ EventTypeNames::mousemove, m_frameSetBeingResized.get(), mouseEvent);
+ }
// Send events right to a scrollbar if the mouse is pressed.
- if (m_lastScrollbarUnderMouse && m_mousePressed) {
+ if (m_lastScrollbarUnderMouse && m_mouseEventManager->mousePressed()) {
m_lastScrollbarUnderMouse->mouseMoved(mouseEvent);
return WebInputEventResult::HandledSystem;
}
@@ -1022,7 +780,7 @@ WebInputEventResult EventHandler::handleMouseMoveOrLeaveEvent(
ASSERT(!mouseEvent.fromTouch());
HitTestRequest::HitTestRequestType hitType = HitTestRequest::Move;
- if (m_mousePressed) {
+ if (m_mouseEventManager->mousePressed()) {
hitType |= HitTestRequest::Active;
} else if (onlyUpdateScrollbars) {
// Mouse events should be treated as "read-only" if we're updating only scrollbars. This
@@ -1041,10 +799,12 @@ WebInputEventResult EventHandler::handleMouseMoveOrLeaveEvent(
// We don't want to do a hit-test in forceLeave scenarios because there might actually be some other frame above this one at the specified co-ordinate.
// So we must force the hit-test to fail, while still clearing hover/active state.
- if (forceLeave)
+ if (forceLeave) {
m_frame->document()->updateHoverActiveState(request, 0);
- else
- mev = prepareMouseEvent(request, mouseEvent);
+ } else {
+ mev = EventHandlingUtil::performMouseEventHitTest(m_frame, request,
+ mouseEvent);
+ }
if (hoveredNode)
*hoveredNode = mev.hitTestResult();
@@ -1057,7 +817,8 @@ WebInputEventResult EventHandler::handleMouseMoveOrLeaveEvent(
if (!scrollbar)
scrollbar = mev.scrollbar();
- updateLastScrollbarUnderMouse(scrollbar, !m_mousePressed);
+ updateLastScrollbarUnderMouse(scrollbar,
+ !m_mouseEventManager->mousePressed());
if (onlyUpdateScrollbars)
return WebInputEventResult::HandledSuppressed;
}
@@ -1077,14 +838,15 @@ WebInputEventResult EventHandler::handleMouseMoveOrLeaveEvent(
if (newSubframe) {
// Update over/out state before passing the event to the subframe.
- updateMouseEventTargetNodeAndSendEvents(mev.innerNode(), mev.event(), true);
+ m_pointerEventManager->sendMouseAndPointerBoundaryEvents(
+ updateMouseEventTargetNode(mev.innerNode()), mev.event());
- // Event dispatch in updateMouseEventTargetNodeAndSendEvents may have caused the subframe of the target
+ // Event dispatch in sendMouseAndPointerBoundaryEvents 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())
eventResult = passMouseMoveEventToSubframe(mev, newSubframe, hoveredNode);
} else {
- if (scrollbar && !m_mousePressed)
+ if (scrollbar && !m_mouseEventManager->mousePressed())
scrollbar->mouseMoved(
mev.event()); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
if (FrameView* view = m_frame->view()) {
@@ -1101,25 +863,11 @@ WebInputEventResult EventHandler::handleMouseMoveOrLeaveEvent(
return eventResult;
eventResult = updatePointerTargetAndDispatchEvents(
- EventTypeNames::mousemove, mev.innerNode(), 0, mev.event());
+ EventTypeNames::mousemove, mev.innerNode(), mev.event());
if (eventResult != WebInputEventResult::NotHandled)
return eventResult;
- return handleMouseDraggedEvent(mev);
-}
-
-void EventHandler::invalidateClick() {
- m_clickCount = 0;
- m_clickNode = nullptr;
-}
-
-ContainerNode* EventHandler::parentForClickEvent(const Node& node) {
- // IE doesn't dispatch click events for mousedown/mouseup events across form
- // controls.
- if (node.isHTMLElement() && toHTMLElement(node).isInteractiveContent())
- return nullptr;
-
- return FlatTreeTraversal::parent(node);
+ return m_mouseEventManager->handleMouseDraggedEvent(mev);
}
WebInputEventResult EventHandler::handleMouseReleaseEvent(
@@ -1153,27 +901,22 @@ WebInputEventResult EventHandler::handleMouseReleaseEvent(
m_frame, mouseEvent);
}
- m_mousePressed = false;
- setLastKnownMousePosition(mouseEvent);
+ m_mouseEventManager->setMousePressed(false);
+ m_mouseEventManager->setLastKnownMousePosition(mouseEvent);
+ m_mouseEventManager->handleSvgPanIfNeeded(true);
- if (m_svgPan) {
- m_svgPan = false;
- m_frame->document()->accessSVGExtensions().updatePan(
- m_frame->view()->rootFrameToContents(m_lastKnownMousePosition));
- return WebInputEventResult::HandledSuppressed;
+ if (m_frameSetBeingResized) {
+ return m_mouseEventManager->setMousePositionAndDispatchMouseEvent(
+ updateMouseEventTargetNode(m_frameSetBeingResized.get()),
+ EventTypeNames::mouseup, mouseEvent);
}
- if (m_frameSetBeingResized)
- return dispatchMouseEvent(EventTypeNames::mouseup,
- m_frameSetBeingResized.get(), m_clickCount,
- mouseEvent);
-
if (m_lastScrollbarUnderMouse) {
- invalidateClick();
+ m_mouseEventManager->invalidateClick();
m_lastScrollbarUnderMouse->mouseUp(mouseEvent);
- return updatePointerTargetAndDispatchEvents(EventTypeNames::mouseup,
- m_nodeUnderMouse.get(),
- m_clickCount, mouseEvent);
+ return updatePointerTargetAndDispatchEvents(
+ EventTypeNames::mouseup, m_mouseEventManager->getNodeUnderMouse(),
+ mouseEvent);
}
// Mouse events simulated from touch should not hit-test again.
@@ -1181,7 +924,8 @@ WebInputEventResult EventHandler::handleMouseReleaseEvent(
HitTestRequest::HitTestRequestType hitType = HitTestRequest::Release;
HitTestRequest request(hitType);
- MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
+ MouseEventWithHitTestResults mev =
+ EventHandlingUtil::performMouseEventHitTest(m_frame, request, mouseEvent);
LocalFrame* subframe =
m_capturingMouseEventsNode.get()
? subframeForTargetNode(m_capturingMouseEventsNode.get())
@@ -1192,91 +936,22 @@ WebInputEventResult EventHandler::handleMouseReleaseEvent(
return passMouseReleaseEventToSubframe(mev, subframe);
WebInputEventResult eventResult = updatePointerTargetAndDispatchEvents(
- EventTypeNames::mouseup, mev.innerNode(), m_clickCount, mev.event());
+ EventTypeNames::mouseup, mev.innerNode(), mev.event());
- // We only prevent click event when the click may cause contextmenu to popup.
- // However, we always send auxclick.
- bool contextMenuEvent = !RuntimeEnabledFeatures::auxclickEnabled() &&
- mouseEvent.pointerProperties().button ==
- WebPointerProperties::Button::Right;
-#if OS(MACOSX)
- // FIXME: The Mac port achieves the same behavior by checking whether the context menu is currently open in WebPage::mouseEvent(). Consider merging the implementations.
- if (mouseEvent.pointerProperties().button ==
- WebPointerProperties::Button::Left &&
- mouseEvent.getModifiers() & PlatformEvent::CtrlKey)
- contextMenuEvent = true;
-#endif
-
- WebInputEventResult clickEventResult = WebInputEventResult::NotHandled;
- const bool shouldDispatchClickEvent =
- m_clickCount > 0 && !contextMenuEvent && mev.innerNode() && m_clickNode &&
- mev.innerNode()->canParticipateInFlatTree() &&
- m_clickNode->canParticipateInFlatTree() &&
- !(selectionController().hasExtendedSelection() && isLinkSelection(mev));
- if (shouldDispatchClickEvent) {
- Node* clickTargetNode = nullptr;
- // Updates distribution because a 'mouseup' event listener can make the
- // tree dirty at dispatchMouseEvent() invocation above.
- // Unless distribution is updated, commonAncestor would hit ASSERT.
- if (m_clickNode == mev.innerNode()) {
- clickTargetNode = m_clickNode;
- clickTargetNode->updateDistribution();
- } else if (m_clickNode->document() == mev.innerNode()->document()) {
- m_clickNode->updateDistribution();
- mev.innerNode()->updateDistribution();
- clickTargetNode =
- mev.innerNode()->commonAncestor(*m_clickNode, parentForClickEvent);
- }
- if (clickTargetNode) {
- // Dispatch mouseup directly w/o calling updateMouseEventTargetNodeAndSendEvents
- // because the mouseup dispatch above has already updated it
- // correctly. Moreover, clickTargetNode is different from
- // mev.innerNode at drag-release.
- clickEventResult = EventHandlingUtil::toWebInputEventResult(
- clickTargetNode->dispatchMouseEvent(
- mev.event(), !RuntimeEnabledFeatures::auxclickEnabled() ||
- (mev.event().pointerProperties().button ==
- WebPointerProperties::Button::Left)
- ? EventTypeNames::click
- : EventTypeNames::auxclick,
- m_clickCount));
- }
- }
+ WebInputEventResult clickEventResult =
+ m_mouseEventManager->dispatchMouseClickIfNeeded(mev);
m_scrollManager->clearResizeScrollableArea(false);
if (eventResult == WebInputEventResult::NotHandled)
- eventResult = handleMouseReleaseEvent(mev);
- clearDragHeuristicState();
+ eventResult = m_mouseEventManager->handleMouseReleaseEvent(mev);
+ m_mouseEventManager->clearDragHeuristicState();
- invalidateClick();
+ m_mouseEventManager->invalidateClick();
return EventHandlingUtil::mergeEventResult(clickEventResult, eventResult);
}
-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 WebInputEventResult::NotHandled;
-
- DragEvent* me = DragEvent::create(
- eventType, true, true, m_frame->document()->domWindow(), 0,
- event.globalPosition().x(), event.globalPosition().y(),
- event.position().x(), event.position().y(), event.movementDelta().x(),
- event.movementDelta().y(), event.getModifiers(), 0,
- MouseEvent::platformModifiersToButtons(event.getModifiers()), nullptr,
- event.timestamp(), dataTransfer, event.getSyntheticEventType());
-
- return EventHandlingUtil::toWebInputEventResult(
- dragTarget->dispatchEvent(me));
-}
-
static bool targetIsFrame(Node* target, LocalFrame*& frame) {
if (!isHTMLFrameElementBase(target))
return false;
@@ -1341,7 +1016,8 @@ WebInputEventResult EventHandler::updateDragAndDrop(
return eventResult;
HitTestRequest request(HitTestRequest::ReadOnly);
- MouseEventWithHitTestResults mev = prepareMouseEvent(request, event);
+ MouseEventWithHitTestResults mev =
+ EventHandlingUtil::performMouseEventHitTest(m_frame, request, event);
// Drag events should never go to text nodes (following IE, and proper mouseover/out dispatch)
Node* newTarget = mev.innerNode();
@@ -1366,12 +1042,12 @@ WebInputEventResult EventHandler::updateDragAndDrop(
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) {
+ if (m_mouseEventManager->dragState().m_dragSrc) {
// for now we don't care if event handler cancels default behavior, since there is none
- dispatchDragSrcEvent(EventTypeNames::drag, event);
+ m_mouseEventManager->dispatchDragSrcEvent(EventTypeNames::drag, event);
}
- eventResult = dispatchDragEvent(EventTypeNames::dragenter, newTarget,
- event, dataTransfer);
+ eventResult = m_mouseEventManager->dispatchDragEvent(
+ EventTypeNames::dragenter, newTarget, event, dataTransfer);
if (eventResult == WebInputEventResult::NotHandled &&
findDropZone(newTarget, dataTransfer))
eventResult = WebInputEventResult::HandledSystem;
@@ -1382,12 +1058,12 @@ WebInputEventResult EventHandler::updateDragAndDrop(
eventResult =
targetFrame->eventHandler().updateDragAndDrop(event, dataTransfer);
} else if (m_dragTarget) {
- dispatchDragEvent(EventTypeNames::dragleave, m_dragTarget.get(), event,
- dataTransfer);
+ m_mouseEventManager->dispatchDragEvent(
+ EventTypeNames::dragleave, m_dragTarget.get(), event, dataTransfer);
}
if (newTarget) {
- // We do not explicitly call dispatchDragEvent here because it could ultimately result in the appearance that
+ // We do not explicitly call m_mouseEventManager->dispatchDragEvent here because it could ultimately result in the appearance that
// two dragover events fired. So, we mark that we should only fire a dragover event on the next call to this function.
m_shouldOnlyFireDragOverEvent = true;
}
@@ -1399,12 +1075,13 @@ WebInputEventResult EventHandler::updateDragAndDrop(
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) {
+ if (!m_shouldOnlyFireDragOverEvent &&
+ m_mouseEventManager->dragState().m_dragSrc) {
// for now we don't care if event handler cancels default behavior, since there is none
- dispatchDragSrcEvent(EventTypeNames::drag, event);
+ m_mouseEventManager->dispatchDragSrcEvent(EventTypeNames::drag, event);
}
- eventResult = dispatchDragEvent(EventTypeNames::dragover, newTarget,
- event, dataTransfer);
+ eventResult = m_mouseEventManager->dispatchDragEvent(
+ EventTypeNames::dragover, newTarget, event, dataTransfer);
if (eventResult == WebInputEventResult::NotHandled &&
findDropZone(newTarget, dataTransfer))
eventResult = WebInputEventResult::HandledSystem;
@@ -1423,10 +1100,10 @@ void EventHandler::cancelDragAndDrop(const PlatformMouseEvent& event,
if (targetFrame)
targetFrame->eventHandler().cancelDragAndDrop(event, dataTransfer);
} else if (m_dragTarget.get()) {
- if (dragState().m_dragSrc)
- dispatchDragSrcEvent(EventTypeNames::drag, event);
- dispatchDragEvent(EventTypeNames::dragleave, m_dragTarget.get(), event,
- dataTransfer);
+ if (m_mouseEventManager->dragState().m_dragSrc)
+ m_mouseEventManager->dispatchDragSrcEvent(EventTypeNames::drag, event);
+ m_mouseEventManager->dispatchDragEvent(
+ EventTypeNames::dragleave, m_dragTarget.get(), event, dataTransfer);
}
clearDragState();
}
@@ -1441,22 +1118,13 @@ WebInputEventResult EventHandler::performDragAndDrop(
result =
targetFrame->eventHandler().performDragAndDrop(event, dataTransfer);
} else if (m_dragTarget.get()) {
- result = dispatchDragEvent(EventTypeNames::drop, m_dragTarget.get(), event,
- dataTransfer);
+ result = m_mouseEventManager->dispatchDragEvent(
+ EventTypeNames::drop, m_dragTarget.get(), event, dataTransfer);
}
clearDragState();
return result;
}
-void EventHandler::clearDragHeuristicState() {
- // Used to prevent mouseMoveEvent from initiating a drag before
- // the mouse is pressed again.
- m_mousePressed = false;
- m_capturesDragging = false;
- m_mouseDownMayStartDrag = false;
- m_mouseDownMayStartAutoscroll = false;
-}
-
void EventHandler::clearDragState() {
m_scrollManager->stopAutoscroll();
m_dragTarget = nullptr;
@@ -1469,19 +1137,7 @@ void EventHandler::setCapturingMouseEventsNode(Node* n) {
m_eventHandlerWillResetCapturingMouseEventsNode = false;
}
-MouseEventWithHitTestResults EventHandler::prepareMouseEvent(
- const HitTestRequest& request,
- const PlatformMouseEvent& mev) {
- ASSERT(m_frame);
- ASSERT(m_frame->document());
-
- return m_frame->document()->prepareMouseEvent(
- request, contentPointFromRootFrame(m_frame, mev.position()), mev);
-}
-
-Node* EventHandler::updateMouseEventTargetNode(
- Node* targetNode,
- const PlatformMouseEvent& mouseEvent) {
+Node* EventHandler::updateMouseEventTargetNode(Node* targetNode) {
Node* newNodeUnderMouse = targetNode;
// If we're capturing, we always go right to that node.
@@ -1498,75 +1154,7 @@ Node* EventHandler::updateMouseEventTargetNode(
if (newNodeUnderMouse && newNodeUnderMouse->isTextNode())
newNodeUnderMouse = FlatTreeTraversal::parent(*newNodeUnderMouse);
}
- Node* lastNodeUnderMouse = m_nodeUnderMouse;
- m_nodeUnderMouse = newNodeUnderMouse;
-
- PaintLayer* layerForLastNode = layerForNode(lastNodeUnderMouse);
- PaintLayer* layerForNodeUnderMouse = layerForNode(m_nodeUnderMouse.get());
- Page* page = m_frame->page();
-
- if (lastNodeUnderMouse &&
- (!m_nodeUnderMouse ||
- m_nodeUnderMouse->document() != m_frame->document())) {
- // The mouse has moved between frames.
- if (LocalFrame* frame = lastNodeUnderMouse->document().frame()) {
- if (FrameView* frameView = frame->view())
- frameView->mouseExitedContentArea();
- }
- } else if (page && (layerForLastNode &&
- (!layerForNodeUnderMouse ||
- layerForNodeUnderMouse != layerForLastNode))) {
- // The mouse has moved between layers.
- if (ScrollableArea* scrollableAreaForLastNode =
- associatedScrollableArea(layerForLastNode))
- scrollableAreaForLastNode->mouseExitedContentArea();
- }
-
- if (m_nodeUnderMouse &&
- (!lastNodeUnderMouse ||
- lastNodeUnderMouse->document() != m_frame->document())) {
- // The mouse has moved between frames.
- if (LocalFrame* frame = m_nodeUnderMouse->document().frame()) {
- if (FrameView* frameView = frame->view())
- frameView->mouseEnteredContentArea();
- }
- } else if (page && (layerForNodeUnderMouse &&
- (!layerForLastNode ||
- layerForNodeUnderMouse != layerForLastNode))) {
- // The mouse has moved between layers.
- if (ScrollableArea* scrollableAreaForNodeUnderMouse =
- associatedScrollableArea(layerForNodeUnderMouse))
- scrollableAreaForNodeUnderMouse->mouseEnteredContentArea();
- }
-
- if (lastNodeUnderMouse &&
- lastNodeUnderMouse->document() != m_frame->document()) {
- lastNodeUnderMouse = nullptr;
- m_lastScrollbarUnderMouse = nullptr;
- }
-
- return lastNodeUnderMouse;
-}
-
-void EventHandler::updateMouseEventTargetNodeAndSendEvents(
- Node* targetNode,
- const PlatformMouseEvent& mouseEvent,
- bool isFrameBoundaryTransition) {
- Node* lastNodeUnderMouse = updateMouseEventTargetNode(targetNode, mouseEvent);
- m_pointerEventManager->sendMouseAndPossiblyPointerBoundaryEvents(
- lastNodeUnderMouse, m_nodeUnderMouse, mouseEvent,
- isFrameBoundaryTransition);
-}
-
-WebInputEventResult EventHandler::dispatchMouseEvent(
- const AtomicString& eventType,
- Node* targetNode,
- int clickCount,
- const PlatformMouseEvent& mouseEvent) {
- updateMouseEventTargetNodeAndSendEvents(targetNode, mouseEvent);
-
- return m_mouseEventManager->dispatchMouseEvent(
- m_nodeUnderMouse, eventType, mouseEvent, nullptr, clickCount);
+ return newNodeUnderMouse;
}
bool EventHandler::isPointerEventActive(int pointerId) {
@@ -1596,128 +1184,19 @@ void EventHandler::elementRemoved(EventTarget* target) {
m_pointerEventManager->elementRemoved(target);
}
-// TODO(mustaq): Make PE drive ME dispatch & bookkeeping in EventHandler.
WebInputEventResult EventHandler::updatePointerTargetAndDispatchEvents(
const AtomicString& mouseEventType,
Node* targetNode,
- int clickCount,
const PlatformMouseEvent& mouseEvent) {
ASSERT(mouseEventType == EventTypeNames::mousedown ||
mouseEventType == EventTypeNames::mousemove ||
mouseEventType == EventTypeNames::mouseup);
- Node* lastNodeUnderMouse = updateMouseEventTargetNode(targetNode, mouseEvent);
-
- Node* newNodeUnderMouse = nullptr;
const auto& eventResult = m_pointerEventManager->sendMousePointerEvent(
- m_nodeUnderMouse, mouseEventType, clickCount, mouseEvent,
- lastNodeUnderMouse, &newNodeUnderMouse);
- m_nodeUnderMouse = newNodeUnderMouse;
+ updateMouseEventTargetNode(targetNode), mouseEventType, mouseEvent);
return eventResult;
}
-void EventHandler::setClickNode(Node* node) {
- m_clickNode = node;
-}
-
-WebInputEventResult EventHandler::handleMouseFocus(
- const HitTestResult& hitTestResult,
- InputDeviceCapabilities* sourceCapabilities) {
- // If clicking on a frame scrollbar, do not mess up with content focus.
- if (hitTestResult.scrollbar() && !m_frame->contentLayoutItem().isNull()) {
- if (hitTestResult.scrollbar()->getScrollableArea() ==
- m_frame->contentLayoutItem().getScrollableArea())
- return WebInputEventResult::NotHandled;
- }
-
- // The layout needs to be up to date to determine if an element is focusable.
- m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets();
-
- Element* element = nullptr;
- if (m_nodeUnderMouse)
- element = m_nodeUnderMouse->isElementNode()
- ? toElement(m_nodeUnderMouse)
- : m_nodeUnderMouse->parentOrShadowHostElement();
- for (; element; element = element->parentOrShadowHostElement()) {
- if (element->isFocusable() && element->isFocusedElementInDocument())
- return WebInputEventResult::NotHandled;
- if (element->isMouseFocusable())
- break;
- }
- ASSERT(!element || element->isMouseFocusable());
-
- // To fix <rdar://problem/4895428> Can't drag selected ToDo, we don't focus
- // a node on mouse down if it's selected and inside a focused node. It will
- // be focused if the user does a mouseup over it, however, because the
- // mouseup will set a selection inside it, which will call
- // FrameSelection::setFocusedNodeIfNeeded.
- if (element && m_frame->selection().isRange()) {
- // TODO(yosin) We should not create |Range| object for calling
- // |isNodeFullyContained()|.
- if (createRange(
- m_frame->selection().selection().toNormalizedEphemeralRange())
- ->isNodeFullyContained(*element) &&
- element->isDescendantOf(m_frame->document()->focusedElement()))
- return WebInputEventResult::NotHandled;
- }
-
- // Only change the focus when clicking scrollbars if it can transfered to a
- // mouse focusable node.
- if (!element && hitTestResult.scrollbar())
- return WebInputEventResult::HandledSystem;
-
- if (Page* page = m_frame->page()) {
- // If focus shift is blocked, we eat the event. Note we should never
- // clear swallowEvent if the page already set it (e.g., by canceling
- // default behavior).
- if (element) {
- if (slideFocusOnShadowHostIfNecessary(*element))
- return WebInputEventResult::HandledSystem;
- if (!page->focusController().setFocusedElement(
- element, m_frame,
- FocusParams(SelectionBehaviorOnFocus::None, WebFocusTypeMouse,
- sourceCapabilities)))
- 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 WebInputEventResult::HandledSystem;
- }
- }
-
- return WebInputEventResult::NotHandled;
-}
-
-bool EventHandler::slideFocusOnShadowHostIfNecessary(const Element& element) {
- if (element.authorShadowRoot() &&
- element.authorShadowRoot()->delegatesFocus()) {
- Document* doc = m_frame->document();
- if (element.isShadowIncludingInclusiveAncestorOf(doc->focusedElement())) {
- // If the inner element is already focused, do nothing.
- return true;
- }
-
- // If the host has a focusable inner element, focus it. Otherwise, the host takes focus.
- Page* page = m_frame->page();
- ASSERT(page);
- Element* found =
- page->focusController().findFocusableElementInShadowHost(element);
- if (found && element.isShadowIncludingInclusiveAncestorOf(found)) {
- // Use WebFocusTypeForward instead of WebFocusTypeMouse here to mean the focus has slided.
- found->focus(FocusParams(SelectionBehaviorOnFocus::Reset,
- WebFocusTypeForward, nullptr));
- return true;
- }
- }
- return false;
-}
-
WebInputEventResult EventHandler::handleWheelEvent(
const PlatformWheelEvent& event) {
#if OS(MACOSX)
@@ -1833,6 +1312,10 @@ WebInputEventResult EventHandler::handleGestureScrollEnd(
return m_scrollManager->handleGestureScrollEnd(gestureEvent);
}
+void EventHandler::setMouseDownMayStartAutoscroll() {
+ m_mouseEventManager->setMouseDownMayStartAutoscroll();
+}
+
bool EventHandler::isScrollbarHandlingGestures() const {
return m_scrollManager->isScrollbarHandlingGestures();
}
@@ -2004,8 +1487,8 @@ void EventHandler::updateGestureTargetNodeForMouseEvent(
HeapVector<Member<LocalFrame>> exitedFrameChain;
// Insert the frame from the disagreement between last frames and entered frames
while (exitedFrameInDocument) {
- Node* lastNodeUnderTap =
- exitedFrameInDocument->eventHandler().m_nodeUnderMouse.get();
+ Node* lastNodeUnderTap = exitedFrameInDocument->eventHandler()
+ .m_mouseEventManager->getNodeUnderMouse();
if (!lastNodeUnderTap)
break;
@@ -2043,8 +1526,8 @@ void EventHandler::updateGestureTargetNodeForMouseEvent(
size_t indexExitedFrameChain = exitedFrameChain.size();
while (indexExitedFrameChain) {
LocalFrame* leaveFrame = exitedFrameChain[--indexExitedFrameChain];
- leaveFrame->eventHandler().updateMouseEventTargetNodeAndSendEvents(
- nullptr, fakeMouseMove);
+ leaveFrame->eventHandler().m_mouseEventManager->setNodeUnderMouse(
+ updateMouseEventTargetNode(nullptr), fakeMouseMove);
}
// update the mouseover/mouseenter event
@@ -2054,9 +1537,9 @@ void EventHandler::updateGestureTargetNodeForMouseEvent(
if (parentFrame && parentFrame->isLocalFrame())
toLocalFrame(parentFrame)
->eventHandler()
- .updateMouseEventTargetNodeAndSendEvents(
- toHTMLFrameOwnerElement(
- enteredFrameChain[indexEnteredFrameChain]->owner()),
+ .m_mouseEventManager->setNodeUnderMouse(
+ updateMouseEventTargetNode(toHTMLFrameOwnerElement(
+ enteredFrameChain[indexEnteredFrameChain]->owner())),
fakeMouseMove);
}
}
@@ -2195,12 +1678,13 @@ WebInputEventResult EventHandler::sendContextMenuEvent(
return WebInputEventResult::NotHandled;
// Clear mouse press state to avoid initiating a drag while context menu is up.
- m_mousePressed = false;
+ m_mouseEventManager->setMousePressed(false);
LayoutPoint positionInContents = v->rootFrameToContents(event.position());
HitTestRequest request(HitTestRequest::Active);
- MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(
- request, positionInContents, event);
- // Since |Document::prepareMouseEvent()| modifies layout tree for setting
+ MouseEventWithHitTestResults mev =
+ m_frame->document()->performMouseEventHitTest(request, positionInContents,
+ event);
+ // Since |Document::performMouseEventHitTest()| modifies layout tree for setting
// hover element, we need to update layout tree for requirement of
// |SelectionController::sendContextMenuEvent()|.
m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets();
@@ -2208,7 +1692,9 @@ WebInputEventResult EventHandler::sendContextMenuEvent(
selectionController().sendContextMenuEvent(mev, positionInContents);
Node* targetNode = overrideTargetNode ? overrideTargetNode : mev.innerNode();
- return dispatchMouseEvent(EventTypeNames::contextmenu, targetNode, 0, event);
+ return m_mouseEventManager->dispatchMouseEvent(
+ updateMouseEventTargetNode(targetNode), EventTypeNames::contextmenu,
+ event, 0);
}
WebInputEventResult EventHandler::sendContextMenuEventForKey(
@@ -2315,71 +1801,11 @@ bool EventHandler::cursorUpdatePending() {
}
void EventHandler::dispatchFakeMouseMoveEventSoon() {
- if (m_mousePressed)
- return;
-
- if (m_mousePositionIsUnknown)
- return;
-
- Settings* settings = m_frame->settings();
- if (settings && !settings->deviceSupportsMouse())
- return;
-
- // Reschedule the timer, to prevent dispatching mouse move events
- // during a scroll. This avoids a potential source of scroll jank.
- if (m_fakeMouseMoveEventTimer.isActive())
- m_fakeMouseMoveEventTimer.stop();
- m_fakeMouseMoveEventTimer.startOneShot(fakeMouseMoveInterval,
- BLINK_FROM_HERE);
+ m_mouseEventManager->dispatchFakeMouseMoveEventSoon();
}
void EventHandler::dispatchFakeMouseMoveEventSoonInQuad(const FloatQuad& quad) {
- FrameView* view = m_frame->view();
- if (!view)
- return;
-
- if (!quad.containsPoint(view->rootFrameToContents(m_lastKnownMousePosition)))
- return;
-
- dispatchFakeMouseMoveEventSoon();
-}
-
-void EventHandler::fakeMouseMoveEventTimerFired(TimerBase* timer) {
- TRACE_EVENT0("input", "EventHandler::fakeMouseMoveEventTimerFired");
- ASSERT_UNUSED(timer, timer == &m_fakeMouseMoveEventTimer);
- ASSERT(!m_mousePressed);
-
- Settings* settings = m_frame->settings();
- if (settings && !settings->deviceSupportsMouse())
- return;
-
- FrameView* view = m_frame->view();
- if (!view)
- return;
-
- if (!m_frame->page() || !m_frame->page()->focusController().isActive())
- return;
-
- // Don't dispatch a synthetic mouse move event if the mouse cursor is not visible to the user.
- if (!isCursorVisible())
- return;
-
- PlatformMouseEvent fakeMouseMoveEvent(
- m_lastKnownMousePosition, m_lastKnownMouseGlobalPosition,
- WebPointerProperties::Button::NoButton, PlatformEvent::MouseMoved, 0,
- static_cast<PlatformEvent::Modifiers>(
- KeyboardEventManager::getCurrentModifierState()),
- PlatformMouseEvent::RealOrIndistinguishable,
- monotonicallyIncreasingTime(), WebPointerProperties::PointerType::Mouse);
- handleMouseMoveEvent(fakeMouseMoveEvent);
-}
-
-void EventHandler::cancelFakeMouseMoveEvent() {
- m_fakeMouseMoveEventTimer.stop();
-}
-
-bool EventHandler::isCursorVisible() const {
- return m_frame->page()->isCursorVisible();
+ m_mouseEventManager->dispatchFakeMouseMoveEventSoonInQuad(quad);
}
void EventHandler::setResizingFrameSet(HTMLFrameSetElement* frameSet) {
@@ -2401,7 +1827,8 @@ void EventHandler::hoverTimerFired(TimerBase*) {
if (FrameView* view = m_frame->view()) {
HitTestRequest request(HitTestRequest::Move);
HitTestResult result(request,
- view->rootFrameToContents(m_lastKnownMousePosition));
+ view->rootFrameToContents(
+ m_mouseEventManager->lastKnownMousePosition()));
layoutItem.hitTest(result);
m_frame->document()->updateHoverActiveState(request,
result.innerElement());
@@ -2441,227 +1868,21 @@ WebInputEventResult EventHandler::keyEvent(
}
void EventHandler::defaultKeyboardEventHandler(KeyboardEvent* event) {
- m_keyboardEventManager->defaultKeyboardEventHandler(event, m_mousePressNode);
-}
-
-bool EventHandler::dragHysteresisExceeded(
- const IntPoint& dragLocationInRootFrame) const {
- FrameView* view = m_frame->view();
- if (!view)
- return false;
- IntPoint dragLocation = view->rootFrameToContents(dragLocationInRootFrame);
- IntSize delta = dragLocation - m_mouseDownPos;
-
- int threshold = GeneralDragHysteresis;
- switch (dragState().m_dragType) {
- case DragSourceActionSelection:
- threshold = TextDragHysteresis;
- break;
- case DragSourceActionImage:
- threshold = ImageDragHysteresis;
- break;
- case DragSourceActionLink:
- threshold = LinkDragHysteresis;
- break;
- case DragSourceActionDHTML:
- break;
- case DragSourceActionNone:
- ASSERT_NOT_REACHED();
- }
-
- return abs(delta.width()) >= threshold || abs(delta.height()) >= threshold;
-}
-
-void EventHandler::clearDragDataTransfer() {
- if (dragState().m_dragDataTransfer) {
- dragState().m_dragDataTransfer->clearDragImage();
- dragState().m_dragDataTransfer->setAccessPolicy(DataTransferNumb);
- }
+ m_keyboardEventManager->defaultKeyboardEventHandler(
+ event, m_mouseEventManager->mousePressNode());
}
void EventHandler::dragSourceEndedAt(const PlatformMouseEvent& event,
DragOperation operation) {
- // Send a hit test request so that Layer gets a chance to update the :hover and :active pseudoclasses.
- HitTestRequest request(HitTestRequest::Release);
- prepareMouseEvent(request, event);
-
- if (dragState().m_dragSrc) {
- dragState().m_dragDataTransfer->setDestinationOperation(operation);
- // for now we don't care if event handler cancels default behavior, since there is none
- dispatchDragSrcEvent(EventTypeNames::dragend, event);
- }
- clearDragDataTransfer();
- dragState().m_dragSrc = nullptr;
- // In case the drag was ended due to an escape key press we need to ensure
- // that consecutive mousemove events don't reinitiate the drag and drop.
- m_mouseDownMayStartDrag = false;
+ m_mouseEventManager->dragSourceEndedAt(event, operation);
}
void EventHandler::updateDragStateAfterEditDragIfNeeded(
Element* rootEditableElement) {
// If inserting the dragged contents removed the drag source, we still want to fire dragend at the root editble element.
- if (dragState().m_dragSrc && !dragState().m_dragSrc->isConnected())
- dragState().m_dragSrc = rootEditableElement;
-}
-
-// returns if we should continue "default processing", i.e., whether eventhandler canceled
-WebInputEventResult EventHandler::dispatchDragSrcEvent(
- const AtomicString& eventType,
- const PlatformMouseEvent& event) {
- return dispatchDragEvent(eventType, dragState().m_dragSrc.get(), event,
- dragState().m_dragDataTransfer.get());
-}
-
-bool EventHandler::handleDragDropIfPossible(
- const GestureEventWithHitTestResults& targetedEvent) {
- if (m_frame->settings() && m_frame->settings()->touchDragDropEnabled() &&
- m_frame->view()) {
- const PlatformGestureEvent& gestureEvent = targetedEvent.event();
- IntPoint adjustedPoint = gestureEvent.position();
- unsigned modifiers = gestureEvent.getModifiers();
-
- // TODO(mustaq): Suppressing long-tap MouseEvents could break
- // drag-drop. Will do separately because of the risk. crbug.com/606938.
- PlatformMouseEvent mouseDownEvent(
- adjustedPoint, gestureEvent.globalPosition(),
- WebPointerProperties::Button::Left, PlatformEvent::MousePressed, 1,
- static_cast<PlatformEvent::Modifiers>(modifiers |
- PlatformEvent::LeftButtonDown),
- PlatformMouseEvent::FromTouch, WTF::monotonicallyIncreasingTime(),
- WebPointerProperties::PointerType::Mouse);
- m_mouseDown = mouseDownEvent;
-
- PlatformMouseEvent mouseDragEvent(
- adjustedPoint, gestureEvent.globalPosition(),
- WebPointerProperties::Button::Left, PlatformEvent::MouseMoved, 1,
- static_cast<PlatformEvent::Modifiers>(modifiers |
- PlatformEvent::LeftButtonDown),
- PlatformMouseEvent::FromTouch, WTF::monotonicallyIncreasingTime(),
- WebPointerProperties::PointerType::Mouse);
- HitTestRequest request(HitTestRequest::ReadOnly);
- MouseEventWithHitTestResults mev =
- prepareMouseEvent(request, mouseDragEvent);
- m_mouseDownMayStartDrag = true;
- dragState().m_dragSrc = nullptr;
- m_mouseDownPos =
- m_frame->view()->rootFrameToContents(mouseDragEvent.position());
- return handleDrag(mev, DragInitiator::Touch);
- }
- return false;
-}
-
-bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event,
- DragInitiator initiator) {
- ASSERT(event.event().type() == PlatformEvent::MouseMoved);
- // Callers must protect the reference to FrameView, since this function may dispatch DOM
- // events, causing page/FrameView to go away.
- ASSERT(m_frame);
- ASSERT(m_frame->view());
- if (!m_frame->page())
- return false;
-
- if (m_mouseDownMayStartDrag) {
- HitTestRequest request(HitTestRequest::ReadOnly);
- HitTestResult result(request, m_mouseDownPos);
- m_frame->contentLayoutItem().hitTest(result);
- Node* node = result.innerNode();
- if (node) {
- DragController::SelectionDragPolicy selectionDragPolicy =
- event.event().timestamp() - m_mouseDownTimestamp < TextDragDelay
- ? DragController::DelayedSelectionDragResolution
- : DragController::ImmediateSelectionDragResolution;
- dragState().m_dragSrc = m_frame->page()->dragController().draggableNode(
- m_frame, node, m_mouseDownPos, selectionDragPolicy,
- dragState().m_dragType);
- } else {
- dragState().m_dragSrc = nullptr;
- }
-
- if (!dragState().m_dragSrc)
- m_mouseDownMayStartDrag = false; // no element is draggable
- }
-
- if (!m_mouseDownMayStartDrag)
- return initiator == DragInitiator::Mouse &&
- !selectionController().mouseDownMayStartSelect() &&
- !m_mouseDownMayStartAutoscroll;
-
- // We are starting a text/image/url drag, so the cursor should be an arrow
- // FIXME <rdar://7577595>: Custom cursors aren't supported during drag and drop (default to pointer).
- m_frame->view()->setCursor(pointerCursor());
-
- if (initiator == DragInitiator::Mouse &&
- !dragHysteresisExceeded(event.event().position()))
- return true;
-
- // Once we're past the hysteresis point, we don't want to treat this gesture as a click
- invalidateClick();
-
- if (!tryStartDrag(event)) {
- // Something failed to start the drag, clean up.
- clearDragDataTransfer();
- dragState().m_dragSrc = nullptr;
- }
-
- m_mouseDownMayStartDrag = false;
- // Whether or not the drag actually started, no more default handling (like selection).
- return true;
-}
-
-bool EventHandler::tryStartDrag(const MouseEventWithHitTestResults& event) {
- // The DataTransfer would only be non-empty if we missed a dragEnd.
- // Clear it anyway, just to make sure it gets numbified.
- clearDragDataTransfer();
-
- dragState().m_dragDataTransfer = createDraggingDataTransfer();
-
- // Check to see if this a DOM based drag, if it is get the DOM specified drag
- // image and offset
- if (dragState().m_dragType == DragSourceActionDHTML) {
- if (LayoutObject* layoutObject = dragState().m_dragSrc->layoutObject()) {
- IntRect boundingIncludingDescendants =
- layoutObject->absoluteBoundingBoxRectIncludingDescendants();
- IntSize delta = m_mouseDownPos - boundingIncludingDescendants.location();
- dragState().m_dragDataTransfer->setDragImageElement(
- dragState().m_dragSrc.get(), IntPoint(delta));
- } else {
- // The layoutObject has disappeared, this can happen if the onStartDrag handler has hidden
- // the element in some way. In this case we just kill the drag.
- return false;
- }
- }
-
- DragController& dragController = m_frame->page()->dragController();
- if (!dragController.populateDragDataTransfer(m_frame, dragState(),
- m_mouseDownPos))
- return false;
-
- // If dispatching dragstart brings about another mouse down -- one way
- // this will happen is if a DevTools user breaks within a dragstart
- // handler and then clicks on the suspended page -- the drag state is
- // 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) ==
- WebInputEventResult::NotHandled &&
- !m_frame->selection().isInPasswordField() && dragState().m_dragSrc;
-
- // Invalidate clipboard here against anymore pasteboard writing for security. The drag
- // image can still be changed as we drag, but not the pasteboard data.
- dragState().m_dragDataTransfer->setAccessPolicy(DataTransferImageWritable);
-
- if (m_mouseDownMayStartDrag) {
- // Dispatching the event could cause Page to go away. Make sure it's still valid before trying to use DragController.
- if (m_frame->page() &&
- dragController.startDrag(m_frame, dragState(), event.event(),
- m_mouseDownPos))
- return true;
- // Drag was canned at the last minute - we owe m_dragSrc a DRAGEND event
- dispatchDragSrcEvent(EventTypeNames::dragend, event.event());
- }
-
- return false;
+ if (m_mouseEventManager->dragState().m_dragSrc &&
+ !m_mouseEventManager->dragState().m_dragSrc->isConnected())
+ m_mouseEventManager->dragState().m_dragSrc = rootEditableElement;
}
bool EventHandler::handleTextInputEvent(const String& text,
@@ -2734,12 +1955,6 @@ WebInputEventResult EventHandler::handleTouchEvent(
return m_pointerEventManager->handleTouchEvents(event);
}
-void EventHandler::setLastKnownMousePosition(const PlatformMouseEvent& event) {
- m_mousePositionIsUnknown = false;
- m_lastKnownMousePosition = event.position();
- m_lastKnownMouseGlobalPosition = event.globalPosition();
-}
-
WebInputEventResult EventHandler::passMousePressEventToSubframe(
MouseEventWithHitTestResults& mev,
LocalFrame* subframe) {
@@ -2755,7 +1970,7 @@ WebInputEventResult EventHandler::passMouseMoveEventToSubframe(
MouseEventWithHitTestResults& mev,
LocalFrame* subframe,
HitTestResult* hoveredNode) {
- if (m_mouseDownMayStartDrag)
+ if (m_mouseEventManager->mouseDownMayStartDrag())
return WebInputEventResult::NotHandled;
WebInputEventResult result =
subframe->eventHandler().handleMouseMoveOrLeaveEvent(mev.event(),
@@ -2775,17 +1990,6 @@ WebInputEventResult EventHandler::passMouseReleaseEventToSubframe(
return WebInputEventResult::HandledSystem;
}
-DataTransfer* EventHandler::createDraggingDataTransfer() const {
- return DataTransfer::create(DataTransfer::DragAndDrop, DataTransferWritable,
- DataObject::create());
-}
-
-void EventHandler::focusDocumentView() {
- Page* page = m_frame->page();
- if (!page)
- return;
- page->focusController().focusDocumentView(m_frame);
-}
FrameHost* EventHandler::frameHost() const {
if (!m_frame->page())
« no previous file with comments | « third_party/WebKit/Source/core/input/EventHandler.h ('k') | third_party/WebKit/Source/core/input/EventHandlingUtil.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698