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

Unified Diff: third_party/WebKit/Source/core/editing/VisibleSelection.cpp

Issue 2759943004: CANCELLED Merge SelectionAdjuster into VisibleSelection part 2 (Closed)
Patch Set: Rebased Created 3 years, 9 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
Index: third_party/WebKit/Source/core/editing/VisibleSelection.cpp
diff --git a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
index 7c92aedaa22475018ccdb02c82e6ae8896b64974..89729a709525abcb7eeb12cc0fe823870dd0f974 100644
--- a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
@@ -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 "platform/geometry/LayoutPoint.h"
#include "wtf/Assertions.h"
@@ -40,6 +39,179 @@
namespace blink {
+namespace {
+
+enum class AdjustDirection { kAdjustNone, kAdjustStart, kAdjustEnd };
+
+Node* enclosingShadowHost(Node* node) {
+ for (Node* runner = node; runner;
+ runner = FlatTreeTraversal::parent(*runner)) {
+ if (isShadowHost(runner))
+ return runner;
+ }
+ return nullptr;
+}
+
+bool isEnclosedBy(const PositionInFlatTree& position, const Node& node) {
+ DCHECK(position.isNotNull());
+ Node* anchorNode = position.anchorNode();
+ if (anchorNode == node)
+ return !position.isAfterAnchor() && !position.isBeforeAnchor();
+
+ return FlatTreeTraversal::isDescendantOf(*anchorNode, node);
+}
+
+bool isSelectionBoundary(const Node& node) {
+ return isHTMLTextAreaElement(node) || isHTMLInputElement(node) ||
+ isHTMLSelectElement(node);
+}
+
+Node* enclosingShadowHostForStart(const PositionInFlatTree& 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;
+}
+
+Node* enclosingShadowHostForEnd(const PositionInFlatTree& 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;
+}
+
+PositionInFlatTree adjustPositionInFlatTreeForStart(
+ const PositionInFlatTree& position,
+ Node* shadowHost) {
+ if (isEnclosedBy(position, *shadowHost)) {
+ if (position.isBeforeChildren())
+ return PositionInFlatTree::beforeNode(shadowHost);
+ return PositionInFlatTree::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 = FlatTreeTraversal::firstChild(*shadowHost))
+ return PositionInFlatTree::beforeNode(firstChild);
+ return PositionInFlatTree();
+}
+
+Position adjustPositionForEnd(const Position& currentPosition,
+ Node* startContainerNode) {
+ TreeScope& treeScope = startContainerNode->treeScope();
+
+ DCHECK(currentPosition.computeContainerNode()->treeScope() != treeScope);
+
+ if (Node* ancestor = treeScope.ancestorInThisScope(
+ currentPosition.computeContainerNode())) {
+ if (ancestor->contains(startContainerNode))
+ return Position::afterNode(ancestor);
+ return Position::beforeNode(ancestor);
+ }
+
+ if (Node* lastChild = treeScope.rootNode().lastChild())
+ return Position::afterNode(lastChild);
+
+ return Position();
+}
+
+PositionInFlatTree adjustPositionInFlatTreeForEnd(
+ const PositionInFlatTree& position,
+ Node* shadowHost) {
+ if (isEnclosedBy(position, *shadowHost)) {
+ if (position.isAfterChildren())
+ return PositionInFlatTree::afterNode(shadowHost);
+ return PositionInFlatTree::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 = FlatTreeTraversal::lastChild(*shadowHost))
+ return PositionInFlatTree::afterNode(lastChild);
+ return PositionInFlatTree();
+}
+
+Position adjustPositionForStart(const Position& currentPosition,
+ Node* endContainerNode) {
+ TreeScope& treeScope = endContainerNode->treeScope();
+
+ DCHECK(currentPosition.computeContainerNode()->treeScope() != treeScope);
+
+ if (Node* ancestor = treeScope.ancestorInThisScope(
+ currentPosition.computeContainerNode())) {
+ if (ancestor->contains(endContainerNode))
+ return Position::beforeNode(ancestor);
+ return Position::afterNode(ancestor);
+ }
+
+ if (Node* firstChild = treeScope.rootNode().firstChild())
+ return Position::beforeNode(firstChild);
+
+ return Position();
+}
+
+std::pair<AdjustDirection, Position> adjustmentToAvoidCrossingShadowBoundaries(
+ const VisibleSelection& selection) {
+ // Note: |m_selectionType| isn't computed yet.
+ DCHECK(selection.base().isNotNull());
+ DCHECK(selection.extent().isNotNull());
+ DCHECK(selection.start().isNotNull());
+ DCHECK(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 std::make_pair(AdjustDirection::kAdjustNone, Position());
+
+ if (selection.isBaseFirst()) {
+ const Position& newEnd = adjustPositionForEnd(
+ selection.end(), selection.start().computeContainerNode());
+ return std::make_pair(AdjustDirection::kAdjustEnd, newEnd);
+ }
+
+ const Position& newStart = adjustPositionForStart(
+ selection.start(), selection.end().computeContainerNode());
+ return std::make_pair(AdjustDirection::kAdjustStart, newStart);
+}
+
+// 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.
+std::pair<AdjustDirection, PositionInFlatTree>
+adjustmentToAvoidCrossingShadowBoundaries(
+ const VisibleSelectionInFlatTree& selection) {
+ Node* const shadowHostStart = enclosingShadowHostForStart(selection.start());
+ Node* const shadowHostEnd = enclosingShadowHostForEnd(selection.end());
+ if (shadowHostStart == shadowHostEnd)
+ return std::make_pair(AdjustDirection::kAdjustNone, PositionInFlatTree());
+
+ if (selection.isBaseFirst()) {
+ Node* const shadowHost = shadowHostStart ? shadowHostStart : shadowHostEnd;
+ const PositionInFlatTree& newEnd =
+ adjustPositionInFlatTreeForEnd(selection.end(), shadowHost);
+ return std::make_pair(AdjustDirection::kAdjustEnd, newEnd);
+ }
+ Node* const shadowHost = shadowHostEnd ? shadowHostEnd : shadowHostStart;
+ const PositionInFlatTree& newStart =
+ adjustPositionInFlatTreeForStart(selection.start(), shadowHost);
+ return std::make_pair(AdjustDirection::kAdjustStart, newStart);
+}
+
+} // namespace
+
template <typename Strategy>
VisibleSelectionTemplate<Strategy>::VisibleSelectionTemplate()
: m_affinity(TextAffinity::Downstream),

Powered by Google App Engine
This is Rietveld 408576698