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 75bb44fae0d3d228394b0e9bef71477c02904a08..050e170031e297f6d6650e49f6c528ae2671507b 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 |
| @@ -18,7 +18,9 @@ import android.view.KeyCharacterMap; |
| import android.view.KeyEvent; |
| import android.view.View; |
| import android.view.inputmethod.BaseInputConnection; |
| +import android.view.inputmethod.CursorAnchorInfo; |
| import android.view.inputmethod.EditorInfo; |
| +import android.view.inputmethod.InputMethodManager; |
| import org.chromium.base.Log; |
| import org.chromium.base.VisibleForTesting; |
| @@ -26,6 +28,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; |
| @@ -101,6 +104,14 @@ public class ImeAdapter { |
| // Every time the user, IME, javascript (Blink), autofill etc. modifies the content, the new |
| // state must be reflected to this to keep consistency. |
| private final Editable mEditable; |
| + // 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; |
| + |
| + @VisibleForTesting |
| + int mLastSyntheticKeyCode; |
| private int mTextInputType = TextInputType.NONE; |
| private int mTextInputFlags; |
| @@ -122,6 +133,7 @@ public class ImeAdapter { |
| // Deep copy newConfig so that we can notice the difference. |
| mCurrentConfig = new Configuration( |
| mViewEmbedder.getAttachedView().getResources().getConfiguration()); |
| + mCursorAnchorInfoController = CursorAnchorInfoController.create(wrapper); |
| } |
| /** |
| @@ -162,6 +174,9 @@ public class ImeAdapter { |
| int initialSelEnd = outAttrs.initialSelEnd = Selection.getSelectionEnd(mEditable); |
| mInputConnection = mInputConnectionFactory.get( |
| mViewEmbedder.getAttachedView(), this, initialSelStart, initialSelEnd, outAttrs); |
| + if (mCursorAnchorInfoController != null) { |
| + mCursorAnchorInfoController.resetMonitoringState(); |
|
aelias_OOO_until_Jul13
2016/02/10 08:23:42
Anything else needs to be reset here? How about m
kinaba
2016/02/19 12:28:29
Done (mHasPendingImmediateRequest will also be res
|
| + } |
| if (DEBUG_LOGS) Log.w(TAG, "onCreateInputConnection"); |
| return mInputConnection; |
| } |
| @@ -174,6 +189,9 @@ public class ImeAdapter { |
| @VisibleForTesting |
| public void setInputMethodManagerWrapperForTest(InputMethodManagerWrapper immw) { |
| mInputMethodManagerWrapper = immw; |
| + if (mCursorAnchorInfoController != null) { |
| + mCursorAnchorInfoController.setInputMethodManagerWrapper(immw); |
| + } |
| } |
| @VisibleForTesting |
| @@ -562,11 +580,64 @@ 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(); |
| } |
| } |
| + public boolean onRequestCursorUpdates(int cursorUpdateMode) { |
| + if (mCursorAnchorInfoController == null) return false; |
| + return mCursorAnchorInfoController.onRequestCursorUpdates(cursorUpdateMode, |
| + mViewEmbedder.getAttachedView()); |
| + } |
| + |
| + /** |
| + * Update the parameters that are to be passed to the IME through |
| + * {@link InputMethodManager#updateCursorAnchorInfo(View, CursorAnchorInfo)}. |
| + * @param text 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 updateTextAndSelection(String text, int selectionStart, int selectionEnd, |
| + int compositionStart, int compositionEnd) { |
| + if (mCursorAnchorInfoController == null) return; |
| + mCursorAnchorInfoController.updateTextAndSelection(text, compositionStart, compositionEnd, |
| + selectionStart, selectionEnd); |
| + } |
| + |
| + /** |
| + * Notify the location of composing characters to the IME if it explicitly requested them. |
| + * @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) { |
| @@ -596,9 +667,19 @@ 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; |
| + mTextInputType = 0; |
| + if (mCursorAnchorInfoController != null) { |
| + mCursorAnchorInfoController.focusedNodeChanged(false); |
| + } |
| } |
| private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndroid, |