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

Side by Side Diff: third_party/WebKit/Source/core/editing/FrameCaret.cpp

Issue 2401363003: Use anchor node, rather than current selected node, to check editability. (Closed)
Patch Set: Feedback. Created 4 years, 2 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 unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/core/editing/FrameCaret.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/editing/FrameCaret.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698