| Index: third_party/WebKit/Source/core/editing/CaretDisplayItemClient.cpp
|
| diff --git a/third_party/WebKit/Source/core/editing/CaretDisplayItemClient.cpp b/third_party/WebKit/Source/core/editing/CaretDisplayItemClient.cpp
|
| index 88ef35c3a152c177b5e43fd1244ab872d89cf678..80930cebdb36b5b90b90111f5db06ad9b0e957d9 100644
|
| --- a/third_party/WebKit/Source/core/editing/CaretDisplayItemClient.cpp
|
| +++ b/third_party/WebKit/Source/core/editing/CaretDisplayItemClient.cpp
|
| @@ -34,10 +34,11 @@
|
| #include "core/layout/api/LayoutBlockItem.h"
|
| #include "core/layout/api/LayoutItem.h"
|
| #include "core/layout/api/LayoutViewItem.h"
|
| +#include "core/paint/ObjectPaintInvalidator.h"
|
| #include "core/paint/PaintInfo.h"
|
| +#include "core/paint/PaintInvalidator.h"
|
| #include "core/paint/PaintLayer.h"
|
| #include "platform/graphics/GraphicsContext.h"
|
| -#include "platform/graphics/GraphicsLayer.h"
|
| #include "platform/graphics/paint/DrawingRecorder.h"
|
|
|
| namespace blink {
|
| @@ -45,11 +46,11 @@ namespace blink {
|
| CaretDisplayItemClient::CaretDisplayItemClient() = default;
|
| CaretDisplayItemClient::~CaretDisplayItemClient() = default;
|
|
|
| -static inline bool caretRendersInsideNode(Node* node) {
|
| +static inline bool caretRendersInsideNode(const Node* node) {
|
| return node && !isDisplayInsideTable(node) && !editingIgnoresContent(*node);
|
| }
|
|
|
| -LayoutBlock* CaretDisplayItemClient::caretLayoutObject(Node* node) {
|
| +LayoutBlock* CaretDisplayItemClient::caretLayoutBlock(const Node* node) {
|
| if (!node)
|
| return nullptr;
|
|
|
| @@ -107,54 +108,136 @@ LayoutRect CaretDisplayItemClient::computeCaretRect(
|
| // Get the layoutObject that will be responsible for painting the caret
|
| // (which is either the layoutObject we just found, or one of its containers).
|
| LayoutBlockItem caretPainterItem =
|
| - LayoutBlockItem(caretLayoutObject(caretPosition.anchorNode()));
|
| + LayoutBlockItem(caretLayoutBlock(caretPosition.anchorNode()));
|
|
|
| return mapCaretRectToCaretPainter(LayoutItem(layoutObject), caretPainterItem,
|
| caretLocalRect);
|
| }
|
|
|
| -// TODO(yoichio): |node| is FrameSelection::m_previousCaretNode and this is bad
|
| -// design. We should use only previous layoutObject or Rectangle to invalidate
|
| -// old caret.
|
| -void CaretDisplayItemClient::invalidateLocalCaretRect(Node* node,
|
| - const LayoutRect& rect) {
|
| - LayoutBlock* caretLayoutBlock = caretLayoutObject(node);
|
| - if (!caretLayoutBlock)
|
| +void CaretDisplayItemClient::updateStyleAndLayoutIfNeeded(
|
| + const PositionWithAffinity& caretPosition) {
|
| + LayoutBlock* newLayoutBlock = caretLayoutBlock(caretPosition.anchorNode());
|
| + if (newLayoutBlock != m_layoutBlock) {
|
| + if (m_layoutBlock)
|
| + m_layoutBlock->setMayNeedPaintInvalidation();
|
| + m_previousLayoutBlock = m_layoutBlock;
|
| + m_layoutBlock = newLayoutBlock;
|
| + m_needsPaintInvalidation = true;
|
| + } else {
|
| + m_previousLayoutBlock = nullptr;
|
| + }
|
| +
|
| + if (!newLayoutBlock) {
|
| + m_color = Color();
|
| + m_localRect = LayoutRect();
|
| + return;
|
| + }
|
| +
|
| + Color newColor;
|
| + if (caretPosition.anchorNode()) {
|
| + newColor = caretPosition.anchorNode()->layoutObject()->resolveColor(
|
| + CSSPropertyCaretColor);
|
| + }
|
| + if (newColor != m_color) {
|
| + m_needsPaintInvalidation = true;
|
| + m_color = newColor;
|
| + }
|
| +
|
| + LayoutRect newLocalRect = computeCaretRect(caretPosition);
|
| + if (newLocalRect != m_localRect) {
|
| + m_needsPaintInvalidation = true;
|
| + m_localRect = newLocalRect;
|
| + }
|
| +
|
| + if (m_needsPaintInvalidation)
|
| + newLayoutBlock->setMayNeedPaintInvalidation();
|
| +}
|
| +
|
| +void CaretDisplayItemClient::invalidatePaintIfNeeded(
|
| + const LayoutBlock& block,
|
| + const PaintInvalidatorContext& context,
|
| + PaintInvalidationReason layoutBlockPaintInvalidationReason) {
|
| + if (block == m_previousLayoutBlock) {
|
| + // Invalidate the previous caret if it was in a different block.
|
| + // m_previousLayoutBlock is set only when it's different from m_layoutBlock.
|
| + DCHECK(block != m_layoutBlock);
|
| +
|
| + ObjectPaintInvalidatorWithContext objectInvalidator(*m_previousLayoutBlock,
|
| + context);
|
| + if (!isImmediateFullPaintInvalidationReason(
|
| + layoutBlockPaintInvalidationReason)) {
|
| + objectInvalidator.fullyInvalidatePaint(PaintInvalidationCaret,
|
| + m_visualRect, LayoutRect());
|
| + }
|
| +
|
| + // If m_layoutBlock is not null, the following will be done when
|
| + // the new caret is invalidated in m_layoutBlock.
|
| + if (!m_layoutBlock) {
|
| + context.paintingLayer->setNeedsRepaint();
|
| + objectInvalidator.invalidateDisplayItemClient(*this,
|
| + PaintInvalidationCaret);
|
| + m_visualRect = LayoutRect();
|
| + m_needsPaintInvalidation = false;
|
| + }
|
| +
|
| + m_previousLayoutBlock = nullptr;
|
| + return;
|
| + }
|
| +
|
| + if (block != m_layoutBlock)
|
| return;
|
|
|
| - // FIXME: Need to over-paint 1 pixel to workaround some rounding problems.
|
| - // https://bugs.webkit.org/show_bug.cgi?id=108283
|
| - LayoutRect inflatedRect = rect;
|
| - inflatedRect.inflate(LayoutUnit(1));
|
| + // Invalidate the new caret, and the old caret if it was in the same block.
|
| + LayoutRect newVisualRect;
|
| + if (m_layoutBlock && !m_localRect.isEmpty()) {
|
| + newVisualRect = m_localRect;
|
| + context.mapLocalRectToPaintInvalidationBacking(*m_layoutBlock,
|
| + newVisualRect);
|
| + newVisualRect.move(m_layoutBlock->scrollAdjustmentForPaintInvalidation(
|
| + *context.paintInvalidationContainer));
|
| +
|
| + if (m_layoutBlock->usesCompositedScrolling()) {
|
| + // The caret should use scrolling coordinate space.
|
| + DCHECK(m_layoutBlock == context.paintInvalidationContainer);
|
| + newVisualRect.move(LayoutSize(m_layoutBlock->scrolledContentOffset()));
|
| + }
|
| + }
|
| +
|
| + if (m_needsPaintInvalidation || newVisualRect != m_visualRect) {
|
| + m_needsPaintInvalidation = false;
|
|
|
| - // FIXME: We should not allow paint invalidation out of paint invalidation
|
| - // state. crbug.com/457415
|
| - DisablePaintInvalidationStateAsserts disabler;
|
| + ObjectPaintInvalidatorWithContext objectInvalidator(*m_layoutBlock,
|
| + context);
|
| + if (!isImmediateFullPaintInvalidationReason(
|
| + layoutBlockPaintInvalidationReason)) {
|
| + objectInvalidator.fullyInvalidatePaint(PaintInvalidationCaret,
|
| + m_visualRect, newVisualRect);
|
| + }
|
| +
|
| + context.paintingLayer->setNeedsRepaint();
|
| + objectInvalidator.invalidateDisplayItemClient(*this,
|
| + PaintInvalidationCaret);
|
| + }
|
|
|
| - m_visualRect =
|
| - node->layoutObject()->invalidatePaintRectangle(inflatedRect, this);
|
| + m_visualRect = newVisualRect;
|
| }
|
|
|
| -void CaretDisplayItemClient::paintCaret(Node* node,
|
| - GraphicsContext& context,
|
| - const LayoutRect& caretLocalRect,
|
| - const LayoutPoint& paintOffset,
|
| - DisplayItem::Type displayItemType) {
|
| +void CaretDisplayItemClient::paintCaret(
|
| + GraphicsContext& context,
|
| + const LayoutPoint& paintOffset,
|
| + DisplayItem::Type displayItemType) const {
|
| if (DrawingRecorder::useCachedDrawingIfPossible(context, *this,
|
| displayItemType))
|
| return;
|
|
|
| - LayoutRect drawingRect = caretLocalRect;
|
| - if (LayoutBlock* layoutObject = caretLayoutObject(node))
|
| - layoutObject->flipForWritingMode(drawingRect);
|
| + LayoutRect drawingRect = m_localRect;
|
| + m_layoutBlock->flipForWritingMode(drawingRect);
|
| drawingRect.moveBy(paintOffset);
|
|
|
| - const Color caretColor =
|
| - node->layoutObject()->resolveColor(CSSPropertyCaretColor);
|
| IntRect paintRect = pixelSnappedIntRect(drawingRect);
|
| DrawingRecorder drawingRecorder(context, *this, DisplayItem::kCaret,
|
| paintRect);
|
| - context.fillRect(paintRect, caretColor);
|
| + context.fillRect(paintRect, m_color);
|
| }
|
|
|
| String CaretDisplayItemClient::debugName() const {
|
|
|