| Index: third_party/WebKit/Source/core/editing/InputMethodController.cpp
|
| diff --git a/third_party/WebKit/Source/core/editing/InputMethodController.cpp b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
|
| index fd9f11c877fc25da37f18aca218068bf7c11f140..343e89aad7a0aaf3644dca5f79449d6d75138bc9 100644
|
| --- a/third_party/WebKit/Source/core/editing/InputMethodController.cpp
|
| +++ b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
|
| @@ -321,6 +321,11 @@ void InputMethodController::setComposition(const String& text, const Vector<Comp
|
| if (!target)
|
| return;
|
|
|
| + int selectionOffsetsStart = static_cast<int>(getSelectionOffsets().start());
|
| + int start = selectionOffsetsStart + selectionStart;
|
| + int end = selectionOffsetsStart + selectionEnd;
|
| + PlainTextRange selectedRange = createRangeForSelection(start, end, text.length());
|
| +
|
| // Dispatch an appropriate composition event to the focused node.
|
| // We check the composition status and choose an appropriate composition event since this
|
| // function is used for three purposes:
|
| @@ -339,11 +344,13 @@ void InputMethodController::setComposition(const String& text, const Vector<Comp
|
| if (text.isEmpty()) {
|
| if (hasComposition()) {
|
| confirmComposition(emptyString());
|
| - return;
|
| + } else {
|
| + // It's weird to call |setComposition()| with empty text outside composition, however some IME
|
| + // (e.g. Japanese IBus-Anthy) did this, so we simply delete selection without sending extra events.
|
| + TypingCommand::deleteSelection(*frame().document(), TypingCommand::PreventSpellChecking);
|
| }
|
| - // It's weird to call |setComposition()| with empty text outside composition, however some IME
|
| - // (e.g. Japanese IBus-Anthy) did this, so we simply delete selection without sending extra events.
|
| - TypingCommand::deleteSelection(*frame().document(), TypingCommand::PreventSpellChecking);
|
| +
|
| + setEditableSelectionOffsets(selectedRange);
|
| return;
|
| }
|
|
|
| @@ -394,31 +401,8 @@ void InputMethodController::setComposition(const String& text, const Vector<Comp
|
| if (baseNode->layoutObject())
|
| baseNode->layoutObject()->setShouldDoFullPaintInvalidation();
|
|
|
| - // In case of exceeding the left boundary.
|
| - int selectionOffsetsStart = static_cast<int>(getSelectionOffsets().start());
|
| - int start = std::max(selectionOffsetsStart + selectionStart, 0);
|
| - int end = std::max(selectionOffsetsStart + selectionEnd, start);
|
| -
|
| - Element* rootEditableElement = frame().selection().rootEditableElement();
|
| - if (!rootEditableElement)
|
| - return;
|
| -
|
| - // In case of exceeding the right boundary.
|
| - // If both |value1| and |value2| exceed right boundary,
|
| - // PlainTextRange(value1, value2)::createRange() will return a default
|
| - // value, which is [0,0]. In order to get the correct Position in that case,
|
| - // we should make sure |value1| is within range at least.
|
| - const EphemeralRange& startRange = PlainTextRange(0, start).createRange(*rootEditableElement);
|
| - const EphemeralRange& endRange = PlainTextRange(0, end).createRange(*rootEditableElement);
|
| -
|
| - // TODO(yabinh): There should be a better way to create |startPosition| and
|
| - // |endPosition|. But for now, since we can't get |anchorNode| and |offset|,
|
| - // we can't create the 2 Position objects directly. So we use
|
| - // PlainTextRange::createRange as a workaround.
|
| - const Position& startPosition = startRange.endPosition();
|
| - const Position& endPosition = endRange.endPosition();
|
| - const EphemeralRange selectedRange(startPosition, endPosition);
|
| - frame().selection().setSelectedRange(selectedRange, TextAffinity::Downstream, SelectionDirectionalMode::NonDirectional, NotUserTriggered);
|
| + // We shouldn't close typing in the middle of setComposition.
|
| + setEditableSelectionOffsets(selectedRange, NotUserTriggered);
|
|
|
| if (underlines.isEmpty()) {
|
| frame().document()->markers().addCompositionMarker(m_compositionRange->startPosition(), m_compositionRange->endPosition(), Color::black, false, LayoutTheme::theme().platformDefaultCompositionBackgroundColor());
|
| @@ -501,7 +485,7 @@ PlainTextRange InputMethodController::getSelectionOffsets() const
|
| return PlainTextRange::create(*editable, range);
|
| }
|
|
|
| -bool InputMethodController::setSelectionOffsets(const PlainTextRange& selectionOffsets)
|
| +bool InputMethodController::setSelectionOffsets(const PlainTextRange& selectionOffsets, FrameSelection::SetSelectionOptions options)
|
| {
|
| if (selectionOffsets.isNull())
|
| return false;
|
| @@ -517,14 +501,46 @@ bool InputMethodController::setSelectionOffsets(const PlainTextRange& selectionO
|
| if (range.isNull())
|
| return false;
|
|
|
| - return frame().selection().setSelectedRange(range, VP_DEFAULT_AFFINITY, SelectionDirectionalMode::NonDirectional, FrameSelection::CloseTyping);
|
| + return frame().selection().setSelectedRange(range, VP_DEFAULT_AFFINITY, SelectionDirectionalMode::NonDirectional, options);
|
| }
|
|
|
| -bool InputMethodController::setEditableSelectionOffsets(const PlainTextRange& selectionOffsets)
|
| +bool InputMethodController::setEditableSelectionOffsets(const PlainTextRange& selectionOffsets, FrameSelection::SetSelectionOptions options)
|
| {
|
| if (!editor().canEdit())
|
| return false;
|
| - return setSelectionOffsets(selectionOffsets);
|
| + return setSelectionOffsets(selectionOffsets, options);
|
| +}
|
| +
|
| +PlainTextRange InputMethodController::createRangeForSelection(int start, int end, size_t textLength) const
|
| +{
|
| + // In case of exceeding the left boundary.
|
| + start = std::max(start, 0);
|
| + end = std::max(end, start);
|
| +
|
| + Element* rootEditableElement = frame().selection().rootEditableElement();
|
| + if (!rootEditableElement)
|
| + return PlainTextRange();
|
| + const EphemeralRange& range = EphemeralRange::rangeOfContents(*rootEditableElement);
|
| + if (range.isNull())
|
| + return PlainTextRange();
|
| +
|
| + const TextIteratorBehaviorFlags behaviorFlags = TextIteratorEmitsObjectReplacementCharacter | TextIteratorEmitsCharactersBetweenAllVisiblePositions;
|
| + TextIterator it(range.startPosition(), range.endPosition(), behaviorFlags);
|
| +
|
| + int rightBoundary = 0;
|
| + for (; !it.atEnd(); it.advance())
|
| + rightBoundary += it.length();
|
| +
|
| + if (hasComposition())
|
| + rightBoundary -= compositionRange()->text().length();
|
| +
|
| + rightBoundary += textLength;
|
| +
|
| + // In case of exceeding the right boundary.
|
| + start = std::min(start, rightBoundary);
|
| + end = std::min(end, rightBoundary);
|
| +
|
| + return PlainTextRange(start, end);
|
| }
|
|
|
| void InputMethodController::extendSelectionAndDelete(int before, int after)
|
|
|