| 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
|
|
|