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

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

Issue 1958093002: CONTINUED Make FrameSelection to hold non-canonicalized positions Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 2017-01-16T20:04:35 Created 3 years, 11 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 d2073529efe2d7d9646f90be25e7dc9b17de5883..67610628f9fbe8884b6df8edd98cb6833a33fe05 100644
--- a/third_party/WebKit/Source/core/editing/FrameCaret.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameCaret.cpp
@@ -26,6 +26,7 @@
#include "core/editing/FrameCaret.h"
#include "core/dom/TaskRunnerHelper.h"
+#include "core/editing/CaretBase.h"
#include "core/editing/EditingUtilities.h"
#include "core/editing/Editor.h"
#include "core/editing/SelectionEditor.h"
@@ -34,6 +35,7 @@
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/html/TextControlElement.h"
+#include "core/layout/LayoutBlock.h"
#include "core/layout/LayoutTheme.h"
#include "core/layout/api/LayoutPartItem.h"
#include "core/page/Page.h"
@@ -46,12 +48,13 @@ FrameCaret::FrameCaret(LocalFrame& frame,
const SelectionEditor& selectionEditor)
: m_selectionEditor(&selectionEditor),
m_frame(frame),
+ m_caretBase(new CaretBase()),
m_caretVisibility(CaretVisibility::Hidden),
m_previousCaretVisibility(CaretVisibility::Hidden),
m_caretBlinkTimer(TaskRunnerHelper::get(TaskType::UnspecedTimer, &frame),
this,
&FrameCaret::caretBlinkTimerFired),
- m_caretRectDirty(true),
+ m_didScheduleUpdate(true),
m_shouldPaintCaret(true),
m_isCaretBlinkingSuspended(false),
m_shouldShowBlockCursor(false) {}
@@ -63,36 +66,40 @@ DEFINE_TRACE(FrameCaret) {
visitor->trace(m_frame);
visitor->trace(m_previousCaretNode);
visitor->trace(m_previousCaretAnchorNode);
- CaretBase::trace(visitor);
+ SynchronousMutationObserver::trace(visitor);
+}
+
+void FrameCaret::documentAttached(Document* document) {
+ setContext(document);
}
const PositionWithAffinity FrameCaret::caretPosition() const {
const VisibleSelection& selection =
- m_selectionEditor->visibleSelection<EditingStrategy>();
+ m_selectionEditor->computeVisibleSelectionInDOMTree();
if (!selection.isCaret())
return PositionWithAffinity();
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();
}
void FrameCaret::updateAppearance() {
+ DCHECK_GE(lifecycleContext()->lifecycle().state(),
+ DocumentLifecycle::AfterPerformLayout);
// Paint a block cursor instead of a caret in overtype mode unless the caret
// is at the end of a line (in this case the FrameSelection will paint a
// blinking caret as usual).
bool paintBlockCursor = m_shouldShowBlockCursor && isActive();
- if (paintBlockCursor) {
- // TODO(editing-dev): Use of updateStyleAndLayoutIgnorePendingStylesheets
- // needs to be audited. see http://crbug.com/590369 for more details.
- // In the long term, we should defer the update of the caret's appearance
- // to prevent synchronous layout.
- m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets();
-
- if (isLogicalEndOfLine(createVisiblePosition(caretPosition())))
- paintBlockCursor = false;
+ if (paintBlockCursor &&
+ isLogicalEndOfLine(createVisiblePosition(caretPosition()))) {
+ paintBlockCursor = false;
}
bool shouldBlink = !paintBlockCursor && shouldBlinkCaret();
@@ -134,13 +141,13 @@ void FrameCaret::setCaretVisibility(CaretVisibility visibility) {
m_caretVisibility = visibility;
- updateAppearance();
+ setCaretRectNeedsUpdate();
}
void FrameCaret::setCaretRectNeedsUpdate() {
- if (m_caretRectDirty)
+ if (m_didScheduleUpdate)
return;
- m_caretRectDirty = true;
+ m_didScheduleUpdate = true;
if (Page* page = m_frame->page())
page->animator().scheduleVisualUpdate(m_frame->localFrameRoot());
@@ -161,15 +168,27 @@ 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;
+ updateAppearance();
+ m_didScheduleUpdate = false;
DCHECK(caretPositionIsValidForDocument(*m_frame->document()));
LayoutObject* layoutObject = nullptr;
LayoutRect newRect;
PositionWithAffinity currentCaretPosition = caretPosition();
+ const Node* const colorNode = caretPosition().anchorNode();
+ Color newCaretColor =
+ colorNode ? colorNode->layoutObject()->resolveColor(CSSPropertyCaretColor)
+ : Color();
if (isActive())
newRect = localCaretRectOfPosition(currentCaretPosition, layoutObject);
Node* newNode = layoutObject ? layoutObject->node() : nullptr;
@@ -193,20 +212,34 @@ void FrameCaret::invalidateCaretRect(bool forceInvalidation) {
// of timer state.
if (!forceInvalidation && !m_caretBlinkTimer.isActive() &&
newNode == m_previousCaretNode && newRect == m_previousCaretRect &&
- m_caretVisibility == m_previousCaretVisibility)
+ m_caretVisibility == m_previousCaretVisibility &&
+ newCaretColor == m_previousCaretColor) {
return;
+ }
if (m_previousCaretAnchorNode &&
shouldRepaintCaret(*m_previousCaretAnchorNode)) {
- invalidateLocalCaretRect(m_previousCaretAnchorNode.get(),
- m_previousCaretRect);
+ m_caretBase->invalidateLocalCaretRect(m_previousCaretAnchorNode.get(),
+ m_previousCaretRect);
}
if (newAnchorNode && shouldRepaintCaret(*newAnchorNode))
- invalidateLocalCaretRect(newAnchorNode, newRect);
+ m_caretBase->invalidateLocalCaretRect(newAnchorNode, newRect);
m_previousCaretNode = newNode;
m_previousCaretAnchorNode = newAnchorNode;
m_previousCaretRect = newRect;
m_previousCaretVisibility = m_caretVisibility;
+ m_previousCaretColor = newCaretColor;
+}
+
+static IntRect absoluteBoundsForLocalRect(Node* node, const LayoutRect& rect) {
+ LayoutBlock* caretPainter = CaretBase::caretLayoutObject(node);
+ if (!caretPainter)
+ return IntRect();
+
+ LayoutRect localRect(rect);
+ caretPainter->flipForWritingMode(localRect);
+ return caretPainter->localToAbsoluteQuad(FloatRect(localRect))
+ .enclosingBoundingBox();
}
// TDOO(yosin): We should mark |FrameCaret::absoluteCaretBounds()| to |const|.
@@ -224,11 +257,13 @@ IntRect FrameCaret::absoluteCaretBounds() {
// tree is clean.
if (enclosingTextControl(caretPosition().position()) &&
isVisuallyEquivalentCandidate(caretPosition().position())) {
- return absoluteBoundsForLocalRect(caretNode,
- computeCaretRect(caretPosition()));
+ return absoluteBoundsForLocalRect(
+ caretNode, CaretBase::computeCaretRect(caretPosition()));
}
return absoluteBoundsForLocalRect(
- caretNode, computeCaretRect(createVisiblePosition(caretPosition())));
+ caretNode,
+ CaretBase::computeCaretRect(
+ createVisiblePosition(caretPosition()).toPositionWithAffinity()));
}
void FrameCaret::setShouldShowBlockCursor(bool shouldShowBlockCursor) {
@@ -236,7 +271,7 @@ void FrameCaret::setShouldShowBlockCursor(bool shouldShowBlockCursor) {
m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets();
- updateAppearance();
+ setCaretRectNeedsUpdate();
}
void FrameCaret::paintCaret(GraphicsContext& context,
@@ -247,17 +282,18 @@ void FrameCaret::paintCaret(GraphicsContext& context,
if (!(isActive() && m_shouldPaintCaret))
return;
- const LayoutRect caretLocalRect = computeCaretRect(caretPosition());
- CaretBase::paintCaret(caretPosition().anchorNode(), context, *this,
- caretLocalRect, paintOffset, DisplayItem::kCaret);
+ const LayoutRect caretLocalRect =
+ CaretBase::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;
- invalidateLocalCaretRect(m_previousCaretAnchorNode.get(),
- m_previousCaretRect);
+ m_caretBase->invalidateLocalCaretRect(m_previousCaretAnchorNode.get(),
+ m_previousCaretRect);
}
}
@@ -266,15 +302,15 @@ void FrameCaret::nodeWillBeRemoved(Node& node) {
return;
// Hits in ManualTests/caret-paint-after-last-text-is-removed.html
DisableCompositingQueryAsserts disabler;
- invalidateLocalCaretRect(m_previousCaretAnchorNode.get(),
- m_previousCaretRect);
+ m_caretBase->invalidateLocalCaretRect(m_previousCaretAnchorNode.get(),
+ m_previousCaretRect);
m_previousCaretNode = nullptr;
m_previousCaretAnchorNode = nullptr;
m_previousCaretRect = LayoutRect();
m_previousCaretVisibility = CaretVisibility::Hidden;
}
-void FrameCaret::documentDetached() {
+void FrameCaret::contextDestroyed(Document*) {
m_caretBlinkTimer.stop();
m_previousCaretNode.clear();
m_previousCaretAnchorNode.clear();
« 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