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, |