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 bc92bd0cb0716549647c03cc525fbf757c653e38..662af7df52fd6a49aea01d6fae7a4b5c13a64668 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 |
| @@ -324,44 +324,55 @@ public class ImeAdapter { |
| } |
| /** |
| - * @return Android keycode for a single unicode character. |
| + * @return Android KeyEvent for a single unicode character. Only one KeyEvent is returned |
| + * even if the system determined that various modifier keys (like Shift) would also have |
| + * been pressed. |
| */ |
| - private static int androidKeyCodeForCharacter(char chr) { |
| + private static KeyEvent androidKeyEventForCharacter(char chr) { |
| if (sKeyCharacterMap == null) { |
| sKeyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); |
| } |
| sSingleCharArray[0] = chr; |
| // TODO: Evaluate cost of this system call. |
| KeyEvent[] events = sKeyCharacterMap.getEvents(sSingleCharArray); |
| - if (events == null || events.length != 2) // One key-down event and one key-up event. |
| - return KeyEvent.KEYCODE_UNKNOWN; |
| - return events[0].getKeyCode(); |
| + if (events == null) { // No known key sequence will create that character. |
| + return null; |
| + } |
| + |
| + for (int i = 0; i < events.length; ++i) { |
| + if (events[i].getAction() == KeyEvent.ACTION_DOWN && |
| + !KeyEvent.isModifierKey(events[i].getKeyCode())) { |
| + return events[i]; |
| + } |
| + } |
| + |
| + return null; // No printing characters were found. |
| } |
| @VisibleForTesting |
| - public static int getTypedKeycodeGuess(String oldtext, String newtext) { |
| + public static KeyEvent getTypedKeyEventGuess(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)); |
| + return androidKeyEventForCharacter(newtext.charAt(0)); |
| } else { |
| - return 0; |
| + return null; |
| } |
| } |
| // 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)); |
| + return androidKeyEventForCharacter(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; |
| + return new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL); |
|
jdduke (slow)
2014/08/07 13:56:36
A shame to create garbage here, not sure if it's w
bcwhite
2014/08/07 15:16:40
Given how slow typing is to a machine, I don't thi
|
| // 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; |
| + return null; |
| } |
| void sendKeyEventWithKeyCode(int keyCode, int flags) { |
| @@ -395,9 +406,26 @@ public class ImeAdapter { |
| sendKeyEventWithKeyCode(keyCode, |
| KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE); |
| } else { |
| - keyCode = getTypedKeycodeGuess(mLastComposeText, textStr); |
| - mLastComposeText = textStr; |
| - mLastSyntheticKeyCode = keyCode; |
| + KeyEvent keyEvent = getTypedKeyEventGuess(mLastComposeText, textStr); |
| + int modifiers = 0; |
| + if (keyEvent != null) { |
| + keyCode = keyEvent.getKeyCode(); |
| + modifiers = getModifiers(keyEvent.getMetaState()); |
| + } else if (!textStr.equals(mLastComposeText)) { |
| + keyCode = KeyEvent.KEYCODE_UNKNOWN; |
| + } else { |
| + keyCode = -1; |
| + } |
| + |
| + // If this is a commit with no previous composition, then treat it as a native |
| + // KeyDown/KeyUp pair with no composition rather than a synthetic pair with |
| + // composition below. |
| + if (keyCode > 0 && isCommit && mLastComposeText == null) { |
| + mLastSyntheticKeyCode = keyCode; |
| + return translateAndSendNativeEvents(keyEvent) && |
| + translateAndSendNativeEvents(KeyEvent.changeAction( |
| + keyEvent, KeyEvent.ACTION_UP)); |
| + } |
| // When typing, there is no issue sending KeyDown and KeyUp events around the |
| // composition event because those key events do nothing (other than call JS |
| @@ -417,20 +445,27 @@ public class ImeAdapter { |
| // For now, the solution is to endure the restarting of composition and only dive |
| // into the alternate solution should there be problems in the field. --bcwhite |
| - nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeRawKeyDown, |
| - timeStampMs, keyCode, 0); |
| + if (keyCode >= 0) { |
| + nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeRawKeyDown, |
| + timeStampMs, keyCode, modifiers, 0); |
| + } |
| if (isCommit) { |
| nativeCommitText(mNativeImeAdapterAndroid, textStr); |
| - mLastComposeText = null; |
| + textStr = null; |
| } else { |
| nativeSetComposingText(mNativeImeAdapterAndroid, text, textStr, newCursorPosition); |
| } |
| - nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeKeyUp, |
| - timeStampMs, keyCode, 0); |
| + if (keyCode >= 0) { |
| + nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeKeyUp, |
| + timeStampMs, keyCode, modifiers, 0); |
| + } |
| + |
| + mLastSyntheticKeyCode = keyCode; |
| } |
| + mLastComposeText = textStr; |
| return true; |
| } |
| @@ -463,11 +498,12 @@ public class ImeAdapter { |
| /*isSystemKey=*/false, event.getUnicodeChar()); |
| } |
| - boolean sendSyntheticKeyEvent(int eventType, long timestampMs, int keyCode, int unicodeChar) { |
| + boolean sendSyntheticKeyEvent(int eventType, long timestampMs, int keyCode, int modifiers, |
| + int unicodeChar) { |
| if (mNativeImeAdapterAndroid == 0) return false; |
| nativeSendSyntheticKeyEvent( |
| - mNativeImeAdapterAndroid, eventType, timestampMs, keyCode, unicodeChar); |
| + mNativeImeAdapterAndroid, eventType, timestampMs, keyCode, modifiers, unicodeChar); |
| return true; |
| } |
| @@ -632,7 +668,7 @@ public class ImeAdapter { |
| } |
| private native boolean nativeSendSyntheticKeyEvent(long nativeImeAdapterAndroid, |
| - int eventType, long timestampMs, int keyCode, int unicodeChar); |
| + int eventType, long timestampMs, int keyCode, int modifiers, int unicodeChar); |
| private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyEvent event, |
| int action, int modifiers, long timestampMs, int keyCode, boolean isSystemKey, |