Commit 39d0fed9 authored by lushnikov's avatar lushnikov Committed by Commit bot

Revert of Move SelectionAdjust to its own file (patchset #2 id:20001 of...

Revert of Move SelectionAdjust to its own file (patchset #2 id:20001 of https://codereview.chromium.org/1640623002/ )

Reason for revert:
This refactoring breaks text selection in DevTools console. Please see http://crbug.com/581800 for details

Original issue's description:
> Move SelectionAdjuster to its own file
>
> This patch moves implementations of |SelectionAdjuster| into its own file.
>
> This is a follow-up patch of http://crrev.com/1630903005, which introduces
> |SelectionAdjuster| into "SelectionEditor.cpp" and "VisibleSelection.cpp".
>
> BUG=n/a
> TEST=n/a; no behavior changes
>
> Committed: https://crrev.com/da8f47a0153b025331e2c8ed62c4f6510c63c703
> Cr-Commit-Position: refs/heads/master@{#371751}

TBR=tkent@chromium.org,yosin@chromium.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=n/a

Review URL: https://codereview.chromium.org/1640913002

Cr-Commit-Position: refs/heads/master@{#371854}
parent d02c46df
......@@ -1399,8 +1399,6 @@
'editing/PositionWithAffinity.h',
'editing/RenderedPosition.cpp',
'editing/RenderedPosition.h',
'editing/SelectionAdjuster.cpp',
'editing/SelectionAdjuster.h',
'editing/SelectionController.cpp',
'editing/SelectionController.h',
'editing/SelectionEditor.cpp',
......
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SelectionAdjuster_h
#define SelectionAdjuster_h
#include "core/editing/VisibleSelection.h"
#include "wtf/Allocator.h"
namespace blink {
// |SelectionAdjuster| adjusts positions in |VisibleSelection| directly without
// calling |validate()|. Users of |SelectionAdjuster| should keep invariant of
// |VisibleSelection|, e.g. all positions are canonicalized.
class SelectionAdjuster final {
STATIC_ONLY(SelectionAdjuster);
public:
static void adjustSelectionInComposedTree(VisibleSelectionInComposedTree*, const VisibleSelection&);
static void adjustSelectionInDOMTree(VisibleSelection*, const VisibleSelectionInComposedTree&);
static void adjustSelectionToAvoidCrossingShadowBoundaries(VisibleSelection*);
static void adjustSelectionToAvoidCrossingShadowBoundaries(VisibleSelectionInComposedTree*);
};
} // namespace blink
#endif // SelectionAdjuster_h
......@@ -27,7 +27,6 @@
#include "core/editing/EditingUtilities.h"
#include "core/editing/Editor.h"
#include "core/editing/SelectionAdjuster.h"
#include "core/events/Event.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
......@@ -98,6 +97,83 @@ void SelectionEditor::setVisibleSelection(const VisibleSelectionInComposedTree&
SelectionAdjuster::adjustSelectionInDOMTree(&m_selection, m_selectionInComposedTree);
}
// TODO(yosin): We should move
// |SelectionAdjuster::adjustSelectionInComposedTree()| to
// "SelectionAdjuster.cpp"
// Updates |selectionInComposedTree| to match with |selection|.
void SelectionAdjuster::adjustSelectionInComposedTree(VisibleSelectionInComposedTree* selectionInComposedTree, const VisibleSelection& selection)
{
if (selection.isNone()) {
*selectionInComposedTree = VisibleSelectionInComposedTree();
return;
}
const PositionInComposedTree& base = toPositionInComposedTree(selection.base());
const PositionInComposedTree& extent = toPositionInComposedTree(selection.extent());
const PositionInComposedTree& position1 = toPositionInComposedTree(selection.start());
const PositionInComposedTree& position2 = toPositionInComposedTree(selection.end());
position1.anchorNode()->updateDistribution();
position2.anchorNode()->updateDistribution();
selectionInComposedTree->m_base = base;
selectionInComposedTree->m_extent = extent;
selectionInComposedTree->m_affinity = selection.m_affinity;
selectionInComposedTree->m_isDirectional = selection.m_isDirectional;
selectionInComposedTree->m_baseIsFirst = base.isNull() || base.compareTo(extent) <= 0;
if (position1.compareTo(position2) <= 0) {
selectionInComposedTree->m_start = position1;
selectionInComposedTree->m_end = position2;
} else {
selectionInComposedTree->m_start = position2;
selectionInComposedTree->m_end = position1;
}
selectionInComposedTree->updateSelectionType();
}
static bool isCrossingShadowBoundaries(const VisibleSelectionInComposedTree& selection)
{
if (!selection.isRange())
return false;
TreeScope& treeScope = selection.base().anchorNode()->treeScope();
return selection.extent().anchorNode()->treeScope() != treeScope
|| selection.start().anchorNode()->treeScope() != treeScope
|| selection.end().anchorNode()->treeScope() != treeScope;
}
// TODO(yosin): We should move
// |SelectionAdjuster::adjustSelectionInDOMTree()| to
// "SelectionAdjuster.cpp"
void SelectionAdjuster::adjustSelectionInDOMTree(VisibleSelection* selection, const VisibleSelectionInComposedTree& selectionInComposedTree)
{
if (selectionInComposedTree.isNone()) {
*selection = VisibleSelection();
return;
}
const Position& base = toPositionInDOMTree(selectionInComposedTree.base());
const Position& extent = toPositionInDOMTree(selectionInComposedTree.extent());
if (isCrossingShadowBoundaries(selectionInComposedTree)) {
*selection = VisibleSelection(base, extent);
return;
}
const Position& position1 = toPositionInDOMTree(selectionInComposedTree.start());
const Position& position2 = toPositionInDOMTree(selectionInComposedTree.end());
selection->m_base = base;
selection->m_extent = extent;
selection->m_affinity = selectionInComposedTree.m_affinity;
selection->m_isDirectional = selectionInComposedTree.m_isDirectional;
selection->m_baseIsFirst = base.isNull() || base.compareTo(extent) <= 0;
if (position1.compareTo(position2) <= 0) {
selection->m_start = position1;
selection->m_end = position2;
} else {
selection->m_start = position2;
selection->m_end = position1;
}
selection->updateSelectionType();
}
void SelectionEditor::resetXPosForVerticalArrowNavigation()
{
m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation();
......
......@@ -30,7 +30,6 @@
#include "core/dom/Element.h"
#include "core/dom/Range.h"
#include "core/editing/EditingUtilities.h"
#include "core/editing/SelectionAdjuster.h"
#include "core/editing/iterators/CharacterIterator.h"
#include "core/layout/LayoutObject.h"
#include "platform/geometry/LayoutPoint.h"
......@@ -514,6 +513,56 @@ void VisibleSelectionTemplate<Strategy>::updateSelectionType()
m_affinity = TextAffinity::Downstream;
}
static Node* enclosingShadowHost(Node* node)
{
for (Node* runner = node; runner; runner = ComposedTreeTraversal::parent(*runner)) {
if (isShadowHost(runner))
return runner;
}
return nullptr;
}
static bool isEnclosedBy(const PositionInComposedTree& position, const Node& node)
{
ASSERT(position.isNotNull());
Node* anchorNode = position.anchorNode();
if (anchorNode == node)
return !position.isAfterAnchor() && !position.isBeforeAnchor();
return ComposedTreeTraversal::isDescendantOf(*anchorNode, node);
}
static bool isSelectionBoundary(const Node& node)
{
return isHTMLTextAreaElement(node) || isHTMLInputElement(node) || isHTMLSelectElement(node);
}
static Node* enclosingShadowHostForStart(const PositionInComposedTree& position)
{
Node* node = position.nodeAsRangeFirstNode();
if (!node)
return nullptr;
Node* shadowHost = enclosingShadowHost(node);
if (!shadowHost)
return nullptr;
if (!isEnclosedBy(position, *shadowHost))
return nullptr;
return isSelectionBoundary(*shadowHost) ? shadowHost : nullptr;
}
static Node* enclosingShadowHostForEnd(const PositionInComposedTree& position)
{
Node* node = position.nodeAsRangeLastNode();
if (!node)
return nullptr;
Node* shadowHost = enclosingShadowHost(node);
if (!shadowHost)
return nullptr;
if (!isEnclosedBy(position, *shadowHost))
return nullptr;
return isSelectionBoundary(*shadowHost) ? shadowHost : nullptr;
}
template <typename Strategy>
void VisibleSelectionTemplate<Strategy>::validate(TextGranularity granularity)
{
......@@ -596,6 +645,128 @@ void VisibleSelectionTemplate<Strategy>::setWithoutValidation(const PositionTemp
didChange();
}
static PositionInComposedTree adjustPositionInComposedTreeForStart(const PositionInComposedTree& position, Node* shadowHost)
{
if (isEnclosedBy(position, *shadowHost)) {
if (position.isBeforeChildren())
return PositionInComposedTree::beforeNode(shadowHost);
return PositionInComposedTree::afterNode(shadowHost);
}
// We use |firstChild|'s after instead of beforeAllChildren for backward
// compatibility. The positions are same but the anchors would be different,
// and selection painting uses anchor nodes.
if (Node* firstChild = ComposedTreeTraversal::firstChild(*shadowHost))
return PositionInComposedTree::beforeNode(firstChild);
return PositionInComposedTree();
}
static Position adjustPositionForEnd(const Position& currentPosition, Node* startContainerNode)
{
TreeScope& treeScope = startContainerNode->treeScope();
ASSERT(currentPosition.computeContainerNode()->treeScope() != treeScope);
if (Node* ancestor = treeScope.ancestorInThisScope(currentPosition.computeContainerNode())) {
if (ancestor->contains(startContainerNode))
return positionAfterNode(ancestor);
return positionBeforeNode(ancestor);
}
if (Node* lastChild = treeScope.rootNode().lastChild())
return positionAfterNode(lastChild);
return Position();
}
static PositionInComposedTree adjustPositionInComposedTreeForEnd(const PositionInComposedTree& position, Node* shadowHost)
{
if (isEnclosedBy(position, *shadowHost)) {
if (position.isAfterChildren())
return PositionInComposedTree::afterNode(shadowHost);
return PositionInComposedTree::beforeNode(shadowHost);
}
// We use |lastChild|'s after instead of afterAllChildren for backward
// compatibility. The positions are same but the anchors would be different,
// and selection painting uses anchor nodes.
if (Node* lastChild = ComposedTreeTraversal::lastChild(*shadowHost))
return PositionInComposedTree::afterNode(lastChild);
return PositionInComposedTree();
}
static Position adjustPositionForStart(const Position& currentPosition, Node* endContainerNode)
{
TreeScope& treeScope = endContainerNode->treeScope();
ASSERT(currentPosition.computeContainerNode()->treeScope() != treeScope);
if (Node* ancestor = treeScope.ancestorInThisScope(currentPosition.computeContainerNode())) {
if (ancestor->contains(endContainerNode))
return positionBeforeNode(ancestor);
return positionAfterNode(ancestor);
}
if (Node* firstChild = treeScope.rootNode().firstChild())
return positionBeforeNode(firstChild);
return Position();
}
// TODO(yosin): We should move
// |SelectionAdjuster::adjustSelectionToAvoidCrossingShadowBoundaries()| to
// "SelectionAdjuster.cpp"
void SelectionAdjuster::adjustSelectionToAvoidCrossingShadowBoundaries(VisibleSelection* selection)
{
// Note: |m_selectionType| isn't computed yet.
ASSERT(selection->base().isNotNull());
ASSERT(selection->extent().isNotNull());
ASSERT(selection->start().isNotNull());
ASSERT(selection->end().isNotNull());
// TODO(hajimehoshi): Checking treeScope is wrong when a node is
// distributed, but we leave it as it is for backward compatibility.
if (selection->start().anchorNode()->treeScope() == selection->end().anchorNode()->treeScope())
return;
if (selection->isBaseFirst()) {
const Position& newEnd = adjustPositionForEnd(selection->end(), selection->start().computeContainerNode());
selection->m_extent = newEnd;
selection->m_end = newEnd;
return;
}
const Position& newStart = adjustPositionForStart(selection->start(), selection->end().computeContainerNode());
selection->m_extent = newStart;
selection->m_start = newStart;
}
// TODO(yosin): We should move
// |SelectionAdjuster::adjustSelectionToAvoidCrossingShadowBoundaries()| to
// "SelectionAdjuster.cpp"
// This function is called twice. The first is called when |m_start| and |m_end|
// or |m_extent| are same, and the second when |m_start| and |m_end| are changed
// after downstream/upstream.
void SelectionAdjuster::adjustSelectionToAvoidCrossingShadowBoundaries(VisibleSelectionInComposedTree* selection)
{
Node* const shadowHostStart = enclosingShadowHostForStart(selection->start());
Node* const shadowHostEnd = enclosingShadowHostForEnd(selection->end());
if (shadowHostStart == shadowHostEnd)
return;
if (selection->isBaseFirst()) {
Node* const shadowHost = shadowHostStart ? shadowHostStart : shadowHostEnd;
const PositionInComposedTree& newEnd = adjustPositionInComposedTreeForEnd(selection->end(), shadowHost);
selection->m_extent = newEnd;
selection->m_end = newEnd;
return;
}
Node* const shadowHost = shadowHostEnd ? shadowHostEnd : shadowHostStart;
const PositionInComposedTree& newStart = adjustPositionInComposedTreeForStart(selection->start(), shadowHost);
selection->m_extent = newStart;
selection->m_start = newStart;
}
template <typename Strategy>
void VisibleSelectionTemplate<Strategy>::adjustSelectionToAvoidCrossingShadowBoundaries()
{
......
......@@ -205,6 +205,16 @@ extern template class CORE_EXTERN_TEMPLATE_EXPORT VisibleSelectionTemplate<Editi
using VisibleSelection = VisibleSelectionTemplate<EditingStrategy>;
using VisibleSelectionInComposedTree = VisibleSelectionTemplate<EditingInComposedTreeStrategy>;
// TODO(yosin): We should move |SelectionAdjuster| to its own file.
class SelectionAdjuster final {
STATIC_ONLY(SelectionAdjuster);
public:
static void adjustSelectionInComposedTree(VisibleSelectionInComposedTree*, const VisibleSelection&);
static void adjustSelectionInDOMTree(VisibleSelection*, const VisibleSelectionInComposedTree&);
static void adjustSelectionToAvoidCrossingShadowBoundaries(VisibleSelection*);
static void adjustSelectionToAvoidCrossingShadowBoundaries(VisibleSelectionInComposedTree*);
};
// TODO(yosin): We should use |operator==()| instead of
// |equalSelectionsInDOMTree()|.
bool equalSelectionsInDOMTree(const VisibleSelection&, const VisibleSelection&);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment