Chromium Code Reviews| Index: third_party/WebKit/Source/core/editing/FrameSelection.cpp |
| diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.cpp b/third_party/WebKit/Source/core/editing/FrameSelection.cpp |
| index 10a702562f5f21f4b2e96cf80b2d4582bd1f1942..686b2ca9dd7e35c840640d079ed19f09f4ba5fd9 100644 |
| --- a/third_party/WebKit/Source/core/editing/FrameSelection.cpp |
| +++ b/third_party/WebKit/Source/core/editing/FrameSelection.cpp |
| @@ -110,16 +110,17 @@ const DisplayItemClient& FrameSelection::caretDisplayItemClientForTesting() |
| return m_frameCaret->displayItemClient(); |
| } |
| -const Document& FrameSelection::document() const { |
| +Document& FrameSelection::document() const { |
| DCHECK(lifecycleContext()); |
| return *lifecycleContext(); |
| } |
| -Document& FrameSelection::document() { |
| - DCHECK(lifecycleContext()); |
| - return *lifecycleContext(); |
| +bool FrameSelection::isHandleVisible() const { |
| + return selectionInDOMTree().isHandleVisible(); |
| } |
| +// TODO(yosin): We should replace // |visibleSelection<EditingStrategy>()| to |
|
tkent
2017/02/10 08:47:40
nit: Looks the second "//" is unnecessary.
yosin_UTC9
2017/02/10 10:13:20
Done.
|
| +// |computeVisibleSelectionInDOMTree()|. |
| // TODO(yosin): To avoid undefined symbols in clang, we explicitly |
| // have specialized version of |FrameSelection::visibleSelection<Strategy>| |
| // before |FrameSelection::selection()| which refers this. |
| @@ -129,12 +130,29 @@ const VisibleSelection& FrameSelection::visibleSelection<EditingStrategy>() |
| return m_selectionEditor->visibleSelection<EditingStrategy>(); |
| } |
| +// TODO(yosin): We should replace |
| +// |visibleSelection<EditingInFlatTreeStrategy>()| to |
|
tkent
2017/02/10 08:47:41
nit |to| -> |with| or |by|
yosin_UTC9
2017/02/10 10:13:20
Done.
|
| +// |computeVisibleSelectionInFlatTree()|. |
| template <> |
| const VisibleSelectionInFlatTree& |
| FrameSelection::visibleSelection<EditingInFlatTreeStrategy>() const { |
| return m_selectionEditor->visibleSelection<EditingInFlatTreeStrategy>(); |
| } |
| +const VisibleSelection& FrameSelection::computeVisibleSelectionInDOMTree() |
| + const { |
| + return m_selectionEditor->computeVisibleSelectionInDOMTree(); |
| +} |
| + |
| +const VisibleSelectionInFlatTree& |
| +FrameSelection::computeVisibleSelectionInFlatTree() const { |
| + return m_selectionEditor->computeVisibleSelectionInFlatTree(); |
| +} |
| + |
| +const SelectionInDOMTree& FrameSelection::selectionInDOMTree() const { |
| + return m_selectionEditor->selectionInDOMTree(); |
| +} |
| + |
| Element* FrameSelection::rootEditableElementOrDocumentElement() const { |
| Element* selectionRoot = selection().rootEditableElement(); |
| return selectionRoot ? selectionRoot : document().documentElement(); |
| @@ -149,8 +167,13 @@ ContainerNode* FrameSelection::rootEditableElementOrTreeScopeRootNode() const { |
| return node ? &node->treeScope().rootNode() : 0; |
| } |
| +// TODO(yosin): We should rename |FrameSelection::selection()| to |
| +// |selectionDeprecated()|. |
| const VisibleSelection& FrameSelection::selection() const { |
| - return visibleSelection<EditingStrategy>(); |
| + // TODO(yosin): We should hoist updateStyleAndLayoutIgnorePendingStylesheets |
| + // to caller. See http://crbug.com/590369 for more details. |
| + document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| + return computeVisibleSelectionInDOMTree(); |
| } |
| const VisibleSelectionInFlatTree& FrameSelection::selectionInFlatTree() const { |
| @@ -174,29 +197,22 @@ void FrameSelection::moveCaretSelection(const IntPoint& point) { |
| setSelection(builder.build(), CloseTyping | ClearTypingStyle | UserTriggered); |
| } |
| -template <typename Strategy> |
| -void FrameSelection::setSelectionAlgorithm( |
| - const VisibleSelectionTemplate<Strategy>& newSelection, |
| - HandleVisibility handleVisibility, |
| - SetSelectionOptions options, |
| - CursorAlignOnScroll align, |
| - TextGranularity granularity) { |
| +void FrameSelection::setSelection(const SelectionInDOMTree& passedSelection, |
| + SetSelectionOptions options, |
| + CursorAlignOnScroll align, |
| + TextGranularity granularity) { |
| DCHECK(isAvailable()); |
| - DCHECK(newSelection.isValidFor(document())); |
| - const Document& currentDocument = document(); |
| + passedSelection.assertValidFor(document()); |
| + |
| + SelectionInDOMTree::Builder builder(passedSelection); |
| + if (shouldAlwaysUseDirectionalSelection(m_frame)) |
| + builder.setIsDirectional(true); |
| + SelectionInDOMTree newSelection = builder.build(); |
| if (m_granularityStrategy && |
| (options & FrameSelection::DoNotClearStrategy) == 0) |
| m_granularityStrategy->Clear(); |
| bool closeTyping = options & CloseTyping; |
| bool shouldClearTypingStyle = options & ClearTypingStyle; |
| - EUserTriggered userTriggered = selectionOptionsToUserTriggered(options); |
| - |
| - // TODO(editing-dev): We should rename variable |s| to another name to avoid |
| - // using one letter variable name. |
| - VisibleSelectionTemplate<Strategy> s = newSelection; |
| - if (shouldAlwaysUseDirectionalSelection(m_frame)) |
| - s.setIsDirectional(true); |
| - |
| m_granularity = granularity; |
| // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to |
| @@ -207,23 +223,27 @@ void FrameSelection::setSelectionAlgorithm( |
| if (shouldClearTypingStyle) |
| m_frame->editor().clearTypingStyle(); |
| - if (m_selectionEditor->visibleSelection<Strategy>() == s && |
| - m_handleVisibility == handleVisibility) { |
| - // Even if selection was not changed, selection offsets may have been |
| - // changed. |
| - notifyLayoutObjectOfSelectionChange(userTriggered); |
| + const SelectionInDOMTree oldSelectionInDOMTree = |
| + m_selectionEditor->selectionInDOMTree(); |
| + if (oldSelectionInDOMTree == newSelection) |
| return; |
| - } |
| - |
| - const VisibleSelectionTemplate<Strategy> oldSelection = |
| - visibleSelection<Strategy>(); |
| - const Position& oldSelectionStart = selection().start(); |
| - |
| - m_handleVisibility = handleVisibility; |
| - m_selectionEditor->setVisibleSelection(s, options); |
| + m_selectionEditor->setSelection(newSelection); |
| scheduleVisualUpdateForPaintInvalidationIfNeeded(); |
| - if (!s.isNone() && !(options & DoNotSetFocus)) { |
| + // TODO(yosin): The use of updateStyleAndLayoutIgnorePendingStylesheets |
| + // needs to be audited. see http://crbug.com/590369 for more details. |
| + document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| + |
| + const Document& currentDocument = document(); |
| + // TODO(yosin): We should get rid of unsued |options| for |
| + // |Editor::respondToChangedSelection()|. |
| + // Note: Since, setting focus can modify DOM tree, we should use |
| + // |oldSelection| before setting focus |
| + m_frame->editor().respondToChangedSelection( |
| + createVisibleSelection(oldSelectionInDOMTree).start(), options); |
| + DCHECK_EQ(currentDocument, document()); |
| + |
| + if (!selection().isNone() && !(options & DoNotSetFocus)) { |
| setFocusedNodeIfNeeded(); |
| // |setFocusedNodeIfNeeded()| dispatches sync events "FocusOut" and |
| // "FocusIn", |m_frame| may associate to another document. |
| @@ -243,6 +263,7 @@ void FrameSelection::setSelectionAlgorithm( |
| // Always clear the x position used for vertical arrow navigation. |
| // It will be restored by the vertical arrow navigation code if necessary. |
| m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation(); |
| + // TODO(yosin): Can we move this to at end of this function? |
| // This may dispatch a synchronous focus-related events. |
| selectFrameElementInParentIfFullySelected(); |
| if (!isAvailable() || document() != currentDocument) { |
| @@ -251,16 +272,8 @@ void FrameSelection::setSelectionAlgorithm( |
| // reach here. |
| return; |
| } |
| + EUserTriggered userTriggered = selectionOptionsToUserTriggered(options); |
| notifyLayoutObjectOfSelectionChange(userTriggered); |
| - // If the selections are same in the DOM tree but not in the flat tree, |
| - // don't fire events. For example, if the selection crosses shadow tree |
| - // boundary, selection for the DOM tree is shrunk while that for the |
| - // flat tree is not. Additionally, this case occurs in some edge cases. |
| - // See also: editing/pasteboard/4076267-3.html |
| - if (oldSelection == m_selectionEditor->visibleSelection<Strategy>()) |
| - return; |
| - |
| - m_frame->editor().respondToChangedSelection(oldSelectionStart, options); |
| if (userTriggered == UserTriggered) { |
| ScrollAlignment alignment; |
| @@ -273,6 +286,11 @@ void FrameSelection::setSelectionAlgorithm( |
| ? ScrollAlignment::alignTopAlways |
| : ScrollAlignment::alignToEdgeIfNeeded; |
| + // TODO(editing-dev): The use of |
| + // updateStyleAndLayoutIgnorePendingStylesheets |
| + // needs to be audited. See http://crbug.com/590369 for more details. |
| + document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| + |
| revealSelection(alignment, RevealExtent); |
| } |
| @@ -283,44 +301,20 @@ void FrameSelection::setSelectionAlgorithm( |
| Event::create(EventTypeNames::selectionchange)); |
| } |
| -// TODO(yosin): We will make |selectionInDOMTree| version of |SetSelection()| |
| -// as primary function instead of wrapper. |
| -void FrameSelection::setSelection(const SelectionInDOMTree& newSelection, |
| - SetSelectionOptions options, |
| - CursorAlignOnScroll align, |
| - TextGranularity granularity) { |
| - if (!newSelection.isNone()) { |
| - // TODO(editing-dev): The use of |
| - // updateStyleAndLayoutIgnorePendingStylesheets |
| - // needs to be audited. See http://crbug.com/590369 for more details. |
| - newSelection.base() |
| - .document() |
| - ->updateStyleAndLayoutIgnorePendingStylesheets(); |
| - } |
| - setSelection(createVisibleSelection(newSelection), |
| - newSelection.isHandleVisible() ? HandleVisibility::Visible |
| - : HandleVisibility::NotVisible, |
| - options, align, granularity); |
| -} |
| - |
| -// TODO(yosin): We will make |selectionInFlatTree| version of |SetSelection()| |
| -// as primary function instead of wrapper. |
| void FrameSelection::setSelection(const SelectionInFlatTree& newSelection, |
| SetSelectionOptions options, |
| CursorAlignOnScroll align, |
| TextGranularity granularity) { |
| - if (!newSelection.isNone()) { |
| - // TODO(editing-dev): The use of |
| - // updateStyleAndLayoutIgnorePendingStylesheets |
| - // needs to be audited. See http://crbug.com/590369 for more details. |
| - newSelection.base() |
| - .document() |
| - ->updateStyleAndLayoutIgnorePendingStylesheets(); |
| - } |
| - setSelection(createVisibleSelection(newSelection), |
| - newSelection.isHandleVisible() ? HandleVisibility::Visible |
| - : HandleVisibility::NotVisible, |
| - options, align, granularity); |
| + newSelection.assertValidFor(document()); |
| + SelectionInDOMTree::Builder builder; |
| + builder.setAffinity(newSelection.affinity()) |
| + .setBaseAndExtent(toPositionInDOMTree(newSelection.base()), |
| + toPositionInDOMTree(newSelection.extent())) |
| + .setGranularity(newSelection.granularity()) |
| + .setIsDirectional(newSelection.isDirectional()) |
| + .setIsHandleVisible(newSelection.isHandleVisible()) |
| + .setHasTrailingWhitespace(newSelection.hasTrailingWhitespace()); |
| + return setSelection(builder.build(), options, align, granularity); |
| } |
| void FrameSelection::setSelection(const VisibleSelection& newSelection, |
| @@ -328,13 +322,16 @@ void FrameSelection::setSelection(const VisibleSelection& newSelection, |
| SetSelectionOptions options, |
| CursorAlignOnScroll align, |
| TextGranularity granularity) { |
| - setSelectionAlgorithm<EditingStrategy>(newSelection, handleVisibility, |
| - options, align, granularity); |
| + setSelection( |
| + SelectionInDOMTree::Builder(newSelection.asSelection()) |
| + .setIsHandleVisible(handleVisibility == HandleVisibility::Visible) |
| + .build(), |
| + options, align, granularity); |
| } |
| void FrameSelection::setSelection(const VisibleSelection& newSelection, |
| SetSelectionOptions options) { |
| - setSelection(newSelection, HandleVisibility::NotVisible, options); |
| + setSelection(newSelection.asSelection(), options); |
| } |
| void FrameSelection::setSelection( |
| @@ -343,30 +340,22 @@ void FrameSelection::setSelection( |
| SetSelectionOptions options, |
| CursorAlignOnScroll align, |
| TextGranularity granularity) { |
| - setSelectionAlgorithm<EditingInFlatTreeStrategy>( |
| - newSelection, handleVisibility, options, align, granularity); |
| + setSelection( |
| + SelectionInFlatTree::Builder(newSelection.asSelection()) |
| + .setIsHandleVisible(handleVisibility == HandleVisibility::Visible) |
| + .build(), |
| + options, align, granularity); |
| } |
| void FrameSelection::setSelection( |
| const VisibleSelectionInFlatTree& newSelection, |
| SetSelectionOptions options) { |
| - setSelection(newSelection, HandleVisibility::NotVisible, options); |
| -} |
| - |
| -static bool removingNodeRemovesPosition(Node& node, const Position& position) { |
| - if (!position.anchorNode()) |
| - return false; |
| - |
| - if (position.anchorNode() == node) |
| - return true; |
| - |
| - if (!node.isElementNode()) |
| - return false; |
| - |
| - Element& element = toElement(node); |
| - return element.isShadowIncludingInclusiveAncestorOf(position.anchorNode()); |
| + setSelection(newSelection.asSelection(), options); |
| } |
| +// TODO(yosin): We should remove |computePositionForChildrenRemoval()| to |
|
tkent
2017/02/10 08:47:40
nit: remove -> move
yosin_UTC9
2017/02/10 10:13:20
Done.
|
| +// "SelectionEditor.cpp" since it used only in |
| +// |SelectionEditor::nodeChildrenWillBeRemoved()|. |
| static Position computePositionForChildrenRemoval(const Position& position, |
| ContainerNode& container) { |
| Node* node = position.computeContainerNode(); |
| @@ -376,122 +365,67 @@ static Position computePositionForChildrenRemoval(const Position& position, |
| } |
| void FrameSelection::nodeChildrenWillBeRemoved(ContainerNode& container) { |
| - if (isNone() || !container.inActiveDocument()) |
| + if (!container.inActiveDocument()) |
| + return; |
| + // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to |
| + // |Editor| class. |
| + if (!document().isRunningExecCommand()) |
| + TypingCommand::closeTyping(m_frame); |
| +} |
| + |
| +// TODO(yosin): We should move |SelectionEditor::nodeChildrenWillBeRemoved()| |
| +// to "SelectionEditor.cpp". |
| +void SelectionEditor::nodeChildrenWillBeRemoved(ContainerNode& container) { |
| + if (m_selection.isNone()) |
| return; |
| - const Position& oldStart = selection().start(); |
| - const Position& newStart = |
| - computePositionForChildrenRemoval(oldStart, container); |
| - const Position& oldEnd = selection().end(); |
| - const Position& newEnd = computePositionForChildrenRemoval(oldEnd, container); |
| - const Position& oldBase = selection().base(); |
| + const Position oldBase = m_selection.m_base; |
| + const Position oldExtent = m_selection.m_extent; |
| const Position& newBase = |
| computePositionForChildrenRemoval(oldBase, container); |
| - const Position& oldExtent = selection().extent(); |
| const Position& newExtent = |
| computePositionForChildrenRemoval(oldExtent, container); |
| - if (newStart == oldStart && newEnd == oldEnd && newBase == oldBase && |
| - newExtent == oldExtent) |
| + if (newBase == oldBase && newExtent == oldExtent) |
| return; |
| - if (selection().isBaseFirst()) |
| - m_selectionEditor->setWithoutValidation(newStart, newEnd); |
| - else |
| - m_selectionEditor->setWithoutValidation(newEnd, newStart); |
| - if (document().isRunningExecCommand()) |
| - return; |
| - TypingCommand::closeTyping(m_frame); |
| + m_selection = SelectionInDOMTree::Builder() |
| + .setBaseAndExtent(newBase, newExtent) |
| + .build(); |
| + markCacheDirty(); |
| } |
| void FrameSelection::nodeWillBeRemoved(Node& node) { |
| // There can't be a selection inside a fragment, so if a fragment's node is |
| - // being removed, the selection in the document that created the fragment |
| - // needs no adjustment. |
| - if (isNone() || !node.inActiveDocument()) |
| + // being removed, |
|
tkent
2017/02/10 08:47:40
nit: Text wrapping looks weird.
yosin_UTC9
2017/02/10 10:13:20
Done.
|
| + // the selection in the document that created the fragment needs no |
| + // adjustment. |
| + if (!node.inActiveDocument()) |
| return; |
| - |
| - respondToNodeModification( |
| - node, removingNodeRemovesPosition(node, selection().base()), |
| - removingNodeRemovesPosition(node, selection().extent()), |
| - removingNodeRemovesPosition(node, selection().start()), |
| - removingNodeRemovesPosition(node, selection().end())); |
| -} |
| - |
| -static SelectionState selectionStateOf(const Node& node) { |
| - const LayoutObject* layoutObject = node.layoutObject(); |
| - if (!layoutObject) |
| - return SelectionNone; |
| - return layoutObject->getSelectionState(); |
| -} |
| - |
| -void FrameSelection::respondToNodeModification(Node& node, |
| - bool baseRemoved, |
| - bool extentRemoved, |
| - bool startRemoved, |
| - bool endRemoved) { |
| - DCHECK(node.document().isActive()) << node; |
| - |
| - bool clearLayoutTreeSelection = false; |
| - bool clearDOMTreeSelection = false; |
| - |
| - if (startRemoved || endRemoved) { |
| - Position start = selection().start(); |
| - Position end = selection().end(); |
| - if (startRemoved) |
| - updatePositionForNodeRemoval(start, node); |
| - if (endRemoved) |
| - updatePositionForNodeRemoval(end, node); |
| - |
| - if (Position::commonAncestorTreeScope(start, end) && start.isNotNull() && |
| - end.isNotNull()) { |
| - if (selection().isBaseFirst()) |
| - m_selectionEditor->setWithoutValidation(start, end); |
| - else |
| - m_selectionEditor->setWithoutValidation(end, start); |
| - } else { |
| - clearDOMTreeSelection = true; |
| - } |
| - |
| - clearLayoutTreeSelection = true; |
| - } else if (baseRemoved || extentRemoved) { |
| - // The base and/or extent are about to be removed, but the start and end |
| - // aren't. Change the base and extent to the start and end, but don't |
| - // re-validate the selection, since doing so could move the start and end |
| - // into the node that is about to be removed. |
| - if (selection().isBaseFirst()) |
| - m_selectionEditor->setWithoutValidation(selection().start(), |
| - selection().end()); |
| - else |
| - m_selectionEditor->setWithoutValidation(selection().end(), |
| - selection().start()); |
| - } else if (selectionStateOf(node) != SelectionNone) { |
| - // When node to be removed is part of selection, we invalidate |
| - // selection to paint again. |
| - // TODO(yosin): We should paint changed area only rather than whole |
| - // selected range. |
| - clearLayoutTreeSelection = true; |
| - } |
| - |
| - if (clearLayoutTreeSelection) |
| - selection().start().document()->layoutViewItem().clearSelection(); |
| - |
| - if (clearDOMTreeSelection) |
| - setSelection(SelectionInDOMTree(), DoNotSetFocus); |
| - |
| // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to |
| // |Editor| class. |
| if (!document().isRunningExecCommand()) |
| TypingCommand::closeTyping(m_frame); |
| } |
| +// TODO(yosin): We should remove |updatePositionAfterAdoptingTextReplacement()| |
|
tkent
2017/02/10 08:47:41
nit: remove -> move
yosin_UTC9
2017/02/10 10:13:20
Done.
|
| +// to // "SelectionEditor.cpp" since it used only in |
|
tkent
2017/02/10 08:47:40
nit: the second '//' looks unnecessary.
yosin_UTC9
2017/02/10 10:13:20
Done.
|
| +// |SelectionEditor::didUpdateCharacterData()|. |
| static Position updatePositionAfterAdoptingTextReplacement( |
| const Position& position, |
| CharacterData* node, |
| unsigned offset, |
| unsigned oldLength, |
| unsigned newLength) { |
| - if (!position.anchorNode() || position.anchorNode() != node || |
| - !position.isOffsetInAnchor()) |
| + if (position.anchorNode() != node) |
| return position; |
| + if (position.isBeforeAnchor()) { |
| + return updatePositionAfterAdoptingTextReplacement( |
| + Position(node, 0), node, offset, oldLength, newLength); |
| + } |
| + if (position.isAfterAnchor()) { |
| + return updatePositionAfterAdoptingTextReplacement( |
| + Position(node, oldLength), node, offset, oldLength, newLength); |
| + } |
| + |
| // See: |
| // http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Mutation |
| DCHECK_GE(position.offsetInContainerNode(), 0); |
| @@ -514,69 +448,85 @@ static Position updatePositionAfterAdoptingTextReplacement( |
| if (positionOffset > node->length()) |
| positionOffset = node->length(); |
| - // CharacterNode in VisibleSelection must be Text node, because Comment |
| - // and ProcessingInstruction node aren't visible. |
| - return Position(toText(node), positionOffset); |
| + return Position(node, positionOffset); |
| } |
| -void FrameSelection::didUpdateCharacterData(CharacterData* node, |
| - unsigned offset, |
| - unsigned oldLength, |
| - unsigned newLength) { |
| +void SelectionEditor::didUpdateCharacterData(CharacterData* node, |
|
tkent
2017/02/10 08:47:40
nit: Add TODO comment about moving it to Selection
yosin_UTC9
2017/02/10 10:13:20
Done.
|
| + unsigned offset, |
| + unsigned oldLength, |
| + unsigned newLength) { |
| // The fragment check is a performance optimization. See |
| // http://trac.webkit.org/changeset/30062. |
| - if (isNone() || !node || !node->isConnected()) |
| + if (m_selection.isNone() || !node || !node->isConnected()) { |
| + didFinishDOMMutation(); |
| return; |
| - |
| - Position base = updatePositionAfterAdoptingTextReplacement( |
| - selection().base(), node, offset, oldLength, newLength); |
| - Position extent = updatePositionAfterAdoptingTextReplacement( |
| - selection().extent(), node, offset, oldLength, newLength); |
| - Position start = updatePositionAfterAdoptingTextReplacement( |
| - selection().start(), node, offset, oldLength, newLength); |
| - Position end = updatePositionAfterAdoptingTextReplacement( |
| - selection().end(), node, offset, oldLength, newLength); |
| - updateSelectionIfNeeded(base, extent, start, end); |
| + } |
| + const Position& newBase = updatePositionAfterAdoptingTextReplacement( |
| + m_selection.m_base, node, offset, oldLength, newLength); |
| + const Position& newExtent = updatePositionAfterAdoptingTextReplacement( |
| + m_selection.m_extent, node, offset, oldLength, newLength); |
| + didFinishTextChange(newBase, newExtent); |
| } |
| +// TODO(yosin): We should remove |updatePostionAfterAdoptingTextNodesMerged()| |
|
tkent
2017/02/10 08:47:41
nit: remove -> move
yosin_UTC9
2017/02/10 10:13:20
Done.
|
| +// to // "SelectionEditor.cpp" since it used only in |
|
tkent
2017/02/10 08:47:40
nit: the second '//' looks unnecessary.
yosin_UTC9
2017/02/10 10:13:20
Done.
|
| +// |SelectionEditor::didMergeTextNodes()|. |
| static Position updatePostionAfterAdoptingTextNodesMerged( |
| const Position& position, |
| - const Text& oldNode, |
| - unsigned offset) { |
| - if (!position.anchorNode() || !position.isOffsetInAnchor()) |
| - return position; |
| - |
| - DCHECK_GE(position.offsetInContainerNode(), 0); |
| - unsigned positionOffset = |
| - static_cast<unsigned>(position.offsetInContainerNode()); |
| - |
| - if (position.anchorNode() == &oldNode) |
| - return Position(toText(oldNode.previousSibling()), positionOffset + offset); |
| - |
| - if (position.anchorNode() == oldNode.parentNode() && positionOffset == offset) |
| - return Position(toText(oldNode.previousSibling()), offset); |
| - |
| + const Text& mergedNode, |
| + const NodeWithIndex& nodeToBeRemovedWithIndex, |
| + unsigned oldLength) { |
| + Node* const anchorNode = position.anchorNode(); |
| + const Node& nodeToBeRemoved = nodeToBeRemovedWithIndex.node(); |
| + switch (position.anchorType()) { |
| + case PositionAnchorType::BeforeChildren: |
| + case PositionAnchorType::AfterChildren: |
| + return position; |
| + case PositionAnchorType::BeforeAnchor: |
| + if (anchorNode == nodeToBeRemoved) |
| + return Position(const_cast<Text*>(&mergedNode), mergedNode.length()); |
| + return position; |
| + case PositionAnchorType::AfterAnchor: |
| + if (anchorNode == nodeToBeRemoved) |
| + return Position(const_cast<Text*>(&mergedNode), mergedNode.length()); |
| + if (anchorNode == mergedNode) |
| + return Position(const_cast<Text*>(&mergedNode), oldLength); |
| + return position; |
| + case PositionAnchorType::OffsetInAnchor: { |
| + const int offset = position.offsetInContainerNode(); |
| + if (anchorNode == nodeToBeRemoved) |
| + return Position(const_cast<Text*>(&mergedNode), oldLength + offset); |
| + if (anchorNode == nodeToBeRemoved.parentNode() && |
| + offset == nodeToBeRemovedWithIndex.index()) { |
| + return Position(const_cast<Text*>(&mergedNode), oldLength); |
| + } |
| + return position; |
| + } |
| + } |
| + NOTREACHED() << position; |
| return position; |
| } |
| -void FrameSelection::didMergeTextNodes( |
| +// TODO(yosin): We should move |SelectionEditor::didMergeTextNodes()| to |
| +// "SelectionEditor.cpp". |
| +void SelectionEditor::didMergeTextNodes( |
| const Text& mergedNode, |
| const NodeWithIndex& nodeToBeRemovedWithIndex, |
| - unsigned offset) { |
| - const Text& oldNode = toText(nodeToBeRemovedWithIndex.node()); |
| - if (isNone() || !oldNode.isConnected()) |
| + unsigned oldLength) { |
| + if (m_selection.isNone()) { |
| + didFinishDOMMutation(); |
| return; |
| - Position base = updatePostionAfterAdoptingTextNodesMerged(selection().base(), |
| - oldNode, offset); |
| - Position extent = updatePostionAfterAdoptingTextNodesMerged( |
| - selection().extent(), oldNode, offset); |
| - Position start = updatePostionAfterAdoptingTextNodesMerged( |
| - selection().start(), oldNode, offset); |
| - Position end = updatePostionAfterAdoptingTextNodesMerged(selection().end(), |
| - oldNode, offset); |
| - updateSelectionIfNeeded(base, extent, start, end); |
| + } |
| + const Position& newBase = updatePostionAfterAdoptingTextNodesMerged( |
| + m_selection.m_base, mergedNode, nodeToBeRemovedWithIndex, oldLength); |
| + const Position& newExtent = updatePostionAfterAdoptingTextNodesMerged( |
| + m_selection.m_extent, mergedNode, nodeToBeRemovedWithIndex, oldLength); |
| + didFinishTextChange(newBase, newExtent); |
| } |
| +// TODO(yosin): We should remove |updatePostionAfterAdoptingTextNodeSplit()| |
|
tkent
2017/02/10 08:47:40
nit: remove -> move
yosin_UTC9
2017/02/10 10:13:20
Done.
|
| +// to // "SelectionEditor.cpp" since it used only in |
|
tkent
2017/02/10 08:47:41
nit: the second '//' looks unnecessary.
yosin_UTC9
2017/02/10 10:13:20
Done.
|
| +// |SelectionEditor::didSplitTextNode()|. |
| static Position updatePostionAfterAdoptingTextNodeSplit( |
| const Position& position, |
| const Text& oldNode) { |
| @@ -594,37 +544,18 @@ static Position updatePostionAfterAdoptingTextNodeSplit( |
| return Position(toText(oldNode.nextSibling()), positionOffset - oldLength); |
| } |
| -void FrameSelection::didSplitTextNode(const Text& oldNode) { |
| - if (isNone() || !oldNode.isConnected()) |
| +// TODO(yosin): We should move |SelectionEditor::didSplitTextNode()| to |
| +// "SelectionEditor.cpp". |
| +void SelectionEditor::didSplitTextNode(const Text& oldNode) { |
| + if (m_selection.isNone() || !oldNode.isConnected()) { |
| + didFinishDOMMutation(); |
| return; |
| - Position base = |
| - updatePostionAfterAdoptingTextNodeSplit(selection().base(), oldNode); |
| - Position extent = |
| - updatePostionAfterAdoptingTextNodeSplit(selection().extent(), oldNode); |
| - Position start = |
| - updatePostionAfterAdoptingTextNodeSplit(selection().start(), oldNode); |
| - Position end = |
| - updatePostionAfterAdoptingTextNodeSplit(selection().end(), oldNode); |
| - updateSelectionIfNeeded(base, extent, start, end); |
| -} |
| - |
| -void FrameSelection::updateSelectionIfNeeded(const Position& base, |
| - const Position& extent, |
| - const Position& start, |
| - const Position& end) { |
| - if (base == selection().base() && extent == selection().extent() && |
| - start == selection().start() && end == selection().end()) |
| - return; |
| - // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to |
| - // |Editor| class. |
| - if (!document().isRunningExecCommand()) |
| - TypingCommand::closeTyping(m_frame); |
| - VisibleSelection newSelection; |
| - if (selection().isBaseFirst()) |
| - newSelection.setWithoutValidation(start, end); |
| - else |
| - newSelection.setWithoutValidation(end, start); |
| - setSelection(newSelection, DoNotSetFocus); |
| + } |
| + const Position& newBase = |
| + updatePostionAfterAdoptingTextNodeSplit(m_selection.m_base, oldNode); |
| + const Position& newExtent = |
| + updatePostionAfterAdoptingTextNodeSplit(m_selection.m_extent, oldNode); |
| + didFinishTextChange(newBase, newExtent); |
| } |
| void FrameSelection::didChangeFocus() { |
| @@ -731,7 +662,6 @@ void FrameSelection::contextDestroyed(Document* document) { |
| view.clearSelection(); |
| m_frame->editor().clearTypingStyle(); |
| - m_selectionEditor->documentDetached(*document); |
| } |
| void FrameSelection::clearPreviousCaretVisualRect(const LayoutBlock& block) { |
| @@ -754,8 +684,7 @@ void FrameSelection::invalidatePaintIfNeeded( |
| } |
| bool FrameSelection::shouldPaintCaret(const LayoutBlock& block) const { |
| - DCHECK(selection().isValidFor(document())); |
| - |
| + DCHECK_GE(document().lifecycle().state(), DocumentLifecycle::LayoutClean); |
| bool result = m_frameCaret->shouldPaintCaret(block); |
| DCHECK(!result || (isCaret() && hasEditableStyle())); |
| return result; |
| @@ -1075,10 +1004,8 @@ void FrameSelection::didLayout() { |
| } |
| void FrameSelection::updateAppearance() { |
| - m_frameCaret->updateAppearance(); |
| - |
| - if (m_frame->contentLayoutItem().isNull()) |
| - return; |
| + DCHECK(!m_frame->contentLayoutItem().isNull()); |
| + m_frameCaret->scheduleVisualUpdateForPaintInvalidationIfNeeded(); |
| m_pendingSelection->setHasPendingSelection(); |
| } |
| @@ -1281,10 +1208,6 @@ void FrameSelection::setSelectionFromNone() { |
| return; |
| if (HTMLBodyElement* body = |
| Traversal<HTMLBodyElement>::firstChild(*documentElement)) { |
| - // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
| - // needs to be audited. See http://crbug.com/590369 for more details. |
| - document->updateStyleAndLayoutIgnorePendingStylesheets(); |
| - |
| setSelection(SelectionInDOMTree::Builder() |
| .collapse(firstPositionInOrBeforeNode(body)) |
| .build()); |
| @@ -1395,18 +1318,19 @@ void FrameSelection::moveRangeSelectionExtent(const IntPoint& contentsPoint) { |
| void FrameSelection::moveRangeSelection(const VisiblePosition& basePosition, |
| const VisiblePosition& extentPosition, |
| TextGranularity granularity) { |
| - VisibleSelection newSelection = createVisibleSelection( |
| + SelectionInDOMTree newSelection = |
| SelectionInDOMTree::Builder() |
| .setBaseAndExtentDeprecated(basePosition.deepEquivalent(), |
| extentPosition.deepEquivalent()) |
| .setAffinity(basePosition.affinity()) |
| .setGranularity(granularity) |
| - .build()); |
| + .setIsHandleVisible(isHandleVisible()) |
| + .build(); |
| if (newSelection.isNone()) |
| return; |
| - setSelection(newSelection, m_handleVisibility, CloseTyping | ClearTypingStyle, |
| + setSelection(newSelection, CloseTyping | ClearTypingStyle, |
| CursorAlignOnScroll::IfNeeded, granularity); |
| } |