| Index: Source/core/input/EventHandler.cpp
|
| diff --git a/Source/core/input/EventHandler.cpp b/Source/core/input/EventHandler.cpp
|
| index 484cf6b4fd24e70e9054f3d0c9d1e834967fb7ea..0e66ca528a2bee45a5deb23ea97efac88841b081 100644
|
| --- a/Source/core/input/EventHandler.cpp
|
| +++ b/Source/core/input/EventHandler.cpp
|
| @@ -34,14 +34,12 @@
|
| #include "core/clipboard/DataObject.h"
|
| #include "core/clipboard/DataTransfer.h"
|
| #include "core/dom/Document.h"
|
| -#include "core/dom/DocumentMarkerController.h"
|
| #include "core/dom/TouchList.h"
|
| #include "core/dom/shadow/ComposedTreeTraversal.h"
|
| #include "core/dom/shadow/ShadowRoot.h"
|
| #include "core/editing/Editor.h"
|
| #include "core/editing/FrameSelection.h"
|
| -#include "core/editing/htmlediting.h"
|
| -#include "core/editing/iterators/TextIterator.h"
|
| +#include "core/editing/SelectionController.h"
|
| #include "core/events/EventPath.h"
|
| #include "core/events/KeyboardEvent.h"
|
| #include "core/events/MouseEvent.h"
|
| @@ -219,10 +217,8 @@ EventHandler::EventHandler(LocalFrame* frame)
|
| : m_frame(frame)
|
| , m_mousePressed(false)
|
| , m_capturesDragging(false)
|
| - , m_mouseDownMayStartSelect(false)
|
| , m_mouseDownMayStartDrag(false)
|
| - , m_mouseDownWasSingleClickInSelection(false)
|
| - , m_selectionInitiationState(HaveNotStartedSelection)
|
| + , m_selectionController(SelectionController::create(*frame))
|
| , m_hoverTimer(this, &EventHandler::hoverTimerFired)
|
| , m_cursorUpdateTimer(this, &EventHandler::cursorUpdateTimerFired)
|
| , m_mouseDownMayStartAutoscroll(false)
|
| @@ -273,6 +269,7 @@ DEFINE_TRACE(EventHandler)
|
| visitor->trace(m_previousGestureScrolledNode);
|
| visitor->trace(m_lastDeferredTapElement);
|
| visitor->trace(m_currentScrollChain);
|
| + visitor->trace(m_selectionController);
|
| #endif
|
| }
|
|
|
| @@ -317,13 +314,10 @@ void EventHandler::clear()
|
| m_scrollbarHandlingScrollGesture = nullptr;
|
| m_maxMouseMovedDuration = 0;
|
| m_touchPressed = false;
|
| - m_mouseDownMayStartSelect = false;
|
| m_mouseDownMayStartDrag = false;
|
| m_lastShowPressTimestamp = 0;
|
| m_lastDeferredTapElement = nullptr;
|
| m_eventHandlerWillResetCapturingMouseEventsNode = false;
|
| - m_mouseDownWasSingleClickInSelection = false;
|
| - m_selectionInitiationState = HaveNotStartedSelection;
|
| m_mouseDownMayStartAutoscroll = false;
|
| m_svgPan = false;
|
| m_mouseDownPos = IntPoint();
|
| @@ -343,258 +337,6 @@ void EventHandler::nodeWillBeRemoved(Node& nodeToBeRemoved)
|
| }
|
| }
|
|
|
| -static void setSelectionIfNeeded(FrameSelection& selection, const VisibleSelection& newSelection)
|
| -{
|
| - if (selection.selection() != newSelection)
|
| - selection.setSelection(newSelection);
|
| -}
|
| -
|
| -static inline bool dispatchSelectStart(Node* node)
|
| -{
|
| - if (!node || !node->layoutObject())
|
| - return true;
|
| -
|
| - return node->dispatchEvent(Event::createCancelableBubble(EventTypeNames::selectstart));
|
| -}
|
| -
|
| -static VisibleSelection expandSelectionToRespectUserSelectAll(Node* targetNode, const VisibleSelection& selection)
|
| -{
|
| - Node* rootUserSelectAll = Position::rootUserSelectAllForNode(targetNode);
|
| - if (!rootUserSelectAll)
|
| - return selection;
|
| -
|
| - VisibleSelection newSelection(selection);
|
| - newSelection.setBase(positionBeforeNode(rootUserSelectAll).upstream(CanCrossEditingBoundary));
|
| - newSelection.setExtent(positionAfterNode(rootUserSelectAll).downstream(CanCrossEditingBoundary));
|
| -
|
| - return newSelection;
|
| -}
|
| -
|
| -bool EventHandler::updateSelectionForMouseDownDispatchingSelectStart(Node* targetNode, const VisibleSelection& selection, TextGranularity granularity)
|
| -{
|
| - if (Position::nodeIsUserSelectNone(targetNode))
|
| - return false;
|
| -
|
| - if (!dispatchSelectStart(targetNode))
|
| - return false;
|
| -
|
| - if (selection.isRange()) {
|
| - m_selectionInitiationState = ExtendedSelection;
|
| - } else {
|
| - granularity = CharacterGranularity;
|
| - m_selectionInitiationState = PlacedCaret;
|
| - }
|
| -
|
| - m_frame->selection().setNonDirectionalSelectionIfNeeded(selection, granularity);
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void EventHandler::selectClosestWordFromHitTestResult(const HitTestResult& result, AppendTrailingWhitespace appendTrailingWhitespace)
|
| -{
|
| - Node* innerNode = result.innerNode();
|
| - VisibleSelection newSelection;
|
| -
|
| - if (innerNode && innerNode->layoutObject()) {
|
| - VisiblePosition pos(innerNode->layoutObject()->positionForPoint(result.localPoint()));
|
| - if (pos.isNotNull()) {
|
| - newSelection = VisibleSelection(pos);
|
| - newSelection.expandUsingGranularity(WordGranularity);
|
| - }
|
| -
|
| - if (appendTrailingWhitespace == ShouldAppendTrailingWhitespace && newSelection.isRange())
|
| - newSelection.appendTrailingWhitespace();
|
| -
|
| - updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), WordGranularity);
|
| - }
|
| -}
|
| -
|
| -void EventHandler::selectClosestMisspellingFromHitTestResult(const HitTestResult& result, AppendTrailingWhitespace appendTrailingWhitespace)
|
| -{
|
| - Node* innerNode = result.innerNode();
|
| - VisibleSelection newSelection;
|
| -
|
| - if (innerNode && innerNode->layoutObject()) {
|
| - VisiblePosition pos(innerNode->layoutObject()->positionForPoint(result.localPoint()));
|
| - Position start = pos.deepEquivalent();
|
| - Position end = pos.deepEquivalent();
|
| - if (pos.isNotNull()) {
|
| - DocumentMarkerVector markers = innerNode->document().markers().markersInRange(makeRange(pos, pos).get(), DocumentMarker::MisspellingMarkers());
|
| - if (markers.size() == 1) {
|
| - start.moveToOffset(markers[0]->startOffset());
|
| - end.moveToOffset(markers[0]->endOffset());
|
| - newSelection = VisibleSelection(start, end);
|
| - }
|
| - }
|
| -
|
| - if (appendTrailingWhitespace == ShouldAppendTrailingWhitespace && newSelection.isRange())
|
| - newSelection.appendTrailingWhitespace();
|
| -
|
| - updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), WordGranularity);
|
| - }
|
| -}
|
| -
|
| -void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& result)
|
| -{
|
| - if (m_mouseDownMayStartSelect) {
|
| - selectClosestWordFromHitTestResult(result.hitTestResult(),
|
| - (result.event().clickCount() == 2 && m_frame->editor().isSelectTrailingWhitespaceEnabled()) ? ShouldAppendTrailingWhitespace : DontAppendTrailingWhitespace);
|
| - }
|
| -}
|
| -
|
| -void EventHandler::selectClosestMisspellingFromMouseEvent(const MouseEventWithHitTestResults& result)
|
| -{
|
| - if (m_mouseDownMayStartSelect) {
|
| - selectClosestMisspellingFromHitTestResult(result.hitTestResult(),
|
| - (result.event().clickCount() == 2 && m_frame->editor().isSelectTrailingWhitespaceEnabled()) ? ShouldAppendTrailingWhitespace : DontAppendTrailingWhitespace);
|
| - }
|
| -}
|
| -
|
| -void EventHandler::selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHitTestResults& result)
|
| -{
|
| - if (!result.hitTestResult().isLiveLink())
|
| - return selectClosestWordFromMouseEvent(result);
|
| -
|
| - Node* innerNode = result.innerNode();
|
| -
|
| - if (innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect) {
|
| - VisibleSelection newSelection;
|
| - Element* URLElement = result.hitTestResult().URLElement();
|
| - VisiblePosition pos(innerNode->layoutObject()->positionForPoint(result.localPoint()));
|
| - if (pos.isNotNull() && pos.deepEquivalent().deprecatedNode()->isDescendantOf(URLElement))
|
| - newSelection = VisibleSelection::selectionFromContentsOfNode(URLElement);
|
| -
|
| - updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), WordGranularity);
|
| - }
|
| -}
|
| -
|
| -bool EventHandler::handleMousePressEventDoubleClick(const MouseEventWithHitTestResults& event)
|
| -{
|
| - TRACE_EVENT0("blink", "EventHandler::handleMousePressEventDoubleClick");
|
| -
|
| - if (event.event().button() != LeftButton)
|
| - return false;
|
| -
|
| - if (m_frame->selection().isRange()) {
|
| - // A double-click when range is already selected
|
| - // should not change the selection. So, do not call
|
| - // selectClosestWordFromMouseEvent, but do set
|
| - // m_beganSelectingText to prevent handleMouseReleaseEvent
|
| - // from setting caret selection.
|
| - m_selectionInitiationState = ExtendedSelection;
|
| - } else {
|
| - selectClosestWordFromMouseEvent(event);
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestResults& event)
|
| -{
|
| - TRACE_EVENT0("blink", "EventHandler::handleMousePressEventTripleClick");
|
| -
|
| - if (event.event().button() != LeftButton)
|
| - return false;
|
| -
|
| - Node* innerNode = event.innerNode();
|
| - if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect))
|
| - return false;
|
| -
|
| - VisibleSelection newSelection;
|
| - VisiblePosition pos(innerNode->layoutObject()->positionForPoint(event.localPoint()));
|
| - if (pos.isNotNull()) {
|
| - newSelection = VisibleSelection(pos);
|
| - newSelection.expandUsingGranularity(ParagraphGranularity);
|
| - }
|
| -
|
| - return updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), ParagraphGranularity);
|
| -}
|
| -
|
| -static int textDistance(const Position& start, const Position& end)
|
| -{
|
| - RefPtrWillBeRawPtr<Range> range = Range::create(*start.document(), start, end);
|
| - return TextIterator::rangeLength(range->startPosition(), range->endPosition(), true);
|
| -}
|
| -
|
| -bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestResults& event)
|
| -{
|
| - TRACE_EVENT0("blink", "EventHandler::handleMousePressEventSingleClick");
|
| -
|
| - m_frame->document()->updateLayoutIgnorePendingStylesheets();
|
| - Node* innerNode = event.innerNode();
|
| - if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect))
|
| - return false;
|
| -
|
| - // Extend the selection if the Shift key is down, unless the click is in a link.
|
| - bool extendSelection = event.event().shiftKey() && !event.isOverLink();
|
| -
|
| - // Don't restart the selection when the mouse is pressed on an
|
| - // existing selection so we can allow for text dragging.
|
| - if (FrameView* view = m_frame->view()) {
|
| - LayoutPoint vPoint = view->rootFrameToContents(event.event().position());
|
| - if (!extendSelection && m_frame->selection().contains(vPoint)) {
|
| - m_mouseDownWasSingleClickInSelection = true;
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - VisiblePosition visiblePos(innerNode->layoutObject()->positionForPoint(event.localPoint()));
|
| - if (visiblePos.isNull())
|
| - visiblePos = VisiblePosition(firstPositionInOrBeforeNode(innerNode), DOWNSTREAM);
|
| - Position pos = visiblePos.deepEquivalent();
|
| -
|
| - VisibleSelection newSelection = m_frame->selection().selection();
|
| - TextGranularity granularity = CharacterGranularity;
|
| -
|
| - if (extendSelection && newSelection.isCaretOrRange()) {
|
| - VisibleSelection selectionInUserSelectAll(expandSelectionToRespectUserSelectAll(innerNode, VisibleSelection(VisiblePosition(pos))));
|
| - if (selectionInUserSelectAll.isRange()) {
|
| - if (comparePositions(selectionInUserSelectAll.start(), newSelection.start()) < 0)
|
| - pos = selectionInUserSelectAll.start();
|
| - else if (comparePositions(newSelection.end(), selectionInUserSelectAll.end()) < 0)
|
| - pos = selectionInUserSelectAll.end();
|
| - }
|
| -
|
| - if (!m_frame->editor().behavior().shouldConsiderSelectionAsDirectional()) {
|
| - if (pos.isNotNull()) {
|
| - // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection
|
| - // was created right-to-left
|
| - Position start = newSelection.start();
|
| - Position end = newSelection.end();
|
| - int distanceToStart = textDistance(start, pos);
|
| - int distanceToEnd = textDistance(pos, end);
|
| - if (distanceToStart <= distanceToEnd)
|
| - newSelection = VisibleSelection(end, pos);
|
| - else
|
| - newSelection = VisibleSelection(start, pos);
|
| - }
|
| - } else {
|
| - newSelection.setExtent(pos);
|
| - }
|
| -
|
| - if (m_frame->selection().granularity() != CharacterGranularity) {
|
| - granularity = m_frame->selection().granularity();
|
| - newSelection.expandUsingGranularity(m_frame->selection().granularity());
|
| - }
|
| - } else {
|
| - newSelection = expandSelectionToRespectUserSelectAll(innerNode, VisibleSelection(visiblePos));
|
| - }
|
| -
|
| - // Updating the selection is considered side-effect of the event and so it doesn't impact the handled state.
|
| - updateSelectionForMouseDownDispatchingSelectStart(innerNode, newSelection, granularity);
|
| - return false;
|
| -}
|
| -
|
| -static inline bool canMouseDownStartSelect(Node* node)
|
| -{
|
| - if (!node || !node->layoutObject())
|
| - return true;
|
| -
|
| - if (!node->canStartSelection())
|
| - return false;
|
| -
|
| - return true;
|
| -}
|
| -
|
| bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& event)
|
| {
|
| TRACE_EVENT0("blink", "EventHandler::handleMousePressEvent");
|
| @@ -613,13 +355,9 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve
|
|
|
| bool singleClick = event.event().clickCount() <= 1;
|
|
|
| - // If we got the event back, that must mean it wasn't prevented,
|
| - // so it's allowed to start a drag or selection if it wasn't in a scrollbar.
|
| - m_mouseDownMayStartSelect = canMouseDownStartSelect(event.innerNode()) && !event.scrollbar();
|
| -
|
| m_mouseDownMayStartDrag = singleClick;
|
|
|
| - m_mouseDownWasSingleClickInSelection = false;
|
| + selectionController().handleMousePressEvent(event);
|
|
|
| m_mouseDown = event.event();
|
|
|
| @@ -643,16 +381,16 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve
|
|
|
| bool swallowEvent = false;
|
| m_mousePressed = true;
|
| - m_selectionInitiationState = HaveNotStartedSelection;
|
| + selectionController().initializeSelectionState();
|
|
|
| if (event.event().clickCount() == 2)
|
| - swallowEvent = handleMousePressEventDoubleClick(event);
|
| + swallowEvent = selectionController().handleMousePressEventDoubleClick(event);
|
| else if (event.event().clickCount() >= 3)
|
| - swallowEvent = handleMousePressEventTripleClick(event);
|
| + swallowEvent = selectionController().handleMousePressEventTripleClick(event);
|
| else
|
| - swallowEvent = handleMousePressEventSingleClick(event);
|
| + swallowEvent = selectionController().handleMousePressEventSingleClick(event);
|
|
|
| - m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect
|
| + m_mouseDownMayStartAutoscroll = selectionController().mouseDownMayStartSelect()
|
| || (m_mousePressNode && m_mousePressNode->layoutBox() && m_mousePressNode->layoutBox()->canBeProgramaticallyScrolled());
|
|
|
| return swallowEvent;
|
| @@ -709,97 +447,13 @@ bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e
|
| }
|
| }
|
|
|
| - if (m_selectionInitiationState != ExtendedSelection) {
|
| - HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
|
| - HitTestResult result(request, m_mouseDownPos);
|
| - m_frame->document()->layoutView()->hitTest(result);
|
| -
|
| - updateSelectionForMouseDrag(result);
|
| - }
|
| - updateSelectionForMouseDrag(event.hitTestResult());
|
| + selectionController().handleMouseDraggedEvent(event, m_mouseDownPos, m_dragStartPos, m_mousePressNode.get(), m_lastKnownMousePosition);
|
| return true;
|
| }
|
|
|
| void EventHandler::updateSelectionForMouseDrag()
|
| {
|
| - FrameView* view = m_frame->view();
|
| - if (!view)
|
| - return;
|
| - LayoutView* layoutObject = m_frame->contentLayoutObject();
|
| - if (!layoutObject)
|
| - return;
|
| -
|
| - HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::Move);
|
| - HitTestResult result(request, view->rootFrameToContents(m_lastKnownMousePosition));
|
| - layoutObject->hitTest(result);
|
| - updateSelectionForMouseDrag(result);
|
| -}
|
| -
|
| -void EventHandler::updateSelectionForMouseDrag(const HitTestResult& hitTestResult)
|
| -{
|
| - if (!m_mouseDownMayStartSelect)
|
| - return;
|
| -
|
| - Node* target = hitTestResult.innerNode();
|
| - if (!target)
|
| - return;
|
| -
|
| - VisiblePosition targetPosition = m_frame->selection().selection().visiblePositionRespectingEditingBoundary(hitTestResult.localPoint(), target);
|
| - // Don't modify the selection if we're not on a node.
|
| - if (targetPosition.isNull())
|
| - return;
|
| -
|
| - // Restart the selection if this is the first mouse move. This work is usually
|
| - // done in handleMousePressEvent, but not if the mouse press was on an existing selection.
|
| - VisibleSelection newSelection = m_frame->selection().selection();
|
| -
|
| - // Special case to limit selection to the containing block for SVG text.
|
| - // FIXME: Isn't there a better non-SVG-specific way to do this?
|
| - if (Node* selectionBaseNode = newSelection.base().deprecatedNode()) {
|
| - if (LayoutObject* selectionBaseLayoutObject = selectionBaseNode->layoutObject()) {
|
| - if (selectionBaseLayoutObject->isSVGText()) {
|
| - if (target->layoutObject()->containingBlock() != selectionBaseLayoutObject->containingBlock())
|
| - return;
|
| - }
|
| - }
|
| - }
|
| -
|
| - if (m_selectionInitiationState == HaveNotStartedSelection && !dispatchSelectStart(target))
|
| - return;
|
| -
|
| - if (m_selectionInitiationState != ExtendedSelection) {
|
| - // Always extend selection here because it's caused by a mouse drag
|
| - m_selectionInitiationState = ExtendedSelection;
|
| - newSelection = VisibleSelection(targetPosition);
|
| - }
|
| -
|
| - if (RuntimeEnabledFeatures::userSelectAllEnabled()) {
|
| - Node* rootUserSelectAllForMousePressNode = Position::rootUserSelectAllForNode(m_mousePressNode.get());
|
| - if (rootUserSelectAllForMousePressNode && rootUserSelectAllForMousePressNode == Position::rootUserSelectAllForNode(target)) {
|
| - newSelection.setBase(positionBeforeNode(rootUserSelectAllForMousePressNode).upstream(CanCrossEditingBoundary));
|
| - newSelection.setExtent(positionAfterNode(rootUserSelectAllForMousePressNode).downstream(CanCrossEditingBoundary));
|
| - } else {
|
| - // Reset base for user select all when base is inside user-select-all area and extent < base.
|
| - if (rootUserSelectAllForMousePressNode && comparePositions(target->layoutObject()->positionForPoint(hitTestResult.localPoint()), m_mousePressNode->layoutObject()->positionForPoint(m_dragStartPos)) < 0)
|
| - newSelection.setBase(positionAfterNode(rootUserSelectAllForMousePressNode).downstream(CanCrossEditingBoundary));
|
| -
|
| - Node* rootUserSelectAllForTarget = Position::rootUserSelectAllForNode(target);
|
| - if (rootUserSelectAllForTarget && m_mousePressNode->layoutObject() && comparePositions(target->layoutObject()->positionForPoint(hitTestResult.localPoint()), m_mousePressNode->layoutObject()->positionForPoint(m_dragStartPos)) < 0)
|
| - newSelection.setExtent(positionBeforeNode(rootUserSelectAllForTarget).upstream(CanCrossEditingBoundary));
|
| - else if (rootUserSelectAllForTarget && m_mousePressNode->layoutObject())
|
| - newSelection.setExtent(positionAfterNode(rootUserSelectAllForTarget).downstream(CanCrossEditingBoundary));
|
| - else
|
| - newSelection.setExtent(targetPosition);
|
| - }
|
| - } else {
|
| - newSelection.setExtent(targetPosition);
|
| - }
|
| -
|
| - if (m_frame->selection().granularity() != CharacterGranularity)
|
| - newSelection.expandUsingGranularity(m_frame->selection().granularity());
|
| -
|
| - m_frame->selection().setNonDirectionalSelectionIfNeeded(newSelection, m_frame->selection().granularity(),
|
| - FrameSelection::AdjustEndpointsAtBidiBoundary);
|
| + selectionController().updateSelectionForMouseDrag(m_mousePressNode.get(), m_dragStartPos, m_lastKnownMousePosition);
|
| }
|
|
|
| bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event)
|
| @@ -813,42 +467,9 @@ bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e
|
| m_mousePressed = false;
|
| m_capturesDragging = false;
|
| m_mouseDownMayStartDrag = false;
|
| - m_mouseDownMayStartSelect = false;
|
| m_mouseDownMayStartAutoscroll = false;
|
|
|
| - bool handled = false;
|
| -
|
| - // Clear the selection if the mouse didn't move after the last mouse
|
| - // press and it's not a context menu click. We do this so when clicking
|
| - // on the selection, the selection goes away. However, if we are
|
| - // editing, place the caret.
|
| - if (m_mouseDownWasSingleClickInSelection && m_selectionInitiationState != ExtendedSelection
|
| - && m_dragStartPos == event.event().position()
|
| - && m_frame->selection().isRange()
|
| - && event.event().button() != RightButton) {
|
| - VisibleSelection newSelection;
|
| - Node* node = event.innerNode();
|
| - bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBrowsingEnabled();
|
| - if (node && node->layoutObject() && (caretBrowsing || node->hasEditableStyle())) {
|
| - VisiblePosition pos = VisiblePosition(node->layoutObject()->positionForPoint(event.localPoint()));
|
| - newSelection = VisibleSelection(pos);
|
| - }
|
| -
|
| - setSelectionIfNeeded(m_frame->selection(), newSelection);
|
| -
|
| - handled = true;
|
| - }
|
| -
|
| - m_frame->selection().notifyLayoutObjectOfSelectionChange(UserTriggered);
|
| -
|
| - m_frame->selection().selectFrameElementInParentIfFullySelected();
|
| -
|
| - if (event.event().button() == MiddleButton && !event.isOverLink()) {
|
| - // Ignore handled, since we want to paste to where the caret was placed anyway.
|
| - handled = handlePasteGlobalSelection(event.event()) || handled;
|
| - }
|
| -
|
| - return handled;
|
| + return selectionController().handleMouseReleaseEvent(event, m_dragStartPos);
|
| }
|
|
|
| #if OS(WIN)
|
| @@ -1240,7 +861,7 @@ OptionalCursor EventHandler::selectAutoCursor(const HitTestResult& result, Node*
|
|
|
| // 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 && m_mouseDownMayStartSelect
|
| + if (m_mousePressed && selectionController().mouseDownMayStartSelect()
|
| && !m_mouseDownMayStartDrag
|
| && m_frame->selection().isCaretOrRange()
|
| && !m_capturingMouseEventsNode) {
|
| @@ -1277,7 +898,7 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
|
| setLastKnownMousePosition(mouseEvent);
|
| m_mouseDownTimestamp = mouseEvent.timestamp();
|
| m_mouseDownMayStartDrag = false;
|
| - m_mouseDownMayStartSelect = false;
|
| + selectionController().setMouseDownMayStartSelect(false);
|
| m_mouseDownMayStartAutoscroll = false;
|
| if (FrameView* view = m_frame->view()) {
|
| m_mouseDownPos = view->rootFrameToContents(mouseEvent.position());
|
| @@ -1648,38 +1269,6 @@ bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
|
| return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
|
| }
|
|
|
| -bool EventHandler::handlePasteGlobalSelection(const PlatformMouseEvent& mouseEvent)
|
| -{
|
| - // If the event was a middle click, attempt to copy global selection in after
|
| - // the newly set caret position.
|
| - //
|
| - // This code is called from either the mouse up or mouse down handling. There
|
| - // is some debate about when the global selection is pasted:
|
| - // xterm: pastes on up.
|
| - // GTK: pastes on down.
|
| - // Qt: pastes on up.
|
| - // Firefox: pastes on up.
|
| - // Chromium: pastes on up.
|
| - //
|
| - // There is something of a webcompat angle to this well, as highlighted by
|
| - // crbug.com/14608. Pages can clear text boxes 'onclick' and, if we paste on
|
| - // down then the text is pasted just before the onclick handler runs and
|
| - // clears the text box. So it's important this happens after the event
|
| - // handlers have been fired.
|
| - if (mouseEvent.type() != PlatformEvent::MouseReleased)
|
| - return false;
|
| -
|
| - if (!m_frame->page())
|
| - return false;
|
| - Frame* focusFrame = m_frame->page()->focusController().focusedOrMainFrame();
|
| - // Do not paste here if the focus was moved somewhere else.
|
| - if (m_frame == focusFrame && m_frame->editor().behavior().supportsGlobalSelection())
|
| - return m_frame->editor().command("PasteGlobalSelection").execute();
|
| -
|
| - return false;
|
| -}
|
| -
|
| -
|
| bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTarget, const PlatformMouseEvent& event, DataTransfer* dataTransfer)
|
| {
|
| FrameView* view = m_frame->view();
|
| @@ -2515,27 +2104,14 @@ bool EventHandler::handleGestureLongPress(const GestureEventWithHitTestResults&
|
| return true;
|
| }
|
| }
|
| -#if OS(ANDROID)
|
| - bool shouldLongPressSelectWord = true;
|
| -#else
|
| - bool shouldLongPressSelectWord = m_frame->settings() && m_frame->settings()->touchEditingEnabled();
|
| -#endif
|
| - if (shouldLongPressSelectWord) {
|
| - IntPoint hitTestPoint = m_frame->view()->rootFrameToContents(gestureEvent.position());
|
| - HitTestResult result = hitTestResultAtPoint(hitTestPoint);
|
| - Node* innerNode = result.innerNode();
|
| - if (!result.isLiveLink() && innerNode && (innerNode->isContentEditable() || innerNode->isTextNode()
|
| -#if OS(ANDROID)
|
| - || innerNode->canStartSelection()
|
| -#endif
|
| - )) {
|
| - selectClosestWordFromHitTestResult(result, DontAppendTrailingWhitespace);
|
| - if (m_frame->selection().isRange()) {
|
| - focusDocumentView();
|
| - return true;
|
| - }
|
| - }
|
| +
|
| + IntPoint hitTestPoint = m_frame->view()->rootFrameToContents(gestureEvent.position());
|
| + HitTestResult result = hitTestResultAtPoint(hitTestPoint);
|
| + if (selectionController().handleGestureLongPress(gestureEvent, result)) {
|
| + focusDocumentView();
|
| + return true;
|
| }
|
| +
|
| return sendContextMenuEventForGesture(targetedEvent);
|
| }
|
|
|
| @@ -3041,19 +2617,7 @@ bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event, Node* o
|
| HitTestRequest request(HitTestRequest::Active);
|
| MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(request, positionInContents, event);
|
|
|
| - if (!m_frame->selection().contains(positionInContents)
|
| - && !mev.scrollbar()
|
| - // FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse.
|
| - // If the selection is non-editable, we do word selection to make it easier to use the contextual menu items
|
| - // available for text selections. But only if we're above text.
|
| - && (m_frame->selection().isContentEditable() || (mev.innerNode() && mev.innerNode()->isTextNode()))) {
|
| - m_mouseDownMayStartSelect = true; // context menu events are always allowed to perform a selection
|
| -
|
| - if (mev.hitTestResult().isMisspelled())
|
| - selectClosestMisspellingFromMouseEvent(mev);
|
| - else if (m_frame->editor().behavior().shouldSelectOnContextualMenuClick())
|
| - selectClosestWordOrLinkFromMouseEvent(mev);
|
| - }
|
| + selectionController().sendContextMenuEvent(mev, positionInContents);
|
|
|
| Node* targetNode = overrideTargetNode ? overrideTargetNode : mev.innerNode();
|
| return !dispatchMouseEvent(EventTypeNames::contextmenu, targetNode, 0, event, false);
|
| @@ -3562,7 +3126,7 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event, DragIni
|
| }
|
|
|
| if (!m_mouseDownMayStartDrag)
|
| - return initiator == DragInitiator::Mouse && !mouseDownMayStartSelect() && !m_mouseDownMayStartAutoscroll;
|
| + 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).
|
| @@ -4147,18 +3711,7 @@ void EventHandler::setLastKnownMousePosition(const PlatformMouseEvent& event)
|
|
|
| bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, LocalFrame* subframe)
|
| {
|
| - // If we're clicking into a frame that is selected, the frame will appear
|
| - // greyed out even though we're clicking on the selection. This looks
|
| - // really strange (having the whole frame be greyed out), so we deselect the
|
| - // selection.
|
| - IntPoint p = m_frame->view()->rootFrameToContents(mev.event().position());
|
| - if (m_frame->selection().contains(p)) {
|
| - VisiblePosition visiblePos(
|
| - mev.innerNode()->layoutObject()->positionForPoint(mev.localPoint()));
|
| - VisibleSelection newSelection(visiblePos);
|
| - m_frame->selection().setSelection(newSelection);
|
| - }
|
| -
|
| + selectionController().passMousePressEventToSubframe(mev);
|
| subframe->eventHandler().handleMousePressEvent(mev.event());
|
| return true;
|
| }
|
|
|