Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor caret painting logic #10049

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
54 changes: 40 additions & 14 deletions Source/WebCore/editing/FrameSelection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,17 +163,37 @@ static inline bool isPageActive(Document* document)
#import <WebKitAdditions/FrameSelectionAdditions.cpp>
#else
#if ENABLE(TEXT_CARET)
static void fillCaretRect(const Node&, GraphicsContext& context, const FloatRect& caret, const Color&color, const CaretAnimator::PresentationProperties&)
static void fillCaretRect(const Node&, GraphicsContext& context, const FloatRect& caret, const Color&color, const LayoutPoint&, CaretAnimator*)
{
context.fillRect(caret, color);
}
#endif

static UniqueRef<CaretAnimator> createCaretAnimator(FrameSelection* frameSelection)
static UniqueRef<CaretAnimator> createCaretAnimator(FrameSelection* frameSelection, CaretAnimatorType = CaretAnimatorType::Default)
{
return makeUniqueRef<SimpleCaretAnimator>(*frameSelection);
}
#endif // USE(APPLE_INTERNAL_SDK)

// FIXME: Remove staging once repaintCaretRectForLocalRect is defined in FrameSelectionAdditions.cpp
#ifndef FRAME_SELECTION_ADDITIONS_REPAINT_CARET_RECT_FOR_LOCAL_RECT_DEFINED
static LayoutRect repaintCaretRectForLocalRect(LayoutRect rect, CaretAnimator*)
{
return rect;
}

#if USE(APPLE_INTERNAL_SDK)
static void fillCaretRect(const Node& node, GraphicsContext& context, const FloatRect& caret, const Color& color, const LayoutPoint&, CaretAnimator* animator)
{
fillCaretRect(node, context, caret, color, animator ? animator->presentationProperties() : CaretAnimator::PresentationProperties());
}

static UniqueRef<CaretAnimator> createCaretAnimator(FrameSelection* frameSelection, CaretAnimatorType)
{
return createCaretAnimator(frameSelection);
}
#endif
#endif // FRAME_SELECTION_ADDITIONS_REPAINT_CARET_RECT_FOR_LOCAL_RECT_DEFINED

FrameSelection::FrameSelection(Document* document)
: m_document(document)
Expand Down Expand Up @@ -1766,10 +1786,10 @@ IntRect FrameSelection::absoluteCaretBounds(bool* insideFixed)
return m_absCaretBounds;
}

static void repaintCaretForLocalRect(Node* node, const LayoutRect& rect)
static void repaintCaretForLocalRect(Node* node, const LayoutRect& rect, CaretAnimator* caretAnimator)
{
if (auto* caretPainter = rendererForCaretPainting(node))
caretPainter->repaintRectangle(rect);
caretPainter->repaintRectangle(repaintCaretRectForLocalRect(rect, caretAnimator));
}

bool FrameSelection::recomputeCaretRect()
Expand Down Expand Up @@ -1821,9 +1841,9 @@ bool FrameSelection::recomputeCaretRect()
bool previousOrNewCaretNodeIsContentEditable = m_selection.isContentEditable() || (m_previousCaretNode && m_previousCaretNode->isContentEditable());
if (shouldRepaintCaret(view, previousOrNewCaretNodeIsContentEditable)) {
if (m_previousCaretNode)
repaintCaretForLocalRect(m_previousCaretNode.get(), oldRect);
repaintCaretForLocalRect(m_previousCaretNode.get(), oldRect, m_caretAnimator.ptr());
m_previousCaretNode = caretNode;
repaintCaretForLocalRect(caretNode.get(), newRect);
repaintCaretForLocalRect(caretNode.get(), newRect, m_caretAnimator.ptr());
}
}
#endif
Expand All @@ -1843,10 +1863,10 @@ void FrameSelection::invalidateCaretRect()
if (!isCaret())
return;

CaretBase::invalidateCaretRect(m_selection.start().deprecatedNode(), recomputeCaretRect());
CaretBase::invalidateCaretRect(m_selection.start().deprecatedNode(), recomputeCaretRect(), m_caretAnimator.ptr());
}

void CaretBase::invalidateCaretRect(Node* node, bool caretRectChanged)
void CaretBase::invalidateCaretRect(Node* node, bool caretRectChanged, CaretAnimator* caretAnimator)
{
// EDIT FIXME: This is an unfortunate hack.
// Basically, we can't trust this layout position since we
Expand All @@ -1866,14 +1886,14 @@ void CaretBase::invalidateCaretRect(Node* node, bool caretRectChanged)

if (RenderView* view = node->document().renderView()) {
if (shouldRepaintCaret(view, isEditableNode(*node)))
repaintCaretForLocalRect(node, localCaretRectWithoutUpdate());
repaintCaretForLocalRect(node, localCaretRectWithoutUpdate(), caretAnimator);
}
}

void FrameSelection::paintCaret(GraphicsContext& context, const LayoutPoint& paintOffset, const LayoutRect& clipRect)
{
if (m_selection.isCaret() && m_selection.start().deprecatedNode())
CaretBase::paintCaret(*m_selection.start().deprecatedNode(), context, paintOffset, clipRect, m_caretAnimator->presentationProperties());
CaretBase::paintCaret(*m_selection.start().deprecatedNode(), context, paintOffset, clipRect, m_caretAnimator.ptr());
}

Color CaretBase::computeCaretColor(const RenderStyle& elementStyle, const Node* node)
Expand All @@ -1899,9 +1919,10 @@ Color CaretBase::computeCaretColor(const RenderStyle& elementStyle, const Node*
#endif
}

void CaretBase::paintCaret(const Node& node, GraphicsContext& context, const LayoutPoint& paintOffset, const LayoutRect& clipRect, const CaretAnimator::PresentationProperties& caretPresentationProperties) const
void CaretBase::paintCaret(const Node& node, GraphicsContext& context, const LayoutPoint& paintOffset, const LayoutRect& clipRect, CaretAnimator* caretAnimator) const
{
#if ENABLE(TEXT_CARET)
auto caretPresentationProperties = caretAnimator ? caretAnimator->presentationProperties() : CaretAnimator::PresentationProperties();
if (m_caretVisibility == Hidden || caretPresentationProperties.blinkState == CaretAnimator::PresentationProperties::BlinkState::Off)
return;

Expand All @@ -1919,13 +1940,13 @@ void CaretBase::paintCaret(const Node& node, GraphicsContext& context, const Lay
caretColor = CaretBase::computeCaretColor(element->renderer()->style(), &node);

auto pixelSnappedCaretRect = snapRectToDevicePixels(caret, node.document().deviceScaleFactor());
fillCaretRect(node, context, pixelSnappedCaretRect, caretColor, caretPresentationProperties);
fillCaretRect(node, context, pixelSnappedCaretRect, caretColor, paintOffset, caretAnimator);
#else
UNUSED_PARAM(node);
UNUSED_PARAM(context);
UNUSED_PARAM(paintOffset);
UNUSED_PARAM(clipRect);
UNUSED_PARAM(caretPresentationProperties);
UNUSED_PARAM(caretAnimator);
#endif
}

Expand All @@ -1944,6 +1965,11 @@ void FrameSelection::caretAnimationDidUpdate(CaretAnimator&)
invalidateCaretRect();
}

void FrameSelection::caretAnimatorInvalidated(CaretAnimator&, CaretAnimatorType newCaretType)
{
m_caretAnimator = createCaretAnimator(this, newCaretType);
}

Document* FrameSelection::document()
{
return m_document.get();
Expand Down Expand Up @@ -2344,7 +2370,7 @@ void DragCaretController::paintDragCaret(Frame* frame, GraphicsContext& p, const
{
#if ENABLE(TEXT_CARET)
if (m_position.deepEquivalent().deprecatedNode() && m_position.deepEquivalent().deprecatedNode()->document().frame() == frame)
paintCaret(*m_position.deepEquivalent().deprecatedNode(), p, paintOffset, clipRect, { });
paintCaret(*m_position.deepEquivalent().deprecatedNode(), p, paintOffset, clipRect);
#else
UNUSED_PARAM(frame);
UNUSED_PARAM(p);
Expand Down
6 changes: 4 additions & 2 deletions Source/WebCore/editing/FrameSelection.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ class CaretBase {
enum CaretVisibility { Visible, Hidden };
explicit CaretBase(CaretVisibility = Hidden);

void invalidateCaretRect(Node*, bool caretRectChanged = false);
void invalidateCaretRect(Node*, bool caretRectChanged = false, CaretAnimator* = nullptr);
void clearCaretRect();
bool updateCaretRect(Document&, const VisiblePosition& caretPosition);
bool shouldRepaintCaret(const RenderView*, bool isContentEditable) const;
void paintCaret(const Node&, GraphicsContext&, const LayoutPoint&, const LayoutRect& clipRect, const CaretAnimator::PresentationProperties&) const;
void paintCaret(const Node&, GraphicsContext&, const LayoutPoint&, const LayoutRect& clipRect, CaretAnimator* = nullptr) const;

const LayoutRect& localCaretRectWithoutUpdate() const { return m_caretLocalRect; }

Expand Down Expand Up @@ -320,6 +320,7 @@ class FrameSelection final : private CaretBase, public CaretAnimationClient {
void invalidateCaretRect();

void caretAnimationDidUpdate(CaretAnimator&) final;
void caretAnimatorInvalidated(CaretAnimator&, CaretAnimatorType) final;

Document* document() final;

Expand All @@ -330,6 +331,7 @@ class FrameSelection final : private CaretBase, public CaretAnimationClient {
#endif

void updateAssociatedLiveRange();
LayoutRect localCaretRect() const final { return localCaretRectWithoutUpdate(); }

WeakPtr<Document, WeakPtrImplWithEventTargetData> m_document;
RefPtr<Range> m_associatedLiveRange;
Expand Down
9 changes: 9 additions & 0 deletions Source/WebCore/platform/CaretAnimator.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#pragma once

#include "LayoutRect.h"
#include "ReducedResolutionSeconds.h"
#include "Timer.h"

Expand All @@ -34,11 +35,18 @@ class CaretAnimator;
class Document;
class Page;

enum class CaretAnimatorType {
Default,
Alternate
};

class CaretAnimationClient {
public:
virtual ~CaretAnimationClient() = default;

virtual void caretAnimationDidUpdate(CaretAnimator&) { }
virtual void caretAnimatorInvalidated(CaretAnimator&, CaretAnimatorType) { }
virtual LayoutRect localCaretRect() const = 0;

virtual Document* document() = 0;
};
Expand Down Expand Up @@ -78,6 +86,7 @@ class CaretAnimator {
virtual void setVisible(bool) = 0;

PresentationProperties presentationProperties() const { return m_presentationProperties; }
virtual CaretAnimatorType type() const { return CaretAnimatorType::Default; }

protected:
explicit CaretAnimator(CaretAnimationClient& client)
Expand Down
26 changes: 22 additions & 4 deletions Source/WebCore/rendering/RenderBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,15 @@

namespace WebCore {

#if USE(APPLE_INTERNAL_SDK) && __has_include(<WebKitAdditions/RenderBlockAdditions.h>)
#include <WebKitAdditions/RenderBlockAdditions.h>
#else
static bool renderCaretInsideContentsClip()
{
return true;
}
#endif

using namespace HTMLNames;
using namespace WTF::Unicode;

Expand Down Expand Up @@ -1093,6 +1102,14 @@ void RenderBlock::markForPaginationRelayoutIfNeeded()
setChildNeedsLayout(MarkOnlyThis);
}

void RenderBlock::paintCarets(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
if (paintInfo.phase == PaintPhase::Foreground) {
paintCaret(paintInfo, paintOffset, CursorCaret);
paintCaret(paintInfo, paintOffset, DragCaret);
}
}

void RenderBlock::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
auto adjustedPaintOffset = paintOffset + location();
Expand Down Expand Up @@ -1120,6 +1137,9 @@ void RenderBlock::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
if (pushedClip)
popContentsClip(paintInfo, phase, adjustedPaintOffset);

if (!renderCaretInsideContentsClip())
paintCarets(paintInfo, adjustedPaintOffset);

// Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
// z-index. We paint after we painted the background/border, so that the scrollbars will
// sit above the background/border.
Expand Down Expand Up @@ -1367,10 +1387,8 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs
// 7. paint caret.
// If the caret's node's render object's containing block is this block, and the paint action is PaintPhase::Foreground,
// then paint the caret.
if (paintPhase == PaintPhase::Foreground) {
paintCaret(paintInfo, paintOffset, CursorCaret);
paintCaret(paintInfo, paintOffset, DragCaret);
}
if (renderCaretInsideContentsClip())
paintCarets(paintInfo, paintOffset);
}

static ContinuationOutlineTableMap* continuationOutlineTable()
Expand Down
1 change: 1 addition & 0 deletions Source/WebCore/rendering/RenderBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,7 @@ class RenderBlock : public RenderBox {
virtual void paintColumnRules(PaintInfo&, const LayoutPoint&) { };
void paintSelection(PaintInfo&, const LayoutPoint&);
void paintCaret(PaintInfo&, const LayoutPoint&, CaretType);
void paintCarets(PaintInfo&, const LayoutPoint&);

virtual bool hitTestContents(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
// FIXME-BLOCKFLOW: Remove virtualization when all callers have moved to RenderBlockFlow
Expand Down