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

Unified Diff: Source/core/page/EventHandler.cpp

Issue 1157833002: Revert of Refactor the selection code in EventHandler (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 7 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
« no previous file with comments | « Source/core/page/EventHandler.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/page/EventHandler.cpp
diff --git a/Source/core/page/EventHandler.cpp b/Source/core/page/EventHandler.cpp
index e180f3b39bb6b66fadd8062332cecdc001a91b97..d26cd614a18903911ad11f4746158ee73bb540f4 100644
--- a/Source/core/page/EventHandler.cpp
+++ b/Source/core/page/EventHandler.cpp
@@ -34,12 +34,14 @@
#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/SelectionController.h"
+#include "core/editing/htmlediting.h"
+#include "core/editing/iterators/TextIterator.h"
#include "core/events/EventPath.h"
#include "core/events/KeyboardEvent.h"
#include "core/events/MouseEvent.h"
@@ -218,8 +220,10 @@
: m_frame(frame)
, m_mousePressed(false)
, m_capturesDragging(false)
+ , m_mouseDownMayStartSelect(false)
, m_mouseDownMayStartDrag(false)
- , m_selectionController(SelectionController::create(frame))
+ , m_mouseDownWasSingleClickInSelection(false)
+ , m_selectionInitiationState(HaveNotStartedSelection)
, m_hoverTimer(this, &EventHandler::hoverTimerFired)
, m_cursorUpdateTimer(this, &EventHandler::cursorUpdateTimerFired)
, m_mouseDownMayStartAutoscroll(false)
@@ -269,7 +273,6 @@
visitor->trace(m_previousGestureScrolledNode);
visitor->trace(m_lastDeferredTapElement);
visitor->trace(m_currentScrollChain);
- visitor->trace(m_selectionController);
#endif
}
@@ -314,10 +317,13 @@
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();
@@ -337,6 +343,258 @@
}
}
+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");
@@ -355,9 +613,13 @@
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;
- selectionController().handleMousePressEvent(event);
+ m_mouseDownWasSingleClickInSelection = false;
m_mouseDown = event.event();
@@ -381,16 +643,16 @@
bool swallowEvent = false;
m_mousePressed = true;
- selectionController().initializeSelectionState();
+ m_selectionInitiationState = HaveNotStartedSelection;
if (event.event().clickCount() == 2)
- swallowEvent = selectionController().handleMousePressEventDoubleClick(event);
+ swallowEvent = handleMousePressEventDoubleClick(event);
else if (event.event().clickCount() >= 3)
- swallowEvent = selectionController().handleMousePressEventTripleClick(event);
+ swallowEvent = handleMousePressEventTripleClick(event);
else
- swallowEvent = selectionController().handleMousePressEventSingleClick(event);
-
- m_mouseDownMayStartAutoscroll = selectionController().mouseDownMayStartSelect()
+ swallowEvent = handleMousePressEventSingleClick(event);
+
+ m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect
|| (m_mousePressNode && m_mousePressNode->layoutBox() && m_mousePressNode->layoutBox()->canBeProgramaticallyScrolled());
return swallowEvent;
@@ -447,13 +709,97 @@
}
}
- selectionController().handleMouseDraggedEvent(event, m_mouseDownPos, m_dragStartPos, m_mousePressNode.get(), m_lastKnownMousePosition);
+ 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());
return true;
}
void EventHandler::updateSelectionForMouseDrag()
{
- selectionController().updateSelectionForMouseDrag(m_mousePressNode.get(), m_dragStartPos, m_lastKnownMouseGlobalPosition);
+ 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);
}
bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event)
@@ -467,9 +813,42 @@
m_mousePressed = false;
m_capturesDragging = false;
m_mouseDownMayStartDrag = false;
+ m_mouseDownMayStartSelect = false;
m_mouseDownMayStartAutoscroll = false;
- return selectionController().handleMouseReleaseEvent(event, m_dragStartPos);
+ 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;
}
#if OS(WIN)
@@ -855,7 +1234,7 @@
// 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()
+ if (m_mousePressed && m_mouseDownMayStartSelect
&& !m_mouseDownMayStartDrag
&& m_frame->selection().isCaretOrRange()
&& !m_capturingMouseEventsNode) {
@@ -892,7 +1271,7 @@
setLastKnownMousePosition(mouseEvent);
m_mouseDownTimestamp = mouseEvent.timestamp();
m_mouseDownMayStartDrag = false;
- selectionController().setMouseDownMayStartSelect(false);
+ m_mouseDownMayStartSelect = false;
m_mouseDownMayStartAutoscroll = false;
if (FrameView* view = m_frame->view()) {
m_mouseDownPos = view->rootFrameToContents(mouseEvent.position());
@@ -1263,6 +1642,38 @@
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)
{
@@ -2099,12 +2510,27 @@
return true;
}
}
-
- IntPoint hitTestPoint = m_frame->view()->rootFrameToContents(gestureEvent.position());
- HitTestResult result = hitTestResultAtPoint(hitTestPoint);
- if (selectionController().handleGestureLongPress(gestureEvent, result))
- 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;
+ }
+ }
+ }
return sendContextMenuEventForGesture(targetedEvent);
}
@@ -2581,7 +3007,19 @@
HitTestRequest request(HitTestRequest::Active);
MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(request, positionInContents, event);
- selectionController().prepareForContextMenu(mev, positionInContents);
+ 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);
+ }
Node* targetNode = overrideTargetNode ? overrideTargetNode : mev.innerNode();
return !dispatchMouseEvent(EventTypeNames::contextmenu, targetNode, 0, event, false);
@@ -3090,7 +3528,7 @@
}
if (!m_mouseDownMayStartDrag)
- return initiator == DragInitiator::Mouse && !selectionController().mouseDownMayStartSelect() && !m_mouseDownMayStartAutoscroll;
+ return initiator == DragInitiator::Mouse && !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).
@@ -3675,7 +4113,18 @@
bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, LocalFrame* subframe)
{
- selectionController().preparePassMousePressEventToSubframe(mev);
+ // 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);
+ }
+
subframe->eventHandler().handleMousePressEvent(mev.event());
return true;
}
« no previous file with comments | « Source/core/page/EventHandler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698