From ca7ec2097ca6af1505c1e6aa8b81b6068ba46dae Mon Sep 17 00:00:00 2001 From: satok Date: Tue, 6 Mar 2012 14:56:46 +0900 Subject: [PATCH] Integrate the logic to calculate the proximities Bug: 4343280 Change-Id: I0f6a7e6912ed4abea07c10d266da4c7ccb0dae76 --- .../keyboard/KeyboardActionListener.java | 10 ++-- .../keyboard/LatinKeyboardView.java | 3 +- .../keyboard/MoreKeysKeyboardView.java | 4 +- .../inputmethod/keyboard/PointerTracker.java | 13 ++--- .../android/inputmethod/latin/LatinIME.java | 38 +++++++------- .../android/inputmethod/latin/Suggest.java | 1 - .../inputmethod/latin/WordComposer.java | 50 +++++++++++++++++-- .../AndroidSpellCheckerService.java | 18 +------ .../suggestions/MoreSuggestionsView.java | 2 +- .../inputmethod/latin/InputLogicTests.java | 30 ++--------- 10 files changed, 83 insertions(+), 86 deletions(-) diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java index 6e13b95b5..16b4eafc9 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java @@ -41,11 +41,6 @@ public interface KeyboardActionListener { * Send a key code to the listener. * * @param primaryCode this is the code of the key that was pressed - * @param keyCodes the codes for all the possible alternative keys with the primary code being - * the first. If the primary key code is a single character such as an alphabet or - * number or symbol, the alternatives will include other characters that may be on - * the same key or adjacent keys. These codes are useful to correct for accidental - * presses of a key adjacent to the intended key. * @param x x-coordinate pixel of touched event. If {@link #onCodeInput} is not called by * {@link PointerTracker#onTouchEvent} or so, the value should be * {@link #NOT_A_TOUCH_COORDINATE}. If it's called on insertion from the suggestion @@ -55,10 +50,11 @@ public interface KeyboardActionListener { * {@link #NOT_A_TOUCH_COORDINATE}. If it's called on insertion from the suggestion * strip, it should be {@link #SUGGESTION_STRIP_COORDINATE}. */ - public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y); + public void onCodeInput(int primaryCode, int x, int y); public static final int NOT_A_TOUCH_COORDINATE = -1; public static final int SUGGESTION_STRIP_COORDINATE = -2; + public static final int SPELL_CHECKER_COORDINATE = -3; /** * Sends a sequence of characters to the listener. @@ -84,7 +80,7 @@ public interface KeyboardActionListener { @Override public void onReleaseKey(int primaryCode, boolean withSliding) {} @Override - public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) {} + public void onCodeInput(int primaryCode, int x, int y) {} @Override public void onTextInput(CharSequence text) {} @Override diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index 8a2f89257..78c371ff0 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -505,7 +505,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke } private void invokeCodeInput(int primaryCode) { - mKeyboardActionListener.onCodeInput(primaryCode, null, + mKeyboardActionListener.onCodeInput(primaryCode, KeyboardActionListener.NOT_A_TOUCH_COORDINATE, KeyboardActionListener.NOT_A_TOUCH_COORDINATE); } @@ -740,6 +740,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke * @return {@code true} if the event was handled by the view, {@code false} * otherwise */ + //Should not annotate @override public boolean dispatchHoverEvent(MotionEvent event) { if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) { final PointerTracker tracker = PointerTracker.getPointerTracker(0, this); diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java index b030dd95a..9970d1d0b 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java @@ -46,8 +46,8 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel private final KeyboardActionListener mMoreKeysKeyboardListener = new KeyboardActionListener.Adapter() { @Override - public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { - mListener.onCodeInput(primaryCode, keyCodes, x, y); + public void onCodeInput(int primaryCode, int x, int y) { + mListener.onCodeInput(primaryCode, x, y); } @Override diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index f8f17bdd9..7a9915be0 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -105,7 +105,6 @@ public class PointerTracker { } } - private static KeyboardSwitcher sKeyboardSwitcher; // Parameters for pointer handling. private static LatinKeyboardView.PointerTrackerParams sParams; private static int sTouchNoiseThresholdDistanceSquared; @@ -172,7 +171,6 @@ public class PointerTracker { } setParameters(LatinKeyboardView.PointerTrackerParams.DEFAULT); - sKeyboardSwitcher = KeyboardSwitcher.getInstance(); } public static void setParameters(LatinKeyboardView.PointerTrackerParams params) { @@ -254,13 +252,13 @@ public class PointerTracker { // Note that we need primaryCode argument because the keyboard may in shifted state and the // primaryCode is different from {@link Key#mCode}. - private void callListenerOnCodeInput(Key key, int primaryCode, int[] keyCodes, int x, int y) { + private void callListenerOnCodeInput(Key key, int primaryCode, int x, int y) { final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier(); final boolean alterCode = key.altCodeWhileTyping() && mTimerProxy.isTyping(); final int code = alterCode ? key.mAltCode : primaryCode; if (DEBUG_LISTENER) { Log.d(TAG, "onCodeInput: " + Keyboard.printableCode(code) + " text=" + key.mOutputText - + " codes="+ KeyDetector.printableCodes(keyCodes) + " x=" + x + " y=" + y + + " x=" + x + " y=" + y + " ignoreModifier=" + ignoreModifierKey + " alterCode=" + alterCode + " enabled=" + key.isEnabled()); } @@ -271,7 +269,7 @@ public class PointerTracker { if (code == Keyboard.CODE_OUTPUT_TEXT) { mListener.onTextInput(key.mOutputText); } else if (code != Keyboard.CODE_UNSPECIFIED) { - mListener.onCodeInput(code, keyCodes, x, y); + mListener.onCodeInput(code, x, y); } if (!key.altCodeWhileTyping() && !key.isModifier()) { mTimerProxy.startKeyTypedTimer(); @@ -719,10 +717,7 @@ public class PointerTracker { } int code = key.mCode; - final int[] codes = mKeyDetector.newCodeArray(); - mKeyDetector.getKeyAndNearbyCodes(x, y, codes); - - callListenerOnCodeInput(key, code, codes, x, y); + callListenerOnCodeInput(key, code, x, y); callListenerOnRelease(key, code, false); } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 64b9f3364..044f05014 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -728,10 +728,17 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final KeyboardSwitcher switcher = mKeyboardSwitcher; LatinKeyboardView inputView = switcher.getKeyboardView(); + if (editorInfo == null) { + Log.e(TAG, "Null EditorInfo in onStartInputView()"); + if (LatinImeLogger.sDBG) { + throw new NullPointerException("Null EditorInfo in onStartInputView()"); + } + return; + } if (DEBUG) { - Log.d(TAG, "onStartInputView: editorInfo:" + ((editorInfo == null) ? "none" - : String.format("inputType=0x%08x imeOptions=0x%08x", - editorInfo.inputType, editorInfo.imeOptions))); + Log.d(TAG, "onStartInputView: editorInfo:" + + String.format("inputType=0x%08x imeOptions=0x%08x", + editorInfo.inputType, editorInfo.imeOptions)); } if (Utils.inPrivateImeOptions(null, IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo)) { Log.w(TAG, "Deprecated private IME option specified: " @@ -761,7 +768,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Most such things we decide below in initializeInputAttributesAndGetMode, but we need to // know now whether this is a password text field, because we need to know now whether we // want to enable the voice button. - final int inputType = (editorInfo != null) ? editorInfo.inputType : 0; + final int inputType = editorInfo.inputType; mVoiceProxy.resetVoiceStates(InputTypeCompatUtils.isPasswordInputType(inputType) || InputTypeCompatUtils.isVisiblePasswordInputType(inputType)); @@ -1245,12 +1252,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar return mOptionsDialog != null && mOptionsDialog.isShowing(); } - private void insertPunctuationFromSuggestionStrip(final int code) { - onCodeInput(code, new int[] { code }, - KeyboardActionListener.SUGGESTION_STRIP_COORDINATE, - KeyboardActionListener.SUGGESTION_STRIP_COORDINATE); - } - private static int getActionId(Keyboard keyboard) { return keyboard != null ? keyboard.mId.imeActionId() : EditorInfo.IME_ACTION_NONE; } @@ -1279,7 +1280,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Implementation of {@link KeyboardActionListener}. @Override - public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { + public void onCodeInput(int primaryCode, int x, int y) { final long when = SystemClock.uptimeMillis(); if (primaryCode != Keyboard.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) { mDeleteCount = 0; @@ -1331,7 +1332,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (mSettingsValues.isWordSeparator(primaryCode)) { didAutoCorrect = handleSeparator(primaryCode, x, y, spaceState); } else { - handleCharacter(primaryCode, keyCodes, x, y, spaceState); + handleCharacter(primaryCode, x, y, spaceState); } mExpectingUpdateSelection = true; break; @@ -1498,18 +1499,18 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } } - private void handleCharacter(final int primaryCode, final int[] keyCodes, final int x, + private void handleCharacter(final int primaryCode, final int x, final int y, final int spaceState) { mVoiceProxy.handleCharacter(); final InputConnection ic = getCurrentInputConnection(); if (null != ic) ic.beginBatchEdit(); // TODO: if ic is null, does it make any sense to call this? - handleCharacterWhileInBatchEdit(primaryCode, keyCodes, x, y, spaceState, ic); + handleCharacterWhileInBatchEdit(primaryCode, x, y, spaceState, ic); if (null != ic) ic.endBatchEdit(); } // "ic" may be null without this crashing, but the behavior will be really strange - private void handleCharacterWhileInBatchEdit(final int primaryCode, final int[] keyCodes, + private void handleCharacterWhileInBatchEdit(final int primaryCode, final int x, final int y, final int spaceState, final InputConnection ic) { boolean isComposingWord = mWordComposer.isComposingWord(); @@ -1541,7 +1542,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } } if (isComposingWord) { - mWordComposer.add(primaryCode, keyCodes, x, y); + mWordComposer.add( + primaryCode, x, y, mKeyboardSwitcher.getKeyboardView().getKeyDetector()); if (ic != null) { // If it's the first letter, make note of auto-caps state if (mWordComposer.size() == 1) { @@ -1912,7 +1914,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar LatinImeLogger.logOnManualSuggestion("", suggestion.toString(), index, suggestedWords); // Rely on onCodeInput to do the complicated swapping/stripping logic consistently. final int primaryCode = suggestion.charAt(0); - onCodeInput(primaryCode, new int[] { primaryCode }, + onCodeInput(primaryCode, KeyboardActionListener.SUGGESTION_STRIP_COORDINATE, KeyboardActionListener.SUGGESTION_STRIP_COORDINATE); return; @@ -2158,7 +2160,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final String originallyTypedWord = mLastComposedWord.mTypedWord; final CharSequence committedWord = mLastComposedWord.mCommittedWord; final int cancelLength = committedWord.length(); - final int separatorLength = mLastComposedWord.getSeparatorLength( + final int separatorLength = LastComposedWord.getSeparatorLength( mLastComposedWord.mSeparatorCode); // TODO: should we check our saved separator against the actual contents of the text view? if (DEBUG) { diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index f6e177aaf..298ead665 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -323,7 +323,6 @@ public class Suggest implements Dictionary.WordCallback { } } else { // Word entered: return only bigrams that match the first char of the typed word - @SuppressWarnings("null") final char currentChar = consideredWord.charAt(0); // TODO: Must pay attention to locale when changing case. final char currentCharUpper = Character.toUpperCase(currentChar); diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index 8121ada7f..2a597b86d 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -19,6 +19,9 @@ package com.android.inputmethod.latin; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.keyboard.KeyboardActionListener; +import com.android.inputmethod.latin.spellcheck.AndroidSpellCheckerService; +import com.android.inputmethod.latin.spellcheck.SpellCheckerProximityInfo; import java.util.ArrayList; import java.util.Arrays; @@ -119,19 +122,60 @@ public class WordComposer { return previous && !Character.isUpperCase(codePoint); } + // TODO: remove input keyDetector + public void add(int primaryCode, int keyX, int keyY, KeyDetector keyDetector) { + final int[] codes; + if (keyX == KeyboardActionListener.SPELL_CHECKER_COORDINATE + || keyY == KeyboardActionListener.SPELL_CHECKER_COORDINATE) { + // only used for tests in InputLogicTests + addKeyForSpellChecker(primaryCode, AndroidSpellCheckerService.SCRIPT_LATIN); + return; + } else if (keyX == KeyboardActionListener.SUGGESTION_STRIP_COORDINATE + || keyY == KeyboardActionListener.SUGGESTION_STRIP_COORDINATE + || keyX == KeyboardActionListener.NOT_A_TOUCH_COORDINATE + || keyY == KeyboardActionListener.NOT_A_TOUCH_COORDINATE) { + codes = new int[] { primaryCode }; + } else { + codes = keyDetector.newCodeArray(); + keyDetector.getKeyAndNearbyCodes(keyX, keyY, codes); + } + add(primaryCode, codes, keyX, keyY); + } + + // TODO: remove this function + public void addKeyForSpellChecker(int primaryCode, int script) { + final int[] proximities; + final int proximityIndex = + SpellCheckerProximityInfo.getIndexOfCodeForScript(primaryCode, script); + if (-1 == proximityIndex) { + proximities = new int[] { primaryCode }; + } else { + // TODO: an initial examination seems to reveal this is actually used + // read-only. It should be possible to compute the arrays statically once + // and skip doing a copy each time here. + proximities = Arrays.copyOfRange( + SpellCheckerProximityInfo.getProximityForScript(script), + proximityIndex, + proximityIndex + SpellCheckerProximityInfo.ROW_SIZE); + } + add(primaryCode, proximities, + KeyboardActionListener.NOT_A_TOUCH_COORDINATE, + KeyboardActionListener.NOT_A_TOUCH_COORDINATE); + } + /** * Add a new keystroke, with codes[0] containing the pressed key's unicode and the rest of * the array containing unicode for adjacent keys, sorted by reducing probability/proximity. * @param codes the array of unicode values */ - public void add(int primaryCode, int[] codes, int x, int y) { + private void add(int primaryCode, int[] codes, int keyX, int keyY) { final int newIndex = mCodes.size(); mTypedWord.appendCodePoint(primaryCode); correctPrimaryJuxtapos(primaryCode, codes); mCodes.add(codes); if (newIndex < BinaryDictionary.MAX_WORD_LENGTH) { - mXCoordinates[newIndex] = x; - mYCoordinates[newIndex] = y; + mXCoordinates[newIndex] = keyX; + mYCoordinates[newIndex] = keyY; } mIsFirstCharCapitalized = isFirstCharCapitalized( newIndex, primaryCode, mIsFirstCharCapitalized); diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 8ac82ee5b..755c75b2e 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -570,23 +570,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService final WordComposer composer = new WordComposer(); final int length = text.length(); for (int i = 0; i < length; i = text.offsetByCodePoints(i, 1)) { - final int character = text.codePointAt(i); - final int proximityIndex = - SpellCheckerProximityInfo.getIndexOfCodeForScript(character, mScript); - final int[] proximities; - if (-1 == proximityIndex) { - proximities = new int[] { character }; - } else { - // TODO: an initial examination seems to reveal this is actually used - // read-only. It should be possible to compute the arrays statically once - // and skip doing a copy each time here. - proximities = Arrays.copyOfRange( - SpellCheckerProximityInfo.getProximityForScript(mScript), - proximityIndex, - proximityIndex + SpellCheckerProximityInfo.ROW_SIZE); - } - composer.add(character, proximities, - WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); + composer.addKeyForSpellChecker(text.codePointAt(i), mScript); } final int capitalizeType = getCapitalizationType(text); diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java index cd83c3e21..1f7214777 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java @@ -66,7 +66,7 @@ public class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel { } @Override - public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { + public void onCodeInput(int primaryCode, int x, int y) { final int index = primaryCode - MoreSuggestions.SUGGESTION_CODE_BASE; if (index >= 0 && index < SuggestionsView.MAX_SUGGESTIONS) { mListener.onCustomRequest(index); diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java index 9d53b63f1..1ea70a98f 100644 --- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java +++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java @@ -51,29 +51,9 @@ public class InputLogicTests extends ServiceTestCase { private LatinIME mLatinIME; private TextView mTextView; private InputConnection mInputConnection; - private HashMap mProximity; public InputLogicTests() { super(LatinIME.class); - mProximity = createProximity(); - } - - private static HashMap createProximity() { - final HashMap proximity = new HashMap(); - final int[] testProximity = SpellCheckerProximityInfo.getProximityForScript( - AndroidSpellCheckerService.SCRIPT_LATIN); - final int ROW_SIZE = SpellCheckerProximityInfo.ROW_SIZE; - final int NUL = SpellCheckerProximityInfo.NUL; - for (int row = 0; row * ROW_SIZE < testProximity.length; ++row) { - final int rowBase = row * ROW_SIZE; - int column; - for (column = 1; NUL != testProximity[rowBase + column]; ++column) { - // Do nothing, just search for a NUL element - } - proximity.put(testProximity[row * ROW_SIZE], - Arrays.copyOfRange(testProximity, rowBase, rowBase + column)); - } - return proximity; } // returns the previous setting value @@ -185,13 +165,9 @@ public class InputLogicTests extends ServiceTestCase { // to keep these tests as pinpoint as possible and avoid bringing it too many dependencies, // but keep them in mind if something breaks. Commenting them out as is should work. //mLatinIME.onPressKey(codePoint); - int[] proximityKeys = mProximity.get(codePoint); - if (null == proximityKeys) { - proximityKeys = new int[] { codePoint }; - } - mLatinIME.onCodeInput(codePoint, proximityKeys, - KeyboardActionListener.NOT_A_TOUCH_COORDINATE, - KeyboardActionListener.NOT_A_TOUCH_COORDINATE); + mLatinIME.onCodeInput(codePoint, + KeyboardActionListener.SPELL_CHECKER_COORDINATE, + KeyboardActionListener.SPELL_CHECKER_COORDINATE); //mLatinIME.onReleaseKey(codePoint, false); }