author | Jim Chen <nchen@mozilla.com> |
Tue, 16 Jun 2015 19:02:39 -0400 | |
changeset 249202 | 860d548d92d0202485d68869f3ce3614becc1334 |
parent 249201 | 9a77983bf7b07e9ceb3cea80bea09faa5165ca2b |
child 249203 | 0a03c1ef13d098287902a197db167b23577dcb14 |
push id | 61171 |
push user | nchen@mozilla.com |
push date | Tue, 16 Jun 2015 23:02:58 +0000 |
treeherder | mozilla-inbound@0a03c1ef13d0 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | cpeterson |
bugs | 1112212 |
milestone | 41.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
mobile/android/base/GeckoEvent.java | file | annotate | diff | comparison | revisions | |
mobile/android/base/GeckoInputConnection.java | file | annotate | diff | comparison | revisions |
--- a/mobile/android/base/GeckoEvent.java +++ b/mobile/android/base/GeckoEvent.java @@ -239,19 +239,19 @@ public class GeckoEvent { public static GeckoEvent createAppForegroundingEvent() { return GeckoEvent.get(NativeGeckoEvent.APP_FOREGROUNDING); } public static GeckoEvent createNoOpEvent() { return GeckoEvent.get(NativeGeckoEvent.NOOP); } - public static GeckoEvent createKeyEvent(KeyEvent k, int metaState) { + public static GeckoEvent createKeyEvent(KeyEvent k, int action, int metaState) { GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.KEY_EVENT); - event.initKeyEvent(k, metaState); + event.initKeyEvent(k, action, metaState); return event; } public static GeckoEvent createCompositorCreateEvent(int width, int height) { GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.COMPOSITOR_CREATE); event.mWidth = width; event.mHeight = height; return event; @@ -260,18 +260,21 @@ public class GeckoEvent { public static GeckoEvent createCompositorPauseEvent() { return GeckoEvent.get(NativeGeckoEvent.COMPOSITOR_PAUSE); } public static GeckoEvent createCompositorResumeEvent() { return GeckoEvent.get(NativeGeckoEvent.COMPOSITOR_RESUME); } - private void initKeyEvent(KeyEvent k, int metaState) { - mAction = k.getAction(); + private void initKeyEvent(KeyEvent k, int action, int metaState) { + // Use a separate action argument so we can override the key's original action, + // e.g. change ACTION_MULTIPLE to ACTION_DOWN. That way we don't have to allocate + // a new key event just to change its action field. + mAction = action; mTime = k.getEventTime(); // Normally we expect k.getMetaState() to reflect the current meta-state; however, // some software-generated key events may not have k.getMetaState() set, e.g. key // events from Swype. Therefore, it's necessary to combine the key's meta-states // with the meta-states that we keep separately in KeyListener mMetaState = k.getMetaState() | metaState; mFlags = k.getFlags(); mKeyCode = k.getKeyCode(); @@ -601,17 +604,17 @@ public class GeckoEvent { public static GeckoEvent createIMEEvent(ImeAction action) { GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.IME_EVENT); event.mAction = action.value; return event; } public static GeckoEvent createIMEKeyEvent(KeyEvent k) { GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.IME_KEY_EVENT); - event.initKeyEvent(k, 0); + event.initKeyEvent(k, k.getAction(), 0); return event; } public static GeckoEvent createIMEReplaceEvent(int start, int end, String text) { return createIMETextEvent(false, start, end, text); } public static GeckoEvent createIMEComposeEvent(int start, int end, String text) {
--- a/mobile/android/base/GeckoInputConnection.java +++ b/mobile/android/base/GeckoInputConnection.java @@ -572,18 +572,16 @@ class GeckoInputConnection "password".equalsIgnoreCase(mIMETypeHint)) outAttrs.inputType |= InputType.TYPE_TEXT_VARIATION_PASSWORD; else if (mIMEState == IME_STATE_PLUGIN) outAttrs.inputType = InputType.TYPE_NULL; // "send key events" mode else if (mIMETypeHint.equalsIgnoreCase("url")) outAttrs.inputType |= InputType.TYPE_TEXT_VARIATION_URI; else if (mIMETypeHint.equalsIgnoreCase("email")) outAttrs.inputType |= InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS; - else if (mIMETypeHint.equalsIgnoreCase("search")) - outAttrs.imeOptions = EditorInfo.IME_ACTION_SEARCH; else if (mIMETypeHint.equalsIgnoreCase("tel")) outAttrs.inputType = InputType.TYPE_CLASS_PHONE; else if (mIMETypeHint.equalsIgnoreCase("number") || mIMETypeHint.equalsIgnoreCase("range")) outAttrs.inputType = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED | InputType.TYPE_NUMBER_FLAG_DECIMAL; else if (mIMETypeHint.equalsIgnoreCase("week") || @@ -618,17 +616,18 @@ class GeckoInputConnection } if (mIMEActionHint.equalsIgnoreCase("go")) outAttrs.imeOptions = EditorInfo.IME_ACTION_GO; else if (mIMEActionHint.equalsIgnoreCase("done")) outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE; else if (mIMEActionHint.equalsIgnoreCase("next")) outAttrs.imeOptions = EditorInfo.IME_ACTION_NEXT; - else if (mIMEActionHint.equalsIgnoreCase("search")) + else if (mIMEActionHint.equalsIgnoreCase("search") || + mIMETypeHint.equalsIgnoreCase("search")) outAttrs.imeOptions = EditorInfo.IME_ACTION_SEARCH; else if (mIMEActionHint.equalsIgnoreCase("send")) outAttrs.imeOptions = EditorInfo.IME_ACTION_SEND; else if (mIMEActionHint.length() > 0) { if (DEBUG) Log.w(LOGTAG, "Unexpected mIMEActionHint=\"" + mIMEActionHint + "\""); outAttrs.actionLabel = mIMEActionHint; } @@ -798,23 +797,24 @@ class GeckoInputConnection event = GamepadUtils.translateSonyXperiaGamepadKeys(keyCode, event); keyCode = event.getKeyCode(); } if (keyCode > KeyEvent.getMaxKeyCode() || !shouldProcessKey(keyCode, event)) { return false; } + final int action = down ? KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP; event = translateKey(keyCode, event); keyCode = event.getKeyCode(); View view = getView(); if (view == null) { InputThreadUtils.sInstance.sendEventFromUiThread(ThreadUtils.getUiHandler(), - mEditableClient, GeckoEvent.createKeyEvent(event, 0)); + mEditableClient, GeckoEvent.createKeyEvent(event, action, 0)); 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(); Editable uiEditable = InputThreadUtils.sInstance. @@ -822,17 +822,17 @@ class GeckoInputConnection boolean skip = shouldSkipKeyListener(keyCode, event); if (down) { mEditableClient.setSuppressKeyUp(true); } if (skip || (down && !keyListener.onKeyDown(view, uiEditable, keyCode, event)) || (!down && !keyListener.onKeyUp(view, uiEditable, keyCode, event))) { InputThreadUtils.sInstance.sendEventFromUiThread(uiHandler, mEditableClient, - GeckoEvent.createKeyEvent(event, TextKeyListener.getMetaState(uiEditable))); + GeckoEvent.createKeyEvent(event, action, TextKeyListener.getMetaState(uiEditable))); 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); } } if (down) { @@ -846,37 +846,53 @@ class GeckoInputConnection return processKey(keyCode, event, true); } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { return processKey(keyCode, event, false); } + /** + * Get a key that represents a given character. + */ + private KeyEvent getCharKeyEvent(final char c) { + final long time = SystemClock.uptimeMillis(); + return new KeyEvent(time, time, KeyEvent.ACTION_MULTIPLE, + KeyEvent.KEYCODE_UNKNOWN, /* repeat */ 0) { + @Override + public int getUnicodeChar() { + return c; + } + + @Override + public int getUnicodeChar(int metaState) { + return c; + } + }; + } + @Override public boolean onKeyMultiple(int keyCode, int repeatCount, final KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_UNKNOWN) { // KEYCODE_UNKNOWN means the characters are in KeyEvent.getCharacters() - View view = getView(); - if (view != null) { - InputThreadUtils.sInstance.runOnIcThread( - view.getRootView().getHandler(), mEditableClient, - new Runnable() { - @Override public void run() { - // Don't call GeckoInputConnection.commitText because it can - // post a key event back to onKeyMultiple, causing a loop - GeckoInputConnection.super.commitText(event.getCharacters(), 1); - } - }); + final String str = event.getCharacters(); + for (int i = 0; i < str.length(); i++) { + final KeyEvent charEvent = getCharKeyEvent(str.charAt(i)); + if (!processKey(KeyEvent.KEYCODE_UNKNOWN, charEvent, /* down */ true) || + !processKey(KeyEvent.KEYCODE_UNKNOWN, charEvent, /* down */ false)) { + return false; + } } return true; } + while ((repeatCount--) != 0) { - if (!processKey(keyCode, event, true) || - !processKey(keyCode, event, false)) { + if (!processKey(keyCode, event, /* down */ true) || + !processKey(keyCode, event, /* down */ false)) { return false; } } return true; } @Override public boolean onKeyLongPress(int keyCode, KeyEvent event) {