aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin/LatinIME.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/latin/LatinIME.java')
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java143
1 files changed, 82 insertions, 61 deletions
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index a67e4c938..34699a47b 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -203,7 +203,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private boolean mApplicationSpecifiedCompletionOn;
private WordComposer mWordComposer = new WordComposer();
- private CharSequence mBestWord;
private boolean mHasUncommittedTypedChars;
private int mCorrectionMode;
@@ -1019,7 +1018,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
.setHasMinimalSuggestion(false);
// When in fullscreen mode, show completions generated by the application
setSuggestions(builder.build());
- mBestWord = null;
+ mWordComposer.deleteAutoCorrection();
setSuggestionStripShown(true);
}
}
@@ -1415,12 +1414,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
final int length = mWordComposer.size();
if (length > 0) {
mWordComposer.deleteLast();
- final CharSequence textWithUnderline =
- mComposingStateManager.isAutoCorrectionIndicatorOn()
- ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(
- this, mWordComposer.getTypedWord())
- : mWordComposer.getTypedWord();
- ic.setComposingText(textWithUnderline, 1);
+ ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
if (mWordComposer.size() == 0) {
mHasUncommittedTypedChars = false;
// Remaining size equals zero means we just erased the last character of the
@@ -1501,21 +1495,31 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private void handleCharacter(final int primaryCode, final int[] keyCodes, final int x,
final int y, final int spaceState) {
mVoiceProxy.handleCharacter();
-
final InputConnection ic = getCurrentInputConnection();
- if (ic != null) ic.beginBatchEdit();
+ 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);
+ 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,
+ final int x, final int y, final int spaceState, final InputConnection ic) {
if (SPACE_STATE_MAGIC == spaceState
&& mSettingsValues.isMagicSpaceStripper(primaryCode)) {
- removeTrailingSpaceWhileInBatchEdit(ic);
+ if (null != ic) removeTrailingSpaceWhileInBatchEdit(ic);
}
+ boolean isComposingWord = mHasUncommittedTypedChars;
int code = primaryCode;
if ((isAlphabet(code) || mSettingsValues.isSymbolExcludedFromWordSeparators(code))
&& isSuggestionsRequested() && !isCursorTouchingWord()) {
- if (!mHasUncommittedTypedChars) {
+ if (!isComposingWord) {
// Reset entirely the composing state anyway, then start composing a new word unless
- // the character is a single quote.
- mHasUncommittedTypedChars = (Keyboard.CODE_SINGLE_QUOTE != code);
+ // the character is a single quote. The idea here is, single quote is not a
+ // separator and it should be treated as a normal character, except in the first
+ // position where it should not start composing a word.
+ isComposingWord = (Keyboard.CODE_SINGLE_QUOTE != code);
mWordComposer.reset();
clearSuggestions();
mComposingStateManager.onFinishComposingText();
@@ -1525,7 +1529,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (switcher.isShiftedOrShiftLocked()) {
if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT
|| keyCodes[0] > Character.MAX_CODE_POINT) {
- if (null != ic) ic.endBatchEdit();
return;
}
code = keyCodes[0];
@@ -1539,12 +1542,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
} else {
// Some keys, such as [eszett], have upper case as multi-characters.
onTextInput(upperCaseString);
- if (null != ic) ic.endBatchEdit();
return;
}
}
}
- if (mHasUncommittedTypedChars) {
+ if (isComposingWord) {
+ mHasUncommittedTypedChars = true;
mWordComposer.add(code, keyCodes, x, y);
if (ic != null) {
// If it's the first letter, make note of auto-caps state
@@ -1552,12 +1555,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mWordComposer.setAutoCapitalized(getCurrentAutoCapsState());
mComposingStateManager.onStartComposingText();
}
- final CharSequence textWithUnderline =
- mComposingStateManager.isAutoCorrectionIndicatorOn()
- ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(
- this, mWordComposer.getTypedWord())
- : mWordComposer.getTypedWord();
- ic.setComposingText(textWithUnderline, 1);
+ ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
}
mHandler.postUpdateSuggestions();
} else {
@@ -1574,7 +1572,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
} else {
Utils.Stats.onNonSeparator((char)code, x, y);
}
- if (null != ic) ic.endBatchEdit();
}
private void handleSeparator(final int primaryCode, final int x, final int y,
@@ -1611,6 +1608,21 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
}
+ if (pickedDefault) {
+ final CharSequence autoCorrection = mWordComposer.getAutoCorrectionOrNull();
+ final String typedWord = mWordComposer.getTypedWord();
+ if (TextUtils.isEmpty(typedWord)) {
+ throw new RuntimeException("We have non-committed chars but the typed word "
+ + "is empty? Impossible! I must commit suicide.");
+ }
+ if (!typedWord.equals(autoCorrection)) {
+ // This will make the correction flash for a short while as a visual clue
+ // to the user that auto-correction happened.
+ InputConnectionCompatUtils.commitCorrection(
+ ic, mLastSelectionEnd - typedWord.length(), typedWord, autoCorrection);
+ }
+ }
+
final boolean swapMagicSpace;
if (Keyboard.CODE_ENTER == primaryCode && (SPACE_STATE_MAGIC == spaceState
|| SPACE_STATE_SWAP_PUNCTUATION == spaceState)) {
@@ -1658,19 +1670,18 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
Utils.Stats.onSeparator((char)primaryCode, x, y);
- if (pickedDefault) {
- CharSequence typedWord = mWordComposer.getTypedWord();
- if (!TextUtils.isEmpty(typedWord) && !typedWord.equals(mBestWord)) {
- InputConnectionCompatUtils.commitCorrection(
- ic, mLastSelectionEnd - typedWord.length(), typedWord, mBestWord);
- }
- }
mKeyboardSwitcher.updateShiftState();
if (ic != null) {
ic.endBatchEdit();
}
}
+ private CharSequence getTextWithUnderline(final CharSequence text) {
+ return mComposingStateManager.isAutoCorrectionIndicatorOn()
+ ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(this, text)
+ : mWordComposer.getTypedWord();
+ }
+
private void handleClose() {
commitTyped(getCurrentInputConnection());
mVoiceProxy.handleClose();
@@ -1744,18 +1755,21 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mComposingStateManager.isAutoCorrectionIndicatorOn();
final boolean newAutoCorrectionIndicator = Utils.willAutoCorrect(words);
if (oldAutoCorrectionIndicator != newAutoCorrectionIndicator) {
- if (LatinImeLogger.sDBG) {
+ mComposingStateManager.setAutoCorrectionIndicatorOn(newAutoCorrectionIndicator);
+ if (DEBUG) {
Log.d(TAG, "Flip the indicator. " + oldAutoCorrectionIndicator
+ " -> " + newAutoCorrectionIndicator);
+ if (newAutoCorrectionIndicator
+ != mComposingStateManager.isAutoCorrectionIndicatorOn()) {
+ throw new RuntimeException("Couldn't flip the indicator! We are not "
+ + "composing a word right now.");
+ }
}
- final CharSequence textWithUnderline = newAutoCorrectionIndicator
- ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(
- this, mWordComposer.getTypedWord())
- : mWordComposer.getTypedWord();
+ final CharSequence textWithUnderline =
+ getTextWithUnderline(mWordComposer.getTypedWord());
if (!TextUtils.isEmpty(textWithUnderline)) {
ic.setComposingText(textWithUnderline, 1);
}
- mComposingStateManager.setAutoCorrectionIndicatorOn(newAutoCorrectionIndicator);
}
}
}
@@ -1775,7 +1789,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
return;
}
- final WordComposer wordComposer = mWordComposer;
// TODO: May need a better way of retrieving previous word
final InputConnection ic = getCurrentInputConnection();
final CharSequence prevWord;
@@ -1785,18 +1798,18 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
prevWord = EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators);
}
// getSuggestedWordBuilder handles gracefully a null value of prevWord
- final SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(wordComposer,
+ final SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(mWordComposer,
prevWord, mKeyboardSwitcher.getLatinKeyboard().getProximityInfo(), mCorrectionMode);
boolean autoCorrectionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasAutoCorrection();
- final CharSequence typedWord = wordComposer.getTypedWord();
+ final CharSequence typedWord = mWordComposer.getTypedWord();
// Here, we want to promote a whitelisted word if exists.
// TODO: Change this scheme - a boolean is not enough. A whitelisted word may be "valid"
// but still autocorrected from - in the case the whitelist only capitalizes the word.
// The whitelist should be case-insensitive, so it's not possible to be consistent with
// a boolean flag. Right now this is handled with a slight hack in
// WhitelistDictionary#shouldForciblyAutoCorrectFrom.
- final int quotesCount = wordComposer.trailingSingleQuotesCount();
+ final int quotesCount = mWordComposer.trailingSingleQuotesCount();
final boolean allowsToBeAutoCorrected = AutoCorrection.allowsToBeAutoCorrected(
mSuggest.getUnigramDictionaries(),
// If the typed string ends with a single quote, for dictionary lookup purposes
@@ -1812,7 +1825,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
autoCorrectionAvailable |= (!allowsToBeAutoCorrected);
}
// Don't auto-correct words with multiple capital letter
- autoCorrectionAvailable &= !wordComposer.isMostlyCaps();
+ autoCorrectionAvailable &= !mWordComposer.isMostlyCaps();
// Basically, we update the suggestion strip only when suggestion count > 1. However,
// there is an exception: We update the suggestion strip whenever typed word's length
@@ -1848,14 +1861,15 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
setSuggestions(suggestedWords);
if (suggestedWords.size() > 0) {
if (shouldBlockAutoCorrectionBySafetyNet) {
- mBestWord = typedWord;
+ mWordComposer.setAutoCorrection(typedWord);
} else if (suggestedWords.hasAutoCorrectionWord()) {
- mBestWord = suggestedWords.getWord(1);
+ mWordComposer.setAutoCorrection(suggestedWords.getWord(1));
} else {
- mBestWord = typedWord;
+ mWordComposer.setAutoCorrection(typedWord);
}
} else {
- mBestWord = null;
+ // TODO: replace with mWordComposer.deleteAutoCorrection()?
+ mWordComposer.setAutoCorrection(null);
}
setSuggestionStripShown(isSuggestionsStripVisible());
}
@@ -1866,16 +1880,17 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mHandler.cancelUpdateSuggestions();
updateSuggestions();
}
- if (mBestWord != null && mBestWord.length() > 0) {
- Utils.Stats.onAutoCorrection(mWordComposer.getTypedWord(), mBestWord.toString(),
- separatorCode);
+ final CharSequence autoCorrection = mWordComposer.getAutoCorrectionOrNull();
+ if (autoCorrection != null) {
+ final String typedWord = mWordComposer.getTypedWord();
+ Utils.Stats.onAutoCorrection(typedWord, autoCorrection.toString(), separatorCode);
mExpectingUpdateSelection = true;
- commitBestWord(mBestWord);
- if (!mBestWord.equals(mWordComposer.getTypedWord())) {
- mWordSavedForAutoCorrectCancellation = mBestWord.toString();
+ commitBestWord(autoCorrection);
+ if (!autoCorrection.equals(typedWord)) {
+ mWordSavedForAutoCorrectCancellation = autoCorrection.toString();
}
// Add the word to the user unigram dictionary if it's not a known word
- addToUserUnigramAndBigramDictionaries(mBestWord,
+ addToUserUnigramAndBigramDictionaries(autoCorrection,
UserUnigramDictionary.FREQUENCY_FOR_TYPED);
return true;
}
@@ -1947,6 +1962,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
} else {
addToOnlyBigramDictionary(suggestion, 1);
}
+ // TODO: the following is fishy, because if !mHasUncommittedTypedChars we are
+ // going to log an empty string
LatinImeLogger.logOnManualSuggestion(mWordComposer.getTypedWord().toString(),
suggestion.toString(), index, suggestions.mWords);
// Follow it with a space
@@ -2154,8 +2171,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private void restartSuggestionsOnWordBeforeCursor(final InputConnection ic,
final CharSequence word) {
mWordComposer.setComposingWord(word, mKeyboardSwitcher.getLatinKeyboard());
- // mBestWord will be set appropriately by updateSuggestions() called by the handler
- mBestWord = null;
mHasUncommittedTypedChars = true;
mComposingStateManager.onStartComposingText();
ic.deleteSurroundingText(word.length(), 0);
@@ -2226,8 +2241,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// Here we test whether we indeed have a period and a space before us. This should not
// be needed, but it's there just in case something went wrong.
final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0);
- if (!". ".equals(textBeforeCursor))
- return false;
+ if (!". ".equals(textBeforeCursor)) {
+ // We should not have come here if we aren't just after a ". ".
+ throw new RuntimeException("Tried to revert double-space combo but we didn't find "
+ + "\". \" just before the cursor.");
+ }
ic.beginBatchEdit();
ic.deleteSurroundingText(2, 0);
ic.commitText(" ", 1);
@@ -2241,8 +2259,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0);
// NOTE: This does not work with surrogate pairs. Hopefully when the keyboard is able to
// enter surrogate pairs this code will have been removed.
- if (Keyboard.CODE_SPACE != textBeforeCursor.charAt(1))
- return false;
+ if (Keyboard.CODE_SPACE != textBeforeCursor.charAt(1)) {
+ // We should not have come here if the text before the cursor is not a space.
+ throw new RuntimeException("Tried to revert a swap of punctiation but we didn't "
+ + "find a space just before the cursor.");
+ }
ic.beginBatchEdit();
ic.deleteSurroundingText(2, 0);
ic.commitText(" " + textBeforeCursor.subSequence(0, 1), 1);
@@ -2383,8 +2404,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
}
- public WordComposer getCurrentWord() {
- return mWordComposer;
+ public boolean isAutoCapitalized() {
+ return mWordComposer.isAutoCapitalized();
}
boolean isSoundOn() {