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

Unified Diff: third_party/WebKit/Source/core/editing/FrameCaret.cpp

Issue 2665823002: Invalidate caret during paint invalidation (Closed)
Patch Set: NeedsRebaseline Created 3 years, 10 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 side-by-side diff with in-line comments
Download patch
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
« no previous file with comments | « third_party/WebKit/Source/core/editing/FrameCaret.h ('k') | third_party/WebKit/Source/core/editing/FrameSelection.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698