| 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 e075d8e4d400dbef2f502c3f262b3455eed249a6..4d8c29efedf345c6bcb566e4e03bac29a54ba49a 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,6 +4,8 @@
|
|
|
| package org.chromium.content.browser.input;
|
|
|
| +import android.graphics.Matrix;
|
| +import android.os.Build;
|
| import android.os.Handler;
|
| import android.os.ResultReceiver;
|
| import android.os.SystemClock;
|
| @@ -15,7 +17,10 @@ import android.text.style.UnderlineSpan;
|
| import android.view.KeyCharacterMap;
|
| import android.view.KeyEvent;
|
| import android.view.View;
|
| +import android.view.inputmethod.CursorAnchorInfo;
|
| import android.view.inputmethod.EditorInfo;
|
| +import android.view.inputmethod.InputConnection;
|
| +import android.view.inputmethod.InputMethodManager;
|
|
|
| import org.chromium.base.CalledByNative;
|
| import org.chromium.base.JNINamespace;
|
| @@ -143,6 +148,53 @@ public class ImeAdapter {
|
| private int mTextInputFlags;
|
| private String mLastComposeText;
|
|
|
| + private static class CursorAnchorInfoSource {
|
| + private String mText;
|
| + private int mSelectionStart;
|
| + private int mSelectionEnd;
|
| + private int mCompositionStart;
|
| + private int mCompositionEnd;
|
| + private float[] mLastCharacterBounds;
|
| + }
|
| + private CursorAnchorInfoSource mCursorAnchorInfoSource = new CursorAnchorInfoSource();
|
| +
|
| + private static class CursorAnchorInfoBuilderWrapper {
|
| +
|
| + public static boolean isSupported() {
|
| + return false;
|
| + }
|
| +
|
| + public static CursorAnchorInfoBuilderWrapper create() {
|
| + return new CursorAnchorInfoBuilderWrapper();
|
| + }
|
| +
|
| + protected CursorAnchorInfoBuilderWrapper() {
|
| + }
|
| +
|
| + public void update(CursorAnchorInfoSource source, Matrix matrix, boolean hasInertionMarker,
|
| + float insertionMarkerX, float insertionMarkerTop, float insertionMarkerBottom) {
|
| + // This is a stub for platforms that do not support CursorAnchorInfo.
|
| + }
|
| +
|
| + public boolean hasData() {
|
| + // This is a stub for platforms that do not support CursorAnchorInfo.
|
| + return false;
|
| + }
|
| +
|
| + public void reset() {
|
| + // This is a stub for platforms that do not support CursorAnchorInfo.
|
| + }
|
| +
|
| + public void send(InputMethodManagerWrapper inputMethodManagerWrapper, View view) {
|
| + // This is a stub for platforms that do not support CursorAnchorInfo.
|
| + }
|
| + }
|
| +
|
| + private CursorAnchorInfoBuilderWrapper mCursorAnchorInfoBuilder =
|
| + CursorAnchorInfoBuilderWrapper.create();
|
| + private boolean mCursorAnchorInfoMonitorEnabled = false;
|
| + private boolean mOneshotUpdateCursorAnchorInfoEnabled = false;
|
| +
|
| @VisibleForTesting
|
| int mLastSyntheticKeyCode;
|
|
|
| @@ -621,6 +673,82 @@ public class ImeAdapter {
|
| return true;
|
| }
|
|
|
| + /**
|
| + * @return Whether the {@link CursorAnchorInfo} is available or not on this device.
|
| + */
|
| + public boolean isCursorAnchorInfoSupported() {
|
| + return CursorAnchorInfoBuilderWrapper.isSupported();
|
| + }
|
| +
|
| + /**
|
| + * Start or stop calling
|
| + * {@link InputMethodManager#updateCursorAnchorInfo(View, CursorAnchorInfo)}.
|
| + * @param enabled {@code true} if {@link InputConnection#requestCursorUpdates(int)} is called
|
| + * with {@link InputConnection#CURSOR_UPDATE_MONITOR} bit.
|
| + */
|
| + public void setCursorAnchorInfoMonitorEnabled(boolean enabled) {
|
| + mCursorAnchorInfoMonitorEnabled = enabled;
|
| + }
|
| +
|
| + /**
|
| + * Make sure {@link InputMethodManager#updateCursorAnchorInfo(View, CursorAnchorInfo)} is called
|
| + * at least once immediately when the latest position becomes available.
|
| + * @param view The view to be passed to
|
| + * {@link InputMethodManager#updateCursorAnchorInfo(View, CursorAnchorInfo)} if the latest
|
| + * position is already available. Otherwise ignored.
|
| + */
|
| + public void scheduleOneshotUpdateCursorAnchorInfo(View view) {
|
| + if (!mCursorAnchorInfoBuilder.hasData()) {
|
| + // If there is no data, send the data later when it becomes available.
|
| + mOneshotUpdateCursorAnchorInfoEnabled = true;
|
| + return;
|
| + }
|
| + mCursorAnchorInfoBuilder.send(mInputMethodManagerWrapper, view);
|
| + mOneshotUpdateCursorAnchorInfoEnabled = false;
|
| + }
|
| +
|
| + /**
|
| + * Update the parameters that are to be passed to the IME through
|
| + * {@link InputMethodManager#updateCursorAnchorInfo(View, CursorAnchorInfo)}.
|
| + * @param text The text in the focused text field.
|
| + * @param selectionStart Index where the text selection starts. {@code -1} if there is no
|
| + * selection.
|
| + * @param selectionEnd Index where the text selection ends. {@code -1} if there is no
|
| + * selection.
|
| + * @param compositionStart Index where the text composition starts. {@code -1} if there is no
|
| + * selection.
|
| + * @param compositionEnd Index where the text composition ends. {@code -1} if there is no
|
| + * selection.
|
| + */
|
| + public void updateCursorAnchorInfoSource(String text, int selectionStart, int selectionEnd,
|
| + int compositionStart, int compositionEnd) {
|
| + mCursorAnchorInfoSource.mText = text;
|
| + mCursorAnchorInfoSource.mSelectionStart = selectionStart;
|
| + mCursorAnchorInfoSource.mSelectionEnd = selectionEnd;
|
| + mCursorAnchorInfoSource.mCompositionStart = compositionStart;
|
| + mCursorAnchorInfoSource.mCompositionEnd = compositionEnd;
|
| + }
|
| +
|
| + /**
|
| + * Call {@link InputMethodManager#updateCursorAnchorInfo(View, CursorAnchorInfo)} if it is
|
| + * available and the active IME is actually requested it.
|
| + * @param view The view to be passed to
|
| + * {@link InputMethodManager#updateCursorAnchorInfo(View, CursorAnchorInfo)}
|
| + * @param matrix The matrix from CSS coordinates to the absolute display coordinates.
|
| + * @param hasInsertionMaerker Whether the insertion marker exists or not.
|
| + * @param insertionMarkerX The X position of the insertion marker, in CSS coordinates.
|
| + * @param insertionMarkerTop The top position of the insertion marker, in CSS coordinates.
|
| + * @param insertionMarkerBottom The bottom position of the insertion marker, in CSS coordinates.
|
| + */
|
| + public void updateCursorAnchorInfo(View view, Matrix matrix, boolean hasInsertionMaerker,
|
| + float insertionMarkerX, float insertionMarkerTop, float insertionMarkerBottom) {
|
| + mCursorAnchorInfoBuilder.update(mCursorAnchorInfoSource, matrix, hasInsertionMaerker,
|
| + insertionMarkerX, insertionMarkerTop, insertionMarkerBottom);
|
| + if (!mCursorAnchorInfoMonitorEnabled && !mOneshotUpdateCursorAnchorInfoEnabled) return;
|
| + mCursorAnchorInfoBuilder.send(mInputMethodManagerWrapper, view);
|
| + mOneshotUpdateCursorAnchorInfoEnabled = false;
|
| + }
|
| +
|
| // Calls from C++ to Java
|
|
|
| @CalledByNative
|
| @@ -699,7 +827,7 @@ public class ImeAdapter {
|
|
|
| @CalledByNative
|
| private void setCharacterBounds(float[] characterBounds) {
|
| - // TODO(yukawa): Implement this.
|
| + mCursorAnchorInfoSource.mLastCharacterBounds = characterBounds;
|
| }
|
|
|
| @CalledByNative
|
| @@ -710,6 +838,7 @@ public class ImeAdapter {
|
| }
|
| mNativeImeAdapterAndroid = 0;
|
| mTextInputType = 0;
|
| + mCursorAnchorInfoBuilder.reset();
|
| }
|
|
|
| private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndroid,
|
|
|