diff options
Diffstat (limited to 'java/src/com/android/inputmethod/latin')
8 files changed, 86 insertions, 28 deletions
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java index 36a02669d..fd1f51dd6 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java @@ -491,8 +491,9 @@ public class DictionaryFacilitator { final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo, final SettingsValuesForSuggestion settingsValuesForSuggestion, final int sessionId) { final Dictionaries dictionaries = mDictionaries; - final SuggestionResults suggestionResults = - new SuggestionResults(dictionaries.mLocale, SuggestedWords.MAX_SUGGESTIONS); + final SuggestionResults suggestionResults = new SuggestionResults( + dictionaries.mLocale, SuggestedWords.MAX_SUGGESTIONS, + prevWordsInfo.mPrevWordsInfo[0].mIsBeginningOfSentence); final float[] languageWeight = new float[] { Dictionary.NOT_A_LANGUAGE_WEIGHT }; for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) { final Dictionary dictionary = dictionaries.getDict(dictType); diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 81953221e..d57db8e9a 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1033,7 +1033,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // with cursor movement when we have a hardware keyboard since we are not in charge. final SettingsValues settingsValues = mSettings.getCurrent(); if ((!settingsValues.mHasHardwareKeyboard || ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED) - && mInputLogic.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd)) { + && mInputLogic.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, + settingsValues)) { mKeyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(), getCurrentRecapitalizeState()); } @@ -1488,19 +1489,23 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final boolean isEmptyApplicationSpecifiedCompletions = currentSettingsValues.isApplicationSpecifiedCompletionsOn() && suggestedWords.isEmpty(); - final boolean noSuggestionsToShow = (SuggestedWords.EMPTY == suggestedWords) + final boolean noSuggestionsFromDictionaries = (SuggestedWords.EMPTY == suggestedWords) || suggestedWords.isPunctuationSuggestions() || isEmptyApplicationSpecifiedCompletions; - if (shouldShowImportantNotice && noSuggestionsToShow) { + final boolean isBeginningOfSentencePrediction = (suggestedWords.mInputStyle + == SuggestedWords.INPUT_STYLE_BEGINNING_OF_SENTENCE_PREDICTION); + final boolean noSuggestionsToOverrideImportantNotice = noSuggestionsFromDictionaries + || isBeginningOfSentencePrediction; + if (shouldShowImportantNotice && noSuggestionsToOverrideImportantNotice) { if (mSuggestionStripView.maybeShowImportantNoticeTitle()) { return; } } if (currentSettingsValues.isSuggestionsEnabledPerUserSettings() - // We should clear suggestions if there is no suggestion to show. - || noSuggestionsToShow - || currentSettingsValues.isApplicationSpecifiedCompletionsOn()) { + || currentSettingsValues.isApplicationSpecifiedCompletionsOn() + // We should clear the contextual strip if there is no suggestion from dictionaries. + || noSuggestionsFromDictionaries) { mSuggestionStripView.setSuggestions(suggestedWords, SubtypeLocaleUtils.isRtlLanguage(mSubtypeSwitcher.getCurrentSubtype())); } diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 6779351fd..b03818c1d 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -186,8 +186,14 @@ public final class Suggest { suggestionsList = suggestionsContainer; } - final int inputStyle = resultsArePredictions ? SuggestedWords.INPUT_STYLE_PREDICTION : - inputStyleIfNotPrediction; + final int inputStyle; + if (resultsArePredictions) { + inputStyle = suggestionResults.mIsBeginningOfSentence + ? SuggestedWords.INPUT_STYLE_BEGINNING_OF_SENTENCE_PREDICTION + : SuggestedWords.INPUT_STYLE_PREDICTION; + } else { + inputStyle = inputStyleIfNotPrediction; + } callback.onGetSuggestedWords(new SuggestedWords(suggestionsList, suggestionResults.mRawSuggestions, // TODO: this first argument is lying. If this is a whitelisted word which is an @@ -240,6 +246,8 @@ public final class Suggest { // In the batch input mode, the most relevant suggested word should act as a "typed word" // (typedWordValid=true), not as an "auto correct word" (willAutoCorrect=false). + // Note that because this method is never used to get predictions, there is no need to + // modify inputType such in getSuggestedWordsForNonBatchInput. callback.onGetSuggestedWords(new SuggestedWords(suggestionsContainer, suggestionResults.mRawSuggestions, true /* typedWordValid */, diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index 6bc3da885..1d221b77f 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -39,6 +39,7 @@ public class SuggestedWords { public static final int INPUT_STYLE_APPLICATION_SPECIFIED = 4; public static final int INPUT_STYLE_RECORRECTION = 5; public static final int INPUT_STYLE_PREDICTION = 6; + public static final int INPUT_STYLE_BEGINNING_OF_SENTENCE_PREDICTION = 7; // The maximum number of suggestions available. public static final int MAX_SUGGESTIONS = 18; @@ -80,10 +81,9 @@ public class SuggestedWords { final int inputStyle, final int sequenceNumber) { this(suggestedWordInfoList, rawSuggestions, - (suggestedWordInfoList.isEmpty() || INPUT_STYLE_PREDICTION == inputStyle) ? null + (suggestedWordInfoList.isEmpty() || isPrediction(inputStyle)) ? null : suggestedWordInfoList.get(INDEX_OF_TYPED_WORD).mWord, - typedWordValid, willAutoCorrect, isObsoleteSuggestions, inputStyle, - sequenceNumber); + typedWordValid, willAutoCorrect, isObsoleteSuggestions, inputStyle, sequenceNumber); } public SuggestedWords(final ArrayList<SuggestedWordInfo> suggestedWordInfoList, @@ -171,6 +171,7 @@ public class SuggestedWords { return "SuggestedWords:" + " mTypedWordValid=" + mTypedWordValid + " mWillAutoCorrect=" + mWillAutoCorrect + + " mInputStyle=" + mInputStyle + " words=" + Arrays.toString(mSuggestedWordInfoList.toArray()); } @@ -377,8 +378,13 @@ public class SuggestedWords { } } + private static boolean isPrediction(final int inputStyle) { + return INPUT_STYLE_PREDICTION == inputStyle + || INPUT_STYLE_BEGINNING_OF_SENTENCE_PREDICTION == inputStyle; + } + public boolean isPrediction() { - return INPUT_STYLE_PREDICTION == mInputStyle; + return isPrediction(mInputStyle); } // SuggestedWords is an immutable object, as much as possible. We must not just remove diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java index 21e2a1c10..fdab7f25f 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java @@ -358,10 +358,11 @@ public final class InputLogic { * @param oldSelEnd old selection end * @param newSelStart new selection start * @param newSelEnd new selection end + * @param settingsValues the current values of the settings. * @return whether the cursor has moved as a result of user interaction. */ public boolean onUpdateSelection(final int oldSelStart, final int oldSelEnd, - final int newSelStart, final int newSelEnd) { + final int newSelStart, final int newSelEnd, final SettingsValues settingsValues) { if (mConnection.isBelatedExpectedUpdate(oldSelStart, newSelStart, oldSelEnd, newSelEnd)) { return false; } @@ -386,8 +387,9 @@ public final class InputLogic { // should be true, but that is if the framework had taken that wrong cursor position // into account, which means we have to reset the entire composing state whenever there // is or was a selection regardless of whether it changed or not. - if (hasOrHadSelection || (selectionChangedOrSafeToReset - && !mWordComposer.moveCursorByAndReturnIfInsideComposingWord(moveAmount))) { + if (hasOrHadSelection || !settingsValues.needsToLookupSuggestions() + || (selectionChangedOrSafeToReset + && !mWordComposer.moveCursorByAndReturnIfInsideComposingWord(moveAmount))) { // If we are composing a word and moving the cursor, we would want to set a // suggestion span for recorrection to work correctly. Unfortunately, that // would involve the keyboard committing some new text, which would move the diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index 33745a846..0fd5e139e 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -408,8 +408,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick // Decided to be in the sliding suggestion mode only when the touch point has been moved // upward. Further {@link MotionEvent}s will be delivered to // {@link #onTouchEvent(MotionEvent)}. - mNeedsToTransformTouchEventToHoverEvent = AccessibilityUtils.getInstance() - .isTouchExplorationEnabled(); + mNeedsToTransformTouchEventToHoverEvent = + AccessibilityUtils.getInstance().isTouchExplorationEnabled(); mIsDispatchingHoverEventToMoreSuggestions = false; return true; } diff --git a/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java b/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java index 8b7077879..ea406fa75 100644 --- a/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java @@ -23,15 +23,24 @@ import android.provider.Settings.SettingNotFoundException; import android.text.TextUtils; import android.util.Log; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.R; +import java.util.concurrent.TimeUnit; + public final class ImportantNoticeUtils { private static final String TAG = ImportantNoticeUtils.class.getSimpleName(); // {@link SharedPreferences} name to save the last important notice version that has been // displayed to users. private static final String PREFERENCE_NAME = "important_notice_pref"; - private static final String KEY_IMPORTANT_NOTICE_VERSION = "important_notice_version"; + @UsedForTesting + static final String KEY_IMPORTANT_NOTICE_VERSION = "important_notice_version"; + @UsedForTesting + static final String KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE = + "timestamp_of_first_important_notice"; + @UsedForTesting + static final long TIMEOUT_OF_IMPORTANT_NOTICE = TimeUnit.HOURS.toMillis(23); public static final int VERSION_TO_ENABLE_PERSONALIZED_SUGGESTIONS = 1; // Copy of the hidden {@link Settings.Secure#USER_SETUP_COMPLETE} settings key. @@ -56,15 +65,18 @@ public final class ImportantNoticeUtils { } } - private static SharedPreferences getImportantNoticePreferences(final Context context) { + @UsedForTesting + static SharedPreferences getImportantNoticePreferences(final Context context) { return context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); } - private static int getCurrentImportantNoticeVersion(final Context context) { + @UsedForTesting + static int getCurrentImportantNoticeVersion(final Context context) { return context.getResources().getInteger(R.integer.config_important_notice_version); } - private static int getLastImportantNoticeVersion(final Context context) { + @UsedForTesting + static int getLastImportantNoticeVersion(final Context context) { return getImportantNoticePreferences(context).getInt(KEY_IMPORTANT_NOTICE_VERSION, 0); } @@ -77,6 +89,20 @@ public final class ImportantNoticeUtils { return getCurrentImportantNoticeVersion(context) > lastVersion; } + @UsedForTesting + static boolean hasTimeoutPassed(final Context context, final long currentTimeInMillis) { + final SharedPreferences prefs = getImportantNoticePreferences(context); + if (!prefs.contains(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE)) { + prefs.edit() + .putLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE, currentTimeInMillis) + .apply(); + } + final long firstDisplayTimeInMillis = prefs.getLong( + KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE, currentTimeInMillis); + final long elapsedTime = currentTimeInMillis - firstDisplayTimeInMillis; + return elapsedTime >= TIMEOUT_OF_IMPORTANT_NOTICE; + } + public static boolean shouldShowImportantNotice(final Context context) { if (!hasNewImportantNotice(context)) { return false; @@ -88,6 +114,10 @@ public final class ImportantNoticeUtils { if (isInSystemSetupWizard(context)) { return false; } + if (hasTimeoutPassed(context, System.currentTimeMillis())) { + updateLastImportantNoticeVersion(context); + return false; + } return true; } @@ -95,11 +125,12 @@ public final class ImportantNoticeUtils { getImportantNoticePreferences(context) .edit() .putInt(KEY_IMPORTANT_NOTICE_VERSION, getNextImportantNoticeVersion(context)) + .remove(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE) .apply(); } public static String getNextImportantNoticeTitle(final Context context) { - final int nextVersion = getCurrentImportantNoticeVersion(context); + final int nextVersion = getNextImportantNoticeVersion(context); final String[] importantNoticeTitleArray = context.getResources().getStringArray( R.array.important_notice_title_array); if (nextVersion > 0 && nextVersion < importantNoticeTitleArray.length) { diff --git a/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java b/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java index 7170bd789..8cd49509f 100644 --- a/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java +++ b/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java @@ -32,14 +32,18 @@ import java.util.TreeSet; public final class SuggestionResults extends TreeSet<SuggestedWordInfo> { public final Locale mLocale; public final ArrayList<SuggestedWordInfo> mRawSuggestions; + // TODO: Instead of a boolean , we may want to include the context of this suggestion results, + // such as {@link PrevWordsInfo}. + public final boolean mIsBeginningOfSentence; private final int mCapacity; - public SuggestionResults(final Locale locale, final int capacity) { - this(locale, sSuggestedWordInfoComparator, capacity); + public SuggestionResults(final Locale locale, final int capacity, + final boolean isBeginningOfSentence) { + this(locale, sSuggestedWordInfoComparator, capacity, isBeginningOfSentence); } - public SuggestionResults(final Locale locale, final Comparator<SuggestedWordInfo> comparator, - final int capacity) { + private SuggestionResults(final Locale locale, final Comparator<SuggestedWordInfo> comparator, + final int capacity, final boolean isBeginningOfSentence) { super(comparator); mLocale = locale; mCapacity = capacity; @@ -48,6 +52,7 @@ public final class SuggestionResults extends TreeSet<SuggestedWordInfo> { } else { mRawSuggestions = null; } + mIsBeginningOfSentence = isBeginningOfSentence; } @Override |