| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2008, 2009, 2010 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2008, 2009, 2010 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| 11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
| 12 * | 12 * |
| 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY | 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
| 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
| 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 24 */ | 24 */ |
| 25 | 25 |
| 26 #include "core/editing/FrameCaret.h" | 26 #include "core/editing/FrameCaret.h" |
| 27 | 27 |
| 28 #include "core/dom/TaskRunnerHelper.h" | 28 #include "core/dom/TaskRunnerHelper.h" |
| 29 #include "core/editing/CaretBase.h" |
| 29 #include "core/editing/EditingUtilities.h" | 30 #include "core/editing/EditingUtilities.h" |
| 30 #include "core/editing/Editor.h" | 31 #include "core/editing/Editor.h" |
| 31 #include "core/editing/SelectionEditor.h" | 32 #include "core/editing/SelectionEditor.h" |
| 32 #include "core/editing/commands/CompositeEditCommand.h" | 33 #include "core/editing/commands/CompositeEditCommand.h" |
| 33 #include "core/frame/FrameView.h" | 34 #include "core/frame/FrameView.h" |
| 34 #include "core/frame/LocalFrame.h" | 35 #include "core/frame/LocalFrame.h" |
| 35 #include "core/frame/Settings.h" | 36 #include "core/frame/Settings.h" |
| 36 #include "core/html/TextControlElement.h" | 37 #include "core/html/TextControlElement.h" |
| 38 #include "core/layout/LayoutBlock.h" |
| 37 #include "core/layout/LayoutTheme.h" | 39 #include "core/layout/LayoutTheme.h" |
| 38 #include "core/layout/api/LayoutPartItem.h" | 40 #include "core/layout/api/LayoutPartItem.h" |
| 39 #include "core/page/Page.h" | 41 #include "core/page/Page.h" |
| 40 #include "core/paint/PaintLayer.h" | 42 #include "core/paint/PaintLayer.h" |
| 41 #include "public/platform/WebTraceLocation.h" | 43 #include "public/platform/WebTraceLocation.h" |
| 42 | 44 |
| 43 namespace blink { | 45 namespace blink { |
| 44 | 46 |
| 45 FrameCaret::FrameCaret(LocalFrame& frame, | 47 FrameCaret::FrameCaret(LocalFrame& frame, |
| 46 const SelectionEditor& selectionEditor) | 48 const SelectionEditor& selectionEditor) |
| 47 : m_selectionEditor(&selectionEditor), | 49 : m_selectionEditor(&selectionEditor), |
| 48 m_frame(frame), | 50 m_frame(frame), |
| 51 m_caretBase(new CaretBase()), |
| 49 m_caretVisibility(CaretVisibility::Hidden), | 52 m_caretVisibility(CaretVisibility::Hidden), |
| 50 m_previousCaretVisibility(CaretVisibility::Hidden), | 53 m_previousCaretVisibility(CaretVisibility::Hidden), |
| 51 m_caretBlinkTimer(TaskRunnerHelper::get(TaskType::UnspecedTimer, &frame), | 54 m_caretBlinkTimer(TaskRunnerHelper::get(TaskType::UnspecedTimer, &frame), |
| 52 this, | 55 this, |
| 53 &FrameCaret::caretBlinkTimerFired), | 56 &FrameCaret::caretBlinkTimerFired), |
| 54 m_caretRectDirty(true), | 57 m_didScheduleUpdate(true), |
| 55 m_shouldPaintCaret(true), | 58 m_shouldPaintCaret(true), |
| 56 m_isCaretBlinkingSuspended(false), | 59 m_isCaretBlinkingSuspended(false), |
| 57 m_shouldShowBlockCursor(false) {} | 60 m_shouldShowBlockCursor(false) {} |
| 58 | 61 |
| 59 FrameCaret::~FrameCaret() = default; | 62 FrameCaret::~FrameCaret() = default; |
| 60 | 63 |
| 61 DEFINE_TRACE(FrameCaret) { | 64 DEFINE_TRACE(FrameCaret) { |
| 62 visitor->trace(m_selectionEditor); | 65 visitor->trace(m_selectionEditor); |
| 63 visitor->trace(m_frame); | 66 visitor->trace(m_frame); |
| 64 visitor->trace(m_previousCaretNode); | 67 visitor->trace(m_previousCaretNode); |
| 65 visitor->trace(m_previousCaretAnchorNode); | 68 visitor->trace(m_previousCaretAnchorNode); |
| 66 CaretBase::trace(visitor); | 69 SynchronousMutationObserver::trace(visitor); |
| 70 } |
| 71 |
| 72 void FrameCaret::documentAttached(Document* document) { |
| 73 setContext(document); |
| 67 } | 74 } |
| 68 | 75 |
| 69 const PositionWithAffinity FrameCaret::caretPosition() const { | 76 const PositionWithAffinity FrameCaret::caretPosition() const { |
| 70 const VisibleSelection& selection = | 77 const VisibleSelection& selection = |
| 71 m_selectionEditor->visibleSelection<EditingStrategy>(); | 78 m_selectionEditor->computeVisibleSelectionInDOMTree(); |
| 72 if (!selection.isCaret()) | 79 if (!selection.isCaret()) |
| 73 return PositionWithAffinity(); | 80 return PositionWithAffinity(); |
| 74 return PositionWithAffinity(selection.start(), selection.affinity()); | 81 return PositionWithAffinity(selection.start(), selection.affinity()); |
| 75 } | 82 } |
| 76 | 83 |
| 84 const DisplayItemClient& FrameCaret::displayItemClient() const { |
| 85 return *m_caretBase; |
| 86 } |
| 87 |
| 77 inline static bool shouldStopBlinkingDueToTypingCommand(LocalFrame* frame) { | 88 inline static bool shouldStopBlinkingDueToTypingCommand(LocalFrame* frame) { |
| 78 return frame->editor().lastEditCommand() && | 89 return frame->editor().lastEditCommand() && |
| 79 frame->editor().lastEditCommand()->shouldStopCaretBlinking(); | 90 frame->editor().lastEditCommand()->shouldStopCaretBlinking(); |
| 80 } | 91 } |
| 81 | 92 |
| 82 void FrameCaret::updateAppearance() { | 93 void FrameCaret::updateAppearance() { |
| 94 DCHECK_GE(lifecycleContext()->lifecycle().state(), |
| 95 DocumentLifecycle::AfterPerformLayout); |
| 83 // Paint a block cursor instead of a caret in overtype mode unless the caret | 96 // Paint a block cursor instead of a caret in overtype mode unless the caret |
| 84 // is at the end of a line (in this case the FrameSelection will paint a | 97 // is at the end of a line (in this case the FrameSelection will paint a |
| 85 // blinking caret as usual). | 98 // blinking caret as usual). |
| 86 bool paintBlockCursor = m_shouldShowBlockCursor && isActive(); | 99 bool paintBlockCursor = m_shouldShowBlockCursor && isActive(); |
| 87 if (paintBlockCursor) { | 100 if (paintBlockCursor && |
| 88 // TODO(editing-dev): Use of updateStyleAndLayoutIgnorePendingStylesheets | 101 isLogicalEndOfLine(createVisiblePosition(caretPosition()))) { |
| 89 // needs to be audited. see http://crbug.com/590369 for more details. | 102 paintBlockCursor = false; |
| 90 // In the long term, we should defer the update of the caret's appearance | |
| 91 // to prevent synchronous layout. | |
| 92 m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets(); | |
| 93 | |
| 94 if (isLogicalEndOfLine(createVisiblePosition(caretPosition()))) | |
| 95 paintBlockCursor = false; | |
| 96 } | 103 } |
| 97 | 104 |
| 98 bool shouldBlink = !paintBlockCursor && shouldBlinkCaret(); | 105 bool shouldBlink = !paintBlockCursor && shouldBlinkCaret(); |
| 99 | 106 |
| 100 // If the caret moved, stop the blink timer so we can restart with a | 107 // If the caret moved, stop the blink timer so we can restart with a |
| 101 // black caret in the new location. | 108 // black caret in the new location. |
| 102 if (!shouldBlink || shouldStopBlinkingDueToTypingCommand(m_frame)) | 109 if (!shouldBlink || shouldStopBlinkingDueToTypingCommand(m_frame)) |
| 103 stopCaretBlinkTimer(); | 110 stopCaretBlinkTimer(); |
| 104 | 111 |
| 105 // Start blinking with a black caret. Be sure not to restart if we're | 112 // Start blinking with a black caret. Be sure not to restart if we're |
| (...skipping 21 matching lines...) Expand all Loading... |
| 127 m_shouldPaintCaret = true; | 134 m_shouldPaintCaret = true; |
| 128 setCaretRectNeedsUpdate(); | 135 setCaretRectNeedsUpdate(); |
| 129 } | 136 } |
| 130 | 137 |
| 131 void FrameCaret::setCaretVisibility(CaretVisibility visibility) { | 138 void FrameCaret::setCaretVisibility(CaretVisibility visibility) { |
| 132 if (m_caretVisibility == visibility) | 139 if (m_caretVisibility == visibility) |
| 133 return; | 140 return; |
| 134 | 141 |
| 135 m_caretVisibility = visibility; | 142 m_caretVisibility = visibility; |
| 136 | 143 |
| 137 updateAppearance(); | 144 setCaretRectNeedsUpdate(); |
| 138 } | 145 } |
| 139 | 146 |
| 140 void FrameCaret::setCaretRectNeedsUpdate() { | 147 void FrameCaret::setCaretRectNeedsUpdate() { |
| 141 if (m_caretRectDirty) | 148 if (m_didScheduleUpdate) |
| 142 return; | 149 return; |
| 143 m_caretRectDirty = true; | 150 m_didScheduleUpdate = true; |
| 144 | 151 |
| 145 if (Page* page = m_frame->page()) | 152 if (Page* page = m_frame->page()) |
| 146 page->animator().scheduleVisualUpdate(m_frame->localFrameRoot()); | 153 page->animator().scheduleVisualUpdate(m_frame->localFrameRoot()); |
| 147 | 154 |
| 148 // Ensure the frame will be checked for paint invalidation during | 155 // Ensure the frame will be checked for paint invalidation during |
| 149 // PrePaintTreeWalk. | 156 // PrePaintTreeWalk. |
| 150 if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled()) { | 157 if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled()) { |
| 151 if (auto layoutItem = m_frame->ownerLayoutItem()) | 158 if (auto layoutItem = m_frame->ownerLayoutItem()) |
| 152 layoutItem.setMayNeedPaintInvalidation(); | 159 layoutItem.setMayNeedPaintInvalidation(); |
| 153 } | 160 } |
| 154 } | 161 } |
| 155 | 162 |
| 156 bool FrameCaret::caretPositionIsValidForDocument( | 163 bool FrameCaret::caretPositionIsValidForDocument( |
| 157 const Document& document) const { | 164 const Document& document) const { |
| 158 if (!isActive()) | 165 if (!isActive()) |
| 159 return true; | 166 return true; |
| 160 | 167 |
| 161 return caretPosition().document() == document && !caretPosition().isOrphan(); | 168 return caretPosition().document() == document && !caretPosition().isOrphan(); |
| 162 } | 169 } |
| 163 | 170 |
| 171 static bool shouldRepaintCaret(Node& node) { |
| 172 // If PositionAnchorType::BeforeAnchor or PositionAnchorType::AfterAnchor, |
| 173 // carets need to be repainted not only when the node is contentEditable but |
| 174 // also when its parentNode() is contentEditable. |
| 175 node.document().updateStyleAndLayoutTree(); |
| 176 return hasEditableStyle(node) || |
| 177 (node.parentNode() && hasEditableStyle(*node.parentNode())); |
| 178 } |
| 179 |
| 164 void FrameCaret::invalidateCaretRect(bool forceInvalidation) { | 180 void FrameCaret::invalidateCaretRect(bool forceInvalidation) { |
| 165 if (!m_caretRectDirty) | 181 updateAppearance(); |
| 166 return; | 182 m_didScheduleUpdate = false; |
| 167 m_caretRectDirty = false; | |
| 168 | 183 |
| 169 DCHECK(caretPositionIsValidForDocument(*m_frame->document())); | 184 DCHECK(caretPositionIsValidForDocument(*m_frame->document())); |
| 170 LayoutObject* layoutObject = nullptr; | 185 LayoutObject* layoutObject = nullptr; |
| 171 LayoutRect newRect; | 186 LayoutRect newRect; |
| 172 PositionWithAffinity currentCaretPosition = caretPosition(); | 187 PositionWithAffinity currentCaretPosition = caretPosition(); |
| 188 const Node* const colorNode = caretPosition().anchorNode(); |
| 189 Color newCaretColor = |
| 190 colorNode ? colorNode->layoutObject()->resolveColor(CSSPropertyCaretColor) |
| 191 : Color(); |
| 173 if (isActive()) | 192 if (isActive()) |
| 174 newRect = localCaretRectOfPosition(currentCaretPosition, layoutObject); | 193 newRect = localCaretRectOfPosition(currentCaretPosition, layoutObject); |
| 175 Node* newNode = layoutObject ? layoutObject->node() : nullptr; | 194 Node* newNode = layoutObject ? layoutObject->node() : nullptr; |
| 176 // The current selected node |newNode| could be a child multiple levels below | 195 // The current selected node |newNode| could be a child multiple levels below |
| 177 // its associated "anchor node" ancestor, so we reference and keep around the | 196 // its associated "anchor node" ancestor, so we reference and keep around the |
| 178 // anchor node for checking editability. | 197 // anchor node for checking editability. |
| 179 // TODO(wkorman): Consider storing previous Position, rather than Node, and | 198 // TODO(wkorman): Consider storing previous Position, rather than Node, and |
| 180 // making use of EditingUtilies::isEditablePosition() directly. | 199 // making use of EditingUtilies::isEditablePosition() directly. |
| 181 Node* newAnchorNode = | 200 Node* newAnchorNode = |
| 182 currentCaretPosition.position().parentAnchoredEquivalent().anchorNode(); | 201 currentCaretPosition.position().parentAnchoredEquivalent().anchorNode(); |
| 183 if (newNode && newAnchorNode && newNode != newAnchorNode && | 202 if (newNode && newAnchorNode && newNode != newAnchorNode && |
| 184 newAnchorNode->layoutObject() && newAnchorNode->layoutObject()->isBox()) { | 203 newAnchorNode->layoutObject() && newAnchorNode->layoutObject()->isBox()) { |
| 185 newNode->layoutObject()->mapToVisualRectInAncestorSpace( | 204 newNode->layoutObject()->mapToVisualRectInAncestorSpace( |
| 186 toLayoutBoxModelObject(newAnchorNode->layoutObject()), newRect); | 205 toLayoutBoxModelObject(newAnchorNode->layoutObject()), newRect); |
| 187 } | 206 } |
| 188 // It's possible for the timer to be inactive even though we want to | 207 // It's possible for the timer to be inactive even though we want to |
| 189 // invalidate the caret. For example, when running as a layout test the | 208 // invalidate the caret. For example, when running as a layout test the |
| 190 // caret blink interval could be zero and thus |m_caretBlinkTimer| will | 209 // caret blink interval could be zero and thus |m_caretBlinkTimer| will |
| 191 // never be started. We provide |forceInvalidation| for use by paint | 210 // never be started. We provide |forceInvalidation| for use by paint |
| 192 // invalidation internals where we need to invalidate the caret regardless | 211 // invalidation internals where we need to invalidate the caret regardless |
| 193 // of timer state. | 212 // of timer state. |
| 194 if (!forceInvalidation && !m_caretBlinkTimer.isActive() && | 213 if (!forceInvalidation && !m_caretBlinkTimer.isActive() && |
| 195 newNode == m_previousCaretNode && newRect == m_previousCaretRect && | 214 newNode == m_previousCaretNode && newRect == m_previousCaretRect && |
| 196 m_caretVisibility == m_previousCaretVisibility) | 215 m_caretVisibility == m_previousCaretVisibility && |
| 216 newCaretColor == m_previousCaretColor) { |
| 197 return; | 217 return; |
| 218 } |
| 198 | 219 |
| 199 if (m_previousCaretAnchorNode && | 220 if (m_previousCaretAnchorNode && |
| 200 shouldRepaintCaret(*m_previousCaretAnchorNode)) { | 221 shouldRepaintCaret(*m_previousCaretAnchorNode)) { |
| 201 invalidateLocalCaretRect(m_previousCaretAnchorNode.get(), | 222 m_caretBase->invalidateLocalCaretRect(m_previousCaretAnchorNode.get(), |
| 202 m_previousCaretRect); | 223 m_previousCaretRect); |
| 203 } | 224 } |
| 204 if (newAnchorNode && shouldRepaintCaret(*newAnchorNode)) | 225 if (newAnchorNode && shouldRepaintCaret(*newAnchorNode)) |
| 205 invalidateLocalCaretRect(newAnchorNode, newRect); | 226 m_caretBase->invalidateLocalCaretRect(newAnchorNode, newRect); |
| 206 m_previousCaretNode = newNode; | 227 m_previousCaretNode = newNode; |
| 207 m_previousCaretAnchorNode = newAnchorNode; | 228 m_previousCaretAnchorNode = newAnchorNode; |
| 208 m_previousCaretRect = newRect; | 229 m_previousCaretRect = newRect; |
| 209 m_previousCaretVisibility = m_caretVisibility; | 230 m_previousCaretVisibility = m_caretVisibility; |
| 231 m_previousCaretColor = newCaretColor; |
| 232 } |
| 233 |
| 234 static IntRect absoluteBoundsForLocalRect(Node* node, const LayoutRect& rect) { |
| 235 LayoutBlock* caretPainter = CaretBase::caretLayoutObject(node); |
| 236 if (!caretPainter) |
| 237 return IntRect(); |
| 238 |
| 239 LayoutRect localRect(rect); |
| 240 caretPainter->flipForWritingMode(localRect); |
| 241 return caretPainter->localToAbsoluteQuad(FloatRect(localRect)) |
| 242 .enclosingBoundingBox(); |
| 210 } | 243 } |
| 211 | 244 |
| 212 // TDOO(yosin): We should mark |FrameCaret::absoluteCaretBounds()| to |const|. | 245 // TDOO(yosin): We should mark |FrameCaret::absoluteCaretBounds()| to |const|. |
| 213 IntRect FrameCaret::absoluteCaretBounds() { | 246 IntRect FrameCaret::absoluteCaretBounds() { |
| 214 DCHECK_NE(m_frame->document()->lifecycle().state(), | 247 DCHECK_NE(m_frame->document()->lifecycle().state(), |
| 215 DocumentLifecycle::InPaintInvalidation); | 248 DocumentLifecycle::InPaintInvalidation); |
| 216 DCHECK(!m_frame->document()->needsLayoutTreeUpdate()); | 249 DCHECK(!m_frame->document()->needsLayoutTreeUpdate()); |
| 217 DocumentLifecycle::DisallowTransitionScope disallowTransition( | 250 DocumentLifecycle::DisallowTransitionScope disallowTransition( |
| 218 m_frame->document()->lifecycle()); | 251 m_frame->document()->lifecycle()); |
| 219 | 252 |
| 220 Node* const caretNode = caretPosition().anchorNode(); | 253 Node* const caretNode = caretPosition().anchorNode(); |
| 221 if (!isActive()) | 254 if (!isActive()) |
| 222 return absoluteBoundsForLocalRect(caretNode, LayoutRect()); | 255 return absoluteBoundsForLocalRect(caretNode, LayoutRect()); |
| 223 // TODO(yosin): We should get rid of text control short path since layout | 256 // TODO(yosin): We should get rid of text control short path since layout |
| 224 // tree is clean. | 257 // tree is clean. |
| 225 if (enclosingTextControl(caretPosition().position()) && | 258 if (enclosingTextControl(caretPosition().position()) && |
| 226 isVisuallyEquivalentCandidate(caretPosition().position())) { | 259 isVisuallyEquivalentCandidate(caretPosition().position())) { |
| 227 return absoluteBoundsForLocalRect(caretNode, | 260 return absoluteBoundsForLocalRect( |
| 228 computeCaretRect(caretPosition())); | 261 caretNode, CaretBase::computeCaretRect(caretPosition())); |
| 229 } | 262 } |
| 230 return absoluteBoundsForLocalRect( | 263 return absoluteBoundsForLocalRect( |
| 231 caretNode, computeCaretRect(createVisiblePosition(caretPosition()))); | 264 caretNode, |
| 265 CaretBase::computeCaretRect( |
| 266 createVisiblePosition(caretPosition()).toPositionWithAffinity())); |
| 232 } | 267 } |
| 233 | 268 |
| 234 void FrameCaret::setShouldShowBlockCursor(bool shouldShowBlockCursor) { | 269 void FrameCaret::setShouldShowBlockCursor(bool shouldShowBlockCursor) { |
| 235 m_shouldShowBlockCursor = shouldShowBlockCursor; | 270 m_shouldShowBlockCursor = shouldShowBlockCursor; |
| 236 | 271 |
| 237 m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets(); | 272 m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets(); |
| 238 | 273 |
| 239 updateAppearance(); | 274 setCaretRectNeedsUpdate(); |
| 240 } | 275 } |
| 241 | 276 |
| 242 void FrameCaret::paintCaret(GraphicsContext& context, | 277 void FrameCaret::paintCaret(GraphicsContext& context, |
| 243 const LayoutPoint& paintOffset) { | 278 const LayoutPoint& paintOffset) { |
| 244 if (m_caretVisibility == CaretVisibility::Hidden) | 279 if (m_caretVisibility == CaretVisibility::Hidden) |
| 245 return; | 280 return; |
| 246 | 281 |
| 247 if (!(isActive() && m_shouldPaintCaret)) | 282 if (!(isActive() && m_shouldPaintCaret)) |
| 248 return; | 283 return; |
| 249 | 284 |
| 250 const LayoutRect caretLocalRect = computeCaretRect(caretPosition()); | 285 const LayoutRect caretLocalRect = |
| 251 CaretBase::paintCaret(caretPosition().anchorNode(), context, *this, | 286 CaretBase::computeCaretRect(caretPosition()); |
| 252 caretLocalRect, paintOffset, DisplayItem::kCaret); | 287 m_caretBase->paintCaret(caretPosition().anchorNode(), context, caretLocalRect, |
| 288 paintOffset, DisplayItem::kCaret); |
| 253 } | 289 } |
| 254 | 290 |
| 255 void FrameCaret::dataWillChange(const CharacterData& node) { | 291 void FrameCaret::dataWillChange(const CharacterData& node) { |
| 256 if (node == m_previousCaretNode) { | 292 if (node == m_previousCaretNode) { |
| 257 // This invalidation is eager, and intentionally uses stale state. | 293 // This invalidation is eager, and intentionally uses stale state. |
| 258 DisableCompositingQueryAsserts disabler; | 294 DisableCompositingQueryAsserts disabler; |
| 259 invalidateLocalCaretRect(m_previousCaretAnchorNode.get(), | 295 m_caretBase->invalidateLocalCaretRect(m_previousCaretAnchorNode.get(), |
| 260 m_previousCaretRect); | 296 m_previousCaretRect); |
| 261 } | 297 } |
| 262 } | 298 } |
| 263 | 299 |
| 264 void FrameCaret::nodeWillBeRemoved(Node& node) { | 300 void FrameCaret::nodeWillBeRemoved(Node& node) { |
| 265 if (node != m_previousCaretNode && node != m_previousCaretAnchorNode) | 301 if (node != m_previousCaretNode && node != m_previousCaretAnchorNode) |
| 266 return; | 302 return; |
| 267 // Hits in ManualTests/caret-paint-after-last-text-is-removed.html | 303 // Hits in ManualTests/caret-paint-after-last-text-is-removed.html |
| 268 DisableCompositingQueryAsserts disabler; | 304 DisableCompositingQueryAsserts disabler; |
| 269 invalidateLocalCaretRect(m_previousCaretAnchorNode.get(), | 305 m_caretBase->invalidateLocalCaretRect(m_previousCaretAnchorNode.get(), |
| 270 m_previousCaretRect); | 306 m_previousCaretRect); |
| 271 m_previousCaretNode = nullptr; | 307 m_previousCaretNode = nullptr; |
| 272 m_previousCaretAnchorNode = nullptr; | 308 m_previousCaretAnchorNode = nullptr; |
| 273 m_previousCaretRect = LayoutRect(); | 309 m_previousCaretRect = LayoutRect(); |
| 274 m_previousCaretVisibility = CaretVisibility::Hidden; | 310 m_previousCaretVisibility = CaretVisibility::Hidden; |
| 275 } | 311 } |
| 276 | 312 |
| 277 void FrameCaret::documentDetached() { | 313 void FrameCaret::contextDestroyed(Document*) { |
| 278 m_caretBlinkTimer.stop(); | 314 m_caretBlinkTimer.stop(); |
| 279 m_previousCaretNode.clear(); | 315 m_previousCaretNode.clear(); |
| 280 m_previousCaretAnchorNode.clear(); | 316 m_previousCaretAnchorNode.clear(); |
| 281 } | 317 } |
| 282 | 318 |
| 283 bool FrameCaret::shouldBlinkCaret() const { | 319 bool FrameCaret::shouldBlinkCaret() const { |
| 284 if (m_caretVisibility != CaretVisibility::Visible || !isActive()) | 320 if (m_caretVisibility != CaretVisibility::Visible || !isActive()) |
| 285 return false; | 321 return false; |
| 286 | 322 |
| 287 Element* root = rootEditableElementOf(caretPosition().position()); | 323 Element* root = rootEditableElementOf(caretPosition().position()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 298 | 334 |
| 299 void FrameCaret::caretBlinkTimerFired(TimerBase*) { | 335 void FrameCaret::caretBlinkTimerFired(TimerBase*) { |
| 300 DCHECK_EQ(m_caretVisibility, CaretVisibility::Visible); | 336 DCHECK_EQ(m_caretVisibility, CaretVisibility::Visible); |
| 301 if (isCaretBlinkingSuspended() && m_shouldPaintCaret) | 337 if (isCaretBlinkingSuspended() && m_shouldPaintCaret) |
| 302 return; | 338 return; |
| 303 m_shouldPaintCaret = !m_shouldPaintCaret; | 339 m_shouldPaintCaret = !m_shouldPaintCaret; |
| 304 setCaretRectNeedsUpdate(); | 340 setCaretRectNeedsUpdate(); |
| 305 } | 341 } |
| 306 | 342 |
| 307 } // namespace blink | 343 } // namespace blink |
| OLD | NEW |