Bug 687717 - Send key events rather than committing single-character composition strings. r=blassey r=masayuki a=blocking-fennec

--HG--
extra : rebase_source : 7ddc8b05e7a93917b9a20a665f5c958370d91bb0
This commit is contained in:
Chris Peterson 2012-04-18 14:57:55 -07:00
Родитель 79273b6638
Коммит 254b7db74e
1 изменённых файлов: 59 добавлений и 8 удалений

Просмотреть файл

@ -56,6 +56,7 @@ import android.text.style.ForegroundColorSpan;
import android.text.style.UnderlineSpan;
import android.util.Log;
import android.util.LogPrinter;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.BaseInputConnection;
@ -98,6 +99,8 @@ public class GeckoInputConnection
// Is a composition active?
private int mCompositionStart = NO_COMPOSITION_STRING;
private boolean mCommittingText;
private KeyCharacterMap mKeyCharacterMap;
private Editable mEditable;
private Editable.Factory mEditableFactory;
private boolean mBatchMode;
@ -140,7 +143,9 @@ public class GeckoInputConnection
@Override
public boolean commitText(CharSequence text, int newCursorPosition) {
mCommittingText = true;
replaceText(text, newCursorPosition, false);
mCommittingText = false;
if (hasCompositionString()) {
if (DEBUG) Log.d(LOGTAG, ". . . commitText: endComposition");
@ -564,10 +569,13 @@ public class GeckoInputConnection
endComposition();
}
if (count == 1 && s.charAt(start) == '\n') {
CharSequence changedText = s.subSequence(start, start + count);
if (changedText.length() == 1) {
char changedChar = changedText.charAt(0);
// Some IMEs (e.g. SwiftKey X) send a string with '\n' when Enter is pressed
// Such string cannot be handled by Gecko, so we convert it to a key press instead
if (DEBUG) Log.d(LOGTAG, ". . . onTextChanged: Typed <Enter>");
if (changedChar == '\n') {
processKeyDown(KeyEvent.KEYCODE_ENTER, new KeyEvent(KeyEvent.ACTION_DOWN,
KeyEvent.KEYCODE_ENTER), false);
processKeyUp(KeyEvent.KEYCODE_ENTER, new KeyEvent(KeyEvent.ACTION_UP,
@ -575,6 +583,15 @@ public class GeckoInputConnection
return;
}
// If we are committing a single character and didn't have an active composition string,
// we can send Gecko keydown/keyup events instead of composition events.
if (mCommittingText && !hasCompositionString() && synthesizeKeyEvents(changedChar)) {
// Block this thread until all pending events are processed
GeckoAppShell.geckoEventSync();
return;
}
}
if (!hasCompositionString()) {
if (DEBUG) Log.d(LOGTAG, ". . . onTextChanged: IME_COMPOSITION_BEGIN");
GeckoAppShell.sendEventToGecko(
@ -590,7 +607,7 @@ public class GeckoInputConnection
GeckoEvent.createIMEEvent(GeckoEvent.IME_SET_SELECTION, start, before));
}
sendTextToGecko(s.subSequence(start, start + count), start + count);
sendTextToGecko(changedText, start + count);
if (DEBUG) {
Log.d(LOGTAG, ". . . onTextChanged: IME_SET_SELECTION, start=" + (start + count)
@ -609,6 +626,40 @@ public class GeckoInputConnection
GeckoAppShell.geckoEventSync();
}
private boolean synthesizeKeyEvents(char inputChar) {
if (mKeyCharacterMap == null) {
mKeyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
}
// Synthesize VKB key events that could plausibly generate the input character.
char[] inputChars = { inputChar };
KeyEvent[] events = mKeyCharacterMap.getEvents(inputChars);
if (events == null) {
if (DEBUG) {
Log.d(LOGTAG, "synthesizeKeyEvents: char '" + inputChar
+ "' has no virtual key mapping");
}
return false;
}
boolean sentKeyEvents = false;
for (KeyEvent event : events) {
if (!KeyEvent.isModifierKey(event.getKeyCode())) {
if (DEBUG) {
Log.d(LOGTAG, "synthesizeKeyEvents: char '" + inputChar
+ "' -> action=" + event.getAction()
+ ", keyCode=" + event.getKeyCode()
+ ", UnicodeChar='" + (char) event.getUnicodeChar() + "'");
}
GeckoAppShell.sendEventToGecko(GeckoEvent.createKeyEvent(event));
sentKeyEvents = true;
}
}
return sentKeyEvents;
}
private void endComposition() {
if (DEBUG) Log.d(LOGTAG, "IME: endComposition: IME_COMPOSITION_END");
GeckoAppShell.sendEventToGecko(