This source file includes following definitions.
- JNINamespace
- onImeEvent
- onSetFieldValue
- onDismissInput
- getAttachedView
- getNewShowKeyboardReceiver
- run
- get
- setInputMethodManagerWrapper
- getInputMethodManagerWrapper
- setInputConnection
- getTextInputType
- getTextInputTypeNone
- getModifiers
- isActive
- isFor
- attachAndShowIfNeeded
- attach
- attach
- showKeyboard
- dismissInput
- hasInputType
- isTextInputType
- hasTextInputType
- dispatchKeyEvent
- shouldSendKeyEventWithKeyCode
- sendKeyEventWithKeyCode
- checkCompositionQueueAndCallNative
- finishComposingText
- translateAndSendNativeEvents
- sendSyntheticKeyEvent
- deleteSurroundingText
- setEditableSelectionOffsets
- setComposingRegion
- unselect
- selectAll
- cut
- copy
- paste
- initializeWebInputEvents
- initializeTextInputTypes
- focusedNodeChanged
- cancelComposition
- detach
- nativeSendSyntheticKeyEvent
- nativeSendKeyEvent
- nativeSetComposingText
- nativeCommitText
- nativeFinishComposingText
- nativeAttachImeAdapter
- nativeSetEditableSelectionOffsets
- nativeSetComposingRegion
- nativeDeleteSurroundingText
- nativeUnselect
- nativeSelectAll
- nativeCut
- nativeCopy
- nativePaste
- nativeResetImeAdapter
package org.chromium.content.browser.input;
import android.os.Handler;
import android.os.ResultReceiver;
import android.os.SystemClock;
import android.text.Editable;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import com.google.common.annotations.VisibleForTesting;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
@JNINamespace("content")
public class ImeAdapter {
public interface ImeAdapterDelegate {
void onImeEvent(boolean isFinish);
void onSetFieldValue();
void onDismissInput();
View getAttachedView();
ResultReceiver getNewShowKeyboardReceiver();
}
private class DelayedDismissInput implements Runnable {
private final long mNativeImeAdapter;
DelayedDismissInput(long nativeImeAdapter) {
mNativeImeAdapter = nativeImeAdapter;
}
@Override
public void run() {
attach(mNativeImeAdapter, sTextInputTypeNone);
dismissInput(true);
}
}
private static final int COMPOSITION_KEY_CODE = 229;
private static final int INPUT_DISMISS_DELAY = 150;
static int sEventTypeRawKeyDown;
static int sEventTypeKeyUp;
static int sEventTypeChar;
static int sTextInputTypeNone;
static int sTextInputTypeText;
static int sTextInputTypeTextArea;
static int sTextInputTypePassword;
static int sTextInputTypeSearch;
static int sTextInputTypeUrl;
static int sTextInputTypeEmail;
static int sTextInputTypeTel;
static int sTextInputTypeNumber;
static int sTextInputTypeContentEditable;
static int sModifierShift;
static int sModifierAlt;
static int sModifierCtrl;
static int sModifierCapsLockOn;
static int sModifierNumLockOn;
private long mNativeImeAdapterAndroid;
private InputMethodManagerWrapper mInputMethodManagerWrapper;
private AdapterInputConnection mInputConnection;
private final ImeAdapterDelegate mViewEmbedder;
private final Handler mHandler;
private DelayedDismissInput mDismissInput = null;
private int mTextInputType;
@VisibleForTesting
boolean mIsShowWithoutHideOutstanding = false;
public ImeAdapter(InputMethodManagerWrapper wrapper, ImeAdapterDelegate embedder) {
mInputMethodManagerWrapper = wrapper;
mViewEmbedder = embedder;
mHandler = new Handler();
}
public static class AdapterInputConnectionFactory {
public AdapterInputConnection get(View view, ImeAdapter imeAdapter,
Editable editable, EditorInfo outAttrs) {
return new AdapterInputConnection(view, imeAdapter, editable, outAttrs);
}
}
@VisibleForTesting
public void setInputMethodManagerWrapper(InputMethodManagerWrapper immw) {
mInputMethodManagerWrapper = immw;
}
InputMethodManagerWrapper getInputMethodManagerWrapper() {
return mInputMethodManagerWrapper;
}
void setInputConnection(AdapterInputConnection inputConnection) {
mInputConnection = inputConnection;
}
int getTextInputType() {
return mTextInputType;
}
public static int getTextInputTypeNone() {
return sTextInputTypeNone;
}
private static int getModifiers(int metaState) {
int modifiers = 0;
if ((metaState & KeyEvent.META_SHIFT_ON) != 0) {
modifiers |= sModifierShift;
}
if ((metaState & KeyEvent.META_ALT_ON) != 0) {
modifiers |= sModifierAlt;
}
if ((metaState & KeyEvent.META_CTRL_ON) != 0) {
modifiers |= sModifierCtrl;
}
if ((metaState & KeyEvent.META_CAPS_LOCK_ON) != 0) {
modifiers |= sModifierCapsLockOn;
}
if ((metaState & KeyEvent.META_NUM_LOCK_ON) != 0) {
modifiers |= sModifierNumLockOn;
}
return modifiers;
}
public boolean isActive() {
return mInputConnection != null && mInputConnection.isActive();
}
private boolean isFor(long nativeImeAdapter, int textInputType) {
return mNativeImeAdapterAndroid == nativeImeAdapter &&
mTextInputType == textInputType;
}
public void attachAndShowIfNeeded(long nativeImeAdapter, int textInputType,
boolean showIfNeeded) {
mHandler.removeCallbacks(mDismissInput);
if (mTextInputType == sTextInputTypeNone && !showIfNeeded) {
return;
}
if (!isFor(nativeImeAdapter, textInputType)) {
if (textInputType == sTextInputTypeNone) {
mDismissInput = new DelayedDismissInput(nativeImeAdapter);
mHandler.postDelayed(mDismissInput, INPUT_DISMISS_DELAY);
return;
}
attach(nativeImeAdapter, textInputType);
mInputMethodManagerWrapper.restartInput(mViewEmbedder.getAttachedView());
if (showIfNeeded) {
showKeyboard();
}
} else if (hasInputType() && showIfNeeded) {
showKeyboard();
}
}
public void attach(long nativeImeAdapter, int textInputType) {
if (mNativeImeAdapterAndroid != 0) {
nativeResetImeAdapter(mNativeImeAdapterAndroid);
}
mNativeImeAdapterAndroid = nativeImeAdapter;
mTextInputType = textInputType;
if (nativeImeAdapter != 0) {
nativeAttachImeAdapter(mNativeImeAdapterAndroid);
}
}
public void attach(long nativeImeAdapter) {
if (mNativeImeAdapterAndroid != 0) {
nativeResetImeAdapter(mNativeImeAdapterAndroid);
}
mNativeImeAdapterAndroid = nativeImeAdapter;
if (nativeImeAdapter != 0) {
nativeAttachImeAdapter(mNativeImeAdapterAndroid);
}
}
private void showKeyboard() {
mIsShowWithoutHideOutstanding = true;
mInputMethodManagerWrapper.showSoftInput(mViewEmbedder.getAttachedView(), 0,
mViewEmbedder.getNewShowKeyboardReceiver());
}
private void dismissInput(boolean unzoomIfNeeded) {
mIsShowWithoutHideOutstanding = false;
View view = mViewEmbedder.getAttachedView();
if (mInputMethodManagerWrapper.isActive(view)) {
mInputMethodManagerWrapper.hideSoftInputFromWindow(view.getWindowToken(), 0,
unzoomIfNeeded ? mViewEmbedder.getNewShowKeyboardReceiver() : null);
}
mViewEmbedder.onDismissInput();
}
private boolean hasInputType() {
return mTextInputType != sTextInputTypeNone;
}
private static boolean isTextInputType(int type) {
return type != sTextInputTypeNone && !InputDialogContainer.isDialogInputType(type);
}
public boolean hasTextInputType() {
return isTextInputType(mTextInputType);
}
public boolean dispatchKeyEvent(KeyEvent event) {
return translateAndSendNativeEvents(event);
}
private int shouldSendKeyEventWithKeyCode(String text) {
if (text.length() != 1) return COMPOSITION_KEY_CODE;
if (text.equals("\n")) return KeyEvent.KEYCODE_ENTER;
else if (text.equals("\t")) return KeyEvent.KEYCODE_TAB;
else return COMPOSITION_KEY_CODE;
}
void sendKeyEventWithKeyCode(int keyCode, int flags) {
long eventTime = SystemClock.uptimeMillis();
translateAndSendNativeEvents(new KeyEvent(eventTime, eventTime,
KeyEvent.ACTION_DOWN, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
flags));
translateAndSendNativeEvents(new KeyEvent(SystemClock.uptimeMillis(), eventTime,
KeyEvent.ACTION_UP, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
flags));
}
boolean checkCompositionQueueAndCallNative(String text, int newCursorPosition,
boolean isCommit) {
if (mNativeImeAdapterAndroid == 0) return false;
boolean isFinish = text.isEmpty();
mViewEmbedder.onImeEvent(isFinish);
int keyCode = shouldSendKeyEventWithKeyCode(text);
long timeStampMs = SystemClock.uptimeMillis();
if (keyCode != COMPOSITION_KEY_CODE) {
sendKeyEventWithKeyCode(keyCode,
KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE);
} else {
nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeRawKeyDown,
timeStampMs, keyCode, 0);
if (isCommit) {
nativeCommitText(mNativeImeAdapterAndroid, text);
} else {
nativeSetComposingText(mNativeImeAdapterAndroid, text, newCursorPosition);
}
nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeKeyUp,
timeStampMs, keyCode, 0);
}
return true;
}
void finishComposingText() {
if (mNativeImeAdapterAndroid == 0) return;
nativeFinishComposingText(mNativeImeAdapterAndroid);
}
boolean translateAndSendNativeEvents(KeyEvent event) {
if (mNativeImeAdapterAndroid == 0) return false;
int action = event.getAction();
if (action != KeyEvent.ACTION_DOWN &&
action != KeyEvent.ACTION_UP) {
return false;
}
mViewEmbedder.onImeEvent(false);
return nativeSendKeyEvent(mNativeImeAdapterAndroid, event, event.getAction(),
getModifiers(event.getMetaState()), event.getEventTime(), event.getKeyCode(),
event.isSystem(), event.getUnicodeChar());
}
boolean sendSyntheticKeyEvent(
int eventType, long timestampMs, int keyCode, int unicodeChar) {
if (mNativeImeAdapterAndroid == 0) return false;
nativeSendSyntheticKeyEvent(
mNativeImeAdapterAndroid, eventType, timestampMs, keyCode, unicodeChar);
return true;
}
boolean deleteSurroundingText(int beforeLength, int afterLength) {
if (mNativeImeAdapterAndroid == 0) return false;
nativeDeleteSurroundingText(mNativeImeAdapterAndroid, beforeLength, afterLength);
return true;
}
boolean setEditableSelectionOffsets(int start, int end) {
if (mNativeImeAdapterAndroid == 0) return false;
nativeSetEditableSelectionOffsets(mNativeImeAdapterAndroid, start, end);
return true;
}
boolean setComposingRegion(int start, int end) {
if (mNativeImeAdapterAndroid == 0) return false;
nativeSetComposingRegion(mNativeImeAdapterAndroid, start, end);
return true;
}
public boolean unselect() {
if (mNativeImeAdapterAndroid == 0) return false;
nativeUnselect(mNativeImeAdapterAndroid);
return true;
}
public boolean selectAll() {
if (mNativeImeAdapterAndroid == 0) return false;
nativeSelectAll(mNativeImeAdapterAndroid);
return true;
}
public boolean cut() {
if (mNativeImeAdapterAndroid == 0) return false;
nativeCut(mNativeImeAdapterAndroid);
return true;
}
public boolean copy() {
if (mNativeImeAdapterAndroid == 0) return false;
nativeCopy(mNativeImeAdapterAndroid);
return true;
}
public boolean paste() {
if (mNativeImeAdapterAndroid == 0) return false;
nativePaste(mNativeImeAdapterAndroid);
return true;
}
@CalledByNative
private static void initializeWebInputEvents(int eventTypeRawKeyDown, int eventTypeKeyUp,
int eventTypeChar, int modifierShift, int modifierAlt, int modifierCtrl,
int modifierCapsLockOn, int modifierNumLockOn) {
sEventTypeRawKeyDown = eventTypeRawKeyDown;
sEventTypeKeyUp = eventTypeKeyUp;
sEventTypeChar = eventTypeChar;
sModifierShift = modifierShift;
sModifierAlt = modifierAlt;
sModifierCtrl = modifierCtrl;
sModifierCapsLockOn = modifierCapsLockOn;
sModifierNumLockOn = modifierNumLockOn;
}
@CalledByNative
private static void initializeTextInputTypes(int textInputTypeNone, int textInputTypeText,
int textInputTypeTextArea, int textInputTypePassword, int textInputTypeSearch,
int textInputTypeUrl, int textInputTypeEmail, int textInputTypeTel,
int textInputTypeNumber, int textInputTypeContentEditable) {
sTextInputTypeNone = textInputTypeNone;
sTextInputTypeText = textInputTypeText;
sTextInputTypeTextArea = textInputTypeTextArea;
sTextInputTypePassword = textInputTypePassword;
sTextInputTypeSearch = textInputTypeSearch;
sTextInputTypeUrl = textInputTypeUrl;
sTextInputTypeEmail = textInputTypeEmail;
sTextInputTypeTel = textInputTypeTel;
sTextInputTypeNumber = textInputTypeNumber;
sTextInputTypeContentEditable = textInputTypeContentEditable;
}
@CalledByNative
private void focusedNodeChanged(boolean isEditable) {
if (mInputConnection != null && isEditable) mInputConnection.restartInput();
}
@CalledByNative
private void cancelComposition() {
if (mInputConnection != null) mInputConnection.restartInput();
}
@CalledByNative
void detach() {
if (mDismissInput != null) mHandler.removeCallbacks(mDismissInput);
mNativeImeAdapterAndroid = 0;
mTextInputType = 0;
}
private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndroid,
int eventType, long timestampMs, int keyCode, int unicodeChar);
private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyEvent event,
int action, int modifiers, long timestampMs, int keyCode, boolean isSystemKey,
int unicodeChar);
private native void nativeSetComposingText(long nativeImeAdapterAndroid, String text,
int newCursorPosition);
private native void nativeCommitText(long nativeImeAdapterAndroid, String text);
private native void nativeFinishComposingText(long nativeImeAdapterAndroid);
private native void nativeAttachImeAdapter(long nativeImeAdapterAndroid);
private native void nativeSetEditableSelectionOffsets(long nativeImeAdapterAndroid,
int start, int end);
private native void nativeSetComposingRegion(long nativeImeAdapterAndroid, int start, int end);
private native void nativeDeleteSurroundingText(long nativeImeAdapterAndroid,
int before, int after);
private native void nativeUnselect(long nativeImeAdapterAndroid);
private native void nativeSelectAll(long nativeImeAdapterAndroid);
private native void nativeCut(long nativeImeAdapterAndroid);
private native void nativeCopy(long nativeImeAdapterAndroid);
private native void nativePaste(long nativeImeAdapterAndroid);
private native void nativeResetImeAdapter(long nativeImeAdapterAndroid);
}