| 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 a1bf512541883a0f92238bd21d01574a8a03e924..f00e77085e78bef527b756d08495b780ff824b23 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
|
| @@ -5,6 +5,7 @@
|
| package org.chromium.content.browser.input;
|
|
|
| import android.content.res.Configuration;
|
| +import android.os.Build;
|
| import android.os.ResultReceiver;
|
| import android.os.SystemClock;
|
| import android.text.SpannableString;
|
| @@ -24,6 +25,7 @@ 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.browser.RenderCoordinates;
|
| import org.chromium.ui.base.ime.TextInputType;
|
| import org.chromium.ui.picker.InputDialogContainer;
|
|
|
| @@ -94,6 +96,11 @@ public class ImeAdapter {
|
| private ChromiumBaseInputConnection.Factory mInputConnectionFactory;
|
|
|
| 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 int mTextInputType = TextInputType.NONE;
|
| private int mTextInputFlags;
|
| @@ -103,6 +110,9 @@ public class ImeAdapter {
|
|
|
| private int mLastSelectionStart;
|
| private int mLastSelectionEnd;
|
| + private String mLastText;
|
| + private int mLastCompositionStart;
|
| + private int mLastCompositionEnd;
|
|
|
| /**
|
| * @param wrapper InputMethodManagerWrapper that should receive all the call directed to
|
| @@ -116,6 +126,34 @@ public class ImeAdapter {
|
| // Deep copy newConfig so that we can notice the difference.
|
| 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,
|
| + new CursorAnchorInfoController.ComposingTextDelegate() {
|
| + @Override
|
| + public CharSequence getText() {
|
| + return mLastText;
|
| + }
|
| + @Override
|
| + public int getSelectionStart() {
|
| + return mLastSelectionStart;
|
| + }
|
| + @Override
|
| + public int getSelectionEnd() {
|
| + return mLastSelectionEnd;
|
| + }
|
| + @Override
|
| + public int getComposingTextStart() {
|
| + return mLastCompositionStart;
|
| + }
|
| + @Override
|
| + public int getComposingTextEnd() {
|
| + return mLastCompositionEnd;
|
| + }
|
| + });
|
| + } else {
|
| + mCursorAnchorInfoController = null;
|
| + }
|
| }
|
|
|
| private boolean isImeThreadEnabled() {
|
| @@ -155,6 +193,9 @@ public class ImeAdapter {
|
| mViewEmbedder.getAttachedView(), this, mTextInputType, mTextInputFlags,
|
| mLastSelectionStart, mLastSelectionEnd, outAttrs);
|
| if (DEBUG_LOGS) Log.w(TAG, "onCreateInputConnection: " + mInputConnection);
|
| + if (mCursorAnchorInfoController != null) {
|
| + mCursorAnchorInfoController.resetMonitoringState();
|
| + }
|
| return mInputConnection;
|
| }
|
|
|
| @@ -166,6 +207,9 @@ public class ImeAdapter {
|
| @VisibleForTesting
|
| public void setInputMethodManagerWrapperForTest(InputMethodManagerWrapper immw) {
|
| mInputMethodManagerWrapper = immw;
|
| + if (mCursorAnchorInfoController != null) {
|
| + mCursorAnchorInfoController.setInputMethodManagerWrapperForTest(immw);
|
| + }
|
| }
|
|
|
| @VisibleForTesting
|
| @@ -251,8 +295,18 @@ public class ImeAdapter {
|
| */
|
| public void updateState(String text, int selectionStart, int selectionEnd, int compositionStart,
|
| int compositionEnd, boolean isNonImeChange) {
|
| + 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 (mInputConnection == null) return;
|
| boolean singleLine = mTextInputType != TextInputType.TEXT_AREA
|
| && mTextInputType != TextInputType.CONTENT_EDITABLE;
|
| @@ -549,6 +603,12 @@ public class ImeAdapter {
|
| @CalledByNative
|
| private void focusedNodeChanged(boolean isEditable) {
|
| if (DEBUG_LOGS) Log.w(TAG, "focusedNodeChanged: isEditable [%b]", isEditable);
|
| +
|
| + // Update controller before the connection is restarted.
|
| + if (mCursorAnchorInfoController != null) {
|
| + mCursorAnchorInfoController.focusedNodeChanged(isEditable);
|
| + }
|
| +
|
| if (mTextInputType != TextInputType.NONE && mInputConnection != null && isEditable) {
|
| restartInput();
|
| }
|
| @@ -564,6 +624,36 @@ public class ImeAdapter {
|
| return nativeRequestTextInputStateUpdate(mNativeImeAdapterAndroid);
|
| }
|
|
|
| + /**
|
| + * Notified when IME requested Chrome to change the cursor update mode.
|
| + */
|
| + public boolean onRequestCursorUpdates(int cursorUpdateMode) {
|
| + if (mCursorAnchorInfoController == null) return false;
|
| + return mCursorAnchorInfoController.onRequestCursorUpdates(cursorUpdateMode,
|
| + mViewEmbedder.getAttachedView());
|
| + }
|
| +
|
| + /**
|
| + * Notified when a frame has been produced by the renderer and all the associated metadata.
|
| + * @param renderCoordinates coordinate information to convert CSS (document) coordinates to
|
| + * View-local Physical (screen) coordinates
|
| + * @param hasInsertionMarker Whether the insertion marker is visible or not.
|
| + * @param insertionMarkerHorizontal X coordinates (in view-local DIP pixels) of the insertion
|
| + * marker if it exists. Will be ignored otherwise.
|
| + * @param insertionMarkerTop Y coordinates (in view-local DIP pixels) of the top of the
|
| + * insertion marker if it exists. Will be ignored otherwise.
|
| + * @param insertionMarkerBottom Y coordinates (in view-local DIP pixels) of the bottom of
|
| + * the insertion marker if it exists. Will be ignored otherwise.
|
| + */
|
| + public void onUpdateFrameInfo(RenderCoordinates renderCoordinates, boolean hasInsertionMarker,
|
| + boolean isInsertionMarkerVisible, float insertionMarkerHorizontal,
|
| + float insertionMarkerTop, float insertionMarkerBottom) {
|
| + if (mCursorAnchorInfoController == null) return;
|
| + mCursorAnchorInfoController.onUpdateFrameInfo(renderCoordinates, hasInsertionMarker,
|
| + isInsertionMarkerVisible, insertionMarkerHorizontal, insertionMarkerTop,
|
| + insertionMarkerBottom, mViewEmbedder.getAttachedView());
|
| + }
|
| +
|
| @CalledByNative
|
| private void populateUnderlinesFromSpans(CharSequence text, long underlines) {
|
| if (DEBUG_LOGS) {
|
| @@ -593,9 +683,18 @@ public class ImeAdapter {
|
| }
|
|
|
| @CalledByNative
|
| + private void setCharacterBounds(float[] characterBounds) {
|
| + if (mCursorAnchorInfoController == null) return;
|
| + mCursorAnchorInfoController.setCompositionCharacterBounds(characterBounds);
|
| + }
|
| +
|
| + @CalledByNative
|
| private void detach() {
|
| if (DEBUG_LOGS) Log.w(TAG, "detach");
|
| mNativeImeAdapterAndroid = 0;
|
| + if (mCursorAnchorInfoController != null) {
|
| + mCursorAnchorInfoController.focusedNodeChanged(false);
|
| + }
|
| }
|
|
|
| private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndroid,
|
|
|