Index: third_party/WebKit/Source/core/editing/SelectionController.cpp |
diff --git a/third_party/WebKit/Source/core/editing/SelectionController.cpp b/third_party/WebKit/Source/core/editing/SelectionController.cpp |
index ed0c5498987322c3de0cf1de759fd8c68caeeec3..ad43105df5bb556d46b4bf365cb9fda12a595293 100644 |
--- a/third_party/WebKit/Source/core/editing/SelectionController.cpp |
+++ b/third_party/WebKit/Source/core/editing/SelectionController.cpp |
@@ -167,16 +167,6 @@ bool SelectionController::handleMousePressEventSingleClick( |
// link or image. |
bool extendSelection = isExtendingSelection(event); |
- // 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 && selection().contains(vPoint)) { |
- m_mouseDownWasSingleClickInSelection = true; |
- return false; |
- } |
- } |
- |
const VisiblePositionInFlatTree& visibleHitPos = |
visiblePositionOfHitTestResult(event.hitTestResult()); |
const VisiblePositionInFlatTree& visiblePos = |
@@ -187,6 +177,21 @@ bool SelectionController::handleMousePressEventSingleClick( |
const VisibleSelectionInFlatTree& selection = |
this->selection().visibleSelection<EditingInFlatTreeStrategy>(); |
+ // Don't restart the selection when the mouse is pressed on an |
+ // existing selection so we can allow for text dragging. |
+ if (!extendSelection && this->selection().contains(event.hitTestResult())) { |
+ m_mouseDownWasSingleClickInSelection = true; |
+ if (!event.event().fromTouch()) |
+ return false; |
+ |
+ if (!this->selection().isHandleVisible()) { |
+ updateSelectionForMouseDownDispatchingSelectStart( |
+ innerNode, selection, CharacterGranularity, |
+ HandleVisibility::Visible); |
+ return false; |
+ } |
+ } |
+ |
if (extendSelection && !selection.isNone()) { |
// Note: "fast/events/shift-click-user-select-none.html" makes |
// |pos.isNull()| true. |
@@ -211,22 +216,37 @@ bool SelectionController::handleMousePressEventSingleClick( |
updateSelectionForMouseDownDispatchingSelectStart( |
innerNode, createVisibleSelection(builder.build()), |
- this->selection().granularity()); |
+ this->selection().granularity(), HandleVisibility::NotVisible); |
return false; |
} |
if (m_selectionState == SelectionState::ExtendedSelection) { |
- updateSelectionForMouseDownDispatchingSelectStart(innerNode, selection, |
- CharacterGranularity); |
+ updateSelectionForMouseDownDispatchingSelectStart( |
+ innerNode, selection, CharacterGranularity, |
+ HandleVisibility::NotVisible); |
return false; |
} |
if (visiblePos.isNull()) { |
updateSelectionForMouseDownDispatchingSelectStart( |
- innerNode, VisibleSelectionInFlatTree(), CharacterGranularity); |
+ innerNode, VisibleSelectionInFlatTree(), CharacterGranularity, |
+ HandleVisibility::NotVisible); |
return false; |
} |
+ bool isHandleVisible = false; |
+ if (hasEditableStyle(*innerNode)) { |
+ const bool isTextBoxEmpty = |
+ createVisibleSelection(SelectionInFlatTree::Builder() |
+ .selectAllChildren(*innerNode) |
+ .build()) |
+ .isCaret(); |
+ const bool notLeftClick = event.event().pointerProperties().button != |
+ WebPointerProperties::Button::Left; |
+ if (!isTextBoxEmpty || notLeftClick) |
+ isHandleVisible = event.event().fromTouch(); |
+ } |
+ |
updateSelectionForMouseDownDispatchingSelectStart( |
innerNode, |
expandSelectionToRespectUserSelectAll( |
@@ -234,7 +254,8 @@ bool SelectionController::handleMousePressEventSingleClick( |
SelectionInFlatTree::Builder() |
.collapse(visiblePos.toPositionWithAffinity()) |
.build())), |
- CharacterGranularity); |
+ CharacterGranularity, isHandleVisible ? HandleVisibility::Visible |
+ : HandleVisibility::NotVisible); |
return false; |
} |
@@ -364,13 +385,15 @@ void SelectionController::updateSelectionForMouseDrag( |
} |
setNonDirectionalSelectionIfNeeded(newSelection, selection().granularity(), |
- AdjustEndpointsAtBidiBoundary); |
+ AdjustEndpointsAtBidiBoundary, |
+ HandleVisibility::NotVisible); |
} |
bool SelectionController::updateSelectionForMouseDownDispatchingSelectStart( |
Node* targetNode, |
const VisibleSelectionInFlatTree& selection, |
- TextGranularity granularity) { |
+ TextGranularity granularity, |
+ HandleVisibility handleVisibility) { |
if (targetNode && targetNode->layoutObject() && |
!targetNode->layoutObject()->isSelectable()) |
return false; |
@@ -393,7 +416,7 @@ bool SelectionController::updateSelectionForMouseDownDispatchingSelectStart( |
} |
setNonDirectionalSelectionIfNeeded(selection, granularity, |
- DoNotAdjustEndpoints); |
+ DoNotAdjustEndpoints, handleVisibility); |
return true; |
} |
@@ -427,6 +450,7 @@ bool SelectionController::selectClosestWordFromHitTestResult( |
.build()); |
} |
+ HandleVisibility visibility = HandleVisibility::NotVisible; |
if (selectInputEventType == SelectInputEventType::Touch) { |
// If node doesn't have text except space, tab or line break, do not |
// select that 'empty' area. |
@@ -444,6 +468,8 @@ bool SelectionController::selectClosestWordFromHitTestResult( |
newSelection.rootEditableElement()) |
.deepEquivalent()) |
return false; |
+ |
+ visibility = HandleVisibility::Visible; |
} |
if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend) |
@@ -451,7 +477,7 @@ bool SelectionController::selectClosestWordFromHitTestResult( |
return updateSelectionForMouseDownDispatchingSelectStart( |
innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), |
- WordGranularity); |
+ WordGranularity, visibility); |
} |
void SelectionController::selectClosestMisspellingFromHitTestResult( |
@@ -485,7 +511,7 @@ void SelectionController::selectClosestMisspellingFromHitTestResult( |
updateSelectionForMouseDownDispatchingSelectStart( |
innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), |
- WordGranularity); |
+ WordGranularity, HandleVisibility::NotVisible); |
} |
void SelectionController::selectClosestWordFromMouseEvent( |
@@ -542,7 +568,7 @@ void SelectionController::selectClosestWordOrLinkFromMouseEvent( |
updateSelectionForMouseDownDispatchingSelectStart( |
innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), |
- WordGranularity); |
+ WordGranularity, HandleVisibility::NotVisible); |
} |
// TODO(xiaochengh): We should not use reference to return value. |
@@ -600,7 +626,8 @@ static void adjustEndpointsAtBidiBoundary( |
void SelectionController::setNonDirectionalSelectionIfNeeded( |
const VisibleSelectionInFlatTree& passedNewSelection, |
TextGranularity granularity, |
- EndPointsAdjustmentMode endpointsAdjustmentMode) { |
+ EndPointsAdjustmentMode endpointsAdjustmentMode, |
+ HandleVisibility handleVisibility) { |
VisibleSelectionInFlatTree newSelection = passedNewSelection; |
bool isDirectional = |
m_frame->editor().behavior().shouldConsiderSelectionAsDirectional() || |
@@ -640,11 +667,16 @@ void SelectionController::setNonDirectionalSelectionIfNeeded( |
// Adjusting base and extent will make newSelection always directional |
newSelection.setIsDirectional(isDirectional); |
- if (selection().visibleSelection<EditingInFlatTreeStrategy>() == newSelection) |
+ const bool isHandleVisible = handleVisibility == HandleVisibility::Visible; |
+ if (selection().visibleSelection<EditingInFlatTreeStrategy>() == |
+ newSelection && |
+ selection().isHandleVisible() == isHandleVisible) |
return; |
- const FrameSelection::SetSelectionOptions options = |
+ FrameSelection::SetSelectionOptions options = |
FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle; |
+ if (isHandleVisible) |
+ options |= FrameSelection::HandleVisible; |
selection().setSelection(newSelection, options, CursorAlignOnScroll::IfNeeded, |
granularity); |
} |
@@ -670,7 +702,7 @@ bool SelectionController::setCaretAtHitTestResult( |
SelectionInFlatTree::Builder() |
.collapse(visiblePos.toPositionWithAffinity()) |
.build())), |
- CharacterGranularity); |
+ CharacterGranularity, HandleVisibility::Visible); |
} |
bool SelectionController::handleMousePressEventDoubleClick( |
@@ -733,9 +765,12 @@ bool SelectionController::handleMousePressEventTripleClick( |
.build()); |
} |
+ bool isHandleVisible = event.event().fromTouch() && newSelection.isRange(); |
+ |
return updateSelectionForMouseDownDispatchingSelectStart( |
innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), |
- ParagraphGranularity); |
+ ParagraphGranularity, isHandleVisible ? HandleVisibility::Visible |
+ : HandleVisibility::NotVisible); |
} |
void SelectionController::handleMousePressEvent( |
@@ -945,7 +980,7 @@ void SelectionController::sendContextMenuEvent( |
const LayoutPoint& position) { |
if (!selection().isAvailable()) |
return; |
- if (selection().contains(position) || mev.scrollbar() || |
+ if (selection().contains(mev.hitTestResult()) || 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 |
@@ -974,8 +1009,7 @@ void SelectionController::passMousePressEventToSubframe( |
// 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 (!selection().contains(p)) |
+ if (!selection().contains(mev.hitTestResult())) |
return; |
// TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |