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

Commit 2532265d authored by Jean Chalard's avatar Jean Chalard Committed by Android Git Automerger
Browse files

am 34676d92: am a022c538: Merge "If there are no suggestion span, recompute suggestions."

* commit '34676d92':
  If there are no suggestion span, recompute suggestions.
parents da9c04cd 34676d92
Loading
Loading
Loading
Loading
+57 −14
Original line number Diff line number Diff line
@@ -1466,8 +1466,14 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
                                "", mWordComposer.getTypedWord(), " ", mWordComposer);
                    }
                }
                if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
                    // If we are in the middle of a recorrection, we need to commit the recorrection
                    // first so that we can insert the character at the current cursor position.
                    resetEntireInputState(mLastSelectionStart);
                } else {
                    commitTyped(LastComposedWord.NOT_A_SEPARATOR);
                }
            }
            final int keyX, keyY;
            final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
            if (keyboard != null && keyboard.hasProximityCharsCorrection(primaryCode)) {
@@ -1522,8 +1528,12 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
            }
            final int wordComposerSize = mWordComposer.size();
            // Since isComposingWord() is true, the size is at least 1.
            final int lastChar = mWordComposer.getCodeAt(wordComposerSize - 1);
            if (wordComposerSize <= 1) {
            final int lastChar = mWordComposer.getCodeBeforeCursor();
            if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
                // If we are in the middle of a recorrection, we need to commit the recorrection
                // first so that we can insert the batch input at the current cursor position.
                resetEntireInputState(mLastSelectionStart);
            } else if (wordComposerSize <= 1) {
                // We auto-correct the previous (typed, not gestured) string iff it's one character
                // long. The reason for this is, even in the middle of gesture typing, you'll still
                // tap one-letter words and you want them auto-corrected (typically, "i" in English
@@ -1734,8 +1744,11 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
        // during key repeat.
        mHandler.postUpdateShiftState();

        if (mWordComposer.isComposingWord() && !mWordComposer.isCursorAtEndOfComposingWord()) {
        if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
            // If we are in the middle of a recorrection, we need to commit the recorrection
            // first so that we can remove the character at the current cursor position.
            resetEntireInputState(mLastSelectionStart);
            // When we exit this if-clause, mWordComposer.isComposingWord() will return false.
        }
        if (mWordComposer.isComposingWord()) {
            final int length = mWordComposer.size();
@@ -1870,7 +1883,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
            promotePhantomSpace();
        }

        if (mWordComposer.isComposingWord() && !mWordComposer.isCursorAtEndOfComposingWord()) {
        if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
            // If we are in the middle of a recorrection, we need to commit the recorrection
            // first so that we can insert the character at the current cursor position.
            resetEntireInputState(mLastSelectionStart);
            isComposingWord = false;
        }
@@ -1935,7 +1950,11 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
            ResearchLogger.latinIME_handleSeparator(primaryCode, mWordComposer.isComposingWord());
        }
        boolean didAutoCorrect = false;
        // Handle separator
        if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
            // If we are in the middle of a recorrection, we need to commit the recorrection
            // first so that we can insert the separator at the current cursor position.
            resetEntireInputState(mLastSelectionStart);
        }
        if (mWordComposer.isComposingWord()) {
            if (mSettings.getCurrent().mCorrectionEnabled) {
                // TODO: maybe cache Strings in an <String> sparse array or something
@@ -2357,9 +2376,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
        final Range range = mConnection.getWordRangeAtCursor(mSettings.getWordSeparators(),
                0 /* additionalPrecedingWordsCount */);
        final ArrayList<SuggestedWordInfo> suggestions = CollectionUtils.newArrayList();
        final String typedWord = range.mWord.toString();
        if (range.mWord instanceof SpannableString) {
            final SpannableString spannableString = (SpannableString)range.mWord;
            final String typedWord = spannableString.toString();
            int i = 0;
            for (Object object : spannableString.getSpans(0, spannableString.length(),
                    SuggestionSpan.class)) {
@@ -2374,18 +2393,42 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
                }
            }
        }
        mWordComposer.setComposingWord(range.mWord, mKeyboardSwitcher.getKeyboard());
        mWordComposer.setComposingWord(typedWord, mKeyboardSwitcher.getKeyboard());
        mWordComposer.setCursorPositionWithinWord(range.mCharsBefore);
        mConnection.setComposingRegion(mLastSelectionStart - range.mCharsBefore,
                mLastSelectionEnd + range.mCharsAfter);
        final SuggestedWords suggestedWords;
        if (suggestions.isEmpty()) {
            suggestions.add(new SuggestedWordInfo(range.mWord.toString(), 1,
                    SuggestedWordInfo.KIND_TYPED, Dictionary.TYPE_RESUMED));
            // We come here if there weren't any suggestion spans on this word. We will try to
            // compute suggestions for it instead.
            final SuggestedWords suggestedWordsIncludingTypedWord =
                    getSuggestedWords(Suggest.SESSION_TYPING);
            if (suggestedWordsIncludingTypedWord.size() > 1) {
                // We were able to compute new suggestions for this word.
                // Remove the typed word, since we don't want to display it in this case.
                // The #getSuggestedWordsExcludingTypedWord() method sets willAutoCorrect to false.
                suggestedWords =
                        suggestedWordsIncludingTypedWord.getSuggestedWordsExcludingTypedWord();
            } else {
                // No saved suggestions, and we were unable to compute any good one either.
                // Rather than displaying an empty suggestion strip, we'll display the original
                // word alone in the middle.
                // Since there is only one word, willAutoCorrect is false.
                suggestedWords = suggestedWordsIncludingTypedWord;
            }
        showSuggestionStrip(new SuggestedWords(suggestions,
        } else {
            // We found suggestion spans in the word. We'll create the SuggestedWords out of
            // them, and make willAutoCorrect false.
            suggestedWords = new SuggestedWords(suggestions,
                    true /* typedWordValid */, false /* willAutoCorrect */,
                    false /* isPunctuationSuggestions */, false /* isObsoleteSuggestions */,
                false /* isPrediction */), range.mWord.toString());
                    false /* isPrediction */);
        }

        // Note that it's very important here that suggestedWords.mWillAutoCorrect is false.
        // We never want to auto-correct on a resumed suggestion. Please refer to the three
        // places above where suggestedWords is affected.
        showSuggestionStrip(suggestedWords, typedWord);
    }

    /**
+17 −0
Original line number Diff line number Diff line
@@ -195,4 +195,21 @@ public final class SuggestedWords {
            }
        }
    }

    // SuggestedWords is an immutable object, as much as possible. We must not just remove
    // words from the member ArrayList as some other parties may expect the object to never change.
    public SuggestedWords getSuggestedWordsExcludingTypedWord() {
        final ArrayList<SuggestedWordInfo> newSuggestions = CollectionUtils.newArrayList();
        for (int i = 0; i < mSuggestedWordInfoList.size(); ++i) {
            final SuggestedWordInfo info = mSuggestedWordInfoList.get(i);
            if (SuggestedWordInfo.KIND_TYPED != info.mKind) {
                newSuggestions.add(info);
            }
        }
        // We should never autocorrect, so we say the typed word is valid. Also, in this case,
        // no auto-correction should take place hence willAutoCorrect = false.
        return new SuggestedWords(newSuggestions, true /* typedWordValid */,
                false /* willAutoCorrect */, mIsPunctuationSuggestions, mIsObsoleteSuggestions,
                mIsPrediction);
    }
}
+14 −2
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import java.util.Arrays;
 */
public final class WordComposer {
    private static final int MAX_WORD_LENGTH = Constants.Dictionary.MAX_WORD_LENGTH;
    private static final boolean DBG = LatinImeLogger.sDBG;

    public static final int CAPS_MODE_OFF = 0;
    // 1 is shift bit, 2 is caps bit, 4 is auto bit but this is just a convention as these bits
@@ -132,6 +133,13 @@ public final class WordComposer {
        return mPrimaryKeyCodes[index];
    }

    public int getCodeBeforeCursor() {
        if (mCursorPositionWithinWord < 1 || mCursorPositionWithinWord > mPrimaryKeyCodes.length) {
            return Constants.NOT_A_CODE;
        }
        return mPrimaryKeyCodes[mCursorPositionWithinWord - 1];
    }

    public InputPointers getInputPointers() {
        return mInputPointers;
    }
@@ -177,8 +185,12 @@ public final class WordComposer {
        mCursorPositionWithinWord = posWithinWord;
    }

    public boolean isCursorAtEndOfComposingWord() {
        return mCursorPositionWithinWord == mCodePointSize;
    public boolean isCursorFrontOrMiddleOfComposingWord() {
        if (DBG && mCursorPositionWithinWord > mCodePointSize) {
            throw new RuntimeException("Wrong cursor position : " + mCursorPositionWithinWord
                    + "in a word of size " + mCodePointSize);
        }
        return mCursorPositionWithinWord != mCodePointSize;
    }

    public void setBatchInputPointers(final InputPointers batchPointers) {
+60 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.inputmethod.latin;

import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;

import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;

import java.util.ArrayList;
import java.util.Locale;

@SmallTest
public class SuggestedWordsTests extends AndroidTestCase {
    public void testGetSuggestedWordsExcludingTypedWord() {
        final String TYPED_WORD = "typed";
        final int TYPED_WORD_FREQ = 5;
        final int NUMBER_OF_ADDED_SUGGESTIONS = 5;
        final ArrayList<SuggestedWordInfo> list = CollectionUtils.newArrayList();
        list.add(new SuggestedWordInfo(TYPED_WORD, TYPED_WORD_FREQ,
                SuggestedWordInfo.KIND_TYPED, ""));
        for (int i = 0; i < NUMBER_OF_ADDED_SUGGESTIONS; ++i) {
            list.add(new SuggestedWordInfo("" + i, 1, SuggestedWordInfo.KIND_CORRECTION, ""));
        }

        final SuggestedWords words = new SuggestedWords(
                list,
                false /* typedWordValid */,
                false /* willAutoCorrect */,
                false /* isPunctuationSuggestions */,
                false /* isObsoleteSuggestions */,
                false /* isPrediction*/);
        assertEquals(NUMBER_OF_ADDED_SUGGESTIONS + 1, words.size());
        assertEquals("typed", words.getWord(0));
        assertEquals(SuggestedWordInfo.KIND_TYPED, words.getInfo(0).mKind);
        assertEquals("0", words.getWord(1));
        assertEquals(SuggestedWordInfo.KIND_CORRECTION, words.getInfo(1).mKind);
        assertEquals("4", words.getWord(5));
        assertEquals(SuggestedWordInfo.KIND_CORRECTION, words.getInfo(5).mKind);

        final SuggestedWords wordsWithoutTyped = words.getSuggestedWordsExcludingTypedWord();
        assertEquals(words.size() - 1, wordsWithoutTyped.size());
        assertEquals("0", wordsWithoutTyped.getWord(0));
        assertEquals(SuggestedWordInfo.KIND_CORRECTION, wordsWithoutTyped.getInfo(0).mKind);
    }
}