Index: third_party/WebKit/Source/core/editing/FrameCaret.cpp |
diff --git a/third_party/WebKit/Source/core/editing/FrameCaret.cpp b/third_party/WebKit/Source/core/editing/FrameCaret.cpp |
index 2c1d4f30bf12d59b9e7c058cdbba8b87a2be4859..f4dfed85200ede073f7b411d56610cdcd476e669 100644 |
--- a/third_party/WebKit/Source/core/editing/FrameCaret.cpp |
+++ b/third_party/WebKit/Source/core/editing/FrameCaret.cpp |
@@ -39,7 +39,6 @@ |
#include "core/layout/LayoutTheme.h" |
#include "core/layout/api/LayoutPartItem.h" |
#include "core/page/Page.h" |
-#include "core/paint/PaintLayer.h" |
#include "public/platform/WebTraceLocation.h" |
namespace blink { |
@@ -50,11 +49,9 @@ FrameCaret::FrameCaret(LocalFrame& frame, |
m_frame(frame), |
m_caretBase(new CaretDisplayItemClient()), |
m_caretVisibility(CaretVisibility::Hidden), |
- m_previousCaretVisibility(CaretVisibility::Hidden), |
m_caretBlinkTimer(TaskRunnerHelper::get(TaskType::UnspecedTimer, &frame), |
this, |
&FrameCaret::caretBlinkTimerFired), |
- m_caretRectDirty(true), |
m_shouldPaintCaret(true), |
m_isCaretBlinkingSuspended(false), |
m_shouldShowBlockCursor(false) {} |
@@ -64,13 +61,10 @@ FrameCaret::~FrameCaret() = default; |
DEFINE_TRACE(FrameCaret) { |
visitor->trace(m_selectionEditor); |
visitor->trace(m_frame); |
- visitor->trace(m_previousCaretNode); |
- visitor->trace(m_previousCaretAnchorNode); |
- SynchronousMutationObserver::trace(visitor); |
} |
-void FrameCaret::documentAttached(Document* document) { |
- setContext(document); |
+const DisplayItemClient& FrameCaret::displayItemClient() const { |
+ return *m_caretBase; |
} |
const PositionWithAffinity FrameCaret::caretPosition() const { |
@@ -81,10 +75,6 @@ const PositionWithAffinity FrameCaret::caretPosition() const { |
return PositionWithAffinity(selection.start(), selection.affinity()); |
} |
-const DisplayItemClient& FrameCaret::displayItemClient() const { |
- return *m_caretBase; |
-} |
- |
inline static bool shouldStopBlinkingDueToTypingCommand(LocalFrame* frame) { |
return frame->editor().lastEditCommand() && |
frame->editor().lastEditCommand()->shouldStopCaretBlinking(); |
@@ -121,7 +111,7 @@ void FrameCaret::updateAppearance() { |
void FrameCaret::stopCaretBlinkTimer() { |
if (m_caretBlinkTimer.isActive() || m_shouldPaintCaret) |
- setCaretRectNeedsUpdate(); |
+ scheduleVisualUpdateForPaintInvalidationIfNeeded(); |
m_shouldPaintCaret = false; |
m_caretBlinkTimer.stop(); |
} |
@@ -136,7 +126,7 @@ void FrameCaret::startBlinkCaret() { |
m_caretBlinkTimer.startRepeating(blinkInterval, BLINK_FROM_HERE); |
m_shouldPaintCaret = true; |
- setCaretRectNeedsUpdate(); |
+ scheduleVisualUpdateForPaintInvalidationIfNeeded(); |
} |
void FrameCaret::setCaretVisibility(CaretVisibility visibility) { |
@@ -146,22 +136,31 @@ void FrameCaret::setCaretVisibility(CaretVisibility visibility) { |
m_caretVisibility = visibility; |
updateAppearance(); |
+ scheduleVisualUpdateForPaintInvalidationIfNeeded(); |
} |
-void FrameCaret::setCaretRectNeedsUpdate() { |
- if (m_caretRectDirty) |
- return; |
- m_caretRectDirty = true; |
+void FrameCaret::clearPreviousVisualRect(const LayoutBlock& block) { |
+ m_caretBase->clearPreviousVisualRect(block); |
+} |
- if (Page* page = m_frame->page()) |
- page->animator().scheduleVisualUpdate(m_frame->localFrameRoot()); |
+void FrameCaret::layoutBlockWillBeDestroyed(const LayoutBlock& block) { |
+ m_caretBase->layoutBlockWillBeDestroyed(block); |
+} |
- // Ensure the frame will be checked for paint invalidation during |
- // PrePaintTreeWalk. |
- if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled()) { |
- if (auto layoutItem = m_frame->ownerLayoutItem()) |
- layoutItem.setMayNeedPaintInvalidation(); |
- } |
+void FrameCaret::updateStyleAndLayoutIfNeeded() { |
+ bool shouldPaintCaret = |
+ m_shouldPaintCaret && isActive() && |
+ m_caretVisibility == CaretVisibility::Visible && |
+ m_selectionEditor->visibleSelection<EditingStrategy>().hasEditableStyle(); |
+ |
+ m_caretBase->updateStyleAndLayoutIfNeeded( |
+ shouldPaintCaret ? caretPosition() : PositionWithAffinity()); |
+} |
+ |
+void FrameCaret::invalidatePaintIfNeeded(const LayoutBlock& block, |
+ const PaintInvalidatorContext& context, |
+ PaintInvalidationReason reason) { |
+ m_caretBase->invalidatePaintIfNeeded(block, context, reason); |
} |
bool FrameCaret::caretPositionIsValidForDocument( |
@@ -172,65 +171,8 @@ bool FrameCaret::caretPositionIsValidForDocument( |
return caretPosition().document() == document && !caretPosition().isOrphan(); |
} |
-static bool shouldRepaintCaret(Node& node) { |
- // If PositionAnchorType::BeforeAnchor or PositionAnchorType::AfterAnchor, |
- // carets need to be repainted not only when the node is contentEditable but |
- // also when its parentNode() is contentEditable. |
- node.document().updateStyleAndLayoutTree(); |
- return hasEditableStyle(node) || |
- (node.parentNode() && hasEditableStyle(*node.parentNode())); |
-} |
- |
-void FrameCaret::invalidateCaretRect(bool forceInvalidation) { |
- if (!m_caretRectDirty) |
- return; |
- m_caretRectDirty = false; |
- |
- DCHECK(caretPositionIsValidForDocument(*m_frame->document())); |
- LayoutObject* layoutObject = nullptr; |
- LayoutRect newRect; |
- PositionWithAffinity currentCaretPosition = caretPosition(); |
- if (isActive()) |
- newRect = localCaretRectOfPosition(currentCaretPosition, layoutObject); |
- Node* newNode = layoutObject ? layoutObject->node() : nullptr; |
- // The current selected node |newNode| could be a child multiple levels below |
- // its associated "anchor node" ancestor, so we reference and keep around the |
- // anchor node for checking editability. |
- // TODO(wkorman): Consider storing previous Position, rather than Node, and |
- // making use of EditingUtilies::isEditablePosition() directly. |
- Node* newAnchorNode = |
- currentCaretPosition.position().parentAnchoredEquivalent().anchorNode(); |
- if (newNode && newAnchorNode && newNode != newAnchorNode && |
- newAnchorNode->layoutObject() && newAnchorNode->layoutObject()->isBox()) { |
- newNode->layoutObject()->mapToVisualRectInAncestorSpace( |
- toLayoutBoxModelObject(newAnchorNode->layoutObject()), newRect); |
- } |
- // It's possible for the timer to be inactive even though we want to |
- // invalidate the caret. For example, when running as a layout test the |
- // caret blink interval could be zero and thus |m_caretBlinkTimer| will |
- // never be started. We provide |forceInvalidation| for use by paint |
- // invalidation internals where we need to invalidate the caret regardless |
- // of timer state. |
- if (!forceInvalidation && !m_caretBlinkTimer.isActive() && |
- newNode == m_previousCaretNode && newRect == m_previousCaretRect && |
- m_caretVisibility == m_previousCaretVisibility) |
- return; |
- |
- if (m_previousCaretAnchorNode && |
- shouldRepaintCaret(*m_previousCaretAnchorNode)) { |
- m_caretBase->invalidateLocalCaretRect(m_previousCaretAnchorNode.get(), |
- m_previousCaretRect); |
- } |
- if (newAnchorNode && shouldRepaintCaret(*newAnchorNode)) |
- m_caretBase->invalidateLocalCaretRect(newAnchorNode, newRect); |
- m_previousCaretNode = newNode; |
- m_previousCaretAnchorNode = newAnchorNode; |
- m_previousCaretRect = newRect; |
- m_previousCaretVisibility = m_caretVisibility; |
-} |
- |
static IntRect absoluteBoundsForLocalRect(Node* node, const LayoutRect& rect) { |
- LayoutBlock* caretPainter = CaretDisplayItemClient::caretLayoutObject(node); |
+ LayoutBlock* caretPainter = CaretDisplayItemClient::caretLayoutBlock(node); |
if (!caretPainter) |
return IntRect(); |
@@ -271,46 +213,13 @@ void FrameCaret::setShouldShowBlockCursor(bool shouldShowBlockCursor) { |
updateAppearance(); |
} |
-void FrameCaret::paintCaret(GraphicsContext& context, |
- const LayoutPoint& paintOffset) { |
- if (m_caretVisibility == CaretVisibility::Hidden) |
- return; |
- |
- if (!(isActive() && m_shouldPaintCaret)) |
- return; |
- |
- const LayoutRect caretLocalRect = |
- CaretDisplayItemClient::computeCaretRect(caretPosition()); |
- m_caretBase->paintCaret(caretPosition().anchorNode(), context, caretLocalRect, |
- paintOffset, DisplayItem::kCaret); |
-} |
- |
-void FrameCaret::dataWillChange(const CharacterData& node) { |
- if (node == m_previousCaretNode) { |
- // This invalidation is eager, and intentionally uses stale state. |
- DisableCompositingQueryAsserts disabler; |
- m_caretBase->invalidateLocalCaretRect(m_previousCaretAnchorNode.get(), |
- m_previousCaretRect); |
- } |
-} |
- |
-void FrameCaret::nodeWillBeRemoved(Node& node) { |
- if (node != m_previousCaretNode && node != m_previousCaretAnchorNode) |
- return; |
- // Hits in ManualTests/caret-paint-after-last-text-is-removed.html |
- DisableCompositingQueryAsserts disabler; |
- m_caretBase->invalidateLocalCaretRect(m_previousCaretAnchorNode.get(), |
- m_previousCaretRect); |
- m_previousCaretNode = nullptr; |
- m_previousCaretAnchorNode = nullptr; |
- m_previousCaretRect = LayoutRect(); |
- m_previousCaretVisibility = CaretVisibility::Hidden; |
+bool FrameCaret::shouldPaintCaret(const LayoutBlock& block) const { |
+ return m_caretBase->shouldPaintCaret(block); |
} |
-void FrameCaret::contextDestroyed(Document*) { |
- m_caretBlinkTimer.stop(); |
- m_previousCaretNode.clear(); |
- m_previousCaretAnchorNode.clear(); |
+void FrameCaret::paintCaret(GraphicsContext& context, |
+ const LayoutPoint& paintOffset) const { |
+ m_caretBase->paintCaret(context, paintOffset, DisplayItem::kCaret); |
} |
bool FrameCaret::shouldBlinkCaret() const { |
@@ -334,7 +243,12 @@ void FrameCaret::caretBlinkTimerFired(TimerBase*) { |
if (isCaretBlinkingSuspended() && m_shouldPaintCaret) |
return; |
m_shouldPaintCaret = !m_shouldPaintCaret; |
- setCaretRectNeedsUpdate(); |
+ scheduleVisualUpdateForPaintInvalidationIfNeeded(); |
+} |
+ |
+void FrameCaret::scheduleVisualUpdateForPaintInvalidationIfNeeded() { |
+ if (FrameView* frameView = m_frame->view()) |
+ frameView->scheduleVisualUpdateForPaintInvalidationIfNeeded(); |
} |
} // namespace blink |