Chromium Code Reviews| 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 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 53 m_shouldShowBlockCursor(false) { | 53 m_shouldShowBlockCursor(false) { |
| 54 DCHECK(frame); | 54 DCHECK(frame); |
| 55 } | 55 } |
| 56 | 56 |
| 57 FrameCaret::~FrameCaret() = default; | 57 FrameCaret::~FrameCaret() = default; |
| 58 | 58 |
| 59 DEFINE_TRACE(FrameCaret) { | 59 DEFINE_TRACE(FrameCaret) { |
| 60 visitor->trace(m_selectionEditor); | 60 visitor->trace(m_selectionEditor); |
| 61 visitor->trace(m_frame); | 61 visitor->trace(m_frame); |
| 62 visitor->trace(m_previousCaretNode); | 62 visitor->trace(m_previousCaretNode); |
| 63 visitor->trace(m_previousCaretAnchorNode); | |
| 63 CaretBase::trace(visitor); | 64 CaretBase::trace(visitor); |
| 64 } | 65 } |
| 65 | 66 |
| 66 const PositionWithAffinity FrameCaret::caretPosition() const { | 67 const PositionWithAffinity FrameCaret::caretPosition() const { |
| 67 const VisibleSelection& selection = | 68 const VisibleSelection& selection = |
| 68 m_selectionEditor->visibleSelection<EditingStrategy>(); | 69 m_selectionEditor->visibleSelection<EditingStrategy>(); |
| 69 if (!selection.isCaret()) | 70 if (!selection.isCaret()) |
| 70 return PositionWithAffinity(); | 71 return PositionWithAffinity(); |
| 71 return PositionWithAffinity(selection.start(), selection.affinity()); | 72 return PositionWithAffinity(selection.start(), selection.affinity()); |
| 72 } | 73 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 145 } | 146 } |
| 146 | 147 |
| 147 void FrameCaret::invalidateCaretRect(bool forceInvalidation) { | 148 void FrameCaret::invalidateCaretRect(bool forceInvalidation) { |
| 148 if (!m_caretRectDirty) | 149 if (!m_caretRectDirty) |
| 149 return; | 150 return; |
| 150 m_caretRectDirty = false; | 151 m_caretRectDirty = false; |
| 151 | 152 |
| 152 DCHECK(caretPositionIsValidForDocument(*m_frame->document())); | 153 DCHECK(caretPositionIsValidForDocument(*m_frame->document())); |
| 153 LayoutObject* layoutObject = nullptr; | 154 LayoutObject* layoutObject = nullptr; |
| 154 LayoutRect newRect; | 155 LayoutRect newRect; |
| 156 PositionWithAffinity currentCaretPosition = caretPosition(); | |
| 155 if (isActive()) | 157 if (isActive()) |
| 156 newRect = localCaretRectOfPosition(caretPosition(), layoutObject); | 158 newRect = localCaretRectOfPosition(currentCaretPosition, layoutObject); |
| 157 Node* newNode = layoutObject ? layoutObject->node() : nullptr; | 159 Node* newNode = layoutObject ? layoutObject->node() : nullptr; |
| 158 | 160 // The current selected node |newNode| could be a child multiple levels below |
| 161 // its associated "anchor node" ancestor, so we reference and keep around the | |
| 162 // anchor node for checking editability. | |
| 163 // TODO(wkorman): Consider storing previous Position, rather than Node, and | |
| 164 // making use of EditingUtilies::isEditablePosition() directly. | |
| 165 Node* newAnchorNode = | |
|
yosin_UTC9
2016/10/13 03:58:47
I think we should use layout object associated Dis
| |
| 166 currentCaretPosition.position().parentAnchoredEquivalent().anchorNode(); | |
| 167 if (newNode && newAnchorNode && newNode != newAnchorNode && | |
| 168 newAnchorNode->layoutObject() && newAnchorNode->layoutObject()->isBox()) { | |
| 169 newNode->layoutObject()->mapToVisualRectInAncestorSpace( | |
| 170 toLayoutBoxModelObject(newAnchorNode->layoutObject()), newRect); | |
| 171 } | |
| 159 // It's possible for the timer to be inactive even though we want to | 172 // It's possible for the timer to be inactive even though we want to |
| 160 // invalidate the caret. For example, when running as a layout test the | 173 // invalidate the caret. For example, when running as a layout test the |
| 161 // caret blink interval could be zero and thus |m_caretBlinkTimer| will | 174 // caret blink interval could be zero and thus |m_caretBlinkTimer| will |
| 162 // never be started. We provide |forceInvalidation| for use by paint | 175 // never be started. We provide |forceInvalidation| for use by paint |
| 163 // invalidation internals where we need to invalidate the caret regardless | 176 // invalidation internals where we need to invalidate the caret regardless |
| 164 // of timer state. | 177 // of timer state. |
| 165 if (!forceInvalidation && !m_caretBlinkTimer.isActive() && | 178 if (!forceInvalidation && !m_caretBlinkTimer.isActive() && |
| 166 newNode == m_previousCaretNode && newRect == m_previousCaretRect && | 179 newNode == m_previousCaretNode && newRect == m_previousCaretRect && |
| 167 m_caretVisibility == m_previousCaretVisibility) | 180 m_caretVisibility == m_previousCaretVisibility) |
| 168 return; | 181 return; |
| 169 | 182 |
| 170 if (m_previousCaretNode && shouldRepaintCaret(*m_previousCaretNode)) | 183 if (m_previousCaretNode && shouldRepaintCaret(*m_previousCaretAnchorNode)) { |
| 171 invalidateLocalCaretRect(m_previousCaretNode.get(), m_previousCaretRect); | 184 invalidateLocalCaretRect(m_previousCaretAnchorNode.get(), |
| 172 if (newNode && shouldRepaintCaret(*newNode)) | 185 m_previousCaretRect); |
| 173 invalidateLocalCaretRect(newNode, newRect); | 186 } |
| 187 if (newNode && shouldRepaintCaret(*newAnchorNode)) | |
| 188 invalidateLocalCaretRect(newAnchorNode, newRect); | |
| 174 m_previousCaretNode = newNode; | 189 m_previousCaretNode = newNode; |
| 190 m_previousCaretAnchorNode = newAnchorNode; | |
| 175 m_previousCaretRect = newRect; | 191 m_previousCaretRect = newRect; |
| 176 m_previousCaretVisibility = m_caretVisibility; | 192 m_previousCaretVisibility = m_caretVisibility; |
| 177 } | 193 } |
| 178 | 194 |
| 179 IntRect FrameCaret::absoluteCaretBounds() { | 195 IntRect FrameCaret::absoluteCaretBounds() { |
| 180 DCHECK_NE(m_frame->document()->lifecycle().state(), | 196 DCHECK_NE(m_frame->document()->lifecycle().state(), |
| 181 DocumentLifecycle::InPaintInvalidation); | 197 DocumentLifecycle::InPaintInvalidation); |
| 182 DCHECK(!m_frame->document()->needsLayoutTreeUpdate()); | 198 DCHECK(!m_frame->document()->needsLayoutTreeUpdate()); |
| 183 DocumentLifecycle::DisallowTransitionScope disallowTransition( | 199 DocumentLifecycle::DisallowTransitionScope disallowTransition( |
| 184 m_frame->document()->lifecycle()); | 200 m_frame->document()->lifecycle()); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 217 | 233 |
| 218 updateCaretRect(caretPosition()); | 234 updateCaretRect(caretPosition()); |
| 219 CaretBase::paintCaret(caretPosition().position().anchorNode(), context, | 235 CaretBase::paintCaret(caretPosition().position().anchorNode(), context, |
| 220 paintOffset, DisplayItem::kCaret); | 236 paintOffset, DisplayItem::kCaret); |
| 221 } | 237 } |
| 222 | 238 |
| 223 void FrameCaret::dataWillChange(const CharacterData& node) { | 239 void FrameCaret::dataWillChange(const CharacterData& node) { |
| 224 if (node == m_previousCaretNode) { | 240 if (node == m_previousCaretNode) { |
| 225 // This invalidation is eager, and intentionally uses stale state. | 241 // This invalidation is eager, and intentionally uses stale state. |
| 226 DisableCompositingQueryAsserts disabler; | 242 DisableCompositingQueryAsserts disabler; |
| 227 invalidateLocalCaretRect(m_previousCaretNode.get(), m_previousCaretRect); | 243 invalidateLocalCaretRect(m_previousCaretAnchorNode.get(), |
| 244 m_previousCaretRect); | |
| 228 } | 245 } |
| 229 } | 246 } |
| 230 | 247 |
| 231 void FrameCaret::nodeWillBeRemoved(Node& node) { | 248 void FrameCaret::nodeWillBeRemoved(Node& node) { |
| 232 if (node != m_previousCaretNode) | 249 if (node != m_previousCaretNode && node != m_previousCaretAnchorNode) |
| 233 return; | 250 return; |
| 234 // Hits in ManualTests/caret-paint-after-last-text-is-removed.html | 251 // Hits in ManualTests/caret-paint-after-last-text-is-removed.html |
| 235 DisableCompositingQueryAsserts disabler; | 252 DisableCompositingQueryAsserts disabler; |
| 236 invalidateLocalCaretRect(m_previousCaretNode.get(), m_previousCaretRect); | 253 invalidateLocalCaretRect(m_previousCaretAnchorNode.get(), |
| 254 m_previousCaretRect); | |
| 237 m_previousCaretNode = nullptr; | 255 m_previousCaretNode = nullptr; |
| 256 m_previousCaretAnchorNode = nullptr; | |
| 238 m_previousCaretRect = LayoutRect(); | 257 m_previousCaretRect = LayoutRect(); |
| 239 m_previousCaretVisibility = CaretVisibility::Hidden; | 258 m_previousCaretVisibility = CaretVisibility::Hidden; |
| 240 } | 259 } |
| 241 | 260 |
| 242 void FrameCaret::documentDetached() { | 261 void FrameCaret::documentDetached() { |
| 243 m_caretBlinkTimer.stop(); | 262 m_caretBlinkTimer.stop(); |
| 244 m_previousCaretNode.clear(); | 263 m_previousCaretNode.clear(); |
| 264 m_previousCaretAnchorNode.clear(); | |
| 245 } | 265 } |
| 246 | 266 |
| 247 bool FrameCaret::shouldBlinkCaret() const { | 267 bool FrameCaret::shouldBlinkCaret() const { |
| 248 if (m_caretVisibility != CaretVisibility::Visible || !isActive()) | 268 if (m_caretVisibility != CaretVisibility::Visible || !isActive()) |
| 249 return false; | 269 return false; |
| 250 | 270 |
| 251 Element* root = rootEditableElementOf(caretPosition().position()); | 271 Element* root = rootEditableElementOf(caretPosition().position()); |
| 252 if (!root) | 272 if (!root) |
| 253 return false; | 273 return false; |
| 254 | 274 |
| 255 Element* focusedElement = root->document().focusedElement(); | 275 Element* focusedElement = root->document().focusedElement(); |
| 256 if (!focusedElement) | 276 if (!focusedElement) |
| 257 return false; | 277 return false; |
| 258 | 278 |
| 259 return focusedElement->isShadowIncludingInclusiveAncestorOf( | 279 return focusedElement->isShadowIncludingInclusiveAncestorOf( |
| 260 caretPosition().position().anchorNode()); | 280 caretPosition().position().anchorNode()); |
| 261 } | 281 } |
| 262 | 282 |
| 263 void FrameCaret::caretBlinkTimerFired(TimerBase*) { | 283 void FrameCaret::caretBlinkTimerFired(TimerBase*) { |
| 264 DCHECK_EQ(m_caretVisibility, CaretVisibility::Visible); | 284 DCHECK_EQ(m_caretVisibility, CaretVisibility::Visible); |
| 265 if (isCaretBlinkingSuspended() && m_shouldPaintCaret) | 285 if (isCaretBlinkingSuspended() && m_shouldPaintCaret) |
| 266 return; | 286 return; |
| 267 m_shouldPaintCaret = !m_shouldPaintCaret; | 287 m_shouldPaintCaret = !m_shouldPaintCaret; |
| 268 setCaretRectNeedsUpdate(); | 288 setCaretRectNeedsUpdate(); |
| 269 } | 289 } |
| 270 | 290 |
| 271 } // nemaspace blink | 291 } // namespace blink |
| OLD | NEW |