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

Commit 91bcf5eb authored by Jean Chalard's avatar Jean Chalard Committed by Android (Google) Code Review
Browse files

Merge "Restart suggestions when the cursor moves."

parents 02ce3dc2 6a114fa7
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@ public abstract class Dictionary {
    public static final String TYPE_USER = "user";
    // User history dictionary internal to LatinIME.
    public static final String TYPE_USER_HISTORY = "history";
    // Spawned by resuming suggestions. Comes from a span that was in the TextView.
    public static final String TYPE_RESUMED = "resumed";
    protected final String mDictType;

    public Dictionary(final String dictType) {
+67 −7
Original line number Diff line number Diff line
@@ -44,7 +44,9 @@ import android.os.Message;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.text.InputType;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.SuggestionSpan;
import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Printer;
@@ -72,6 +74,7 @@ import com.android.inputmethod.keyboard.KeyboardActionListener;
import com.android.inputmethod.keyboard.KeyboardId;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.MainKeyboardView;
import com.android.inputmethod.latin.RichInputConnection.Range;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.Utils.Stats;
import com.android.inputmethod.latin.define.ProductionFlag;
@@ -197,6 +200,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
        private static final int MSG_PENDING_IMS_CALLBACK = 1;
        private static final int MSG_UPDATE_SUGGESTION_STRIP = 2;
        private static final int MSG_SHOW_GESTURE_PREVIEW_AND_SUGGESTION_STRIP = 3;
        private static final int MSG_RESUME_SUGGESTIONS = 4;

        private static final int ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1;

@@ -234,6 +238,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
                latinIme.showGesturePreviewAndSuggestionStrip((SuggestedWords)msg.obj,
                        msg.arg1 == ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT);
                break;
            case MSG_RESUME_SUGGESTIONS:
                latinIme.restartSuggestionsOnWordTouchedByCursor();
                break;
            }
        }

@@ -241,6 +248,10 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
            sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTION_STRIP), mDelayUpdateSuggestions);
        }

        public void postResumeSuggestions() {
            sendMessageDelayed(obtainMessage(MSG_RESUME_SUGGESTIONS), mDelayUpdateSuggestions);
        }

        public void cancelUpdateSuggestionStrip() {
            removeMessages(MSG_UPDATE_SUGGESTION_STRIP);
        }
@@ -910,13 +921,12 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
                resetEntireInputState(newSelStart);
            }

            // We moved the cursor. If we are touching a word, we need to resume suggestion.
            mHandler.postResumeSuggestions();

            mKeyboardSwitcher.updateShiftState();
        }
        mExpectingUpdateSelection = false;
        // TODO: Decide to call restartSuggestionsOnWordBeforeCursorIfAtEndOfWord() or not
        // here. It would probably be too expensive to call directly here but we may want to post a
        // message to delay it. The point would be to unify behavior between backspace to the
        // end of a word and manually put the pointer at the end of the word.

        // Make a note of the cursor position
        mLastSelectionStart = newSelStart;
@@ -1728,6 +1738,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
        // during key repeat.
        mHandler.postUpdateShiftState();

        if (mWordComposer.isComposingWord() && !mWordComposer.isCursorAtEndOfComposingWord()) {
            resetEntireInputState(mLastSelectionStart);
        }
        if (mWordComposer.isComposingWord()) {
            final int length = mWordComposer.size();
            if (length > 0) {
@@ -1859,6 +1872,10 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
            promotePhantomSpace();
        }

        if (mWordComposer.isComposingWord() && !mWordComposer.isCursorAtEndOfComposingWord()) {
            resetEntireInputState(mLastSelectionStart);
            isComposingWord = false;
        }
        // NOTE: isCursorTouchingWord() is a blocking IPC call, so it often takes several
        // dozen milliseconds. Avoid calling it as much as possible, since we are on the UI
        // thread here.
@@ -2331,6 +2348,48 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
        return prevWord;
    }

    /**
     * Check if the cursor is touching a word. If so, restart suggestions on this word, else
     * do nothing.
     */
    private void restartSuggestionsOnWordTouchedByCursor() {
        // If the cursor is not touching a word, or if there is a selection, return right away.
        if (mLastSelectionStart != mLastSelectionEnd) return;
        if (!mConnection.isCursorTouchingWord(mSettings.getCurrent())) return;
        final Range range = mConnection.getWordRangeAtCursor(mSettings.getWordSeparators(),
                0 /* additionalPrecedingWordsCount */);
        final ArrayList<SuggestedWordInfo> suggestions = CollectionUtils.newArrayList();
        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)) {
                SuggestionSpan span = (SuggestionSpan)object;
                for (String s : span.getSuggestions()) {
                    ++i;
                    if (!TextUtils.equals(s, typedWord)) {
                        suggestions.add(new SuggestedWordInfo(s,
                                SuggestionStripView.MAX_SUGGESTIONS - i,
                                SuggestedWordInfo.KIND_RESUMED, Dictionary.TYPE_RESUMED));
                    }
                }
            }
        }
        mWordComposer.setComposingWord(range.mWord, mKeyboardSwitcher.getKeyboard());
        mWordComposer.setCursorPositionWithinWord(range.mCharsBefore);
        mConnection.setComposingRegion(mLastSelectionStart - range.mCharsBefore,
                mLastSelectionEnd + range.mCharsAfter);
        if (suggestions.isEmpty()) {
            suggestions.add(new SuggestedWordInfo(range.mWord.toString(), 1,
                    SuggestedWordInfo.KIND_TYPED, Dictionary.TYPE_RESUMED));
        }
        showSuggestionStrip(new SuggestedWords(suggestions,
                true /* typedWordValid */, false /* willAutoCorrect */,
                false /* isPunctuationSuggestions */, false /* isObsoleteSuggestions */,
                false /* isPrediction */), range.mWord.toString());
    }

    /**
     * Check if the cursor is actually at the end of a word. If so, restart suggestions on this
     * word, else do nothing.
@@ -2339,17 +2398,18 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
        final CharSequence word =
                mConnection.getWordBeforeCursorIfAtEndOfWord(mSettings.getCurrent());
        if (null != word) {
            restartSuggestionsOnWordBeforeCursor(word);
            final String wordString = word.toString();
            restartSuggestionsOnWordBeforeCursor(wordString);
            // TODO: Handle the case where the user manually moves the cursor and then backs up over
            // a separator.  In that case, the current log unit should not be uncommitted.
            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
                ResearchLogger.getInstance().uncommitCurrentLogUnit(word.toString(),
                ResearchLogger.getInstance().uncommitCurrentLogUnit(wordString,
                        true /* dumpCurrentLogUnit */);
            }
        }
    }

    private void restartSuggestionsOnWordBeforeCursor(final CharSequence word) {
    private void restartSuggestionsOnWordBeforeCursor(final String word) {
        mWordComposer.setComposingWord(word, mKeyboardSwitcher.getKeyboard());
        final int length = word.length();
        mConnection.deleteSurroundingText(length, 0);
+12 −7
Original line number Diff line number Diff line
@@ -17,7 +17,9 @@
package com.android.inputmethod.latin;

import android.inputmethodservice.InputMethodService;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.SuggestionSpan;
import android.util.Log;
import android.view.KeyEvent;
import android.view.inputmethod.CompletionInfo;
@@ -444,9 +446,9 @@ public final class RichInputConnection {
        public final int mCharsAfter;

        /** The actual characters that make up a word */
        public final String mWord;
        public final CharSequence mWord;

        public Range(int charsBefore, int charsAfter, String word) {
        public Range(int charsBefore, int charsAfter, CharSequence word) {
            if (charsBefore < 0 || charsAfter < 0) {
                throw new IndexOutOfBoundsException();
            }
@@ -500,7 +502,7 @@ public final class RichInputConnection {
     *   separator. For example, if the field contains "he|llo world", where |
     *   represents the cursor, then "hello " will be returned.
     */
    public String getWordAtCursor(String separators) {
    public CharSequence getWordAtCursor(String separators) {
        // getWordRangeAtCursor returns null if the connection is null
        Range r = getWordRangeAtCursor(separators, 0);
        return (r == null) ? null : r.mWord;
@@ -519,8 +521,10 @@ public final class RichInputConnection {
        if (mIC == null || sep == null) {
            return null;
        }
        final CharSequence before = mIC.getTextBeforeCursor(1000, 0);
        final CharSequence after = mIC.getTextAfterCursor(1000, 0);
        final CharSequence before = mIC.getTextBeforeCursor(1000,
                InputConnection.GET_TEXT_WITH_STYLES);
        final CharSequence after = mIC.getTextAfterCursor(1000,
                InputConnection.GET_TEXT_WITH_STYLES);
        if (before == null || after == null) {
            return null;
        }
@@ -562,8 +566,9 @@ public final class RichInputConnection {
            }
        }

        final String word = before.toString().substring(startIndexInBefore, before.length())
                + after.toString().substring(0, endIndexInAfter);
        final SpannableString word = new SpannableString(TextUtils.concat(
                before.subSequence(startIndexInBefore, before.length()),
                after.subSequence(0, endIndexInAfter)));
        return new Range(before.length() - startIndexInBefore, endIndexInAfter, word);
    }

+4 −0
Original line number Diff line number Diff line
@@ -134,6 +134,10 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
        return mSettingsValues.mIsInternal;
    }

    public String getWordSeparators() {
        return mSettingsValues.mWordSeparators;
    }

    // Accessed from the settings interface, hence public
    public static boolean readKeypressSoundEnabled(final SharedPreferences prefs,
            final Resources res) {
+1 −0
Original line number Diff line number Diff line
@@ -131,6 +131,7 @@ public final class SuggestedWords {
        public static final int KIND_APP_DEFINED = 6; // Suggested by the application
        public static final int KIND_SHORTCUT = 7; // A shortcut
        public static final int KIND_PREDICTION = 8; // A prediction (== a suggestion with no input)
        public static final int KIND_RESUMED = 9; // A resumed suggestion (comes from a span)
        public final String mWord;
        public final int mScore;
        public final int mKind; // one of the KIND_* constants above
Loading