VisiblePosition SelectionModifier::modifyMovingForward(
    TextGranularity granularity) {
  VisiblePosition pos;
  // FIXME: Stay in editable content for the less common granularities.
  switch (granularity) {
    case CharacterGranularity:
      if (m_selection.isRange())
        pos = createVisiblePosition(m_selection.end(), m_selection.affinity());
      else
        pos = nextPositionOf(
            createVisiblePosition(m_selection.extent(), m_selection.affinity()),
            CanSkipOverEditingBoundary);
      break;
    case WordGranularity:
      pos = nextWordPositionForPlatform(
          createVisiblePosition(m_selection.extent(), m_selection.affinity()));
      break;
    case SentenceGranularity:
      pos = nextSentencePosition(
          createVisiblePosition(m_selection.extent(), m_selection.affinity()));
      break;
    case LineGranularity: {
      // down-arrowing from a range selection that ends at the start of a line
      // needs to leave the selection at that line start (no need to call
      // nextLinePosition!)
      pos = endForPlatform();
      if (!m_selection.isRange() || !isStartOfLine(pos))
        pos = nextLinePosition(
            pos, lineDirectionPointForBlockDirectionNavigation(START));
      break;
    }
    case ParagraphGranularity:
      pos = nextParagraphPosition(
          endForPlatform(),
          lineDirectionPointForBlockDirectionNavigation(START));
      break;
    case SentenceBoundary:
      pos = endOfSentence(endForPlatform());
      break;
    case LineBoundary:
      pos = logicalEndOfLine(endForPlatform());
      break;
    case ParagraphBoundary:
      pos = endOfParagraph(endForPlatform());
      break;
    case DocumentBoundary:
      pos = endForPlatform();
      if (isEditablePosition(pos.deepEquivalent()))
        pos = endOfEditableContent(pos);
      else
        pos = endOfDocument(pos);
      break;
  }
  return pos;
}
VisiblePosition SelectionModifier::modifyExtendingForward(
    TextGranularity granularity) {
  VisiblePosition pos =
      createVisiblePosition(m_selection.extent(), m_selection.affinity());
  switch (granularity) {
    case CharacterGranularity:
      pos = nextPositionOf(pos, CanSkipOverEditingBoundary);
      break;
    case WordGranularity:
      pos = nextWordPositionForPlatform(pos);
      break;
    case SentenceGranularity:
      pos = nextSentencePosition(pos);
      break;
    case LineGranularity:
      pos = nextLinePosition(
          pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
      break;
    case ParagraphGranularity:
      pos = nextParagraphPosition(
          pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
      break;
    case SentenceBoundary:
      pos = endOfSentence(endForPlatform());
      break;
    case LineBoundary:
      pos = logicalEndOfLine(endForPlatform());
      break;
    case ParagraphBoundary:
      pos = endOfParagraph(endForPlatform());
      break;
    case DocumentBoundary:
      pos = endForPlatform();
      if (isEditablePosition(pos.deepEquivalent()))
        pos = endOfEditableContent(pos);
      else
        pos = endOfDocument(pos);
      break;
  }
  adjustPositionForUserSelectAll(pos, directionOfEnclosingBlock() == LTR);
  return pos;
}
bool SelectionModifier::modifyWithPageGranularity(EAlteration alter,
                                                  unsigned verticalDistance,
                                                  VerticalDirection direction) {
  if (!verticalDistance)
    return false;

  DCHECK(!frame()->document()->needsLayoutTreeUpdate());
  DocumentLifecycle::DisallowTransitionScope disallowTransition(
      frame()->document()->lifecycle());

  willBeModified(alter, direction == FrameSelection::DirectionUp
                            ? DirectionBackward
                            : DirectionForward);

  VisiblePosition pos;
  LayoutUnit xPos;
  switch (alter) {
    case FrameSelection::AlterationMove:
      pos = createVisiblePosition(direction == FrameSelection::DirectionUp
                                      ? m_selection.start()
                                      : m_selection.end(),
                                  m_selection.affinity());
      xPos = lineDirectionPointForBlockDirectionNavigation(
          direction == FrameSelection::DirectionUp ? START : END);
      m_selection.setAffinity(direction == FrameSelection::DirectionUp
                                  ? TextAffinity::Upstream
                                  : TextAffinity::Downstream);
      break;
    case FrameSelection::AlterationExtend:
      pos = createVisiblePosition(m_selection.extent(), m_selection.affinity());
      xPos = lineDirectionPointForBlockDirectionNavigation(EXTENT);
      m_selection.setAffinity(TextAffinity::Downstream);
      break;
  }

  int startY;
  if (!absoluteCaretY(pos, startY))
    return false;
  if (direction == FrameSelection::DirectionUp)
    startY = -startY;
  int lastY = startY;

  VisiblePosition result;
  VisiblePosition next;
  for (VisiblePosition p = pos;; p = next) {
    if (direction == FrameSelection::DirectionUp)
      next = previousLinePosition(p, xPos);
    else
      next = nextLinePosition(p, xPos);

    if (next.isNull() || next.deepEquivalent() == p.deepEquivalent())
      break;
    int nextY;
    if (!absoluteCaretY(next, nextY))
      break;
    if (direction == FrameSelection::DirectionUp)
      nextY = -nextY;
    if (nextY - startY > static_cast<int>(verticalDistance))
      break;
    if (nextY >= lastY) {
      lastY = nextY;
      result = next;
    }
  }

  if (result.isNull())
    return false;

  switch (alter) {
    case FrameSelection::AlterationMove:
      m_selection = createVisibleSelection(
          SelectionInDOMTree::Builder()
              .collapse(result.toPositionWithAffinity())
              .setIsDirectional(m_selection.isDirectional())
              .build());
      break;
    case FrameSelection::AlterationExtend:
      m_selection.setExtent(result);
      break;
  }

  m_selection.setIsDirectional(shouldAlwaysUseDirectionalSelection(frame()) ||
                               alter == FrameSelection::AlterationExtend);

  return true;
}
Exemple #4
0
bool SelectionEditor::modify(EAlteration alter, unsigned verticalDistance, VerticalDirection direction, EUserTriggered userTriggered, CursorAlignOnScroll align)
{
    if (!verticalDistance)
        return false;

    if (userTriggered == UserTriggered) {
        OwnPtrWillBeRawPtr<FrameSelection> trialFrameSelection = FrameSelection::create();
        trialFrameSelection->setSelection(m_selection);
        trialFrameSelection->modify(alter, verticalDistance, direction, NotUserTriggered);
    }

    willBeModified(alter, direction == FrameSelection::DirectionUp ? DirectionBackward : DirectionForward);

    VisiblePosition pos;
    LayoutUnit xPos = 0;
    switch (alter) {
    case FrameSelection::AlterationMove:
        pos = createVisiblePosition(direction == FrameSelection::DirectionUp ? m_selection.start() : m_selection.end(), m_selection.affinity());
        xPos = lineDirectionPointForBlockDirectionNavigation(direction == FrameSelection::DirectionUp ? START : END);
        m_selection.setAffinity(direction == FrameSelection::DirectionUp ? TextAffinity::Upstream : TextAffinity::Downstream);
        break;
    case FrameSelection::AlterationExtend:
        pos = createVisiblePosition(m_selection.extent(), m_selection.affinity());
        xPos = lineDirectionPointForBlockDirectionNavigation(EXTENT);
        m_selection.setAffinity(TextAffinity::Downstream);
        break;
    }

    int startY;
    if (!absoluteCaretY(pos, startY))
        return false;
    if (direction == FrameSelection::DirectionUp)
        startY = -startY;
    int lastY = startY;

    VisiblePosition result;
    VisiblePosition next;
    for (VisiblePosition p = pos; ; p = next) {
        if (direction == FrameSelection::DirectionUp)
            next = previousLinePosition(p, xPos);
        else
            next = nextLinePosition(p, xPos);

        if (next.isNull() || next.deepEquivalent() == p.deepEquivalent())
            break;
        int nextY;
        if (!absoluteCaretY(next, nextY))
            break;
        if (direction == FrameSelection::DirectionUp)
            nextY = -nextY;
        if (nextY - startY > static_cast<int>(verticalDistance))
            break;
        if (nextY >= lastY) {
            lastY = nextY;
            result = next;
        }
    }

    if (result.isNull())
        return false;

    switch (alter) {
    case FrameSelection::AlterationMove:
        m_frameSelection->moveTo(result, userTriggered, align);
        break;
    case FrameSelection::AlterationExtend:
        m_frameSelection->setExtent(result, userTriggered);
        break;
    }

    m_selection.setIsDirectional(shouldAlwaysUseDirectionalSelection(frame()) || alter == FrameSelection::AlterationExtend);

    return true;
}