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

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

Issue 2680943004: Make FrameSelection to hold non-canonicalized positions (Closed)
Patch Set: 2014-02-14T23:34:22 Update TestExpectation to include extend-{0,2,4}0.html and selectAllChildren.html Created 3 years, 10 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/SelectionEditor.cpp
diff --git a/third_party/WebKit/Source/core/editing/SelectionEditor.cpp b/third_party/WebKit/Source/core/editing/SelectionEditor.cpp
index 7c833994c93ed98299585562a2afc71afda45e92..e34bba5da6c36786ce4d1ba3d03e039e62164cfa 100644
--- a/third_party/WebKit/Source/core/editing/SelectionEditor.cpp
+++ b/third_party/WebKit/Source/core/editing/SelectionEditor.cpp
@@ -25,6 +25,8 @@
#include "core/editing/SelectionEditor.h"
+#include "core/dom/NodeWithIndex.h"
+#include "core/dom/Text.h"
#include "core/editing/EditingUtilities.h"
#include "core/editing/Editor.h"
#include "core/editing/SelectionAdjuster.h"
@@ -32,20 +34,30 @@
namespace blink {
-SelectionEditor::SelectionEditor(LocalFrame& frame)
- : m_frame(frame), m_observingVisibleSelection(false) {
+SelectionEditor::SelectionEditor(LocalFrame& frame) : m_frame(frame) {
clearVisibleSelection();
}
SelectionEditor::~SelectionEditor() {}
+void SelectionEditor::assertSelectionValid() const {
+#if DCHECK_IS_ON()
+ // Since We don't track dom tree version during attribute changes, we can't
+ // use it for validity of |m_selection|.
+ const_cast<SelectionEditor*>(this)->m_selection.m_domTreeVersion =
+ document().domTreeVersion();
+#endif
+ m_selection.assertValidFor(document());
+}
+
void SelectionEditor::clearVisibleSelection() {
- m_selection = VisibleSelection();
- m_selectionInFlatTree = VisibleSelectionInFlatTree();
+ m_selection = SelectionInDOMTree();
+ m_cachedVisibleSelectionInDOMTree = VisibleSelection();
+ m_cachedVisibleSelectionInFlatTree = VisibleSelectionInFlatTree();
+ m_cacheIsDirty = false;
if (!shouldAlwaysUseDirectionalSelection())
return;
- m_selection.setIsDirectional(true);
- m_selectionInFlatTree.setIsDirectional(true);
+ m_selection.m_isDirectional = true;
}
void SelectionEditor::dispose() {
@@ -54,89 +66,114 @@ void SelectionEditor::dispose() {
clearVisibleSelection();
}
-const Document& SelectionEditor::document() const {
- DCHECK(m_document);
- return *m_document;
+Document& SelectionEditor::document() const {
+ DCHECK(lifecycleContext());
+ return *lifecycleContext();
}
template <>
const VisibleSelection& SelectionEditor::visibleSelection<EditingStrategy>()
const {
- DCHECK_EQ(frame()->document(), document());
- DCHECK_EQ(frame(), document().frame());
- if (m_selection.isNone())
- return m_selection;
- DCHECK_EQ(m_selection.base().document(), document());
- return m_selection;
+ return computeVisibleSelectionInDOMTree();
}
template <>
const VisibleSelectionInFlatTree&
SelectionEditor::visibleSelection<EditingInFlatTreeStrategy>() const {
+ return computeVisibleSelectionInFlatTree();
+}
+
+const VisibleSelection& SelectionEditor::computeVisibleSelectionInDOMTree()
+ const {
DCHECK_EQ(frame()->document(), document());
DCHECK_EQ(frame(), document().frame());
- if (m_selectionInFlatTree.isNone())
- return m_selectionInFlatTree;
- DCHECK_EQ(m_selectionInFlatTree.base().document(), document());
- return m_selectionInFlatTree;
+ updateCachedVisibleSelectionIfNeeded();
+ if (m_cachedVisibleSelectionInDOMTree.isNone())
+ return m_cachedVisibleSelectionInDOMTree;
+ DCHECK_EQ(m_cachedVisibleSelectionInDOMTree.base().document(), document());
+ return m_cachedVisibleSelectionInDOMTree;
}
-void SelectionEditor::setVisibleSelection(
- const VisibleSelection& newSelection,
- FrameSelection::SetSelectionOptions options) {
- DCHECK(newSelection.isValidFor(document())) << newSelection;
- resetLogicalRange();
- clearDocumentCachedRange();
+const VisibleSelectionInFlatTree&
+SelectionEditor::computeVisibleSelectionInFlatTree() const {
+ DCHECK_EQ(frame()->document(), document());
+ DCHECK_EQ(frame(), document().frame());
+ updateCachedVisibleSelectionIfNeeded();
+ if (m_cachedVisibleSelectionInFlatTree.isNone())
+ return m_cachedVisibleSelectionInFlatTree;
+ DCHECK_EQ(m_cachedVisibleSelectionInFlatTree.base().document(), document());
+ return m_cachedVisibleSelectionInFlatTree;
+}
- m_selection = newSelection;
- if (options & FrameSelection::DoNotAdjustInFlatTree) {
- m_selectionInFlatTree.setWithoutValidation(
- toPositionInFlatTree(m_selection.base()),
- toPositionInFlatTree(m_selection.extent()));
- return;
- }
+const SelectionInDOMTree& SelectionEditor::selectionInDOMTree() const {
+ assertSelectionValid();
+ return m_selection;
+}
- SelectionAdjuster::adjustSelectionInFlatTree(&m_selectionInFlatTree,
- m_selection);
+bool SelectionEditor::hasEditableStyle() const {
+ return computeVisibleSelectionInDOMTree().hasEditableStyle();
}
-void SelectionEditor::setVisibleSelection(
- const VisibleSelectionInFlatTree& newSelection,
- FrameSelection::SetSelectionOptions options) {
- DCHECK(newSelection.isValidFor(document())) << newSelection;
- DCHECK(!(options & FrameSelection::DoNotAdjustInFlatTree));
- resetLogicalRange();
- clearDocumentCachedRange();
+bool SelectionEditor::isContentEditable() const {
+ return computeVisibleSelectionInDOMTree().isContentEditable();
+}
- m_selectionInFlatTree = newSelection;
- SelectionAdjuster::adjustSelectionInDOMTree(&m_selection,
- m_selectionInFlatTree);
+bool SelectionEditor::isContentRichlyEditable() const {
+ return computeVisibleSelectionInDOMTree().isContentRichlyEditable();
}
-void SelectionEditor::setWithoutValidation(const Position& base,
- const Position& extent) {
+void SelectionEditor::markCacheDirty() {
+ m_cachedVisibleSelectionInFlatTree = VisibleSelectionInFlatTree();
+ m_cachedVisibleSelectionInDOMTree = VisibleSelection();
+ m_cacheIsDirty = true;
+}
+
+void SelectionEditor::setSelection(const SelectionInDOMTree& newSelection) {
+ newSelection.assertValidFor(document());
+ if (m_selection == newSelection)
+ return;
resetLogicalRange();
- if (base.isNotNull())
- DCHECK_EQ(base.document(), document());
- if (extent.isNotNull())
- DCHECK_EQ(extent.document(), document());
clearDocumentCachedRange();
+ markCacheDirty();
+ m_selection = newSelection;
+}
+
+void SelectionEditor::didChangeChildren(const ContainerNode&) {
+ markCacheDirty();
+ didFinishDOMMutation();
+}
+
+void SelectionEditor::didFinishTextChange(const Position& newBase,
+ const Position& newExtent) {
+ if (newBase == m_selection.m_base && newExtent == m_selection.m_extent) {
+ didFinishDOMMutation();
+ return;
+ }
+ m_selection.m_base = newBase;
+ m_selection.m_extent = newExtent;
+ markCacheDirty();
+ didFinishDOMMutation();
+}
- m_selection.setWithoutValidation(base, extent);
- m_selectionInFlatTree.setWithoutValidation(toPositionInFlatTree(base),
- toPositionInFlatTree(extent));
+void SelectionEditor::didFinishDOMMutation() {
+ assertSelectionValid();
}
void SelectionEditor::documentAttached(Document* document) {
DCHECK(document);
- DCHECK(!m_document) << m_document;
- m_document = document;
+ DCHECK(!lifecycleContext()) << lifecycleContext();
+ m_styleVersion = static_cast<uint64_t>(-1);
+ clearVisibleSelection();
+ setContext(document);
}
-void SelectionEditor::documentDetached(const Document& document) {
- DCHECK_EQ(m_document, &document);
+void SelectionEditor::contextDestroyed(Document*) {
dispose();
- m_document = nullptr;
+ m_styleVersion = static_cast<uint64_t>(-1);
+ m_selection = SelectionInDOMTree();
+ m_cachedVisibleSelectionInDOMTree = VisibleSelection();
+ m_cachedVisibleSelectionInFlatTree = VisibleSelectionInFlatTree();
+ m_cacheIsDirty = false;
}
void SelectionEditor::resetLogicalRange() {
@@ -157,7 +194,7 @@ void SelectionEditor::setLogicalRange(Range* range) {
Range* SelectionEditor::firstRange() const {
if (m_logicalRange)
return m_logicalRange->cloneRange();
- return firstRangeOf(m_selection);
+ return firstRangeOf(computeVisibleSelectionInDOMTree());
}
bool SelectionEditor::shouldAlwaysUseDirectionalSelection() const {
@@ -165,10 +202,37 @@ bool SelectionEditor::shouldAlwaysUseDirectionalSelection() const {
}
void SelectionEditor::updateIfNeeded() {
- DCHECK(m_selection.isValidFor(document())) << m_selection;
- DCHECK(m_selectionInFlatTree.isValidFor(document())) << m_selection;
- m_selection.updateIfNeeded();
- m_selectionInFlatTree.updateIfNeeded();
+ // TODO(yosin): We should unify |SelectionEditor::updateIfNeeded()| and
+ // |updateCachedVisibleSelectionIfNeeded()|
+ updateCachedVisibleSelectionIfNeeded();
+}
+
+bool SelectionEditor::needsUpdateVisibleSelection() const {
+ return m_cacheIsDirty || m_styleVersion != document().styleVersion();
+}
+
+void SelectionEditor::updateCachedVisibleSelectionIfNeeded() const {
+ // Note: Since we |FrameCaret::updateApperance()| is called from
+ // |FrameView::performPostLayoutTasks()|, we check lifecycle against
+ // |AfterPerformLayout| instead of |LayoutClean|.
+ DCHECK_GE(document().lifecycle().state(),
+ DocumentLifecycle::AfterPerformLayout);
+ assertSelectionValid();
+ if (!needsUpdateVisibleSelection())
+ return;
+
+ m_cachedVisibleSelectionInDOMTree = createVisibleSelection(m_selection);
+ m_cachedVisibleSelectionInFlatTree = createVisibleSelection(
+ SelectionInFlatTree::Builder()
+ .setBaseAndExtent(toPositionInFlatTree(m_selection.base()),
+ toPositionInFlatTree(m_selection.extent()))
+ .setAffinity(m_selection.affinity())
+ .setHasTrailingWhitespace(m_selection.hasTrailingWhitespace())
+ .setGranularity(m_selection.granularity())
+ .setIsDirectional(m_selection.isDirectional())
+ .build());
+ m_styleVersion = document().styleVersion();
+ m_cacheIsDirty = false;
}
void SelectionEditor::cacheRangeOfDocument(Range* range) {
@@ -184,12 +248,13 @@ void SelectionEditor::clearDocumentCachedRange() {
}
DEFINE_TRACE(SelectionEditor) {
- visitor->trace(m_document);
visitor->trace(m_frame);
visitor->trace(m_selection);
- visitor->trace(m_selectionInFlatTree);
+ visitor->trace(m_cachedVisibleSelectionInDOMTree);
+ visitor->trace(m_cachedVisibleSelectionInFlatTree);
visitor->trace(m_logicalRange);
visitor->trace(m_cachedRange);
+ SynchronousMutationObserver::trace(visitor);
}
} // namespace blink
« no previous file with comments | « third_party/WebKit/Source/core/editing/SelectionEditor.h ('k') | third_party/WebKit/Source/core/editing/VisibleSelection.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698