Chromium Code Reviews| 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 bbd161bf33e0cc0389cf5a6d32762d8a1fefc3da..ae781e136b1174259d4a355467ed2815418ae3a1 100644 | 
| --- a/third_party/WebKit/Source/core/editing/InputMethodController.cpp | 
| +++ b/third_party/WebKit/Source/core/editing/InputMethodController.cpp | 
| @@ -183,19 +183,39 @@ void InputMethodController::selectComposition() const | 
| frame().selection().setSelection(selection, 0); | 
| } | 
| -bool InputMethodController::confirmComposition() | 
| +bool InputMethodController::finishComposingText(ConfirmCompositionBehavior confirmBehavior) | 
| { | 
| - return confirmComposition(composingText()); | 
| + if (!hasComposition()) | 
| + return false; | 
| + | 
| + if (confirmBehavior == KeepSelection) { | 
| + SelectionOffsetsScope selectionOffsetsScope(this); | 
| + Optional<Editor::RevealSelectionScope> revealSelectionScope; | 
| + revealSelectionScope.emplace(&editor()); | 
| + return replaceComposition(composingText()); | 
| + } | 
| + | 
| + return replaceCompositionAndMoveCaret(composingText(), 0); | 
| } | 
| -bool InputMethodController::confirmComposition(const String& text, ConfirmCompositionBehavior confirmBehavior) | 
| +bool InputMethodController::commitText(const String& text, int relativeCaretPosition) | 
| { | 
| - if (!hasComposition()) | 
| + if (hasComposition()) | 
| + return replaceCompositionAndMoveCaret(text, relativeCaretPosition); | 
| + | 
| + // We should do nothing in this case, because: | 
| + // 1. No need to insert text when text is empty. | 
| + // 2. Shouldn't move caret when relativeCaretPosition == 0 to avoid | 
| + // duplicate selection change event. | 
| + if (!text.length() && !relativeCaretPosition) | 
| return false; | 
| + return insertTextAndMoveCaret(text, relativeCaretPosition); | 
| +} | 
| - Optional<Editor::RevealSelectionScope> revealSelectionScope; | 
| - if (confirmBehavior == KeepSelection) | 
| - revealSelectionScope.emplace(&editor()); | 
| +bool InputMethodController::replaceComposition(const String& text) | 
| +{ | 
| + if (!hasComposition()) | 
| + return false; | 
| // If the composition was set from existing text and didn't change, then | 
| // there's nothing to do here (and we should avoid doing anything as that | 
| @@ -233,29 +253,51 @@ bool InputMethodController::confirmComposition(const String& text, ConfirmCompos | 
| return true; | 
| } | 
| -bool InputMethodController::confirmCompositionOrInsertText(const String& text, ConfirmCompositionBehavior confirmBehavior) | 
| +// relativeCaretPosition is relative to the end of the text. | 
| +static int computeAbsoluteCaretPosition(size_t textStart, size_t textLength, int relativeCaretPosition) | 
| { | 
| - if (!hasComposition()) { | 
| - if (!text.length()) | 
| - return false; | 
| + return textStart + textLength + relativeCaretPosition; | 
| +} | 
| - if (dispatchBeforeInputInsertText(frame().document()->focusedElement(), text) != DispatchEventResult::NotCanceled) | 
| - return false; | 
| +bool InputMethodController::replaceCompositionAndMoveCaret(const String& text, int relativeCaretPosition) | 
| +{ | 
| + Element* rootEditableElement = frame().selection().rootEditableElement(); | 
| + if (!rootEditableElement) | 
| + return false; | 
| + PlainTextRange compositionRange = PlainTextRange::create(*rootEditableElement, *m_compositionRange); | 
| + if (compositionRange.isNull()) | 
| + return false; | 
| + int textStart = compositionRange.start(); | 
| - editor().insertText(text, 0); | 
| - return true; | 
| - } | 
| + if (!replaceComposition(text)) | 
| + return false; | 
| + | 
| + int absoluteCaretPosition = computeAbsoluteCaretPosition(textStart, text.length(), relativeCaretPosition); | 
| + return moveCaret(absoluteCaretPosition); | 
| +} | 
| + | 
| +bool InputMethodController::insertText(const String& text) | 
| +{ | 
| + if (dispatchBeforeInputInsertText(frame().document()->focusedElement(), text) != DispatchEventResult::NotCanceled) | 
| + return false; | 
| + editor().insertText(text, 0); | 
| + return true; | 
| +} | 
| + | 
| +bool InputMethodController::insertTextAndMoveCaret(const String& text, int relativeCaretPosition) | 
| +{ | 
| + PlainTextRange selectionRange = getSelectionOffsets(); | 
| + if (selectionRange.isNull()) | 
| + return false; | 
| + int textStart = selectionRange.start(); | 
| if (text.length()) { | 
| - confirmComposition(text); | 
| - return true; | 
| + if (!insertText(text)) | 
| + return false; | 
| } | 
| - if (confirmBehavior == DoNotKeepSelection) | 
| - return confirmComposition(composingText(), DoNotKeepSelection); | 
| - | 
| - SelectionOffsetsScope selectionOffsetsScope(this); | 
| - return confirmComposition(); | 
| + int absoluteCaretPosition = computeAbsoluteCaretPosition(textStart, text.length(), relativeCaretPosition); | 
| + return moveCaret(absoluteCaretPosition); | 
| } | 
| void InputMethodController::cancelComposition() | 
| @@ -347,7 +389,9 @@ void InputMethodController::setComposition(const String& text, const Vector<Comp | 
| // !hasComposition() && test.isEmpty(). | 
| if (text.isEmpty()) { | 
| if (hasComposition()) { | 
| - confirmComposition(emptyString()); | 
| + Optional<Editor::RevealSelectionScope> revealSelectionScope; | 
| 
 
aelias_OOO_until_Jul13
2016/09/13 19:30:08
nit: this doesn't need to use Optional<> anymore.
 
 | 
| + revealSelectionScope.emplace(&editor()); | 
| + replaceComposition(emptyString()); | 
| } 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. | 
| @@ -548,6 +592,15 @@ PlainTextRange InputMethodController::createRangeForSelection(int start, int end | 
| return PlainTextRange(start, end); | 
| } | 
| +bool InputMethodController::moveCaret(int newCaretPosition) | 
| +{ | 
| + frame().document()->updateStyleAndLayoutIgnorePendingStylesheets(); | 
| + PlainTextRange selectedRange = createRangeForSelection(newCaretPosition, newCaretPosition, 0); | 
| + if (selectedRange.isNull()) | 
| + return false; | 
| + return setEditableSelectionOffsets(selectedRange); | 
| +} | 
| + | 
| void InputMethodController::extendSelectionAndDelete(int before, int after) | 
| { | 
| if (!editor().canEdit()) |