Index: content/public/android/java/src/org/chromium/content/browser/input/AdapterInputConnection.java |
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/AdapterInputConnection.java b/content/public/android/java/src/org/chromium/content/browser/input/AdapterInputConnection.java |
index 2e088a354059e624770c343e77546e5bb111711a..9adf69292ab3f7c588a6681aeb1431e7ece67b0d 100644 |
--- a/content/public/android/java/src/org/chromium/content/browser/input/AdapterInputConnection.java |
+++ b/content/public/android/java/src/org/chromium/content/browser/input/AdapterInputConnection.java |
@@ -9,7 +9,6 @@ import android.text.Editable; |
import android.text.InputType; |
import android.text.Selection; |
import android.text.TextUtils; |
-import android.util.Log; |
import android.view.KeyCharacterMap; |
import android.view.KeyEvent; |
import android.view.View; |
@@ -18,6 +17,7 @@ import android.view.inputmethod.EditorInfo; |
import android.view.inputmethod.ExtractedText; |
import android.view.inputmethod.ExtractedTextRequest; |
+import org.chromium.base.Log; |
import org.chromium.base.VisibleForTesting; |
import org.chromium.blink_public.web.WebInputEventType; |
import org.chromium.blink_public.web.WebTextInputFlags; |
@@ -229,8 +229,8 @@ public class AdapterInputConnection extends BaseInputConnection { |
} |
// updateSelection should be called every time the selection or composition changes |
// if it happens not within a batch edit, or at the end of each top level batch edit. |
- getInputMethodManagerWrapper().updateSelection(mInternalView, |
- selectionStart, selectionEnd, compositionStart, compositionEnd); |
+ getInputMethodManagerWrapper().updateSelection( |
+ mInternalView, selectionStart, selectionEnd, compositionStart, compositionEnd); |
mLastUpdateSelectionStart = selectionStart; |
mLastUpdateSelectionEnd = selectionEnd; |
mLastUpdateCompositionStart = compositionStart; |
@@ -350,10 +350,23 @@ public class AdapterInputConnection extends BaseInputConnection { |
return deleteSurroundingTextImpl(beforeLength, afterLength, false); |
} |
+ /** |
+ * Check if the given {@code index} is between UTF-16 surrogate pair. |
+ * @param str The String. |
+ * @param index The index |
+ * @return True if the index is between UTF-16 surrogate pair, false otherwise. |
+ */ |
+ @VisibleForTesting |
+ static boolean isIndexBetweenUtf16SurrogatePair(CharSequence str, int index) { |
+ return index > 0 && index < str.length() && Character.isHighSurrogate(str.charAt(index - 1)) |
+ && Character.isLowSurrogate(str.charAt(index)); |
+ } |
+ |
private boolean deleteSurroundingTextImpl( |
int beforeLength, int afterLength, boolean fromPhysicalKey) { |
if (DEBUG) { |
- Log.w(TAG, "deleteSurroundingText [" + beforeLength + " " + afterLength + "]"); |
+ Log.w(TAG, "deleteSurroundingText [" + beforeLength + " " + afterLength + " " |
+ + fromPhysicalKey + "]"); |
} |
if (mPendingAccent != 0) { |
@@ -362,10 +375,22 @@ public class AdapterInputConnection extends BaseInputConnection { |
int originalBeforeLength = beforeLength; |
int originalAfterLength = afterLength; |
- int availableBefore = Selection.getSelectionStart(mEditable); |
- int availableAfter = mEditable.length() - Selection.getSelectionEnd(mEditable); |
+ int selectionStart = Selection.getSelectionStart(mEditable); |
+ int selectionEnd = Selection.getSelectionEnd(mEditable); |
+ int availableBefore = selectionStart; |
+ int availableAfter = mEditable.length() - selectionEnd; |
beforeLength = Math.min(beforeLength, availableBefore); |
afterLength = Math.min(afterLength, availableAfter); |
+ |
+ // Adjust these values even before calling super.deleteSurroundingText() to be consistent |
+ // with the super class. |
+ if (isIndexBetweenUtf16SurrogatePair(mEditable, selectionStart - beforeLength)) { |
+ beforeLength += 1; |
+ } |
+ if (isIndexBetweenUtf16SurrogatePair(mEditable, selectionEnd + afterLength)) { |
+ afterLength += 1; |
+ } |
+ |
super.deleteSurroundingText(beforeLength, afterLength); |
updateSelectionIfRequired(); |