| Index: content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java
|
| diff --git a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java
|
| index 61aceec9bd50f8d0cf4baa19c0d03010251d39bc..c3ad20c6c7e25687a87bf111dbd70f5669ce59eb 100644
|
| --- a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java
|
| +++ b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java
|
| @@ -7,8 +7,6 @@ package org.chromium.content.browser.input;
|
| import android.content.res.Configuration;
|
| import android.os.ResultReceiver;
|
| import android.os.SystemClock;
|
| -import android.text.Editable;
|
| -import android.text.Selection;
|
| import android.text.SpannableString;
|
| import android.text.style.BackgroundColorSpan;
|
| import android.text.style.CharacterStyle;
|
| @@ -19,12 +17,14 @@ import android.view.View;
|
| import android.view.inputmethod.BaseInputConnection;
|
| import android.view.inputmethod.EditorInfo;
|
|
|
| +import org.chromium.base.CommandLine;
|
| import org.chromium.base.Log;
|
| import org.chromium.base.VisibleForTesting;
|
| import org.chromium.base.annotations.CalledByNative;
|
| import org.chromium.base.annotations.JNINamespace;
|
| import org.chromium.blink_public.web.WebInputEventModifier;
|
| import org.chromium.blink_public.web.WebInputEventType;
|
| +import org.chromium.content.common.ContentSwitches;
|
| import org.chromium.ui.base.ime.TextInputType;
|
| import org.chromium.ui.picker.InputDialogContainer;
|
|
|
| @@ -90,15 +90,10 @@ public class ImeAdapter {
|
|
|
| private long mNativeImeAdapterAndroid;
|
| private InputMethodManagerWrapper mInputMethodManagerWrapper;
|
| - private AdapterInputConnection mInputConnection;
|
| - private AdapterInputConnectionFactory mInputConnectionFactory;
|
| - private final ImeAdapterDelegate mViewEmbedder;
|
| + private ChromiumBaseInputConnection mInputConnection;
|
| + private ChromiumBaseInputConnection.Factory mInputConnectionFactory;
|
|
|
| - // This holds the state of editable text (e.g. contents of <input>, contenteditable) of
|
| - // a focused element.
|
| - // Every time the user, IME, javascript (Blink), autofill etc. modifies the content, the new
|
| - // state must be reflected to this to keep consistency.
|
| - private final Editable mEditable;
|
| + private final ImeAdapterDelegate mViewEmbedder;
|
|
|
| private int mTextInputType = TextInputType.NONE;
|
| private int mTextInputFlags;
|
| @@ -114,49 +109,31 @@ public class ImeAdapter {
|
| public ImeAdapter(InputMethodManagerWrapper wrapper, ImeAdapterDelegate embedder) {
|
| mInputMethodManagerWrapper = wrapper;
|
| mViewEmbedder = embedder;
|
| - mInputConnectionFactory = new AdapterInputConnectionFactory();
|
| - mEditable = Editable.Factory.getInstance().newEditable("");
|
| - Selection.setSelection(mEditable, 0);
|
| + if (CommandLine.getInstance().hasSwitch(ContentSwitches.USE_IME_THREAD)) {
|
| + mInputConnectionFactory = new ChromiumInputConnectionFactory();
|
| + } else {
|
| + mInputConnectionFactory = new AdapterInputConnection.Factory();
|
| + }
|
| // Deep copy newConfig so that we can notice the difference.
|
| mCurrentConfig = new Configuration(
|
| mViewEmbedder.getAttachedView().getResources().getConfiguration());
|
| }
|
|
|
| /**
|
| - * Default factory for AdapterInputConnection classes.
|
| - */
|
| - static class AdapterInputConnectionFactory {
|
| - AdapterInputConnection get(View view, ImeAdapter imeAdapter, int initialSelStart,
|
| - int initialSelEnd, EditorInfo outAttrs) {
|
| - return new AdapterInputConnection(
|
| - view, imeAdapter, initialSelStart, initialSelEnd, outAttrs);
|
| - }
|
| - }
|
| -
|
| - /**
|
| * @see View#onCreateInputConnection(EditorInfo)
|
| */
|
| - public AdapterInputConnection onCreateInputConnection(EditorInfo outAttrs) {
|
| + public ChromiumBaseInputConnection onCreateInputConnection(EditorInfo outAttrs) {
|
| // Without this line, some third-party IMEs will try to compose text even when
|
| - // not on an editable node. Even when we return null here, key events can still go through
|
| - // ImeAdapter#dispatchKeyEvent().
|
| + // not on an editable node. Even when we return null here, key events can still go
|
| + // through ImeAdapter#dispatchKeyEvent().
|
| if (mTextInputType == TextInputType.NONE) {
|
| mInputConnection = null;
|
| - Log.d(TAG, "onCreateInputConnection returns null.");
|
| + Log.d(TAG, "onCreateInputConnection: null");
|
| return null;
|
| }
|
| -
|
| - if (!isTextInputType(mTextInputType)) {
|
| - // Although onCheckIsTextEditor will return false in this case, the EditorInfo
|
| - // is still used by the InputMethodService. Need to make sure the IME doesn't
|
| - // enter fullscreen mode.
|
| - outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN;
|
| - }
|
| - int initialSelStart = Selection.getSelectionStart(mEditable);
|
| - int initialSelEnd = outAttrs.initialSelEnd = Selection.getSelectionEnd(mEditable);
|
| mInputConnection = mInputConnectionFactory.get(
|
| - mViewEmbedder.getAttachedView(), this, initialSelStart, initialSelEnd, outAttrs);
|
| - Log.d(TAG, "onCreateInputConnection");
|
| + mViewEmbedder.getAttachedView(), this, mTextInputType, mTextInputFlags, outAttrs);
|
| + Log.d(TAG, "onCreateInputConnection: ", mInputConnection);
|
| return mInputConnection;
|
| }
|
|
|
| @@ -171,49 +148,18 @@ public class ImeAdapter {
|
| }
|
|
|
| @VisibleForTesting
|
| - void setInputConnectionFactory(AdapterInputConnectionFactory factory) {
|
| + void setInputConnectionFactory(ChromiumBaseInputConnection.Factory factory) {
|
| mInputConnectionFactory = factory;
|
| }
|
|
|
| /**
|
| - * Set the current active InputConnection when a new InputConnection is constructed.
|
| - * @param inputConnection The input connection that is currently used with IME.
|
| - */
|
| - void setInputConnection(AdapterInputConnection inputConnection) {
|
| - mInputConnection = inputConnection;
|
| - }
|
| -
|
| - /**
|
| * Get the current input connection for testing purposes.
|
| */
|
| @VisibleForTesting
|
| - public AdapterInputConnection getInputConnectionForTest() {
|
| + public ChromiumBaseInputConnection getInputConnectionForTest() {
|
| return mInputConnection;
|
| }
|
|
|
| - /**
|
| - * @return The Editable instance that will be shared across AdapterInputConnection instances.
|
| - */
|
| - Editable getEditable() {
|
| - return mEditable;
|
| - }
|
| -
|
| - /**
|
| - * Should be used only by AdapterInputConnection.
|
| - * @return The input type of currently focused element.
|
| - */
|
| - int getTextInputType() {
|
| - return mTextInputType;
|
| - }
|
| -
|
| - /**
|
| - * Should be used only by AdapterInputConnection.
|
| - * @return The input flags of the currently focused element.
|
| - */
|
| - int getTextInputFlags() {
|
| - return mTextInputFlags;
|
| - }
|
| -
|
| private static int getModifiers(int metaState) {
|
| int modifiers = 0;
|
| if ((metaState & KeyEvent.META_SHIFT_ON) != 0) {
|
| @@ -278,8 +224,10 @@ public class ImeAdapter {
|
| public void updateState(String text, int selectionStart, int selectionEnd, int compositionStart,
|
| int compositionEnd, boolean isNonImeChange) {
|
| if (mInputConnection == null) return;
|
| - mInputConnection.updateState(text, selectionStart, selectionEnd, compositionStart,
|
| - compositionEnd, isNonImeChange);
|
| + boolean singleLine = mTextInputType != TextInputType.TEXT_AREA
|
| + && mTextInputType != TextInputType.CONTENT_EDITABLE;
|
| + mInputConnection.updateStateOnUiThread(text, selectionStart, selectionEnd, compositionStart,
|
| + compositionEnd, singleLine, isNonImeChange);
|
| }
|
|
|
| /**
|
| @@ -366,8 +314,7 @@ public class ImeAdapter {
|
| public void moveCursorToSelectionEnd() {
|
| Log.d(TAG, "movecursorToEnd");
|
| if (mInputConnection != null) {
|
| - int selectionEnd = Selection.getSelectionEnd(mEditable);
|
| - mInputConnection.setSelection(selectionEnd, selectionEnd);
|
| + mInputConnection.moveCursorToSelectionEndOnUiThread();
|
| }
|
| }
|
|
|
| @@ -387,9 +334,7 @@ public class ImeAdapter {
|
| public boolean dispatchKeyEvent(KeyEvent event) {
|
| Log.d(TAG, "dispatchKeyEvent: action [%d], keycode [%d]", event.getAction(),
|
| event.getKeyCode());
|
| - if (mInputConnection != null) {
|
| - return mInputConnection.sendKeyEvent(event);
|
| - }
|
| + if (mInputConnection != null) return mInputConnection.sendKeyEventOnUiThread(event);
|
| return sendKeyEvent(event);
|
| }
|
|
|
| @@ -412,7 +357,7 @@ public class ImeAdapter {
|
| */
|
| void restartInput() {
|
| mInputMethodManagerWrapper.restartInput(mViewEmbedder.getAttachedView());
|
| - if (mInputConnection != null) mInputConnection.onRestartInput();
|
| + if (mInputConnection != null) mInputConnection.onRestartInputOnUiThread();
|
| }
|
|
|
| /**
|
| @@ -481,9 +426,10 @@ public class ImeAdapter {
|
| }
|
|
|
| @VisibleForTesting
|
| - void finishComposingText() {
|
| - if (mNativeImeAdapterAndroid == 0) return;
|
| + boolean finishComposingText() {
|
| + if (mNativeImeAdapterAndroid == 0) return false;
|
| nativeFinishComposingText(mNativeImeAdapterAndroid);
|
| + return true;
|
| }
|
|
|
| boolean sendKeyEvent(KeyEvent event) {
|
| @@ -546,7 +492,7 @@ public class ImeAdapter {
|
| * @param end The end of the composition.
|
| * @return Whether the native counterpart of ImeAdapter received the call.
|
| */
|
| - boolean setComposingRegion(CharSequence text, int start, int end) {
|
| + boolean setComposingRegion(int start, int end) {
|
| if (mNativeImeAdapterAndroid == 0) return false;
|
| nativeSetComposingRegion(mNativeImeAdapterAndroid, start, end);
|
| return true;
|
| @@ -560,6 +506,15 @@ public class ImeAdapter {
|
| }
|
| }
|
|
|
| + /**
|
| + * Send a request to the native counterpart to give the latest text input state update.
|
| + */
|
| + boolean requestTextInputStateUpdate() {
|
| + if (mNativeImeAdapterAndroid == 0) return false;
|
| + nativeRequestTextInputStateUpdate(mNativeImeAdapterAndroid);
|
| + return true;
|
| + }
|
| +
|
| @CalledByNative
|
| private void populateUnderlinesFromSpans(CharSequence text, long underlines) {
|
| Log.d(TAG, "populateUnderlinesFromSpans: text [%s], underlines [%d]", text, underlines);
|
| @@ -594,32 +549,22 @@ public class ImeAdapter {
|
|
|
| private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndroid,
|
| int eventType, long timestampMs, int keyCode, int modifiers, int unicodeChar);
|
| -
|
| private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyEvent event,
|
| int action, int modifiers, long timestampMs, int keyCode, int scanCode,
|
| boolean isSystemKey, int unicodeChar);
|
| -
|
| private static native void nativeAppendUnderlineSpan(long underlinePtr, int start, int end);
|
| -
|
| private static native void nativeAppendBackgroundColorSpan(long underlinePtr, int start,
|
| int end, int backgroundColor);
|
| -
|
| private native void nativeSetComposingText(long nativeImeAdapterAndroid, CharSequence text,
|
| String textStr, int newCursorPosition);
|
| -
|
| private native void nativeCommitText(long nativeImeAdapterAndroid, String textStr);
|
| -
|
| private native void nativeFinishComposingText(long nativeImeAdapterAndroid);
|
| -
|
| private native void nativeAttachImeAdapter(long nativeImeAdapterAndroid);
|
| -
|
| private native void nativeSetEditableSelectionOffsets(long nativeImeAdapterAndroid,
|
| int start, int end);
|
| -
|
| private native void nativeSetComposingRegion(long nativeImeAdapterAndroid, int start, int end);
|
| -
|
| private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid,
|
| int before, int after);
|
| -
|
| private native void nativeResetImeAdapter(long nativeImeAdapterAndroid);
|
| + private native void nativeRequestTextInputStateUpdate(long nativeImeAdapterAndroid);
|
| }
|
|
|