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 d85273be9f59e92ddf388eeab157d6da9d7be89a..2590d563fc07e94821624d9677d3c2284357a83a 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 |
| @@ -116,6 +116,7 @@ public class ImeAdapter { |
| static int sModifierCtrl; |
| static int sModifierCapsLockOn; |
| static int sModifierNumLockOn; |
| + static KeyCharacterMap sKeyCharacterMap; |
| private long mNativeImeAdapterAndroid; |
| private InputMethodManagerWrapper mInputMethodManagerWrapper; |
| @@ -124,6 +125,10 @@ public class ImeAdapter { |
| private final Handler mHandler; |
| private DelayedDismissInput mDismissInput = null; |
| private int mTextInputType; |
| + private String mLastComposeText; |
| + |
| + @VisibleForTesting |
| + int mLastComposeKeyCode; |
| @VisibleForTesting |
| boolean mIsShowWithoutHideOutstanding = false; |
| @@ -317,6 +322,42 @@ public class ImeAdapter { |
| else return COMPOSITION_KEY_CODE; |
| } |
| + private static int androidKeyCodeForCharacter(char chr) { |
| + if (sKeyCharacterMap == null) { |
| + sKeyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); |
| + } |
| + char[] chars = new char[1]; |
|
jdduke (slow)
2014/07/08 19:26:23
This will create garbage every time we fetch the k
|
| + chars[0] = chr; |
| + KeyEvent[] events = sKeyCharacterMap.getEvents(chars); |
| + return events[0].getKeyCode(); |
| + } |
| + |
| + @VisibleForTesting |
| + public static int getTypedKeycodeGuess(String oldtext, String newtext) { |
| + // Starting typing a new composition should add only a single character. Any composition |
| + // beginning with text longer than that must come from something other than typing so |
| + // return 0. |
| + if (oldtext == null) { |
| + if (newtext.length() == 1) { |
| + return androidKeyCodeForCharacter(newtext.charAt(0)); |
| + } else { |
| + return 0; |
| + } |
| + } |
| + |
| + // The content has grown in length: assume the last character is the key that caused it. |
| + if (newtext.length() > oldtext.length() && newtext.startsWith(oldtext)) |
| + return androidKeyCodeForCharacter(newtext.charAt(newtext.length() - 1)); |
| + |
| + // The content has shrunk in length: assume that backspace was pressed. |
| + if (oldtext.length() > newtext.length() && oldtext.startsWith(newtext)) |
| + return KeyEvent.KEYCODE_DEL; |
| + |
| + // The content is unchanged or has undergone a complex change (i.e. not a simple tail |
| + // modification) so return an unknown key-code. |
| + return 0; |
| + } |
| + |
| void sendKeyEventWithKeyCode(int keyCode, int flags) { |
| long eventTime = SystemClock.uptimeMillis(); |
| translateAndSendNativeEvents(new KeyEvent(eventTime, eventTime, |
| @@ -346,15 +387,22 @@ public class ImeAdapter { |
| sendKeyEventWithKeyCode(keyCode, |
| KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE); |
| } else { |
| - nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeRawKeyDown, |
| - timeStampMs, keyCode, 0); |
| + keyCode = getTypedKeycodeGuess(mLastComposeText, textStr); |
| + mLastComposeText = textStr; |
| + mLastComposeKeyCode = keyCode; |
| + |
| + if (keyCode != 0) |
| + nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeRawKeyDown, |
| + timeStampMs, keyCode, 0); |
| if (isCommit) { |
| nativeCommitText(mNativeImeAdapterAndroid, textStr); |
| + mLastComposeText = null; |
| } else { |
| nativeSetComposingText(mNativeImeAdapterAndroid, text, textStr, newCursorPosition); |
| } |
| - nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeKeyUp, |
| - timeStampMs, keyCode, 0); |
| + if (keyCode != 0) |
| + nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeKeyUp, |
| + timeStampMs, keyCode, 0); |
| } |
| return true; |
| @@ -362,6 +410,7 @@ public class ImeAdapter { |
| void finishComposingText() { |
| if (mNativeImeAdapterAndroid == 0) return; |
| + mLastComposeText = null; |
| nativeFinishComposingText(mNativeImeAdapterAndroid); |
| } |
| @@ -553,6 +602,7 @@ public class ImeAdapter { |
| @CalledByNative |
| private void cancelComposition() { |
| if (mInputConnection != null) mInputConnection.restartInput(); |
| + mLastComposeText = null; |
| } |
| @CalledByNative |