diff options
Diffstat (limited to 'java/src')
16 files changed, 211 insertions, 126 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index bc1383aff..4fd3bac2f 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -23,6 +23,7 @@ import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.keyboard.internal.KeyboardParams; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.utils.CollectionUtils; +import com.android.inputmethod.latin.utils.CoordinateUtils; /** * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard @@ -217,4 +218,20 @@ public class Keyboard { final int adjustedY = Math.max(0, Math.min(y, mOccupiedHeight - 1)); return mProximityInfo.getNearestKeys(adjustedX, adjustedY); } + + public int[] getCoordinates(final int[] codePoints) { + final int length = codePoints.length; + final int[] coordinates = CoordinateUtils.newCoordinateArray(length); + for (int i = 0; i < length; ++i) { + final Key key = getKey(codePoints[i]); + if (null != key) { + CoordinateUtils.setXYInArray(coordinates, i, + key.getX() + key.getWidth() / 2, key.getY() + key.getHeight() / 2); + } else { + CoordinateUtils.setXYInArray(coordinates, i, + Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE); + } + } + return coordinates; + } } diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java index 5b13e9a41..1891dfc74 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java @@ -142,7 +142,11 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel if (code == Constants.CODE_OUTPUT_TEXT) { mListener.onTextInput(mCurrentKey.getOutputText()); } else if (code != Constants.CODE_UNSPECIFIED) { - mListener.onCodeInput(code, x, y); + if (getKeyboard().hasProximityCharsCorrection(code)) { + mListener.onCodeInput(code, x, y); + } else { + mListener.onCodeInput(code, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE); + } } } diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 5e02926de..093155049 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -346,7 +346,12 @@ public final class PointerTracker implements PointerTrackerQueue.Element, if (code == Constants.CODE_OUTPUT_TEXT) { sListener.onTextInput(key.getOutputText()); } else if (code != Constants.CODE_UNSPECIFIED) { - sListener.onCodeInput(code, x, y); + if (mKeyboard.hasProximityCharsCorrection(code)) { + sListener.onCodeInput(code, x, y); + } else { + sListener.onCodeInput(code, + Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE); + } } } } diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java index 77e99bfba..0477133d7 100644 --- a/java/src/com/android/inputmethod/latin/Constants.java +++ b/java/src/com/android/inputmethod/latin/Constants.java @@ -216,8 +216,9 @@ public final class Constants { public static final int CODE_LANGUAGE_SWITCH = -10; public static final int CODE_EMOJI = -11; public static final int CODE_SHIFT_ENTER = -12; + public static final int CODE_SYMBOL_SHIFT = -13; // Code value representing the code is not specified. - public static final int CODE_UNSPECIFIED = -13; + public static final int CODE_UNSPECIFIED = -14; public static boolean isLetterCode(final int code) { return code >= CODE_SPACE; diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index d3e6a1bc2..b094100c6 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -79,6 +79,7 @@ import com.android.inputmethod.latin.suggestions.SuggestionStripView; import com.android.inputmethod.latin.utils.ApplicationUtils; import com.android.inputmethod.latin.utils.CapsModeUtils; import com.android.inputmethod.latin.utils.CompletionInfoUtils; +import com.android.inputmethod.latin.utils.CoordinateUtils; import com.android.inputmethod.latin.utils.IntentUtils; import com.android.inputmethod.latin.utils.JniUtils; import com.android.inputmethod.latin.utils.LatinImeLoggerUtils; @@ -203,7 +204,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen case MSG_RESUME_SUGGESTIONS: latinIme.mInputLogic.restartSuggestionsOnWordTouchedByCursor( latinIme.mSettings.getCurrent(), - false /* includeResumedWordInSuggestions */, latinIme.mKeyboardSwitcher); + false /* includeResumedWordInSuggestions */); break; case MSG_REOPEN_DICTIONARIES: latinIme.initSuggest(); @@ -217,10 +218,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen (SuggestedWords) msg.obj, latinIme.mKeyboardSwitcher); break; case MSG_RESET_CACHES: - latinIme.mInputLogic.retryResetCaches(latinIme.mSettings.getCurrent(), + final SettingsValues settingsValues = latinIme.mSettings.getCurrent(); + if (latinIme.mInputLogic.retryResetCachesAndReturnSuccess(settingsValues, msg.arg1 == 1 /* tryResumeSuggestions */, - msg.arg2 /* remainingTries */, - latinIme.mKeyboardSwitcher, this); + msg.arg2 /* remainingTries */, this /* handler */)) { + // If we were able to reset the caches, then we can reload the keyboard. + // Otherwise, we'll do it when we can. + latinIme.mKeyboardSwitcher.loadKeyboard(latinIme.getCurrentInputEditorInfo(), + settingsValues); + } break; } } @@ -1194,6 +1200,20 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen return mSubtypeSwitcher.getCurrentSubtypeLocale(); } + /** + * @param codePoints code points to get coordinates for. + * @return x,y coordinates for this keyboard, as a flattened array. + */ + public int[] getCoordinatesForCurrentKeyboard(final int[] codePoints) { + final Keyboard keyboard = mKeyboardSwitcher.getKeyboard(); + if (null == keyboard) { + return CoordinateUtils.newCoordinateArray(codePoints.length, + Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE); + } else { + return keyboard.getCoordinates(codePoints); + } + } + // Callback for the {@link SuggestionStripView}, to call when the "add to dictionary" hint is // pressed. @Override @@ -1246,8 +1266,31 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // Implementation of {@link KeyboardActionListener}. @Override - public void onCodeInput(final int primaryCode, final int x, final int y) { - mInputLogic.onCodeInput(primaryCode, x, y, mHandler, mKeyboardSwitcher, mSubtypeSwitcher); + public void onCodeInput(final int codePoint, final int x, final int y) { + final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView(); + // x and y include some padding, but everything down the line (especially native + // code) needs the coordinates in the keyboard frame. + // TODO: We should reconsider which coordinate system should be used to represent + // keyboard event. Also we should pull this up -- LatinIME has no business doing + // this transformation, it should be done already before calling onCodeInput. + final int keyX = mainKeyboardView.getKeyX(x); + final int keyY = mainKeyboardView.getKeyY(y); + final int codeToSend; + if (Constants.CODE_SHIFT == codePoint) { + // TODO: Instead of checking for alphabetic keyboard here, separate keycodes for + // alphabetic shift and shift while in symbol layout. + final Keyboard currentKeyboard = mKeyboardSwitcher.getKeyboard(); + if (null != currentKeyboard && currentKeyboard.mId.isAlphabetKeyboard()) { + codeToSend = codePoint; + } else { + codeToSend = Constants.CODE_SYMBOL_SHIFT; + } + } else { + codeToSend = codePoint; + } + mInputLogic.onCodeInput(codeToSend, keyX, keyY, mHandler, mKeyboardSwitcher, + mSubtypeSwitcher); + mKeyboardSwitcher.onCodeInput(codePoint); } // Called from PointerTracker through the KeyboardActionListener interface diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index fc85c1388..439c8562e 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -50,8 +50,6 @@ public final class Suggest { // Close to -2**31 private static final int SUPPRESS_SUGGEST_THRESHOLD = -2000000000; - public static final int MAX_SUGGESTIONS = 18; - private static final boolean DBG = LatinImeLogger.sDBG; public final DictionaryFacilitatorForSuggest mDictionaryFacilitator; @@ -109,7 +107,7 @@ public final class Suggest { final OnGetSuggestedWordsCallback callback) { final int trailingSingleQuotesCount = wordComposer.trailingSingleQuotesCount(); final BoundedTreeSet suggestionsSet = new BoundedTreeSet(sSuggestedWordInfoComparator, - MAX_SUGGESTIONS); + SuggestedWords.MAX_SUGGESTIONS); final String typedWord = wordComposer.getTypedWord(); final String consideredWord = trailingSingleQuotesCount > 0 @@ -226,7 +224,7 @@ public final class Suggest { final int sessionId, final int sequenceNumber, final OnGetSuggestedWordsCallback callback) { final BoundedTreeSet suggestionsSet = new BoundedTreeSet(sSuggestedWordInfoComparator, - MAX_SUGGESTIONS); + SuggestedWords.MAX_SUGGESTIONS); mDictionaryFacilitator.getSuggestions(wordComposer, prevWordForBigram, proximityInfo, blockOffensiveWords, additionalFeaturesOptions, sessionId, suggestionsSet); for (SuggestedWordInfo wordInfo : suggestionsSet) { diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index f9de89c80..bb34b7ba9 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -31,6 +31,9 @@ public final class SuggestedWords { public static final int INDEX_OF_AUTO_CORRECTION = 1; public static final int NOT_A_SEQUENCE_NUMBER = -1; + // The maximum number of suggestions available. + public static final int MAX_SUGGESTIONS = 18; + private static final ArrayList<SuggestedWordInfo> EMPTY_WORD_INFO_LIST = CollectionUtils.newArrayList(0); public static final SuggestedWords EMPTY = new SuggestedWords( diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index ebf65630e..125976932 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -16,8 +16,7 @@ package com.android.inputmethod.latin; -import com.android.inputmethod.keyboard.Key; -import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.latin.utils.CoordinateUtils; import com.android.inputmethod.latin.utils.StringUtils; import java.util.Arrays; @@ -274,36 +273,20 @@ public final class WordComposer { } /** - * Add a dummy key by retrieving reasonable coordinates - */ - public void addKeyInfo(final int codePoint, final Keyboard keyboard) { - final int x, y; - final Key key; - if (keyboard != null && (key = keyboard.getKey(codePoint)) != null) { - x = key.getX() + key.getWidth() / 2; - y = key.getY() + key.getHeight() / 2; - } else { - x = Constants.NOT_A_COORDINATE; - y = Constants.NOT_A_COORDINATE; - } - add(codePoint, x, y); - } - - /** * Set the currently composing word to the one passed as an argument. * This will register NOT_A_COORDINATE for X and Ys, and use the passed keyboard for proximity. - * @param word the char sequence to set as the composing word. + * @param codePoints the code points to set as the composing word. + * @param coordinates the x, y coordinates of the key in the CoordinateUtils format * @param previousWord the previous word, to use as context for suggestions. Can be null if * the context is nil (typically, at start of text). - * @param keyboard the keyboard this is typed on, for coordinate info/proximity. */ - public void setComposingWord(final CharSequence word, final CharSequence previousWord, - final Keyboard keyboard) { + public void setComposingWord(final int[] codePoints, final int[] coordinates, + final CharSequence previousWord) { reset(); - final int length = word.length(); - for (int i = 0; i < length; i = Character.offsetByCodePoints(word, i, 1)) { - final int codePoint = Character.codePointAt(word, i); - addKeyInfo(codePoint, keyboard); + final int length = codePoints.length; + for (int i = 0; i < length; ++i) { + add(codePoints[i], CoordinateUtils.xFromArray(coordinates, i), + CoordinateUtils.yFromArray(coordinates, i)); } mIsResumed = true; mPreviousWordForSuggestion = null == previousWord ? null : previousWord.toString(); diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java index 375a42e3b..6e9bdc34a 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java @@ -28,9 +28,7 @@ import android.view.inputmethod.EditorInfo; import com.android.inputmethod.compat.SuggestionSpanUtils; import com.android.inputmethod.event.EventInterpreter; -import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardSwitcher; -import com.android.inputmethod.keyboard.MainKeyboardView; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Dictionary; import com.android.inputmethod.latin.InputPointers; @@ -48,7 +46,6 @@ import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethod.latin.settings.Settings; import com.android.inputmethod.latin.settings.SettingsValues; import com.android.inputmethod.latin.settings.SpacingAndPunctuations; -import com.android.inputmethod.latin.suggestions.SuggestionStripView; import com.android.inputmethod.latin.utils.AsyncResultHolder; import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.InputTypeUtils; @@ -231,20 +228,17 @@ public final class InputLogic { LatinImeLogger.logOnDelete(x, y); break; case Constants.CODE_SHIFT: - // Note: Calling back to the keyboard on Shift key is handled in - // {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}. - final Keyboard currentKeyboard = keyboardSwitcher.getKeyboard(); - if (null != currentKeyboard && currentKeyboard.mId.isAlphabetKeyboard()) { - // TODO: Instead of checking for alphabetic keyboard here, separate keycodes for - // alphabetic shift and shift while in symbol layout. - performRecapitalization(settingsValues); - keyboardSwitcher.updateShiftState(); - } + performRecapitalization(settingsValues); + keyboardSwitcher.updateShiftState(); break; case Constants.CODE_CAPSLOCK: // Note: Changing keyboard to shift lock state is handled in // {@link KeyboardSwitcher#onCodeInput(int)}. break; + case Constants.CODE_SYMBOL_SHIFT: + // Note: Calling back to the keyboard on the symbol Shift key is handled in + // {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}. + break; case Constants.CODE_SWITCH_ALPHA_SYMBOL: // Note: Calling back to the keyboard on symbol key is handled in // {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}. @@ -301,7 +295,6 @@ public final class InputLogic { code, x, y, spaceState, keyboardSwitcher, handler); break; } - keyboardSwitcher.onCodeInput(code); // Reset after any single keystroke, except shift, capslock, and symbol-shift if (!didAutoCorrect && code != Constants.CODE_SHIFT && code != Constants.CODE_CAPSLOCK @@ -449,8 +442,12 @@ public final class InputLogic { final boolean didAutoCorrect; if (settingsValues.isWordSeparator(codePoint) || Character.getType(codePoint) == Character.OTHER_SYMBOL) { - didAutoCorrect = handleSeparator(settingsValues, codePoint, x, y, spaceState, - keyboardSwitcher, handler); + didAutoCorrect = handleSeparator(settingsValues, codePoint, + Constants.SUGGESTION_STRIP_COORDINATE == x, spaceState, keyboardSwitcher, + handler); + if (settingsValues.mIsInternal) { + LatinImeLoggerUtils.onSeparator((char)codePoint, x, y); + } } else { didAutoCorrect = false; if (SpaceState.PHANTOM == spaceState) { @@ -469,16 +466,7 @@ public final class InputLogic { commitTyped(settingsValues, LastComposedWord.NOT_A_SEPARATOR); } } - final int keyX, keyY; - final Keyboard keyboard = keyboardSwitcher.getKeyboard(); - if (keyboard != null && keyboard.hasProximityCharsCorrection(codePoint)) { - keyX = x; - keyY = y; - } else { - keyX = Constants.NOT_A_COORDINATE; - keyY = Constants.NOT_A_COORDINATE; - } - handleNonSeparator(settingsValues, codePoint, keyX, keyY, spaceState, + handleNonSeparator(settingsValues, codePoint, x, y, spaceState, keyboardSwitcher, handler); } return didAutoCorrect; @@ -545,12 +533,7 @@ public final class InputLogic { resetComposingState(false /* alsoResetLastComposedWord */); } if (isComposingWord) { - final MainKeyboardView mainKeyboardView = keyboardSwitcher.getMainKeyboardView(); - // TODO: We should reconsider which coordinate system should be used to represent - // keyboard event. - final int keyX = mainKeyboardView.getKeyX(x); - final int keyY = mainKeyboardView.getKeyY(y); - mWordComposer.add(codePoint, keyX, keyY); + mWordComposer.add(codePoint, x, y); // If it's the first letter, make note of auto-caps state if (mWordComposer.size() == 1) { // We pass 1 to getPreviousWordForSuggestion because we were not composing a word @@ -585,13 +568,12 @@ public final class InputLogic { * Handle input of a separator code point. * @param settingsValues The current settings values. * @param codePoint the code point associated with the key. - * @param x the x-coordinate of the key press, or Contants.NOT_A_COORDINATE if not applicable. - * @param y the y-coordinate of the key press, or Contants.NOT_A_COORDINATE if not applicable. + * @param isFromSuggestionStrip whether this code point comes from the suggestion strip. * @param spaceState the space state at start of the batch input. * @return whether this caused an auto-correction to happen. */ private boolean handleSeparator(final SettingsValues settingsValues, - final int codePoint, final int x, final int y, final int spaceState, + final int codePoint, final boolean isFromSuggestionStrip, final int spaceState, // TODO: remove these arguments final KeyboardSwitcher keyboardSwitcher, final LatinIME.UIHandler handler) { boolean didAutoCorrect = false; @@ -618,7 +600,7 @@ public final class InputLogic { } final boolean swapWeakSpace = maybeStripSpace(settingsValues, codePoint, spaceState, - Constants.SUGGESTION_STRIP_COORDINATE == x); + isFromSuggestionStrip); if (SpaceState.PHANTOM == spaceState && settingsValues.isUsuallyPrecededBySpace(codePoint)) { @@ -667,9 +649,6 @@ public final class InputLogic { // already displayed or not, so it's okay. mLatinIME.setPunctuationSuggestions(); } - if (settingsValues.mIsInternal) { - LatinImeLoggerUtils.onSeparator((char)codePoint, x, y); - } keyboardSwitcher.updateShiftState(); return didAutoCorrect; @@ -723,7 +702,7 @@ public final class InputLogic { if (settingsValues.mIsInternal) { LatinImeLoggerUtils.onAutoCorrectionCancellation(); } - revertCommit(settingsValues, keyboardSwitcher, handler); + revertCommit(settingsValues, handler); return; } if (mEnteredText != null && mConnection.sameAsTextBeforeCursor(mEnteredText)) { @@ -819,7 +798,7 @@ public final class InputLogic { && !mConnection.isCursorFollowedByWordCharacter( settingsValues.mSpacingAndPunctuations)) { restartSuggestionsOnWordTouchedByCursor(settingsValues, - true /* includeResumedWordInSuggestions */, keyboardSwitcher); + true /* includeResumedWordInSuggestions */); } // We just removed at least one character. We need to update the auto-caps state. keyboardSwitcher.updateShiftState(); @@ -1057,9 +1036,7 @@ public final class InputLogic { */ // TODO: make this private. public void restartSuggestionsOnWordTouchedByCursor(final SettingsValues settingsValues, - final boolean includeResumedWordInSuggestions, - // TODO: Remove this argument. - final KeyboardSwitcher keyboardSwitcher) { + final boolean includeResumedWordInSuggestions) { // HACK: We may want to special-case some apps that exhibit bad behavior in case of // recorrection. This is a temporary, stopgap measure that will be removed later. // TODO: remove this. @@ -1086,7 +1063,7 @@ public final class InputLogic { final String typedWord = range.mWord.toString(); if (includeResumedWordInSuggestions) { suggestions.add(new SuggestedWordInfo(typedWord, - SuggestionStripView.MAX_SUGGESTIONS + 1, + SuggestedWords.MAX_SUGGESTIONS + 1, SuggestedWordInfo.KIND_TYPED, Dictionary.DICTIONARY_USER_TYPED, SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */, SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */)); @@ -1098,7 +1075,7 @@ public final class InputLogic { ++i; if (!TextUtils.equals(s, typedWord)) { suggestions.add(new SuggestedWordInfo(s, - SuggestionStripView.MAX_SUGGESTIONS - i, + SuggestedWords.MAX_SUGGESTIONS - i, SuggestedWordInfo.KIND_RESUMED, Dictionary.DICTIONARY_RESUMED, SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */, SuggestedWordInfo.NOT_A_CONFIDENCE @@ -1106,13 +1083,14 @@ public final class InputLogic { } } } - mWordComposer.setComposingWord(typedWord, + final int[] codePoints = StringUtils.toCodePointArray(typedWord); + mWordComposer.setComposingWord(codePoints, + mLatinIME.getCoordinatesForCurrentKeyboard(codePoints), getNthPreviousWordForSuggestion(settingsValues.mSpacingAndPunctuations, // We want the previous word for suggestion. If we have chars in the word // before the cursor, then we want the word before that, hence 2; otherwise, // we want the word immediately before the cursor, hence 1. - 0 == numberOfCharsInWordBeforeCursor ? 1 : 2), - keyboardSwitcher.getKeyboard()); + 0 == numberOfCharsInWordBeforeCursor ? 1 : 2)); mWordComposer.setCursorPositionWithinWord( typedWord.codePointCount(0, numberOfCharsInWordBeforeCursor)); mConnection.setComposingRegion(expectedCursorPosition - numberOfCharsInWordBeforeCursor, @@ -1167,8 +1145,8 @@ public final class InputLogic { * @param settingsValues the current settings values. */ private void revertCommit(final SettingsValues settingsValues, - // TODO: remove these arguments - final KeyboardSwitcher keyboardSwitcher, final LatinIME.UIHandler handler) { + // TODO: remove this argument + final LatinIME.UIHandler handler) { final String previousWord = mLastComposedWord.mPrevWord; final CharSequence originallyTypedWord = mLastComposedWord.mTypedWord; final CharSequence committedWord = mLastComposedWord.mCommittedWord; @@ -1196,8 +1174,8 @@ public final class InputLogic { previousWord, committedWord.toString()); } } - final SpannableString textToCommit = - new SpannableString(originallyTypedWord + mLastComposedWord.mSeparatorString); + final String stringToCommit = originallyTypedWord + mLastComposedWord.mSeparatorString; + final SpannableString textToCommit = new SpannableString(stringToCommit); if (committedWord instanceof SpannableString) { final int lastCharIndex = textToCommit.length() - 1; // Add the auto-correction to the list of suggestions. @@ -1229,8 +1207,9 @@ public final class InputLogic { } else { // For languages without spaces, we revert the typed string but the cursor is flush // with the typed word, so we need to resume suggestions right away. - mWordComposer.setComposingWord(textToCommit, previousWord, - keyboardSwitcher.getKeyboard()); + final int[] codePoints = StringUtils.toCodePointArray(stringToCommit); + mWordComposer.setComposingWord(codePoints, + mLatinIME.getCoordinatesForCurrentKeyboard(codePoints), previousWord); mConnection.setComposingText(textToCommit, 1); } if (settingsValues.mIsInternal) { @@ -1714,26 +1693,27 @@ public final class InputLogic { * @param settingsValues the current values of the settings. * @param tryResumeSuggestions Whether we should resume suggestions or not. * @param remainingTries How many times we may try again before giving up. + * @return whether true if the caches were successfully reset, false otherwise. */ // TODO: make this private - public void retryResetCaches(final SettingsValues settingsValues, + public boolean retryResetCachesAndReturnSuccess(final SettingsValues settingsValues, final boolean tryResumeSuggestions, final int remainingTries, // TODO: remove these arguments - final KeyboardSwitcher keyboardSwitcher, final LatinIME.UIHandler handler) { + final LatinIME.UIHandler handler) { if (!mConnection.resetCachesUponCursorMoveAndReturnSuccess( mConnection.getExpectedSelectionStart(), mConnection.getExpectedSelectionEnd(), - false)) { + false /* shouldFinishComposition */)) { if (0 < remainingTries) { handler.postResetCaches(tryResumeSuggestions, remainingTries - 1); - return; + return false; } - // If remainingTries is 0, we should stop waiting for new tries, but it's still - // better to load the keyboard (less things will be broken). + // If remainingTries is 0, we should stop waiting for new tries, however we'll still + // return true as we need to perform other tasks (for example, loading the keyboard). } mConnection.tryFixLyingCursorPosition(); - keyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), settingsValues); if (tryResumeSuggestions) { handler.postResumeSuggestions(); } + return true; } } diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java index d6e5b75ad..3947019ca 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java @@ -28,11 +28,13 @@ import android.view.textservice.SuggestionsInfo; import android.view.textservice.TextInfo; import com.android.inputmethod.compat.SuggestionsInfoCompatUtils; +import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Dictionary; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.WordComposer; import com.android.inputmethod.latin.spellcheck.AndroidSpellCheckerService.SuggestionsGatherer; +import com.android.inputmethod.latin.utils.CoordinateUtils; import com.android.inputmethod.latin.utils.LocaleUtils; import com.android.inputmethod.latin.utils.StringUtils; @@ -312,11 +314,15 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session { false /* reportAsTypo */); } final WordComposer composer = new WordComposer(); - final int length = text.length(); - for (int i = 0; i < length; i = text.offsetByCodePoints(i, 1)) { - final int codePoint = text.codePointAt(i); - composer.addKeyInfo(codePoint, dictInfo.getKeyboard(codePoint)); + final int[] codePoints = StringUtils.toCodePointArray(text); + final int[] coordinates; + if (null == dictInfo.mKeyboard) { + coordinates = CoordinateUtils.newCoordinateArray(codePoints.length, + Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE); + } else { + coordinates = dictInfo.mKeyboard.getCoordinates(codePoints); } + composer.setComposingWord(codePoints, coordinates, null /* previousWord */); // TODO: make a spell checker option to block offensive words or not final ArrayList<SuggestedWordInfo> suggestions = dictInfo.mDictionary.getSuggestions(composer, prevWord, diff --git a/java/src/com/android/inputmethod/latin/spellcheck/DictAndKeyboard.java b/java/src/com/android/inputmethod/latin/spellcheck/DictAndKeyboard.java index b77f3e2c5..1ffe50681 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/DictAndKeyboard.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/DictAndKeyboard.java @@ -27,7 +27,7 @@ import com.android.inputmethod.keyboard.ProximityInfo; */ public final class DictAndKeyboard { public final Dictionary mDictionary; - private final Keyboard mKeyboard; + public final Keyboard mKeyboard; private final Keyboard mManualShiftedKeyboard; public DictAndKeyboard( @@ -43,13 +43,6 @@ public final class DictAndKeyboard { keyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED); } - public Keyboard getKeyboard(final int codePoint) { - if (mKeyboard == null) { - return null; - } - return mKeyboard.getKey(codePoint) != null ? mKeyboard : mManualShiftedKeyboard; - } - public ProximityInfo getProximityInfo() { return mKeyboard == null ? null : mKeyboard.getProximityInfo(); } diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java index 52012c846..b96175f02 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java @@ -47,10 +47,10 @@ public final class MoreSuggestions extends Keyboard { } private static final class MoreSuggestionsParam extends KeyboardParams { - private final int[] mWidths = new int[SuggestionStripView.MAX_SUGGESTIONS]; - private final int[] mRowNumbers = new int[SuggestionStripView.MAX_SUGGESTIONS]; - private final int[] mColumnOrders = new int[SuggestionStripView.MAX_SUGGESTIONS]; - private final int[] mNumColumnsInRow = new int[SuggestionStripView.MAX_SUGGESTIONS]; + private final int[] mWidths = new int[SuggestedWords.MAX_SUGGESTIONS]; + private final int[] mRowNumbers = new int[SuggestedWords.MAX_SUGGESTIONS]; + private final int[] mColumnOrders = new int[SuggestedWords.MAX_SUGGESTIONS]; + private final int[] mNumColumnsInRow = new int[SuggestedWords.MAX_SUGGESTIONS]; private static final int MAX_COLUMNS_IN_ROW = 3; private int mNumRows; public Drawable mDivider; @@ -72,7 +72,7 @@ public final class MoreSuggestions extends Keyboard { int row = 0; int index = fromIndex; int rowStartIndex = fromIndex; - final int size = Math.min(suggestedWords.size(), SuggestionStripView.MAX_SUGGESTIONS); + final int size = Math.min(suggestedWords.size(), SuggestedWords.MAX_SUGGESTIONS); while (index < size) { final String word = suggestedWords.getWord(index); // TODO: Should take care of text x-scaling. diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index 073148a50..88b57f93b 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -53,9 +53,6 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick public void pickSuggestionManually(int index, SuggestedWordInfo word); } - // The maximum number of suggestions available. See {@link Suggest#mPrefMaxSuggestions}. - public static final int MAX_SUGGESTIONS = 18; - static final boolean DBG = LatinImeLogger.sDBG; private final ViewGroup mSuggestionsStrip; @@ -91,7 +88,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick inflater.inflate(R.layout.suggestions_strip, this); mSuggestionsStrip = (ViewGroup)findViewById(R.id.suggestions_strip); - for (int pos = 0; pos < MAX_SUGGESTIONS; pos++) { + for (int pos = 0; pos < SuggestedWords.MAX_SUGGESTIONS; pos++) { final TextView word = (TextView)inflater.inflate(R.layout.suggestion_word, null); word.setOnClickListener(this); word.setOnLongClickListener(this); diff --git a/java/src/com/android/inputmethod/latin/utils/CoordinateUtils.java b/java/src/com/android/inputmethod/latin/utils/CoordinateUtils.java index 72f2cd2d9..87df013a6 100644 --- a/java/src/com/android/inputmethod/latin/utils/CoordinateUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/CoordinateUtils.java @@ -16,17 +16,19 @@ package com.android.inputmethod.latin.utils; +import java.util.Arrays; + public final class CoordinateUtils { private static final int INDEX_X = 0; private static final int INDEX_Y = 1; - private static final int ARRAY_SIZE = INDEX_Y + 1; + private static final int ELEMENT_SIZE = INDEX_Y + 1; private CoordinateUtils() { // This utility class is not publicly instantiable. } public static int[] newInstance() { - return new int[ARRAY_SIZE]; + return new int[ELEMENT_SIZE]; } public static int x(final int[] coords) { @@ -46,4 +48,44 @@ public final class CoordinateUtils { destination[INDEX_X] = source[INDEX_X]; destination[INDEX_Y] = source[INDEX_Y]; } + + public static int[] newCoordinateArray(final int arraySize) { + return new int[ELEMENT_SIZE * arraySize]; + } + + public static int[] newCoordinateArray(final int arraySize, + final int defaultX, final int defaultY) { + final int[] result = new int[ELEMENT_SIZE * arraySize]; + for (int i = 0; i < arraySize; ++i) { + setXYInArray(result, i, defaultX, defaultY); + } + return result; + } + + public static int xFromArray(final int[] coordsArray, final int index) { + return coordsArray[ELEMENT_SIZE * index + INDEX_X]; + } + + public static int yFromArray(final int[] coordsArray, final int index) { + return coordsArray[ELEMENT_SIZE * index + INDEX_Y]; + } + + public static int[] coordinateFromArray(final int[] coordsArray, final int index) { + final int baseIndex = ELEMENT_SIZE * index; + return Arrays.copyOfRange(coordsArray, baseIndex, baseIndex + ELEMENT_SIZE); + } + + public static void setXYInArray(final int[] coordsArray, final int index, + final int x, final int y) { + final int baseIndex = ELEMENT_SIZE * index; + coordsArray[baseIndex + INDEX_X] = x; + coordsArray[baseIndex + INDEX_Y] = y; + } + + public static void setCoordinateInArray(final int[] coordsArray, final int index, + final int[] coords) { + final int baseIndex = ELEMENT_SIZE * index; + coordsArray[baseIndex + INDEX_X] = coords[INDEX_X]; + coordsArray[baseIndex + INDEX_Y] = coords[INDEX_Y]; + } } diff --git a/java/src/com/android/inputmethod/latin/utils/StringUtils.java b/java/src/com/android/inputmethod/latin/utils/StringUtils.java index 5920c68f1..6f15b11bf 100644 --- a/java/src/com/android/inputmethod/latin/utils/StringUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/StringUtils.java @@ -171,13 +171,26 @@ public final class StringUtils { private static final int[] EMPTY_CODEPOINTS = {}; public static int[] toCodePointArray(final String string) { + return toCodePointArray(string, 0, string.length()); + } + + /** + * Converts a range of a string to an array of code points. + * @param string the source string. + * @param startIndex the start index inside the string in java chars, inclusive. + * @param endIndex the end index inside the string in java chars, exclusive. + * @return a new array of code points. At most endIndex - startIndex, but possibly less. + */ + public static int[] toCodePointArray(final String string, + final int startIndex, final int endIndex) { final int length = string.length(); if (length <= 0) { return EMPTY_CODEPOINTS; } - final int[] codePoints = new int[string.codePointCount(0, length)]; + final int[] codePoints = new int[string.codePointCount(startIndex, endIndex)]; int destIndex = 0; - for (int index = 0; index < length; index = string.offsetByCodePoints(index, 1)) { + for (int index = startIndex; index < endIndex; + index = string.offsetByCodePoints(index, 1)) { codePoints[destIndex] = string.codePointAt(index); destIndex++; } diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java index 11fb3a156..2a8148d02 100644 --- a/java/src/com/android/inputmethod/research/ResearchLogger.java +++ b/java/src/com/android/inputmethod/research/ResearchLogger.java @@ -109,7 +109,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang // feedback mechanism to generate multiple tests. private static final boolean FEEDBACK_DIALOG_SHOULD_PRESERVE_TEXT_FIELD = false; /* package */ static boolean sIsLogging = false; - private static final int OUTPUT_FORMAT_VERSION = 5; + private static final int OUTPUT_FORMAT_VERSION = 6; // Whether all words should be recorded, leaving unsampled word between bigrams. Useful for // testing. /* package for test */ static final boolean IS_LOGGING_EVERYTHING = false |