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

Unified Diff: Source/core/editing/VisibleUnits.cpp

Issue 1314033005: Move canonicalPosition() for VisiblePosition to VisibleUnits.cpp (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: 2015-09-01T14:49:27 Created 5 years, 4 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/editing/VisibleUnits.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/editing/VisibleUnits.cpp
diff --git a/Source/core/editing/VisibleUnits.cpp b/Source/core/editing/VisibleUnits.cpp
index 5ea7f0761594e76895bff49edc5582112b48ebb1..b9362b681ce198aea1eaac76c0670be0b7f40ae5 100644
--- a/Source/core/editing/VisibleUnits.cpp
+++ b/Source/core/editing/VisibleUnits.cpp
@@ -66,6 +66,106 @@ namespace blink {
using namespace HTMLNames;
using namespace WTF::Unicode;
+template <typename PositionType>
+static PositionType canonicalizeCandidate(const PositionType& candidate)
+{
+ if (candidate.isNull())
+ return PositionType();
+ ASSERT(isVisuallyEquivalentCandidate(candidate));
+ PositionType upstream = mostBackwardCaretPosition(candidate);
+ if (isVisuallyEquivalentCandidate(upstream))
+ return upstream;
+ return candidate;
+}
+
+template <typename PositionType>
+static PositionType canonicalPosition(const PositionType& passedPosition)
+{
+ // Sometimes updating selection positions can be extremely expensive and
+ // occur frequently. Often calling preventDefault on mousedown events can
+ // avoid doing unnecessary text selection work. http://crbug.com/472258.
+ TRACE_EVENT0("blink", "VisiblePosition::canonicalPosition");
+
+ // The updateLayout call below can do so much that even the position passed
+ // in to us might get changed as a side effect. Specifically, there are code
+ // paths that pass selection endpoints, and updateLayout can change the
+ // selection.
+ PositionType position = passedPosition;
+
+ // FIXME (9535): Canonicalizing to the leftmost candidate means that if
+ // we're at a line wrap, we will ask layoutObjects to paint downstream
+ // carets for other layoutObjects. To fix this, we need to either a) add
+ // code to all paintCarets to pass the responsibility off to the appropriate
+ // layoutObject for VisiblePosition's like these, or b) canonicalize to the
+ // rightmost candidate unless the affinity is upstream.
+ if (position.isNull())
+ return PositionType();
+
+ ASSERT(position.document());
+ position.document()->updateLayoutIgnorePendingStylesheets();
+
+ Node* node = position.computeContainerNode();
+
+ PositionType candidate = mostBackwardCaretPosition(position);
+ if (isVisuallyEquivalentCandidate(candidate))
+ return candidate;
+ candidate = mostForwardCaretPosition(position);
+ if (isVisuallyEquivalentCandidate(candidate))
+ return candidate;
+
+ // When neither upstream or downstream gets us to a candidate
+ // (upstream/downstream won't leave blocks or enter new ones), we search
+ // forward and backward until we find one.
+ PositionType next = canonicalizeCandidate(nextCandidate(position));
+ PositionType prev = canonicalizeCandidate(previousCandidate(position));
+ Node* nextNode = next.anchorNode();
+ Node* prevNode = prev.anchorNode();
+
+ // The new position must be in the same editable element. Enforce that
+ // first. Unless the descent is from a non-editable html element to an
+ // editable body.
+ if (isHTMLHtmlElement(node) && !node->hasEditableStyle() && node->document().body() && node->document().body()->hasEditableStyle())
+ return next.isNotNull() ? next : prev;
+
+ Element* editingRoot = editableRootForPosition(position);
+
+ // If the html element is editable, descending into its body will look like
+ // a descent from non-editable to editable content since
+ // |rootEditableElementOf()| always stops at the body.
+ if (isHTMLHtmlElement(editingRoot) || position.anchorNode()->isDocumentNode())
+ return next.isNotNull() ? next : prev;
+
+ bool prevIsInSameEditableElement = prevNode && editableRootForPosition(prev) == editingRoot;
+ bool nextIsInSameEditableElement = nextNode && editableRootForPosition(next) == editingRoot;
+ if (prevIsInSameEditableElement && !nextIsInSameEditableElement)
+ return prev;
+
+ if (nextIsInSameEditableElement && !prevIsInSameEditableElement)
+ return next;
+
+ if (!nextIsInSameEditableElement && !prevIsInSameEditableElement)
+ return PositionType();
+
+ // The new position should be in the same block flow element. Favor that.
+ Element* originalBlock = node ? enclosingBlockFlowElement(*node) : 0;
+ bool nextIsOutsideOriginalBlock = !nextNode->isDescendantOf(originalBlock) && nextNode != originalBlock;
+ bool prevIsOutsideOriginalBlock = !prevNode->isDescendantOf(originalBlock) && prevNode != originalBlock;
+ if (nextIsOutsideOriginalBlock && !prevIsOutsideOriginalBlock)
+ return prev;
+
+ return next;
+}
+
+Position canonicalPositionOf(const Position& position)
+{
+ return canonicalPosition(position);
+}
+
+PositionInComposedTree canonicalPositionOf(const PositionInComposedTree& position)
+{
+ return canonicalPosition(position);
+}
+
static Node* previousLeafWithSameEditability(Node* node, EditableType editableType)
{
bool editable = node->hasEditableStyle(editableType);
« no previous file with comments | « Source/core/editing/VisibleUnits.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698