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 d3f14cf6423be7e60d96f9548fce08b54ecd930e..31abce5a2f75f43cd27b7543d239e5052a437ee2 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 |
@@ -16,7 +16,9 @@ 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.InputMethodManager; |
import org.chromium.base.CalledByNative; |
import org.chromium.base.JNINamespace; |
@@ -24,6 +26,7 @@ import org.chromium.base.VisibleForTesting; |
import org.chromium.blink_public.web.WebInputEventModifier; |
import org.chromium.blink_public.web.WebInputEventType; |
import org.chromium.blink_public.web.WebTextInputFlags; |
+import org.chromium.content.browser.RenderCoordinates; |
import org.chromium.ui.base.ime.TextInputType; |
import org.chromium.ui.picker.InputDialogContainer; |
@@ -126,6 +129,8 @@ public class ImeAdapter { |
private int mTextInputFlags; |
private String mLastComposeText; |
+ private final CursorAnchorInfoController mCursorAnchorInfoController; |
+ |
@VisibleForTesting |
int mLastSyntheticKeyCode; |
@@ -141,6 +146,7 @@ public class ImeAdapter { |
mInputMethodManagerWrapper = wrapper; |
mViewEmbedder = embedder; |
mHandler = new Handler(); |
+ mCursorAnchorInfoController = CursorAnchorInfoController.create(wrapper); |
} |
/** |
@@ -161,6 +167,9 @@ public class ImeAdapter { |
@VisibleForTesting |
public void setInputMethodManagerWrapper(InputMethodManagerWrapper immw) { |
mInputMethodManagerWrapper = immw; |
+ if (mCursorAnchorInfoController != null) { |
+ mCursorAnchorInfoController.setInputMethodManagerWrapper(immw); |
+ } |
} |
/** |
@@ -280,8 +289,8 @@ public class ImeAdapter { |
private void showKeyboard() { |
mIsShowWithoutHideOutstanding = true; |
- mInputMethodManagerWrapper.showSoftInput( |
- mViewEmbedder.getAttachedView(), 0, mViewEmbedder.getNewShowKeyboardReceiver()); |
+ mInputMethodManagerWrapper.showSoftInput(mViewEmbedder.getAttachedView(), 0, |
+ mViewEmbedder.getNewShowKeyboardReceiver()); |
if (mViewEmbedder.getAttachedView().getResources().getConfiguration().keyboard |
!= Configuration.KEYBOARD_NOKEYS) { |
mViewEmbedder.onKeyboardBoundsUnchanged(); |
@@ -615,10 +624,67 @@ public class ImeAdapter { |
return true; |
} |
+ 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) { |
jdduke (slow)
2015/02/09 17:01:17
Nit: Early return on same line as if, without brac
yukawa
2015/02/10 17:24:54
Done.
|
+ 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 of the insertion marker if it exists. |
+ * Will be ignored otherwise. |
+ * @param insertionMarkerTop Y coordinates of the top of the insertion marker if it exists. |
+ * Will be ignored otherwise. |
+ * @param insertionMarkerBottom Y coordinates 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()); |
+ } |
+ |
// Calls from C++ to Java |
@CalledByNative |
private void focusedNodeChanged(boolean isEditable) { |
+ // Update controller before the connection is restarted. |
+ if (mCursorAnchorInfoController != null) { |
+ mCursorAnchorInfoController.focusedNodeChanged(isEditable); |
+ } |
if (mInputConnection != null && isEditable) mInputConnection.restartInput(); |
} |
@@ -648,6 +714,13 @@ public class ImeAdapter { |
} |
@CalledByNative |
+ private void setCharacterBounds(float[] characterBounds) { |
jdduke (slow)
2015/02/09 17:01:17
Aren't the coordinates from the renderer in DIPs?
yukawa
2015/02/10 17:24:54
Yes I think it's DIP at least for Android and Wind
|
+ if (mCursorAnchorInfoController != null) { |
+ mCursorAnchorInfoController.setCompositionCharacterBounds(characterBounds); |
+ } |
+ } |
+ |
+ @CalledByNative |
void detach() { |
if (mDismissInput != null) { |
mHandler.removeCallbacks(mDismissInput); |
@@ -655,6 +728,9 @@ public class ImeAdapter { |
} |
mNativeImeAdapterAndroid = 0; |
mTextInputType = 0; |
+ if (mCursorAnchorInfoController != null) { |
+ mCursorAnchorInfoController.focusedNodeChanged(false); |
jdduke (slow)
2015/02/09 17:01:17
Might as well null it out here as well I guess.
yukawa
2015/02/10 17:24:54
I think #attach can be called again after #detach,
|
+ } |
} |
private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndroid, |