Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0fd625bc authored by Jean Chalard's avatar Jean Chalard
Browse files

Fix a bug with wrong auto-correct cancellation

Auto-correct cancellation would sometimes kick in at
wrong times, causing crashes.

Bug: 5784542
Change-Id: I68dd6b8d9237ce9b66af2dc63e77ba6dd5fd69dd
parent 752d8cc4
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -1071,7 +1071,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
    public void commitTyped(final InputConnection ic) {
        if (!mWordComposer.isComposingWord()) return;
        final CharSequence typedWord = mWordComposer.getTypedWord();
        mWordComposer.onCommitWord();
        mWordComposer.onCommitWord(WordComposer.COMMIT_TYPE_USER_TYPED_WORD);
        if (typedWord.length() > 0) {
            if (ic != null) {
                ic.commitText(typedWord, 1);
@@ -1802,7 +1802,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
            }
            Utils.Stats.onAutoCorrection(typedWord, autoCorrection.toString(), separatorCodePoint);
            mExpectingUpdateSelection = true;
            commitBestWord(autoCorrection);
            commitChosenWord(autoCorrection, WordComposer.COMMIT_TYPE_DECIDED_WORD);
            // Add the word to the user unigram dictionary if it's not a known word
            addToUserUnigramAndBigramDictionaries(autoCorrection,
                    UserUnigramDictionary.FREQUENCY_FOR_TYPED);
@@ -1868,7 +1868,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
            return;
        }
        mExpectingUpdateSelection = true;
        commitBestWord(suggestion);
        commitChosenWord(suggestion, WordComposer.COMMIT_TYPE_MANUAL_PICK);
        // Add the word to the auto dictionary if it's not a known word
        if (index == 0) {
            addToUserUnigramAndBigramDictionaries(suggestion,
@@ -1927,7 +1927,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
    /**
     * Commits the chosen word to the text field and saves it for later retrieval.
     */
    private void commitBestWord(CharSequence bestWord) {
    private void commitChosenWord(final CharSequence bestWord, final int commitType) {
        final KeyboardSwitcher switcher = mKeyboardSwitcher;
        if (!switcher.isKeyboardAvailable())
            return;
@@ -1942,7 +1942,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
                ic.commitText(bestWord, 1);
            }
        }
        mWordComposer.onCommitWord();
        // TODO: figure out here if this is an auto-correct or if the best word is actually
        // what user typed. Note: currently this is done much later in
        // WordComposer#didAutoCorrectToAnotherWord by string equality of the remembered
        // strings.
        mWordComposer.onCommitWord(commitType);
    }

    private static final WordComposer sEmptyWordComposer = new WordComposer();
@@ -2118,7 +2122,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
        // Re-insert the separator
        ic.commitText(separator, 1);
        mWordComposer.deleteAutoCorrection();
        mWordComposer.onCommitWord();
        mWordComposer.onCommitWord(WordComposer.COMMIT_TYPE_CANCEL_AUTO_CORRECT);
        Utils.Stats.onSeparator(separator.charAt(0), WordComposer.NOT_A_COORDINATE,
                WordComposer.NOT_A_COORDINATE);
        mHandler.cancelUpdateBigramPredictions();
+37 −7
Original line number Diff line number Diff line
@@ -33,6 +33,23 @@ public class WordComposer {
    public static final int NOT_A_CODE = KeyDetector.NOT_A_CODE;
    public static final int NOT_A_COORDINATE = -1;

    // TODO: Straighten out commit behavior so that the flags here are more understandable,
    // and possibly adjust their names.
    // COMMIT_TYPE_USER_TYPED_WORD is used when the word committed is the exact typed word, with
    // no hinting from the IME. It happens when some external event happens (rotating the device,
    // for example) or when auto-correction is off by settings or editor attributes.
    public static final int COMMIT_TYPE_USER_TYPED_WORD = 0;
    // COMMIT_TYPE_MANUAL_PICK is used when the user pressed a field in the suggestion strip.
    public static final int COMMIT_TYPE_MANUAL_PICK = 1;
    // COMMIT_TYPE_DECIDED_WORD is used when the IME commits the word it decided was best
    // for the current user input. It may be different from what the user typed (true auto-correct)
    // or it may be exactly what the user typed if it's in the dictionary or the IME does not have
    // enough confidence in any suggestion to auto-correct (auto-correct to typed word).
    public static final int COMMIT_TYPE_DECIDED_WORD = 2;
    // COMMIT_TYPE_CANCEL_AUTO_CORRECT is used upon committing back the old word upon cancelling
    // an auto-correction.
    public static final int COMMIT_TYPE_CANCEL_AUTO_CORRECT = 3;

    // Storage for all the info about the current input.
    private static class CharacterStore {
        /**
@@ -329,10 +346,23 @@ public class WordComposer {
        return mCurrentWord.mAutoCorrection;
    }

    // TODO: pass the information about what was committed and how. Was it an auto-correction?
    // Was it a completion? Was is what the user typed?
    public void onCommitWord() {
    // `type' should be one of the COMMIT_TYPE_* constants above.
    public void onCommitWord(final int type) {
        mCommittedWordSavedForSuggestionResuming = mCurrentWord;
        // Note: currently, we come here whenever we commit a word. If it's any *other* kind that
        // DECIDED_WORD, we should reset mAutoCorrection so that we don't attempt to cancel later.
        // If it's a DECIDED_WORD, it may be an actual auto-correction by the IME, or what the user
        // typed because the IME decided *not* to auto-correct for whatever reason.
        // Ideally we would also null it when it was a DECIDED_WORD that was not an auto-correct.
        // As it happens these two cases should behave differently, because the former can be
        // canceled while the latter can't. Currently, we figure this out in
        // #didAutoCorrectToAnotherWord with #equals(). It would be marginally cleaner to do it
        // here, but it would be slower (since we would #equals() for each commit, instead of
        // only on cancel), and ultimately we want to figure it out even earlier anyway.
        if (type != COMMIT_TYPE_DECIDED_WORD) {
            // Only ever revert an auto-correct.
            mCommittedWordSavedForSuggestionResuming.mAutoCorrection = null;
        }
        // TODO: improve performance by swapping buffers instead of creating a new object.
        mCurrentWord = new CharacterStore();
    }