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

Side by Side Diff: Source/core/editing/FrameSelection.cpp

Issue 431983005: FrameSelection::updateApperance for caret should not cause layout. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Add updateLocalCaretRect function Created 6 years, 4 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
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 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 265
266 VisibleSelection oldSelection = m_selection; 266 VisibleSelection oldSelection = m_selection;
267 267
268 m_selection = s; 268 m_selection = s;
269 setCaretRectNeedsUpdate(); 269 setCaretRectNeedsUpdate();
270 270
271 if (!s.isNone() && !(options & DoNotSetFocus)) 271 if (!s.isNone() && !(options & DoNotSetFocus))
272 setFocusedNodeIfNeeded(); 272 setFocusedNodeIfNeeded();
273 273
274 if (!(options & DoNotUpdateAppearance)) { 274 if (!(options & DoNotUpdateAppearance)) {
275 m_frame->document()->updateLayoutIgnorePendingStylesheets();
276
277 // Hits in compositing/overflow/do-not-paint-outline-into-composited-scr olling-contents.html 275 // Hits in compositing/overflow/do-not-paint-outline-into-composited-scr olling-contents.html
278 DisableCompositingQueryAsserts disabler; 276 DisableCompositingQueryAsserts disabler;
279 updateAppearance(); 277 updateAppearance();
esprehn 2014/08/05 01:00:02 updateAppearance creates a VisiblePosition which i
yoichio 2014/08/05 05:56:38 Yes. We call layout to get right caret position in
280 } 278 }
281 279
282 // Always clear the x position used for vertical arrow navigation. 280 // Always clear the x position used for vertical arrow navigation.
283 // It will be restored by the vertical arrow navigation code if necessary. 281 // It will be restored by the vertical arrow navigation code if necessary.
284 m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation(); 282 m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation();
285 selectFrameElementInParentIfFullySelected(); 283 selectFrameElementInParentIfFullySelected();
286 notifyRendererOfSelectionChange(userTriggered); 284 notifyRendererOfSelectionChange(userTriggered);
287 m_frame->editor().respondToChangedSelection(oldSelection, options); 285 m_frame->editor().respondToChangedSelection(oldSelection, options);
288 if (userTriggered == UserTriggered) { 286 if (userTriggered == UserTriggered) {
289 ScrollAlignment alignment; 287 ScrollAlignment alignment;
(...skipping 933 matching lines...) Expand 10 before | Expand all | Expand 10 after
1223 static bool isNonOrphanedCaret(const VisibleSelection& selection) 1221 static bool isNonOrphanedCaret(const VisibleSelection& selection)
1224 { 1222 {
1225 return selection.isCaret() && !selection.start().isOrphan() && !selection.en d().isOrphan(); 1223 return selection.isCaret() && !selection.start().isOrphan() && !selection.en d().isOrphan();
1226 } 1224 }
1227 1225
1228 static bool isTextFormControl(const VisibleSelection& selection) 1226 static bool isTextFormControl(const VisibleSelection& selection)
1229 { 1227 {
1230 return enclosingTextFormControl(selection.start()); 1228 return enclosingTextFormControl(selection.start());
1231 } 1229 }
1232 1230
1233 LayoutRect FrameSelection::localCaretRect() 1231 void FrameSelection::updateLocalCaretRect()
1234 { 1232 {
1235 if (shouldUpdateCaretRect()) { 1233 if (shouldUpdateCaretRect()) {
1236 if (!isNonOrphanedCaret(m_selection)) 1234 if (!isNonOrphanedCaret(m_selection)) {
1237 clearCaretRect(); 1235 clearCaretRect();
1238 else if (isTextFormControl(m_selection)) 1236 } else if (isTextFormControl(m_selection)) {
1237 m_frame->document()->updateLayoutIgnorePendingStylesheets();
1239 m_absCaretBoundsDirty |= updateCaretRect(m_frame->document(), Positi onWithAffinity(m_selection.start().isCandidate() ? m_selection.start() : Positio n(), m_selection.affinity())); 1238 m_absCaretBoundsDirty |= updateCaretRect(m_frame->document(), Positi onWithAffinity(m_selection.start().isCandidate() ? m_selection.start() : Positio n(), m_selection.affinity()));
1240 else 1239 } else {
1241 m_absCaretBoundsDirty |= updateCaretRect(m_frame->document(), Visibl ePosition(m_selection.start(), m_selection.affinity())); 1240 m_absCaretBoundsDirty |= updateCaretRect(m_frame->document(), Visibl ePosition(m_selection.start(), m_selection.affinity()));
1241 }
1242 } 1242 }
1243
1244 return localCaretRectWithoutUpdate();
1245 } 1243 }
1246 1244
1247 IntRect FrameSelection::absoluteCaretBounds() 1245 IntRect FrameSelection::absoluteCaretBounds()
1248 { 1246 {
1249 recomputeCaretRect(); 1247 recomputeCaretRect();
1250 return m_absCaretBounds; 1248 return m_absCaretBounds;
1251 } 1249 }
1252 1250
1253 bool FrameSelection::recomputeCaretRect() 1251 bool FrameSelection::recomputeCaretRect()
1254 { 1252 {
1255 if (!shouldUpdateCaretRect()) 1253 if (!shouldUpdateCaretRect())
1256 return false; 1254 return false;
1257 1255
1258 if (!m_frame || !m_frame->document()->view()) 1256 if (!m_frame || !m_frame->document()->view())
1259 return false; 1257 return false;
1260 1258
1261 LayoutRect oldRect = localCaretRectWithoutUpdate(); 1259 LayoutRect oldRect = localCaretRectWithoutUpdate();
1262 LayoutRect newRect = localCaretRect(); 1260 updateLocalCaretRect();
1261 LayoutRect newRect = localCaretRectWithoutUpdate();
1263 if (oldRect == newRect && !m_absCaretBoundsDirty) 1262 if (oldRect == newRect && !m_absCaretBoundsDirty)
1264 return false; 1263 return false;
1265 1264
1266 IntRect oldAbsCaretBounds = m_absCaretBounds; 1265 IntRect oldAbsCaretBounds = m_absCaretBounds;
1267 m_absCaretBounds = absoluteBoundsForLocalRect(m_selection.start().deprecated Node(), localCaretRectWithoutUpdate()); 1266 m_absCaretBounds = absoluteBoundsForLocalRect(m_selection.start().deprecated Node(), localCaretRectWithoutUpdate());
1268 m_absCaretBoundsDirty = false; 1267 m_absCaretBoundsDirty = false;
1269 1268
1270 if (oldAbsCaretBounds == m_absCaretBounds) 1269 if (oldAbsCaretBounds == m_absCaretBounds)
1271 return false; 1270 return false;
1272 1271
(...skipping 12 matching lines...) Expand all
1285 void FrameSelection::invalidateCaretRect() 1284 void FrameSelection::invalidateCaretRect()
1286 { 1285 {
1287 if (!isCaret()) 1286 if (!isCaret())
1288 return; 1287 return;
1289 1288
1290 CaretBase::invalidateCaretRect(m_selection.start().deprecatedNode(), recompu teCaretRect()); 1289 CaretBase::invalidateCaretRect(m_selection.start().deprecatedNode(), recompu teCaretRect());
1291 } 1290 }
1292 1291
1293 void FrameSelection::paintCaret(GraphicsContext* context, const LayoutPoint& pai ntOffset, const LayoutRect& clipRect) 1292 void FrameSelection::paintCaret(GraphicsContext* context, const LayoutPoint& pai ntOffset, const LayoutRect& clipRect)
1294 { 1293 {
1295 if (m_selection.isCaret() && m_caretPaint) 1294 if (m_selection.isCaret() && m_caretPaint) {
1295 updateLocalCaretRect();
esprehn 2014/08/05 01:00:02 Calling updateLayoutIgnorePendingStylesheets from
yoichio 2014/08/05 05:56:38 OK. How about calling updateLocalCaretRect in WebV
1296 CaretBase::paintCaret(m_selection.start().deprecatedNode(), context, pai ntOffset, clipRect); 1296 CaretBase::paintCaret(m_selection.start().deprecatedNode(), context, pai ntOffset, clipRect);
1297 }
1297 } 1298 }
1298 1299
1299 bool FrameSelection::contains(const LayoutPoint& point) 1300 bool FrameSelection::contains(const LayoutPoint& point)
1300 { 1301 {
1301 Document* document = m_frame->document(); 1302 Document* document = m_frame->document();
1302 1303
1303 // Treat a collapsed selection like no selection. 1304 // Treat a collapsed selection like no selection.
1304 if (!isRange()) 1305 if (!isRange())
1305 return false; 1306 return false;
1306 if (!document->renderView()) 1307 if (!document->renderView())
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
1535 return m_focused && m_frame->page() && m_frame->page()->focusController().is Active(); 1536 return m_focused && m_frame->page() && m_frame->page()->focusController().is Active();
1536 } 1537 }
1537 1538
1538 inline static bool shouldStopBlinkingDueToTypingCommand(LocalFrame* frame) 1539 inline static bool shouldStopBlinkingDueToTypingCommand(LocalFrame* frame)
1539 { 1540 {
1540 return frame->editor().lastEditCommand() && frame->editor().lastEditCommand( )->shouldStopCaretBlinking(); 1541 return frame->editor().lastEditCommand() && frame->editor().lastEditCommand( )->shouldStopCaretBlinking();
1541 } 1542 }
1542 1543
1543 void FrameSelection::updateAppearance() 1544 void FrameSelection::updateAppearance()
1544 { 1545 {
1546 bool isTextForm = isTextFormControl(m_selection);
esprehn 2014/08/05 01:00:02 I don't think we want to special case stuff like t
yoichio 2014/08/05 05:56:38 Actually, this CL is for improvement benchmark sco
1545 // Paint a block cursor instead of a caret in overtype mode unless the caret is at the end of a line (in this case 1547 // Paint a block cursor instead of a caret in overtype mode unless the caret is at the end of a line (in this case
1546 // the FrameSelection will paint a blinking caret as usual). 1548 // the FrameSelection will paint a blinking caret as usual).
1547 VisiblePosition forwardPosition; 1549 VisiblePosition forwardPosition;
1548 if (m_shouldShowBlockCursor && m_selection.isCaret()) { 1550 if (m_shouldShowBlockCursor && m_selection.isCaret()) {
1549 forwardPosition = modifyExtendingForward(CharacterGranularity); 1551 forwardPosition = modifyExtendingForward(CharacterGranularity);
1550 m_caretPaint = forwardPosition.isNull(); 1552 m_caretPaint = forwardPosition.isNull();
1551 } 1553 }
1552 1554
1553 bool caretRectChangedOrCleared = recomputeCaretRect(); 1555 bool caretRectChangedOrCleared = isTextForm || recomputeCaretRect();
1554 bool shouldBlink = shouldBlinkCaret() && forwardPosition.isNull(); 1556 bool shouldBlink = shouldBlinkCaret() && forwardPosition.isNull();
1555 1557
1556 // If the caret moved, stop the blink timer so we can restart with a 1558 // If the caret moved, stop the blink timer so we can restart with a
1557 // black caret in the new location. 1559 // black caret in the new location.
1558 if (caretRectChangedOrCleared || !shouldBlink || shouldStopBlinkingDueToTypi ngCommand(m_frame)) { 1560 if (caretRectChangedOrCleared || !shouldBlink || shouldStopBlinkingDueToTypi ngCommand(m_frame)) {
1559 m_caretBlinkTimer.stop(); 1561 m_caretBlinkTimer.stop();
1560 if (!shouldBlink && m_caretPaint) { 1562 if (!shouldBlink && m_caretPaint) {
1561 m_caretPaint = false; 1563 m_caretPaint = false;
1562 invalidateCaretRect(); 1564 invalidateCaretRect();
1563 } 1565 }
(...skipping 10 matching lines...) Expand all
1574 invalidateCaretRect(); 1576 invalidateCaretRect();
1575 } 1577 }
1576 } 1578 }
1577 1579
1578 RenderView* view = m_frame->contentRenderer(); 1580 RenderView* view = m_frame->contentRenderer();
1579 if (!view) 1581 if (!view)
1580 return; 1582 return;
1581 1583
1582 // Construct a new VisibleSolution, since m_selection is not necessarily val id, and the following steps 1584 // Construct a new VisibleSolution, since m_selection is not necessarily val id, and the following steps
1583 // assume a valid selection. See <https://bugs.webkit.org/show_bug.cgi?id=69 563> and <rdar://problem/10232866>. 1585 // assume a valid selection. See <https://bugs.webkit.org/show_bug.cgi?id=69 563> and <rdar://problem/10232866>.
1584 VisibleSelection selection(m_selection.visibleStart(), forwardPosition.isNot Null() ? forwardPosition : m_selection.visibleEnd()); 1586 VisibleSelection selection;
1587 if (isTextForm)
1588 selection.setWithoutValidation(m_selection.start(), forwardPosition.isNo tNull() ? forwardPosition.deepEquivalent() : m_selection.end());
1589 else
1590 selection = VisibleSelection(m_selection.visibleStart(), forwardPosition .isNotNull() ? forwardPosition : m_selection.visibleEnd());
1585 1591
1586 if (!selection.isRange()) { 1592 if (!selection.isRange()) {
1587 view->clearSelection(); 1593 view->clearSelection();
1588 return; 1594 return;
1589 } 1595 }
1590 1596
1591 // Use the rightmost candidate for the start of the selection, and the leftm ost candidate for the end of the selection. 1597 // Use the rightmost candidate for the start of the selection, and the leftm ost candidate for the end of the selection.
1592 // Example: foo <a>bar</a>. Imagine that a line wrap occurs after 'foo', an d that 'bar' is selected. If we pass [foo, 3] 1598 // Example: foo <a>bar</a>. Imagine that a line wrap occurs after 'foo', an d that 'bar' is selected. If we pass [foo, 3]
1593 // as the start of the selection, the selection painting code will think tha t content on the line containing 'foo' is selected 1599 // as the start of the selection, the selection painting code will think tha t content on the line containing 'foo' is selected
1594 // and will fill the gap before 'bar'. 1600 // and will fill the gap before 'bar'.
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1650 ASSERT(caretIsVisible()); 1656 ASSERT(caretIsVisible());
1651 ASSERT(isCaret()); 1657 ASSERT(isCaret());
1652 if (isCaretBlinkingSuspended() && m_caretPaint) 1658 if (isCaretBlinkingSuspended() && m_caretPaint)
1653 return; 1659 return;
1654 m_caretPaint = !m_caretPaint; 1660 m_caretPaint = !m_caretPaint;
1655 invalidateCaretRect(); 1661 invalidateCaretRect();
1656 } 1662 }
1657 1663
1658 void FrameSelection::notifyRendererOfSelectionChange(EUserTriggered userTriggere d) 1664 void FrameSelection::notifyRendererOfSelectionChange(EUserTriggered userTriggere d)
1659 { 1665 {
1660 m_frame->document()->updateRenderTreeIfNeeded();
1661
1662 if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(start ())) 1666 if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(start ()))
1663 textControl->selectionChanged(userTriggered == UserTriggered); 1667 textControl->selectionChanged(userTriggered == UserTriggered);
1664 } 1668 }
1665 1669
1666 // Helper function that tells whether a particular node is an element that has a n entire 1670 // Helper function that tells whether a particular node is an element that has a n entire
1667 // LocalFrame and FrameView, a <frame>, <iframe>, or <object>. 1671 // LocalFrame and FrameView, a <frame>, <iframe>, or <object>.
1668 static bool isFrameElement(const Node* n) 1672 static bool isFrameElement(const Node* n)
1669 { 1673 {
1670 if (!n) 1674 if (!n)
1671 return false; 1675 return false;
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
1927 sel.showTreeForThis(); 1931 sel.showTreeForThis();
1928 } 1932 }
1929 1933
1930 void showTree(const blink::FrameSelection* sel) 1934 void showTree(const blink::FrameSelection* sel)
1931 { 1935 {
1932 if (sel) 1936 if (sel)
1933 sel->showTreeForThis(); 1937 sel->showTreeForThis();
1934 } 1938 }
1935 1939
1936 #endif 1940 #endif
OLDNEW
« no previous file with comments | « Source/core/editing/FrameSelection.h ('k') | Source/core/html/HTMLTextFormControlElementTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698