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

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: Delay invalidation 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(ResetCaretBlink);
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 936 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 LayoutRect FrameSelection::localCaretRect()
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 {
1239 m_absCaretBoundsDirty |= updateCaretRect(m_frame->document(), Positi onWithAffinity(m_selection.start().isCandidate() ? m_selection.start() : Positio n(), m_selection.affinity())); 1237 m_frame->document()->updateLayoutIgnorePendingStylesheets();
1240 else 1238 if (isTextFormControl(m_selection))
1241 m_absCaretBoundsDirty |= updateCaretRect(m_frame->document(), Visibl ePosition(m_selection.start(), m_selection.affinity())); 1239 m_absCaretBoundsDirty |= updateCaretRect(m_frame->document(), Po sitionWithAffinity(m_selection.start().isCandidate() ? m_selection.start() : Pos ition(), m_selection.affinity()));
1240 else
1241 m_absCaretBoundsDirty |= updateCaretRect(m_frame->document(), Vi siblePosition(m_selection.start(), m_selection.affinity()));
1242 }
1242 } 1243 }
1243
1244 return localCaretRectWithoutUpdate(); 1244 return localCaretRectWithoutUpdate();
1245 } 1245 }
1246 1246
1247 IntRect FrameSelection::absoluteCaretBounds() 1247 IntRect FrameSelection::absoluteCaretBounds()
1248 { 1248 {
1249 recomputeCaretRect(); 1249 recomputeCaretRect();
1250 return m_absCaretBounds; 1250 return m_absCaretBounds;
1251 } 1251 }
1252 1252
1253 bool FrameSelection::recomputeCaretRect() 1253 bool FrameSelection::recomputeCaretRect()
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
1533 bool FrameSelection::isFocusedAndActive() const 1533 bool FrameSelection::isFocusedAndActive() const
1534 { 1534 {
1535 return m_focused && m_frame->page() && m_frame->page()->focusController().is Active(); 1535 return m_focused && m_frame->page() && m_frame->page()->focusController().is Active();
1536 } 1536 }
1537 1537
1538 inline static bool shouldStopBlinkingDueToTypingCommand(LocalFrame* frame) 1538 inline static bool shouldStopBlinkingDueToTypingCommand(LocalFrame* frame)
1539 { 1539 {
1540 return frame->editor().lastEditCommand() && frame->editor().lastEditCommand( )->shouldStopCaretBlinking(); 1540 return frame->editor().lastEditCommand() && frame->editor().lastEditCommand( )->shouldStopCaretBlinking();
1541 } 1541 }
1542 1542
1543 void FrameSelection::updateAppearance() 1543 void FrameSelection::updateAppearance(UpdateAppearanceOption option)
1544 { 1544 {
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 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
1546 // the FrameSelection will paint a blinking caret as usual). 1546 // the FrameSelection will paint a blinking caret as usual).
1547 bool paintBlockCursor = m_shouldShowBlockCursor && m_selection.isCaret() && !isLogicalEndOfLine(m_selection.visibleEnd()); 1547 bool paintBlockCursor = m_shouldShowBlockCursor && m_selection.isCaret() && !isLogicalEndOfLine(m_selection.visibleEnd());
1548 1548
1549 bool caretRectChangedOrCleared = recomputeCaretRect();
1550 bool shouldBlink = !paintBlockCursor && shouldBlinkCaret(); 1549 bool shouldBlink = !paintBlockCursor && shouldBlinkCaret();
1551 1550
1552 // If the caret moved, stop the blink timer so we can restart with a 1551 // If the caret moved, stop the blink timer so we can restart with a
1553 // black caret in the new location. 1552 // black caret in the new location.
1554 if (caretRectChangedOrCleared || !shouldBlink || shouldStopBlinkingDueToTypi ngCommand(m_frame)) { 1553 if (option == ResetCaretBlink || !shouldBlink || shouldStopBlinkingDueToTypi ngCommand(m_frame)) {
1555 m_caretBlinkTimer.stop(); 1554 m_caretBlinkTimer.stop();
1556 if (!shouldBlink && m_caretPaint) { 1555 if (!shouldBlink && m_caretPaint) {
1557 m_caretPaint = false; 1556 m_caretPaint = false;
1558 invalidateCaretRect(); 1557 setCaretRectNeedsUpdate();
1559 } 1558 }
1560 } 1559 }
1561 1560
1562 // Start blinking with a black caret. Be sure not to restart if we're 1561 // Start blinking with a black caret. Be sure not to restart if we're
1563 // already blinking in the right location. 1562 // already blinking in the right location.
1564 if (shouldBlink && !m_caretBlinkTimer.isActive()) { 1563 if (shouldBlink && !m_caretBlinkTimer.isActive()) {
1565 if (double blinkInterval = RenderTheme::theme().caretBlinkInterval()) 1564 if (double blinkInterval = RenderTheme::theme().caretBlinkInterval())
1566 m_caretBlinkTimer.startRepeating(blinkInterval, FROM_HERE); 1565 m_caretBlinkTimer.startRepeating(blinkInterval, FROM_HERE);
1567 1566
1568 if (!m_caretPaint) { 1567 if (!m_caretPaint) {
1569 m_caretPaint = true; 1568 m_caretPaint = true;
1570 invalidateCaretRect(); 1569 setCaretRectNeedsUpdate();
1571 } 1570 }
1572 } 1571 }
1573 1572
1573 if (shouldUpdateCaretRect() && m_frame->page())
1574 m_frame->page()->animator().scheduleVisualUpdate();
1575
1574 RenderView* view = m_frame->contentRenderer(); 1576 RenderView* view = m_frame->contentRenderer();
1575 if (!view) 1577 if (!view)
1576 return; 1578 return;
1577 1579
1578 // Construct a new VisibleSolution, since m_selection is not necessarily val id, and the following steps 1580 // Construct a new VisibleSolution, since m_selection is not necessarily val id, and the following steps
1579 // assume a valid selection. See <https://bugs.webkit.org/show_bug.cgi?id=69 563> and <rdar://problem/10232866>. 1581 // assume a valid selection. See <https://bugs.webkit.org/show_bug.cgi?id=69 563> and <rdar://problem/10232866>.
1580 VisiblePosition endVisiblePosition = paintBlockCursor ? modifyExtendingForwa rd(CharacterGranularity) : m_selection.visibleEnd(); 1582
1581 VisibleSelection selection(m_selection.visibleStart(), endVisiblePosition); 1583 VisibleSelection selection;
1584 if (isTextFormControl(m_selection)) {
1585 Position endPosition = paintBlockCursor ? m_selection.extent().next() : m_selection.end();
1586 selection.setWithoutValidation(m_selection.start(), endPosition);
1587 } else {
1588 VisiblePosition endVisiblePosition = paintBlockCursor ? modifyExtendingF orward(CharacterGranularity) : m_selection.visibleEnd();
1589 selection = VisibleSelection(m_selection.visibleStart(), endVisiblePosit ion);
1590 }
1582 1591
1583 if (!selection.isRange()) { 1592 if (!selection.isRange()) {
1584 view->clearSelection(); 1593 view->clearSelection();
1585 return; 1594 return;
1586 } 1595 }
1587 1596
1588 // 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.
1589 // 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]
1590 // 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
1591 // and will fill the gap before 'bar'. 1600 // and will fill the gap before 'bar'.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1642 return focusedElement->containsIncludingShadowDOM(m_selection.start().anchor Node()); 1651 return focusedElement->containsIncludingShadowDOM(m_selection.start().anchor Node());
1643 } 1652 }
1644 1653
1645 void FrameSelection::caretBlinkTimerFired(Timer<FrameSelection>*) 1654 void FrameSelection::caretBlinkTimerFired(Timer<FrameSelection>*)
1646 { 1655 {
1647 ASSERT(caretIsVisible()); 1656 ASSERT(caretIsVisible());
1648 ASSERT(isCaret()); 1657 ASSERT(isCaret());
1649 if (isCaretBlinkingSuspended() && m_caretPaint) 1658 if (isCaretBlinkingSuspended() && m_caretPaint)
1650 return; 1659 return;
1651 m_caretPaint = !m_caretPaint; 1660 m_caretPaint = !m_caretPaint;
1652 invalidateCaretRect(); 1661 setCaretRectNeedsUpdate();
1662 if (Page* page = m_frame->page())
1663 page->animator().scheduleVisualUpdate();
1653 } 1664 }
1654 1665
1655 void FrameSelection::notifyRendererOfSelectionChange(EUserTriggered userTriggere d) 1666 void FrameSelection::notifyRendererOfSelectionChange(EUserTriggered userTriggere d)
1656 { 1667 {
1657 m_frame->document()->updateRenderTreeIfNeeded();
1658
1659 if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(start ())) 1668 if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(start ()))
1660 textControl->selectionChanged(userTriggered == UserTriggered); 1669 textControl->selectionChanged(userTriggered == UserTriggered);
1661 } 1670 }
1662 1671
1663 // Helper function that tells whether a particular node is an element that has a n entire 1672 // Helper function that tells whether a particular node is an element that has a n entire
1664 // LocalFrame and FrameView, a <frame>, <iframe>, or <object>. 1673 // LocalFrame and FrameView, a <frame>, <iframe>, or <object>.
1665 static bool isFrameElement(const Node* n) 1674 static bool isFrameElement(const Node* n)
1666 { 1675 {
1667 if (!n) 1676 if (!n)
1668 return false; 1677 return false;
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
1924 sel.showTreeForThis(); 1933 sel.showTreeForThis();
1925 } 1934 }
1926 1935
1927 void showTree(const blink::FrameSelection* sel) 1936 void showTree(const blink::FrameSelection* sel)
1928 { 1937 {
1929 if (sel) 1938 if (sel)
1930 sel->showTreeForThis(); 1939 sel->showTreeForThis();
1931 } 1940 }
1932 1941
1933 #endif 1942 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698