Chromium Code Reviews| 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 3c8710a591b2db85dcf5336ca3b30f625940b09c..f3da0d069340805418bf43537b7490a9fc5798aa 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; |
| @@ -25,6 +26,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.content.common.ContentSwitches; |
| import org.chromium.ui.base.ime.TextInputType; |
| import org.chromium.ui.picker.InputDialogContainer; |
| @@ -96,6 +98,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; |
| @@ -105,6 +112,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 |
| @@ -118,6 +128,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; |
| + } |
| } |
| void resetInputConnectionFactory() { |
| @@ -162,6 +200,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; |
| } |
| @@ -173,6 +214,9 @@ public class ImeAdapter { |
| @VisibleForTesting |
| public void setInputMethodManagerWrapperForTest(InputMethodManagerWrapper immw) { |
| mInputMethodManagerWrapper = immw; |
| + if (mCursorAnchorInfoController != null) { |
| + mCursorAnchorInfoController.setInputMethodManagerWrapper(immw); |
|
Ted C
2016/03/07 21:31:45
Should this method also be called setInputMethodMa
kinaba
2016/03/10 06:24:12
Good point. It's only for testing. Done.
|
| + } |
| } |
| @VisibleForTesting |
| @@ -258,8 +302,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; |
| @@ -556,6 +610,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(); |
| } |
| @@ -571,6 +631,36 @@ public class ImeAdapter { |
| return nativeRequestTextInputStateUpdate(mNativeImeAdapterAndroid); |
| } |
| + /* |
|
Ted C
2016/03/07 21:31:45
add another *
kinaba
2016/03/10 06:24:12
Done.
|
| + * Forward the cursor update request to CursorAnchorInfoController. |
|
Ted C
2016/03/07 21:31:45
This comment describes the code not why you should
kinaba
2016/03/10 06:24:12
Done.
|
| + */ |
| + public boolean onRequestCursorUpdates(int cursorUpdateMode) { |
| + if (mCursorAnchorInfoController == null) return false; |
| + return mCursorAnchorInfoController.onRequestCursorUpdates(cursorUpdateMode, |
| + mViewEmbedder.getAttachedView()); |
| + } |
| + |
| + /** |
| + * Notify the location of composing characters to the IME if it explicitly requested them. |
|
Ted C
2016/03/07 21:31:45
Again this comment isn't really a good description
kinaba
2016/03/10 06:24:12
Done.
|
| + * @param renderCoordinates coordinate information to convert CSS (document) coordinates to |
| + * View-local Physical (screen) coordinates |
|
Ted C
2016/03/07 21:31:45
align with the start of the sentence above (coordi
kinaba
2016/03/10 06:24:12
Done.
|
| + * @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) { |
| @@ -600,9 +690,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, |