| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/editing/FrameSelection.h" | 5 #include "core/editing/FrameSelection.h" |
| 6 | 6 |
| 7 #include "bindings/core/v8/ExceptionState.h" | 7 #include "bindings/core/v8/ExceptionState.h" |
| 8 #include "core/dom/Document.h" | 8 #include "core/dom/Document.h" |
| 9 #include "core/dom/Element.h" | 9 #include "core/dom/Element.h" |
| 10 #include "core/dom/Text.h" | 10 #include "core/dom/Text.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 #include <memory> | 26 #include <memory> |
| 27 | 27 |
| 28 namespace blink { | 28 namespace blink { |
| 29 | 29 |
| 30 class FrameSelectionTest : public EditingTestBase { | 30 class FrameSelectionTest : public EditingTestBase { |
| 31 protected: | 31 protected: |
| 32 const VisibleSelection& visibleSelectionInDOMTree() const { | 32 const VisibleSelection& visibleSelectionInDOMTree() const { |
| 33 return selection().selection(); | 33 return selection().selection(); |
| 34 } | 34 } |
| 35 const VisibleSelectionInFlatTree& visibleSelectionInFlatTree() const { | 35 const VisibleSelectionInFlatTree& visibleSelectionInFlatTree() const { |
| 36 return selection().selectionInFlatTree(); | 36 return selection().computeVisibleSelectionInFlatTree(); |
| 37 } | 37 } |
| 38 | 38 |
| 39 Text* appendTextNode(const String& data); | 39 Text* appendTextNode(const String& data); |
| 40 int layoutCount() const { | 40 int layoutCount() const { |
| 41 return dummyPageHolder().frameView().layoutCount(); | 41 return dummyPageHolder().frameView().layoutCount(); |
| 42 } | 42 } |
| 43 | 43 |
| 44 bool shouldPaintCaretForTesting() const { | 44 bool shouldPaintCaretForTesting() const { |
| 45 return selection().shouldPaintCaretForTesting(); | 45 return selection().shouldPaintCaretForTesting(); |
| 46 } | 46 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 EXPECT_FALSE(selection().isCaretBoundsDirty()); | 84 EXPECT_FALSE(selection().isCaretBoundsDirty()); |
| 85 | 85 |
| 86 document().body()->removeChild(text); | 86 document().body()->removeChild(text); |
| 87 document().updateStyleAndLayoutIgnorePendingStylesheets(); | 87 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 88 selection().setCaretRectNeedsUpdate(); | 88 selection().setCaretRectNeedsUpdate(); |
| 89 EXPECT_TRUE(selection().isCaretBoundsDirty()); | 89 EXPECT_TRUE(selection().isCaretBoundsDirty()); |
| 90 selection().invalidateCaretRect(); | 90 selection().invalidateCaretRect(); |
| 91 EXPECT_FALSE(selection().isCaretBoundsDirty()); | 91 EXPECT_FALSE(selection().isCaretBoundsDirty()); |
| 92 } | 92 } |
| 93 | 93 |
| 94 // TODO(yosin): We should get rid of |PaintCaretShouldNotLayout| since |
| 95 // |FrameSelection::paintCaret()| requires up-to-date layout. |
| 96 #if 0 |
| 94 TEST_F(FrameSelectionTest, PaintCaretShouldNotLayout) { | 97 TEST_F(FrameSelectionTest, PaintCaretShouldNotLayout) { |
| 95 Text* text = appendTextNode("Hello, World!"); | 98 Text* text = appendTextNode("Hello, World!"); |
| 96 document().view()->updateAllLifecyclePhases(); | 99 document().view()->updateAllLifecyclePhases(); |
| 97 | 100 |
| 98 document().body()->setContentEditable("true", ASSERT_NO_EXCEPTION); | 101 document().body()->setContentEditable("true", ASSERT_NO_EXCEPTION); |
| 99 document().body()->focus(); | 102 document().body()->focus(); |
| 100 EXPECT_TRUE(document().body()->isFocused()); | 103 EXPECT_TRUE(document().body()->isFocused()); |
| 101 | 104 |
| 102 selection().setCaretVisible(true); | 105 selection().setCaretVisible(true); |
| 103 selection().setSelection( | 106 selection().setSelection( |
| (...skipping 11 matching lines...) Expand all Loading... |
| 115 dummyPageHolder().frameView().setFrameRect(frameRect); | 118 dummyPageHolder().frameView().setFrameRect(frameRect); |
| 116 } | 119 } |
| 117 std::unique_ptr<PaintController> paintController = PaintController::create(); | 120 std::unique_ptr<PaintController> paintController = PaintController::create(); |
| 118 { | 121 { |
| 119 GraphicsContext context(*paintController); | 122 GraphicsContext context(*paintController); |
| 120 selection().paintCaret(context, LayoutPoint()); | 123 selection().paintCaret(context, LayoutPoint()); |
| 121 } | 124 } |
| 122 paintController->commitNewDisplayItems(); | 125 paintController->commitNewDisplayItems(); |
| 123 EXPECT_EQ(startCount, layoutCount()); | 126 EXPECT_EQ(startCount, layoutCount()); |
| 124 } | 127 } |
| 128 #endif |
| 125 | 129 |
| 126 TEST_F(FrameSelectionTest, InvalidatePreviousCaretAfterRemovingLastCharacter) { | 130 TEST_F(FrameSelectionTest, InvalidatePreviousCaretAfterRemovingLastCharacter) { |
| 127 Text* text = appendTextNode("Hello, World!"); | 131 Text* text = appendTextNode("Hello, World!"); |
| 128 document().view()->updateAllLifecyclePhases(); | 132 document().view()->updateAllLifecyclePhases(); |
| 129 | 133 |
| 130 document().body()->setContentEditable("true", ASSERT_NO_EXCEPTION); | 134 document().body()->setContentEditable("true", ASSERT_NO_EXCEPTION); |
| 131 document().body()->focus(); | 135 document().body()->focus(); |
| 132 EXPECT_TRUE(document().body()->isFocused()); | 136 EXPECT_TRUE(document().body()->isFocused()); |
| 133 | 137 |
| 134 selection().setCaretVisible(true); | 138 selection().setCaretVisible(true); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 148 EXPECT_TRUE(isPreviousCaretDirtyForTesting()); | 152 EXPECT_TRUE(isPreviousCaretDirtyForTesting()); |
| 149 | 153 |
| 150 // Simulate to remove all except for "H". | 154 // Simulate to remove all except for "H". |
| 151 text->replaceWholeText("H"); | 155 text->replaceWholeText("H"); |
| 152 document().updateStyleAndLayout(); | 156 document().updateStyleAndLayout(); |
| 153 selection().setSelection( | 157 selection().setSelection( |
| 154 SelectionInDOMTree::Builder().collapse(selection().end()).build()); | 158 SelectionInDOMTree::Builder().collapse(selection().end()).build()); |
| 155 selection().setCaretRectNeedsUpdate(); | 159 selection().setCaretRectNeedsUpdate(); |
| 156 EXPECT_TRUE(selection().isCaretBoundsDirty()); | 160 EXPECT_TRUE(selection().isCaretBoundsDirty()); |
| 157 // "H" remains so early previousCaret invalidation isn't needed. | 161 // "H" remains so early previousCaret invalidation isn't needed. |
| 158 EXPECT_TRUE(isPreviousCaretDirtyForTesting()); | 162 EXPECT_FALSE(isPreviousCaretDirtyForTesting()); |
| 159 selection().invalidateCaretRect(); | 163 selection().invalidateCaretRect(); |
| 160 EXPECT_FALSE(selection().isCaretBoundsDirty()); | 164 EXPECT_FALSE(selection().isCaretBoundsDirty()); |
| 161 EXPECT_TRUE(isPreviousCaretDirtyForTesting()); | 165 EXPECT_TRUE(isPreviousCaretDirtyForTesting()); |
| 162 | 166 |
| 163 // Simulate to remove the last character. | 167 // Simulate to remove the last character. |
| 164 document().body()->removeChild(text); | 168 document().body()->removeChild(text); |
| 165 // This line is the objective of this test. | 169 // This line is the objective of this test. |
| 166 // As removing the last character, early previousCaret invalidation is | 170 // As removing the last character, early previousCaret invalidation is |
| 167 // executed. | 171 // executed. |
| 168 EXPECT_FALSE(isPreviousCaretDirtyForTesting()); | 172 EXPECT_FALSE(isPreviousCaretDirtyForTesting()); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 // "SelectionControllerTest.cpp" | 282 // "SelectionControllerTest.cpp" |
| 279 class SelectionControllerTest : public EditingTestBase { | 283 class SelectionControllerTest : public EditingTestBase { |
| 280 protected: | 284 protected: |
| 281 SelectionControllerTest() = default; | 285 SelectionControllerTest() = default; |
| 282 | 286 |
| 283 const VisibleSelection& visibleSelectionInDOMTree() const { | 287 const VisibleSelection& visibleSelectionInDOMTree() const { |
| 284 return selection().selection(); | 288 return selection().selection(); |
| 285 } | 289 } |
| 286 | 290 |
| 287 const VisibleSelectionInFlatTree& visibleSelectionInFlatTree() const { | 291 const VisibleSelectionInFlatTree& visibleSelectionInFlatTree() const { |
| 288 return selection().selectionInFlatTree(); | 292 return selection().computeVisibleSelectionInFlatTree(); |
| 289 } | 293 } |
| 290 | 294 |
| 291 void setNonDirectionalSelectionIfNeeded(const VisibleSelectionInFlatTree&, | 295 void setNonDirectionalSelectionIfNeeded(const VisibleSelectionInFlatTree&, |
| 292 TextGranularity); | 296 TextGranularity); |
| 293 | 297 |
| 294 private: | 298 private: |
| 295 DISALLOW_COPY_AND_ASSIGN(SelectionControllerTest); | 299 DISALLOW_COPY_AND_ASSIGN(SelectionControllerTest); |
| 296 }; | 300 }; |
| 297 | 301 |
| 298 TEST_F(FrameSelectionTest, SelectAllWithUnselectableRoot) { | 302 TEST_F(FrameSelectionTest, SelectAllWithUnselectableRoot) { |
| 299 Element* select = document().createElement("select"); | 303 Element* select = document().createElement("select"); |
| 300 document().replaceChild(select, document().documentElement()); | 304 document().replaceChild(select, document().documentElement()); |
| 301 selection().selectAll(); | 305 selection().selectAll(); |
| 302 EXPECT_TRUE(selection().isNone()) << "Nothing should be selected if the " | 306 EXPECT_TRUE(selection().isNone()) << "Nothing should be selected if the " |
| 303 "content of the documentElement is not " | 307 "content of the documentElement is not " |
| 304 "selctable."; | 308 "selctable."; |
| 305 } | 309 } |
| 306 | 310 |
| 307 TEST_F(FrameSelectionTest, updateIfNeededAndFrameCaret) { | 311 TEST_F(FrameSelectionTest, updateIfNeededAndFrameCaret) { |
| 308 setBodyContent("<style id=sample></style>"); | 312 setBodyContent("<style id=sample></style>"); |
| 309 document().setDesignMode("on"); | 313 document().setDesignMode("on"); |
| 310 updateAllLifecyclePhases(); | 314 updateAllLifecyclePhases(); |
| 311 Element* sample = document().getElementById("sample"); | 315 Element* sample = document().getElementById("sample"); |
| 312 selection().setSelection( | 316 selection().setSelection( |
| 313 SelectionInDOMTree::Builder().collapse(Position(sample, 0)).build()); | 317 SelectionInDOMTree::Builder().collapse(Position(sample, 0)).build()); |
| 314 EXPECT_EQ(Position(document().body(), 0), selection().start()); | 318 EXPECT_EQ(Position(document().body(), 0), selection().start()); |
| 315 EXPECT_EQ(selection().start(), caretPosition().position()); | 319 EXPECT_EQ(selection().start(), caretPosition().position()); |
| 316 document().body()->remove(); | 320 document().body()->remove(); |
| 317 // TODO(yosin): Once lazy canonicalization implemented, selection.start | 321 EXPECT_EQ(Position(), selection().start()) |
| 318 // should be Position(HTML, 0). | 322 << "Selection has been removed by BODY.remove()."; |
| 319 EXPECT_EQ(Position(document().documentElement(), 1), selection().start()); | |
| 320 EXPECT_EQ(selection().start(), caretPosition().position()); | 323 EXPECT_EQ(selection().start(), caretPosition().position()); |
| 321 document().updateStyleAndLayout(); | 324 document().updateStyleAndLayout(); |
| 322 selection().updateIfNeeded(); | 325 selection().updateIfNeeded(); |
| 323 | 326 |
| 324 // TODO(yosin): Once lazy canonicalization implemented, selection.start | |
| 325 // should be Position(HTML, 0). | |
| 326 EXPECT_EQ(Position(), selection().start()) | 327 EXPECT_EQ(Position(), selection().start()) |
| 327 << "updateIfNeeded() makes selection to null."; | 328 << "updateIfNeeded() does nothing."; |
| 328 EXPECT_EQ(selection().start(), caretPosition().position()); | 329 EXPECT_EQ(selection().start(), caretPosition().position()); |
| 329 } | 330 } |
| 330 | 331 |
| 331 } // namespace blink | 332 } // namespace blink |
| OLD | NEW |