Bug 844290 - Refactor GeckoInputConnection key handling code; r=cpeterson

This commit is contained in:
Jim Chen 2013-02-28 13:17:21 -05:00
parent bc85f57c13
commit 7b87561c4f

View File

@ -661,15 +661,7 @@ class GeckoInputConnection
return false; return false;
} }
@Override private boolean shouldProcessKey(int keyCode, KeyEvent event) {
public boolean onKeyDown(int keyCode, KeyEvent event) {
return processKeyDown(keyCode, event);
}
private boolean processKeyDown(int keyCode, KeyEvent event) {
if (keyCode > KeyEvent.getMaxKeyCode())
return false;
switch (keyCode) { switch (keyCode) {
case KeyEvent.KEYCODE_MENU: case KeyEvent.KEYCODE_MENU:
case KeyEvent.KEYCODE_BACK: case KeyEvent.KEYCODE_BACK:
@ -677,87 +669,96 @@ class GeckoInputConnection
case KeyEvent.KEYCODE_VOLUME_DOWN: case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_SEARCH: case KeyEvent.KEYCODE_SEARCH:
return false; return false;
}
return true;
}
private boolean shouldSkipKeyListener(int keyCode, KeyEvent event) {
if (mIMEState == IME_STATE_DISABLED ||
mIMEState == IME_STATE_PLUGIN) {
return true;
}
// Preserve enter and tab keys for the browser
if (keyCode == KeyEvent.KEYCODE_ENTER ||
keyCode == KeyEvent.KEYCODE_TAB) {
return true;
}
// BaseKeyListener returns false even if it handled these keys for us,
// so we skip the key listener entirely and handle these ourselves
if (keyCode == KeyEvent.KEYCODE_DEL ||
keyCode == KeyEvent.KEYCODE_FORWARD_DEL) {
return true;
}
return false;
}
private KeyEvent translateKey(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_ENTER: case KeyEvent.KEYCODE_ENTER:
if ((event.getFlags() & KeyEvent.FLAG_EDITOR_ACTION) != 0 && if ((event.getFlags() & KeyEvent.FLAG_EDITOR_ACTION) != 0 &&
mIMEActionHint.equalsIgnoreCase("next")) mIMEActionHint.equalsIgnoreCase("next")) {
event = new KeyEvent(event.getAction(), KeyEvent.KEYCODE_TAB); return new KeyEvent(event.getAction(), KeyEvent.KEYCODE_TAB);
break; }
default:
break; break;
} }
return event;
}
private boolean processKey(int keyCode, KeyEvent event, boolean down) {
if (keyCode > KeyEvent.getMaxKeyCode() ||
!shouldProcessKey(keyCode, event)) {
return false;
}
event = translateKey(keyCode, event);
keyCode = event.getKeyCode();
View view = getView(); View view = getView();
KeyListener keyListener = TextKeyListener.getInstance(); if (view == null) {
// KeyListener returns true if it handled the event for us. KeyListener is only
// safe to use on the UI thread; therefore we need to pass a proxy Editable to it
if (mIMEState == IME_STATE_DISABLED ||
mIMEState == IME_STATE_PLUGIN ||
keyCode == KeyEvent.KEYCODE_ENTER ||
keyCode == KeyEvent.KEYCODE_DEL ||
keyCode == KeyEvent.KEYCODE_TAB ||
(event.getFlags() & KeyEvent.FLAG_SOFT_KEYBOARD) != 0 ||
view == null) {
mEditableClient.sendEvent(GeckoEvent.createKeyEvent(event)); mEditableClient.sendEvent(GeckoEvent.createKeyEvent(event));
return true; return true;
} }
// KeyListener returns true if it handled the event for us. KeyListener is only
// safe to use on the UI thread; therefore we need to pass a proxy Editable to it
KeyListener keyListener = TextKeyListener.getInstance();
Handler uiHandler = view.getRootView().getHandler(); Handler uiHandler = view.getRootView().getHandler();
Handler icHandler = mEditableClient.getInputConnectionHandler(); Handler icHandler = mEditableClient.getInputConnectionHandler();
Editable uiEditable = mThreadUtils.getEditableForUiThread(uiHandler, icHandler); Editable uiEditable = mThreadUtils.getEditableForUiThread(uiHandler, icHandler);
if (!keyListener.onKeyDown(view, uiEditable, keyCode, event)) { boolean skip = shouldSkipKeyListener(keyCode, event);
if (skip ||
(down && !keyListener.onKeyDown(view, uiEditable, keyCode, event)) ||
(!down && !keyListener.onKeyUp(view, uiEditable, keyCode, event))) {
mEditableClient.sendEvent(GeckoEvent.createKeyEvent(event)); mEditableClient.sendEvent(GeckoEvent.createKeyEvent(event));
if (skip && down) {
// Usually, the down key listener call above adjusts meta states for us.
// However, if we skip that call above, we have to manually adjust meta
// states so the meta states remain consistent
TextKeyListener.adjustMetaAfterKeypress(uiEditable);
}
} }
return true; return true;
} }
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return processKey(keyCode, event, true);
}
@Override @Override
public boolean onKeyUp(int keyCode, KeyEvent event) { public boolean onKeyUp(int keyCode, KeyEvent event) {
return processKeyUp(keyCode, event); return processKey(keyCode, event, false);
}
private boolean processKeyUp(int keyCode, KeyEvent event) {
if (keyCode > KeyEvent.getMaxKeyCode())
return false;
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
case KeyEvent.KEYCODE_SEARCH:
case KeyEvent.KEYCODE_MENU:
return false;
default:
break;
}
View view = getView();
KeyListener keyListener = TextKeyListener.getInstance();
// KeyListener returns true if it handled the event for us. KeyListener is only
// safe to use on the UI thread; therefore we need to pass a proxy Editable to it
if (mIMEState == IME_STATE_DISABLED ||
mIMEState == IME_STATE_PLUGIN ||
keyCode == KeyEvent.KEYCODE_ENTER ||
keyCode == KeyEvent.KEYCODE_DEL ||
(event.getFlags() & KeyEvent.FLAG_SOFT_KEYBOARD) != 0 ||
view == null) {
mEditableClient.sendEvent(GeckoEvent.createKeyEvent(event));
return true;
}
Handler uiHandler = view.getRootView().getHandler();
Handler icHandler = mEditableClient.getInputConnectionHandler();
Editable uiEditable = mThreadUtils.getEditableForUiThread(uiHandler, icHandler);
if (!keyListener.onKeyUp(view, uiEditable, keyCode, event)) {
mEditableClient.sendEvent(GeckoEvent.createKeyEvent(event));
}
return true;
} }
@Override @Override
public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_UNKNOWN) {
// KEYCODE_UNKNOWN means the characters are in KeyEvent.getCharacters()
return commitText(event.getCharacters(), 1);
}
while ((repeatCount--) != 0) { while ((repeatCount--) != 0) {
if (!processKeyDown(keyCode, event) || if (!processKey(keyCode, event, true) ||
!processKeyUp(keyCode, event)) { !processKey(keyCode, event, false)) {
return false; return false;
} }
} }