Example #1
0
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)) {
    invalidateLocalCaretRect(m_previousCaretAnchorNode.get(),
                             m_previousCaretRect);
  }
  if (newAnchorNode && shouldRepaintCaret(*newAnchorNode))
    invalidateLocalCaretRect(newAnchorNode, newRect);
  m_previousCaretNode = newNode;
  m_previousCaretAnchorNode = newAnchorNode;
  m_previousCaretRect = newRect;
  m_previousCaretVisibility = m_caretVisibility;
}
void CaretBase::invalidateCaretRect(Node* node, bool caretRectChanged)
{
    if (caretRectChanged)
        return;

    if (LayoutView* view = node->document().layoutView()) {
        if (node->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable) || shouldRepaintCaret(view))
            invalidateLocalCaretRect(node, localCaretRectWithoutUpdate());
    }
}