| 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 08686df7c33f5755b475353ad12845aad56b883f..bde6ac90275875c93273cf9890e0ea91c4ecfddb 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
|
| @@ -4,12 +4,8 @@
|
|
|
| package org.chromium.content.browser.input;
|
|
|
| -import android.annotation.SuppressLint;
|
| import android.content.res.Configuration;
|
| -import android.graphics.Rect;
|
| import android.os.Build;
|
| -import android.os.Bundle;
|
| -import android.os.Handler;
|
| import android.os.ResultReceiver;
|
| import android.os.SystemClock;
|
| import android.text.SpannableString;
|
| @@ -23,10 +19,8 @@ import android.view.View;
|
| import android.view.inputmethod.BaseInputConnection;
|
| import android.view.inputmethod.EditorInfo;
|
| import android.view.inputmethod.InputConnection;
|
| -import android.view.inputmethod.InputMethodManager;
|
|
|
| import org.chromium.base.Log;
|
| -import org.chromium.base.TraceEvent;
|
| import org.chromium.base.VisibleForTesting;
|
| import org.chromium.base.annotations.CalledByNative;
|
| import org.chromium.base.annotations.JNINamespace;
|
| @@ -34,16 +28,9 @@ import org.chromium.blink_public.web.WebInputEventModifier;
|
| import org.chromium.blink_public.web.WebInputEventType;
|
| import org.chromium.blink_public.web.WebTextInputMode;
|
| import org.chromium.content.browser.RenderCoordinates;
|
| -import org.chromium.content.browser.ViewUtils;
|
| import org.chromium.content.browser.picker.InputDialogContainer;
|
| -import org.chromium.content_public.browser.ImeEventObserver;
|
| -import org.chromium.content_public.browser.WebContents;
|
| import org.chromium.ui.base.ime.TextInputType;
|
|
|
| -import java.lang.ref.WeakReference;
|
| -import java.util.ArrayList;
|
| -import java.util.List;
|
| -
|
| /**
|
| * Adapts and plumbs android IME service onto the chrome text input API.
|
| * ImeAdapter provides an interface in both ways native <-> java:
|
| @@ -72,6 +59,36 @@ public class ImeAdapter {
|
|
|
| public static final int COMPOSITION_KEY_CODE = 229;
|
|
|
| + /**
|
| + * Interface for the delegate that needs to be notified of IME changes.
|
| + */
|
| + public interface ImeAdapterDelegate {
|
| + /**
|
| + * Called to notify the delegate about synthetic/real key events before sending to renderer.
|
| + */
|
| + void onImeEvent();
|
| +
|
| + /**
|
| + * Called when the keyboard could not be shown due to the hardware keyboard being present.
|
| + */
|
| + void onKeyboardBoundsUnchanged();
|
| +
|
| + /**
|
| + * @see BaseInputConnection#performContextMenuAction(int)
|
| + */
|
| + boolean performContextMenuAction(int id);
|
| +
|
| + /**
|
| + * @return View that the keyboard should be attached to.
|
| + */
|
| + View getAttachedView();
|
| +
|
| + /**
|
| + * @return Object that should be called for all keyboard show and hide requests.
|
| + */
|
| + ResultReceiver getNewShowKeyboardReceiver();
|
| + }
|
| +
|
| static char[] sSingleCharArray = new char[1];
|
| static KeyCharacterMap sKeyCharacterMap;
|
|
|
| @@ -80,30 +97,16 @@ public class ImeAdapter {
|
| private ChromiumBaseInputConnection mInputConnection;
|
| private ChromiumBaseInputConnection.Factory mInputConnectionFactory;
|
|
|
| - // NOTE: This object will not be released by Android framework until the matching
|
| - // ResultReceiver in the InputMethodService (IME app) gets gc'ed.
|
| - private ShowKeyboardResultReceiver mShowKeyboardResultReceiver;
|
| -
|
| - private final WebContents mWebContents;
|
| - private View mContainerView;
|
| -
|
| + private final ImeAdapterDelegate mViewEmbedder;
|
| // This holds the information necessary for constructing CursorAnchorInfo, and notifies to
|
| // InputMethodManager on appropriate timing, depending on how IME requested the information
|
| // via InputConnection. The update request is per InputConnection, hence for each time it is
|
| // re-created, the monitoring status will be reset.
|
| private final CursorAnchorInfoController mCursorAnchorInfoController;
|
|
|
| - private final List<ImeEventObserver> mEventObservers = new ArrayList<>();
|
| -
|
| private int mTextInputType = TextInputType.NONE;
|
| private int mTextInputFlags;
|
| private int mTextInputMode = WebTextInputMode.kDefault;
|
| - private boolean mNodeEditable;
|
| - private boolean mNodePassword;
|
| -
|
| - // Viewport rect before the OSK was brought up.
|
| - // Used to tell View#onSizeChanged to focus a form element.
|
| - private final Rect mFocusPreOSKViewportRect = new Rect();
|
|
|
| // Keep the current configuration to detect the change when onConfigurationChanged() is called.
|
| private Configuration mCurrentConfig;
|
| @@ -115,50 +118,17 @@ public class ImeAdapter {
|
| private int mLastCompositionEnd;
|
| private boolean mRestartInputOnNextStateUpdate;
|
|
|
| - // True if ImeAdapter is connected to render process.
|
| - private boolean mIsConnected;
|
| -
|
| - /**
|
| - * {@ResultReceiver} passed in InputMethodManager#showSoftInput}. We need this to scroll to the
|
| - * editable node at the right timing, which is after input method window shows up.
|
| - */
|
| - // TODO(crbug.com/635567): Fix this properly.
|
| - @SuppressLint("ParcelCreator")
|
| - private static class ShowKeyboardResultReceiver extends ResultReceiver {
|
| - // Unfortunately, the memory life cycle of ResultReceiver object, once passed in
|
| - // showSoftInput(), is in the control of Android's input method framework and IME app,
|
| - // so we use a weakref to avoid tying ImeAdapter's lifetime to that of ResultReceiver
|
| - // object.
|
| - private final WeakReference<ImeAdapter> mImeAdapter;
|
| -
|
| - public ShowKeyboardResultReceiver(ImeAdapter imeAdapter, Handler handler) {
|
| - super(handler);
|
| - mImeAdapter = new WeakReference<>(imeAdapter);
|
| - }
|
| -
|
| - @Override
|
| - public void onReceiveResult(int resultCode, Bundle resultData) {
|
| - ImeAdapter imeAdapter = mImeAdapter.get();
|
| - if (imeAdapter == null) return;
|
| - imeAdapter.onShowKeyboardReceiveResult(resultCode);
|
| - }
|
| - }
|
| -
|
| /**
|
| - * @param webContents WebContents instance with which this ImeAdapter is associated.
|
| - * @param containerView {@link View} instance which input events are posted on.
|
| * @param wrapper InputMethodManagerWrapper that should receive all the call directed to
|
| * InputMethodManager.
|
| + * @param embedder The view that is used for callbacks from ImeAdapter.
|
| */
|
| - public ImeAdapter(
|
| - WebContents webContents, View containerView, InputMethodManagerWrapper wrapper) {
|
| - mWebContents = webContents;
|
| - mContainerView = containerView;
|
| + public ImeAdapter(InputMethodManagerWrapper wrapper, ImeAdapterDelegate embedder) {
|
| mInputMethodManagerWrapper = wrapper;
|
| -
|
| + mViewEmbedder = embedder;
|
| // Deep copy newConfig so that we can notice the difference.
|
| - mCurrentConfig = new Configuration(mContainerView.getResources().getConfiguration());
|
| -
|
| + mCurrentConfig = new Configuration(
|
| + mViewEmbedder.getAttachedView().getResources().getConfiguration());
|
| // CursorAnchroInfo is supported only after L.
|
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
| mCursorAnchorInfoController = CursorAnchorInfoController.create(wrapper,
|
| @@ -187,19 +157,6 @@ public class ImeAdapter {
|
| } else {
|
| mCursorAnchorInfoController = null;
|
| }
|
| - mNativeImeAdapterAndroid = nativeInit(webContents);
|
| - }
|
| -
|
| - /**
|
| - * Set the container view.
|
| - * @param containerView {@link View} which this ImeAdapter works on.
|
| - */
|
| - public void setContainerView(View containerView) {
|
| - mContainerView = containerView;
|
| - }
|
| -
|
| - public void addEventObserver(ImeEventObserver eventObserver) {
|
| - mEventObservers.add(eventObserver);
|
| }
|
|
|
| private void createInputConnectionFactory() {
|
| @@ -207,13 +164,6 @@ public class ImeAdapter {
|
| mInputConnectionFactory = new ThreadedInputConnectionFactory(mInputMethodManagerWrapper);
|
| }
|
|
|
| - // Tells if the ImeAdapter in valid state (i.e. not in destroyed state), and is
|
| - // connected to render process. The former check guards against the call via
|
| - // ThreadedInputConnection from Android framework after ImeAdapter.destroy() is called.
|
| - private boolean isValid() {
|
| - return mNativeImeAdapterAndroid != 0 && mIsConnected;
|
| - }
|
| -
|
| /**
|
| * @see View#onCreateInputConnection(EditorInfo)
|
| */
|
| @@ -230,16 +180,17 @@ public class ImeAdapter {
|
| return null;
|
| }
|
| if (mInputConnectionFactory == null) return null;
|
| - setInputConnection(mInputConnectionFactory.initializeAndGet(mContainerView, this,
|
| - mTextInputType, mTextInputFlags, mTextInputMode, mLastSelectionStart,
|
| + setInputConnection(mInputConnectionFactory.initializeAndGet(mViewEmbedder.getAttachedView(),
|
| + this, mTextInputType, mTextInputFlags, mTextInputMode, mLastSelectionStart,
|
| mLastSelectionEnd, outAttrs));
|
| if (DEBUG_LOGS) Log.i(TAG, "onCreateInputConnection: " + mInputConnection);
|
|
|
| if (mCursorAnchorInfoController != null) {
|
| - mCursorAnchorInfoController.onRequestCursorUpdates(false /* not an immediate request */,
|
| - false /* disable monitoring */, mContainerView);
|
| + mCursorAnchorInfoController.onRequestCursorUpdates(
|
| + false /* not an immediate request */, false /* disable monitoring */,
|
| + mViewEmbedder.getAttachedView());
|
| }
|
| - if (isValid()) {
|
| + if (mNativeImeAdapterAndroid != 0) {
|
| nativeRequestCursorUpdate(mNativeImeAdapterAndroid,
|
| false /* not an immediate request */, false /* disable monitoring */);
|
| }
|
| @@ -323,73 +274,75 @@ public class ImeAdapter {
|
| * selection.
|
| * @param replyToRequest True when the update was requested by IME.
|
| */
|
| - @CalledByNative
|
| - private void updateState(int textInputType, int textInputFlags, int textInputMode,
|
| + public void updateState(int textInputType, int textInputFlags, int textInputMode,
|
| boolean showIfNeeded, String text, int selectionStart, int selectionEnd,
|
| int compositionStart, int compositionEnd, boolean replyToRequest) {
|
| - TraceEvent.begin("ImeAdapter.updateState");
|
| - try {
|
| - if (DEBUG_LOGS) {
|
| - Log.i(TAG, "updateState: type [%d->%d], flags [%d], show [%b], ", mTextInputType,
|
| - textInputType, textInputFlags, showIfNeeded);
|
| - }
|
| - boolean needsRestart = false;
|
| - if (mRestartInputOnNextStateUpdate) {
|
| - needsRestart = true;
|
| - mRestartInputOnNextStateUpdate = false;
|
| - }
|
| + if (DEBUG_LOGS) {
|
| + Log.i(TAG, "updateState: type [%d->%d], flags [%d], show [%b], ", mTextInputType,
|
| + textInputType, textInputFlags, showIfNeeded);
|
| + }
|
| + boolean needsRestart = false;
|
| + if (mRestartInputOnNextStateUpdate) {
|
| + needsRestart = true;
|
| + mRestartInputOnNextStateUpdate = false;
|
| + }
|
| +
|
| + mTextInputFlags = textInputFlags;
|
| + if (mTextInputMode != textInputMode) {
|
| + mTextInputMode = textInputMode;
|
| + needsRestart = true;
|
| + }
|
| + if (mTextInputType != textInputType) {
|
| + mTextInputType = textInputType;
|
| + needsRestart = true;
|
| + }
|
| + if (mCursorAnchorInfoController != null && (!TextUtils.equals(mLastText, text)
|
| + || mLastSelectionStart != selectionStart || mLastSelectionEnd != selectionEnd
|
| + || mLastCompositionStart != compositionStart
|
| + || mLastCompositionEnd != compositionEnd)) {
|
| + mCursorAnchorInfoController.invalidateLastCursorAnchorInfo();
|
| + }
|
| + mLastText = text;
|
| + mLastSelectionStart = selectionStart;
|
| + mLastSelectionEnd = selectionEnd;
|
| + mLastCompositionStart = compositionStart;
|
| + mLastCompositionEnd = compositionEnd;
|
| +
|
| + if (textInputType == TextInputType.NONE) {
|
| + hideKeyboard();
|
| + } else {
|
| + if (needsRestart) restartInput();
|
| + // There is no API for us to get notified of user's dismissal of keyboard.
|
| + // Therefore, we should try to show keyboard even when text input type hasn't changed.
|
| + if (showIfNeeded) showSoftKeyboard();
|
| + }
|
|
|
| - mTextInputFlags = textInputFlags;
|
| - if (mTextInputMode != textInputMode) {
|
| - mTextInputMode = textInputMode;
|
| - needsRestart = true;
|
| - }
|
| - if (mTextInputType != textInputType) {
|
| - mTextInputType = textInputType;
|
| - needsRestart = true;
|
| -
|
| - boolean editable = textInputType != TextInputType.NONE;
|
| - boolean password = textInputType == TextInputType.PASSWORD;
|
| - if (mNodeEditable != editable || mNodePassword != password) {
|
| - for (ImeEventObserver observer : mEventObservers) {
|
| - observer.onNodeAttributeUpdated(editable, password);
|
| - }
|
| - mNodeEditable = editable;
|
| - mNodePassword = password;
|
| - }
|
| - }
|
| - if (mCursorAnchorInfoController != null
|
| - && (!TextUtils.equals(mLastText, text) || mLastSelectionStart != selectionStart
|
| - || mLastSelectionEnd != selectionEnd
|
| - || mLastCompositionStart != compositionStart
|
| - || mLastCompositionEnd != compositionEnd)) {
|
| - mCursorAnchorInfoController.invalidateLastCursorAnchorInfo();
|
| - }
|
| - mLastText = text;
|
| - mLastSelectionStart = selectionStart;
|
| - mLastSelectionEnd = selectionEnd;
|
| - mLastCompositionStart = compositionStart;
|
| - mLastCompositionEnd = compositionEnd;
|
| -
|
| - if (textInputType == TextInputType.NONE) {
|
| - hideKeyboard();
|
| - } else {
|
| - if (needsRestart) restartInput();
|
| - // There is no API for us to get notified of user's dismissal of keyboard.
|
| - // Therefore, we should try to show keyboard even when text input type hasn't
|
| - // changed.
|
| - if (showIfNeeded) showSoftKeyboard();
|
| - }
|
| + if (mInputConnection == null) return;
|
| + boolean singleLine = mTextInputType != TextInputType.TEXT_AREA
|
| + && mTextInputType != TextInputType.CONTENT_EDITABLE;
|
| + mInputConnection.updateStateOnUiThread(text, selectionStart, selectionEnd, compositionStart,
|
| + compositionEnd, singleLine, replyToRequest);
|
| + }
|
|
|
| - if (mInputConnection != null) {
|
| - boolean singleLine = mTextInputType != TextInputType.TEXT_AREA
|
| - && mTextInputType != TextInputType.CONTENT_EDITABLE;
|
| - mInputConnection.updateStateOnUiThread(text, selectionStart, selectionEnd,
|
| - compositionStart, compositionEnd, singleLine, replyToRequest);
|
| - }
|
| - } finally {
|
| - TraceEvent.end("ImeAdapter.updateState");
|
| + /**
|
| + * Attaches the imeAdapter to its native counterpart. This is needed to start forwarding
|
| + * keyboard events to WebKit.
|
| + * @param nativeImeAdapter The pointer to the native ImeAdapter object.
|
| + */
|
| + public void attach(long nativeImeAdapter) {
|
| + if (DEBUG_LOGS) Log.i(TAG, "attach");
|
| + if (mNativeImeAdapterAndroid == nativeImeAdapter) return;
|
| + if (mNativeImeAdapterAndroid != 0) {
|
| + nativeResetImeAdapter(mNativeImeAdapterAndroid);
|
| + }
|
| + if (nativeImeAdapter != 0) {
|
| + nativeAttachImeAdapter(nativeImeAdapter);
|
| + }
|
| + mNativeImeAdapterAndroid = nativeImeAdapter;
|
| + if (nativeImeAdapter != 0) {
|
| + createInputConnectionFactory();
|
| }
|
| + resetAndHideKeyboard();
|
| }
|
|
|
| /**
|
| @@ -397,43 +350,12 @@ public class ImeAdapter {
|
| */
|
| private void showSoftKeyboard() {
|
| if (DEBUG_LOGS) Log.i(TAG, "showSoftKeyboard");
|
| - mInputMethodManagerWrapper.showSoftInput(mContainerView, 0, getNewShowKeyboardReceiver());
|
| - if (mContainerView.getResources().getConfiguration().keyboard
|
| + mInputMethodManagerWrapper.showSoftInput(
|
| + mViewEmbedder.getAttachedView(), 0, mViewEmbedder.getNewShowKeyboardReceiver());
|
| + if (mViewEmbedder.getAttachedView().getResources().getConfiguration().keyboard
|
| != Configuration.KEYBOARD_NOKEYS) {
|
| - mWebContents.scrollFocusedEditableNodeIntoView();
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Call this when we get result from ResultReceiver passed in calling showSoftInput().
|
| - * @param resultCode The result of showSoftInput() as defined in InputMethodManager.
|
| - */
|
| - public void onShowKeyboardReceiveResult(int resultCode) {
|
| - if (resultCode == InputMethodManager.RESULT_SHOWN) {
|
| - // If OSK is newly shown, delay the form focus until
|
| - // the onSizeChanged (in order to adjust relative to the
|
| - // new size).
|
| - // TODO(jdduke): We should not assume that onSizeChanged will
|
| - // always be called, crbug.com/294908.
|
| - mContainerView.getWindowVisibleDisplayFrame(mFocusPreOSKViewportRect);
|
| - } else if (ViewUtils.hasFocus(mContainerView)
|
| - && resultCode == InputMethodManager.RESULT_UNCHANGED_SHOWN) {
|
| - // If the OSK was already there, focus the form immediately.
|
| - mWebContents.scrollFocusedEditableNodeIntoView();
|
| - }
|
| - }
|
| -
|
| - public Rect getFocusPreOSKViewportRect() {
|
| - return mFocusPreOSKViewportRect;
|
| - }
|
| -
|
| - @VisibleForTesting
|
| - public ResultReceiver getNewShowKeyboardReceiver() {
|
| - if (mShowKeyboardResultReceiver == null) {
|
| - // Note: the returned object will get leaked by Android framework.
|
| - mShowKeyboardResultReceiver = new ShowKeyboardResultReceiver(this, new Handler());
|
| + mViewEmbedder.onKeyboardBoundsUnchanged();
|
| }
|
| - return mShowKeyboardResultReceiver;
|
| }
|
|
|
| /**
|
| @@ -441,7 +363,7 @@ public class ImeAdapter {
|
| */
|
| private void hideKeyboard() {
|
| if (DEBUG_LOGS) Log.i(TAG, "hideKeyboard");
|
| - View view = mContainerView;
|
| + View view = mViewEmbedder.getAttachedView();
|
| if (mInputMethodManagerWrapper.isActive(view)) {
|
| // NOTE: we should not set ResultReceiver here. Otherwise, IMM will own ContentViewCore
|
| // and ImeAdapter even after input method goes away and result gets received.
|
| @@ -563,16 +485,6 @@ public class ImeAdapter {
|
| hideKeyboard();
|
| }
|
|
|
| - @CalledByNative
|
| - private void destroy() {
|
| - resetAndHideKeyboard();
|
| - mNativeImeAdapterAndroid = 0;
|
| - mIsConnected = false;
|
| - if (mCursorAnchorInfoController != null) {
|
| - mCursorAnchorInfoController.focusedNodeChanged(false);
|
| - }
|
| - }
|
| -
|
| /**
|
| * Update selection to input method manager.
|
| *
|
| @@ -583,8 +495,8 @@ public class ImeAdapter {
|
| */
|
| void updateSelection(
|
| int selectionStart, int selectionEnd, int compositionStart, int compositionEnd) {
|
| - mInputMethodManagerWrapper.updateSelection(
|
| - mContainerView, selectionStart, selectionEnd, compositionStart, compositionEnd);
|
| + mInputMethodManagerWrapper.updateSelection(mViewEmbedder.getAttachedView(),
|
| + selectionStart, selectionEnd, compositionStart, compositionEnd);
|
| }
|
|
|
| /**
|
| @@ -592,7 +504,7 @@ public class ImeAdapter {
|
| */
|
| void restartInput() {
|
| // This will eventually cause input method manager to call View#onCreateInputConnection().
|
| - mInputMethodManagerWrapper.restartInput(mContainerView);
|
| + mInputMethodManagerWrapper.restartInput(mViewEmbedder.getAttachedView());
|
| if (mInputConnection != null) mInputConnection.onRestartInputOnUiThread();
|
| }
|
|
|
| @@ -601,26 +513,11 @@ public class ImeAdapter {
|
| */
|
| boolean performContextMenuAction(int id) {
|
| if (DEBUG_LOGS) Log.i(TAG, "performContextMenuAction: id [%d]", id);
|
| - switch (id) {
|
| - case android.R.id.selectAll:
|
| - mWebContents.selectAll();
|
| - return true;
|
| - case android.R.id.cut:
|
| - mWebContents.cut();
|
| - return true;
|
| - case android.R.id.copy:
|
| - mWebContents.copy();
|
| - return true;
|
| - case android.R.id.paste:
|
| - mWebContents.paste();
|
| - return true;
|
| - default:
|
| - return false;
|
| - }
|
| + return mViewEmbedder.performContextMenuAction(id);
|
| }
|
|
|
| boolean performEditorAction(int actionCode) {
|
| - if (!isValid()) return false;
|
| + if (mNativeImeAdapterAndroid == 0) return false;
|
| if (actionCode == EditorInfo.IME_ACTION_NEXT) {
|
| sendSyntheticKeyPress(KeyEvent.KEYCODE_TAB,
|
| KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE
|
| @@ -650,14 +547,9 @@ public class ImeAdapter {
|
| flags));
|
| }
|
|
|
| - private void onImeEvent() {
|
| - for (ImeEventObserver observer : mEventObservers) observer.onImeEvent();
|
| - if (mNodeEditable) mWebContents.dismissTextHandles();
|
| - }
|
| -
|
| boolean sendCompositionToNative(
|
| CharSequence text, int newCursorPosition, boolean isCommit, int unicodeFromKeyEvent) {
|
| - if (!isValid()) return false;
|
| + if (mNativeImeAdapterAndroid == 0) return false;
|
|
|
| // One WebView app detects Enter in JS by looking at KeyDown (http://crbug/577967).
|
| if (TextUtils.equals(text, "\n")) {
|
| @@ -666,7 +558,7 @@ public class ImeAdapter {
|
| return true;
|
| }
|
|
|
| - onImeEvent();
|
| + mViewEmbedder.onImeEvent();
|
| long timestampMs = SystemClock.uptimeMillis();
|
| nativeSendKeyEvent(mNativeImeAdapterAndroid, null, WebInputEventType.kRawKeyDown, 0,
|
| timestampMs, COMPOSITION_KEY_CODE, 0, false, unicodeFromKeyEvent);
|
| @@ -685,13 +577,13 @@ public class ImeAdapter {
|
|
|
| @VisibleForTesting
|
| boolean finishComposingText() {
|
| - if (!isValid()) return false;
|
| + if (mNativeImeAdapterAndroid == 0) return false;
|
| nativeFinishComposingText(mNativeImeAdapterAndroid);
|
| return true;
|
| }
|
|
|
| boolean sendKeyEvent(KeyEvent event) {
|
| - if (!isValid()) return false;
|
| + if (mNativeImeAdapterAndroid == 0) return false;
|
|
|
| int action = event.getAction();
|
| int type;
|
| @@ -706,7 +598,7 @@ public class ImeAdapter {
|
| // sends ACTION_DOWN), so it's fine to silently drop it.
|
| return false;
|
| }
|
| - onImeEvent();
|
| + mViewEmbedder.onImeEvent();
|
|
|
| return nativeSendKeyEvent(mNativeImeAdapterAndroid, event, type,
|
| getModifiers(event.getMetaState()), event.getEventTime(), event.getKeyCode(),
|
| @@ -722,8 +614,8 @@ public class ImeAdapter {
|
| * @return Whether the native counterpart of ImeAdapter received the call.
|
| */
|
| boolean deleteSurroundingText(int beforeLength, int afterLength) {
|
| - onImeEvent();
|
| - if (!isValid()) return false;
|
| + mViewEmbedder.onImeEvent();
|
| + if (mNativeImeAdapterAndroid == 0) return false;
|
| nativeSendKeyEvent(mNativeImeAdapterAndroid, null, WebInputEventType.kRawKeyDown, 0,
|
| SystemClock.uptimeMillis(), COMPOSITION_KEY_CODE, 0, false, 0);
|
| nativeDeleteSurroundingText(mNativeImeAdapterAndroid, beforeLength, afterLength);
|
| @@ -741,8 +633,8 @@ public class ImeAdapter {
|
| * @return Whether the native counterpart of ImeAdapter received the call.
|
| */
|
| boolean deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) {
|
| - onImeEvent();
|
| - if (!isValid()) return false;
|
| + mViewEmbedder.onImeEvent();
|
| + if (mNativeImeAdapterAndroid == 0) return false;
|
| nativeSendKeyEvent(mNativeImeAdapterAndroid, null, WebInputEventType.kRawKeyDown, 0,
|
| SystemClock.uptimeMillis(), COMPOSITION_KEY_CODE, 0, false, 0);
|
| nativeDeleteSurroundingTextInCodePoints(
|
| @@ -759,7 +651,7 @@ public class ImeAdapter {
|
| * @return Whether the native counterpart of ImeAdapter received the call.
|
| */
|
| boolean setEditableSelectionOffsets(int start, int end) {
|
| - if (!isValid()) return false;
|
| + if (mNativeImeAdapterAndroid == 0) return false;
|
| nativeSetEditableSelectionOffsets(mNativeImeAdapterAndroid, start, end);
|
| return true;
|
| }
|
| @@ -771,7 +663,7 @@ public class ImeAdapter {
|
| * @return Whether the native counterpart of ImeAdapter received the call.
|
| */
|
| boolean setComposingRegion(int start, int end) {
|
| - if (!isValid()) return false;
|
| + if (mNativeImeAdapterAndroid == 0) return false;
|
| if (start <= end) {
|
| nativeSetComposingRegion(mNativeImeAdapterAndroid, start, end);
|
| } else {
|
| @@ -798,7 +690,7 @@ public class ImeAdapter {
|
| * Send a request to the native counterpart to give the latest text input state update.
|
| */
|
| boolean requestTextInputStateUpdate() {
|
| - if (!isValid()) return false;
|
| + if (mNativeImeAdapterAndroid == 0) return false;
|
| // You won't get state update anyways.
|
| if (mInputConnection == null) return false;
|
| return nativeRequestTextInputStateUpdate(mNativeImeAdapterAndroid);
|
| @@ -813,12 +705,12 @@ public class ImeAdapter {
|
| final boolean monitorRequest =
|
| (cursorUpdateMode & InputConnection.CURSOR_UPDATE_MONITOR) != 0;
|
|
|
| - if (isValid()) {
|
| + if (mNativeImeAdapterAndroid != 0) {
|
| nativeRequestCursorUpdate(mNativeImeAdapterAndroid, immediateRequest, monitorRequest);
|
| }
|
| if (mCursorAnchorInfoController == null) return false;
|
| - return mCursorAnchorInfoController.onRequestCursorUpdates(
|
| - immediateRequest, monitorRequest, mContainerView);
|
| + return mCursorAnchorInfoController.onRequestCursorUpdates(immediateRequest, monitorRequest,
|
| + mViewEmbedder.getAttachedView());
|
| }
|
|
|
| /**
|
| @@ -839,7 +731,7 @@ public class ImeAdapter {
|
| if (mCursorAnchorInfoController == null) return;
|
| mCursorAnchorInfoController.onUpdateFrameInfo(renderCoordinates, hasInsertionMarker,
|
| isInsertionMarkerVisible, insertionMarkerHorizontal, insertionMarkerTop,
|
| - insertionMarkerBottom, mContainerView);
|
| + insertionMarkerBottom, mViewEmbedder.getAttachedView());
|
| }
|
|
|
| @CalledByNative
|
| @@ -873,18 +765,19 @@ public class ImeAdapter {
|
| @CalledByNative
|
| private void setCharacterBounds(float[] characterBounds) {
|
| if (mCursorAnchorInfoController == null) return;
|
| - mCursorAnchorInfoController.setCompositionCharacterBounds(characterBounds, mContainerView);
|
| + mCursorAnchorInfoController.setCompositionCharacterBounds(characterBounds,
|
| + mViewEmbedder.getAttachedView());
|
| }
|
|
|
| @CalledByNative
|
| - private void onConnectedToRenderProcess() {
|
| - if (DEBUG_LOGS) Log.i(TAG, "onConnectedToRenderProcess");
|
| - mIsConnected = true;
|
| - createInputConnectionFactory();
|
| - resetAndHideKeyboard();
|
| + private void detach() {
|
| + if (DEBUG_LOGS) Log.i(TAG, "detach");
|
| + mNativeImeAdapterAndroid = 0;
|
| + if (mCursorAnchorInfoController != null) {
|
| + mCursorAnchorInfoController.focusedNodeChanged(false);
|
| + }
|
| }
|
|
|
| - private native long nativeInit(WebContents webContents);
|
| private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyEvent event,
|
| int type, int modifiers, long timestampMs, int keyCode, int scanCode,
|
| boolean isSystemKey, int unicodeChar);
|
| @@ -896,6 +789,7 @@ public class ImeAdapter {
|
| private native void nativeCommitText(
|
| long nativeImeAdapterAndroid, CharSequence text, String textStr, int newCursorPosition);
|
| 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);
|
| @@ -903,6 +797,7 @@ public class ImeAdapter {
|
| int before, int after);
|
| private native void nativeDeleteSurroundingTextInCodePoints(
|
| long nativeImeAdapterAndroid, int before, int after);
|
| + private native void nativeResetImeAdapter(long nativeImeAdapterAndroid);
|
| private native boolean nativeRequestTextInputStateUpdate(long nativeImeAdapterAndroid);
|
| private native void nativeRequestCursorUpdate(long nativeImeAdapterAndroid,
|
| boolean immediateRequest, boolean monitorRequest);
|
|
|