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); |