diff options
Diffstat (limited to 'java/src')
10 files changed, 182 insertions, 160 deletions
diff --git a/java/src/com/android/inputmethod/accessibility/MainKeyboardAccessibilityDelegate.java b/java/src/com/android/inputmethod/accessibility/MainKeyboardAccessibilityDelegate.java index 94a1ee6eb..e80982fc7 100644 --- a/java/src/com/android/inputmethod/accessibility/MainKeyboardAccessibilityDelegate.java +++ b/java/src/com/android/inputmethod/accessibility/MainKeyboardAccessibilityDelegate.java @@ -269,13 +269,9 @@ public final class MainKeyboardAccessibilityDelegate eventTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0 /* metaState */); // Inject a fake down event to {@link PointerTracker} to handle a long press correctly. tracker.processMotionEvent(downEvent, mKeyDetector); - // The above fake down event triggers an unnecessary long press timer that should be - // canceled. - tracker.cancelLongPressTimer(); downEvent.recycle(); - // Invoke {@link MainKeyboardView#onLongPress(PointerTracker)} as if a long press timeout - // has passed. - mKeyboardView.onLongPress(tracker); + // Invoke {@link PointerTracker#onLongPressed()} as if a long press timeout has passed. + tracker.onLongPressed(); // If {@link Key#hasNoPanelAutoMoreKeys()} is true (such as "0 +" key on the phone layout) // or a key invokes IME switcher dialog, we should just ignore the next // {@link #onRegisterHoverKey(Key,MotionEvent)}. It can be determined by whether diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java index 06b87bd9a..ad15fa223 100644 --- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java @@ -461,12 +461,17 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy windowContentView.addView(mDrawingPreviewPlacerView); } + // Implements {@link DrawingProxy#onKeyPressed(Key,boolean)}. @Override - public void showKeyPreview(@Nonnull final Key key) { - // If the key is invalid or has no key preview, we must not show key preview. - if (key.noKeyPreview()) { - return; + public void onKeyPressed(@Nonnull final Key key, final boolean withPreview) { + key.onPressed(); + invalidateKey(key); + if (withPreview && !key.noKeyPreview()) { + showKeyPreview(key); } + } + + private void showKeyPreview(@Nonnull final Key key) { final Keyboard keyboard = getKeyboard(); if (keyboard == null) { return; @@ -483,15 +488,26 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy getWidth(), mOriginCoords, mDrawingPreviewPlacerView, isHardwareAccelerated()); } - // Implements {@link DrawingProxy#dismissKeyPreviewWithoutDelay(Key)}. - @Override - public void dismissKeyPreviewWithoutDelay(@Nonnull final Key key) { + private void dismissKeyPreviewWithoutDelay(@Nonnull final Key key) { mKeyPreviewChoreographer.dismissKeyPreview(key, false /* withAnimation */); invalidateKey(key); } + // Implements {@link DrawingProxy#onKeyReleased(Key,boolean)}. @Override - public void dismissKeyPreview(@Nonnull final Key key) { + public void onKeyReleased(@Nonnull final Key key, final boolean withAnimation) { + key.onReleased(); + invalidateKey(key); + if (!key.noKeyPreview()) { + if (withAnimation) { + dismissKeyPreview(key); + } else { + dismissKeyPreviewWithoutDelay(key); + } + } + } + + private void dismissKeyPreview(@Nonnull final Key key) { if (isHardwareAccelerated()) { mKeyPreviewChoreographer.dismissKeyPreview(key, true /* withAnimation */); return; @@ -574,7 +590,11 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy mDrawingPreviewPlacerView.removeAllViews(); } - private MoreKeysPanel onCreateMoreKeysPanel(final Key key, final Context context) { + // Implements {@link DrawingProxy@showMoreKeysKeyboard(Key,PointerTracker)}. + @Override + @Nullable + public MoreKeysPanel showMoreKeysKeyboard(@Nonnull final Key key, + @Nonnull final PointerTracker tracker) { final MoreKeySpec[] moreKeys = key.getMoreKeys(); if (moreKeys == null) { return null; @@ -590,7 +610,7 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy && !key.noKeyPreview() && moreKeys.length == 1 && mKeyPreviewDrawParams.getVisibleWidth() > 0; final MoreKeysKeyboard.Builder builder = new MoreKeysKeyboard.Builder( - context, key, getKeyboard(), isSingleMoreKeyWithPreview, + getContext(), key, getKeyboard(), isSingleMoreKeyWithPreview, mKeyPreviewDrawParams.getVisibleWidth(), mKeyPreviewDrawParams.getVisibleHeight(), newLabelPaint(key)); moreKeysKeyboard = builder.build(); @@ -603,50 +623,6 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy (MoreKeysKeyboardView)container.findViewById(R.id.more_keys_keyboard_view); moreKeysKeyboardView.setKeyboard(moreKeysKeyboard); container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); - return moreKeysKeyboardView; - } - - // Implements {@link DrawingProxy@onLongPress(PointerTracker)}. - /** - * Called when a key is long pressed. - * @param tracker the pointer tracker which pressed the parent key - */ - @Override - public void onLongPress(@Nonnull final PointerTracker tracker) { - if (isShowingMoreKeysPanel()) { - return; - } - final Key key = tracker.getKey(); - if (key == null) { - return; - } - final KeyboardActionListener listener = mKeyboardActionListener; - if (key.hasNoPanelAutoMoreKey()) { - final int moreKeyCode = key.getMoreKeys()[0].mCode; - tracker.onLongPressed(); - listener.onPressKey(moreKeyCode, 0 /* repeatCount */, true /* isSinglePointer */); - listener.onCodeInput(moreKeyCode, Constants.NOT_A_COORDINATE, - Constants.NOT_A_COORDINATE, false /* isKeyRepeat */); - listener.onReleaseKey(moreKeyCode, false /* withSliding */); - return; - } - final int code = key.getCode(); - if (code == Constants.CODE_SPACE || code == Constants.CODE_LANGUAGE_SWITCH) { - // Long pressing the space key invokes IME switcher dialog. - if (listener.onCustomRequest(Constants.CUSTOM_CODE_SHOW_INPUT_METHOD_PICKER)) { - tracker.onLongPressed(); - listener.onReleaseKey(code, false /* withSliding */); - return; - } - } - openMoreKeysPanel(key, tracker); - } - - private void openMoreKeysPanel(final Key key, final PointerTracker tracker) { - final MoreKeysPanel moreKeysPanel = onCreateMoreKeysPanel(key, getContext()); - if (moreKeysPanel == null) { - return; - } final int[] lastCoords = CoordinateUtils.newInstance(); tracker.getLastCoordinates(lastCoords); @@ -664,10 +640,8 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy // {@code mPreviewVisibleOffset} has been set appropriately in // {@link KeyboardView#showKeyPreview(PointerTracker)}. final int pointY = key.getY() + mKeyPreviewDrawParams.getVisibleOffset(); - moreKeysPanel.showMoreKeysPanel(this, this, pointX, pointY, mKeyboardActionListener); - tracker.onShowMoreKeysPanel(moreKeysPanel); - // TODO: Implement zoom in animation of more keys panel. - mKeyPreviewChoreographer.dismissKeyPreview(key, false /* withAnimation */); + moreKeysKeyboardView.showMoreKeysPanel(this, this, pointX, pointY, mKeyboardActionListener); + return moreKeysKeyboardView; } public boolean isInDraggingFinger() { diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 7902ce852..7b7dd7b72 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -222,7 +222,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element, final int trackersSize = sTrackers.size(); for (int i = 0; i < trackersSize; ++i) { final PointerTracker tracker = sTrackers.get(i); - tracker.setReleasedKeyGraphics(tracker.getKey()); + tracker.setReleasedKeyGraphics(tracker.getKey(), true /* withAnimation */); } } @@ -382,19 +382,18 @@ public final class PointerTracker implements PointerTrackerQueue.Element, return mKeyDetector.detectHitKey(x, y); } - private void setReleasedKeyGraphics(@Nullable final Key key) { + private void setReleasedKeyGraphics(@Nullable final Key key, final boolean withAnimation) { if (key == null) { return; } - sDrawingProxy.dismissKeyPreview(key); // Even if the key is disabled, update the key release graphics just in case. - updateReleaseKeyGraphics(key); + sDrawingProxy.onKeyReleased(key, withAnimation); if (key.isShift()) { for (final Key shiftKey : mKeyboard.mShiftKeys) { if (shiftKey != key) { - updateReleaseKeyGraphics(shiftKey); + sDrawingProxy.onKeyReleased(shiftKey, false /* withAnimation */); } } } @@ -403,11 +402,11 @@ public final class PointerTracker implements PointerTrackerQueue.Element, final int altCode = key.getAltCode(); final Key altKey = mKeyboard.getKey(altCode); if (altKey != null) { - updateReleaseKeyGraphics(altKey); + sDrawingProxy.onKeyReleased(altKey, false /* withAnimation */); } for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) { if (k != key && k.getAltCode() == altCode) { - updateReleaseKeyGraphics(k); + sDrawingProxy.onKeyReleased(k, false /* withAnimation */); } } } @@ -418,7 +417,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element, return sTypingTimeRecorder.needsToSuppressKeyPreviewPopup(eventTime); } - private void setPressedKeyGraphics(final Key key, final long eventTime) { + private void setPressedKeyGraphics(@Nullable final Key key, final long eventTime) { if (key == null) { return; } @@ -430,15 +429,13 @@ public final class PointerTracker implements PointerTrackerQueue.Element, return; } - if (!key.noKeyPreview() && !sInGesture && !needsToSuppressKeyPreviewPopup(eventTime)) { - sDrawingProxy.showKeyPreview(key); - } - updatePressKeyGraphics(key); + final boolean noKeyPreview = sInGesture || needsToSuppressKeyPreviewPopup(eventTime); + sDrawingProxy.onKeyPressed(key, !noKeyPreview); if (key.isShift()) { for (final Key shiftKey : mKeyboard.mShiftKeys) { if (shiftKey != key) { - updatePressKeyGraphics(shiftKey); + sDrawingProxy.onKeyPressed(shiftKey, false /* withPreview */); } } } @@ -447,26 +444,16 @@ public final class PointerTracker implements PointerTrackerQueue.Element, final int altCode = key.getAltCode(); final Key altKey = mKeyboard.getKey(altCode); if (altKey != null) { - updatePressKeyGraphics(altKey); + sDrawingProxy.onKeyPressed(altKey, false /* withPreview */); } for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) { if (k != key && k.getAltCode() == altCode) { - updatePressKeyGraphics(k); + sDrawingProxy.onKeyPressed(k, false /* withPreview */); } } } } - private static void updateReleaseKeyGraphics(final Key key) { - key.onReleased(); - sDrawingProxy.invalidateKey(key); - } - - private static void updatePressKeyGraphics(final Key key) { - key.onPressed(); - sDrawingProxy.invalidateKey(key); - } - public GestureStrokeDrawingPoints getGestureStrokeDrawingPoints() { return mGestureStrokeDrawingPoints; } @@ -837,7 +824,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element, } private void processDraggingFingerOutFromOldKey(final Key oldKey) { - setReleasedKeyGraphics(oldKey); + setReleasedKeyGraphics(oldKey, true /* withAnimation */); callListenerOnRelease(oldKey, oldKey.getCode(), true /* withSliding */); startKeySelectionByDraggingFinger(oldKey); sTimerProxy.cancelKeyTimersOf(this); @@ -880,12 +867,12 @@ public final class PointerTracker implements PointerTrackerQueue.Element, } onUpEvent(x, y, eventTime); cancelTrackingForAction(); - setReleasedKeyGraphics(oldKey); + setReleasedKeyGraphics(oldKey, true /* withAnimation */); } else { if (!mIsDetectingGesture) { cancelTrackingForAction(); } - setReleasedKeyGraphics(oldKey); + setReleasedKeyGraphics(oldKey, true /* withAnimation */); } } @@ -913,7 +900,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element, onGestureMoveEvent(x, y, eventTime, true /* isMajorEvent */, newKey); if (sInGesture) { mCurrentKey = null; - setReleasedKeyGraphics(oldKey); + setReleasedKeyGraphics(oldKey, true /* withAnimation */); return; } } @@ -978,7 +965,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element, final int currentRepeatingKeyCode = mCurrentRepeatingKeyCode; mCurrentRepeatingKeyCode = Constants.NOT_A_CODE; // Release the last pressed key. - setReleasedKeyGraphics(currentKey); + setReleasedKeyGraphics(currentKey, true /* withAnimation */); if (isShowingMoreKeysPanel()) { if (!mIsTrackingForActionDisabled) { @@ -1015,14 +1002,6 @@ public final class PointerTracker implements PointerTrackerQueue.Element, } } - public void onShowMoreKeysPanel(final MoreKeysPanel panel) { - setReleasedKeyGraphics(mCurrentKey); - final int translatedX = panel.translateX(mLastX); - final int translatedY = panel.translateY(mLastY); - panel.onDownEvent(translatedX, translatedY, mPointerId, SystemClock.uptimeMillis()); - mMoreKeysPanel = panel; - } - @Override public void cancelTrackingForAction() { if (isShowingMoreKeysPanel()) { @@ -1035,14 +1014,49 @@ public final class PointerTracker implements PointerTrackerQueue.Element, return !mIsTrackingForActionDisabled; } - public void cancelLongPressTimer() { + public void onLongPressed() { sTimerProxy.cancelLongPressTimersOf(this); + if (isShowingMoreKeysPanel()) { + return; + } + final Key key = getKey(); + if (key == null) { + return; + } + if (key.hasNoPanelAutoMoreKey()) { + cancelKeyTracking(); + final int moreKeyCode = key.getMoreKeys()[0].mCode; + sListener.onPressKey(moreKeyCode, 0 /* repeatCont */, true /* isSinglePointer */); + sListener.onCodeInput(moreKeyCode, Constants.NOT_A_COORDINATE, + Constants.NOT_A_COORDINATE, false /* isKeyRepeat */); + sListener.onReleaseKey(moreKeyCode, false /* withSliding */); + return; + } + final int code = key.getCode(); + if (code == Constants.CODE_SPACE || code == Constants.CODE_LANGUAGE_SWITCH) { + // Long pressing the space key invokes IME switcher dialog. + if (sListener.onCustomRequest(Constants.CUSTOM_CODE_SHOW_INPUT_METHOD_PICKER)) { + cancelKeyTracking(); + sListener.onReleaseKey(code, false /* withSliding */); + return; + } + } + + setReleasedKeyGraphics(key, false /* withAnimation */); + final MoreKeysPanel moreKeysPanel = sDrawingProxy.showMoreKeysKeyboard(key, this); + if (moreKeysPanel == null) { + return; + } + final int translatedX = moreKeysPanel.translateX(mLastX); + final int translatedY = moreKeysPanel.translateY(mLastY); + moreKeysPanel.onDownEvent(translatedX, translatedY, mPointerId, SystemClock.uptimeMillis()); + mMoreKeysPanel = moreKeysPanel; } - public void onLongPressed() { + private void cancelKeyTracking() { resetKeySelectionByDraggingFinger(); cancelTrackingForAction(); - setReleasedKeyGraphics(mCurrentKey); + setReleasedKeyGraphics(mCurrentKey, true /* withAnimation */); sPointerTrackerQueue.remove(this); } @@ -1059,7 +1073,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element, private void onCancelEventInternal() { sTimerProxy.cancelKeyTimersOf(this); - setReleasedKeyGraphics(mCurrentKey); + setReleasedKeyGraphics(mCurrentKey, true /* withAnimation */); resetKeySelectionByDraggingFinger(); dismissMoreKeysPanel(); } diff --git a/java/src/com/android/inputmethod/keyboard/internal/DrawingProxy.java b/java/src/com/android/inputmethod/keyboard/internal/DrawingProxy.java index 7fc586a0f..06bdfc41b 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/DrawingProxy.java +++ b/java/src/com/android/inputmethod/keyboard/internal/DrawingProxy.java @@ -17,29 +17,36 @@ package com.android.inputmethod.keyboard.internal; import com.android.inputmethod.keyboard.Key; +import com.android.inputmethod.keyboard.MoreKeysPanel; import com.android.inputmethod.keyboard.PointerTracker; import javax.annotation.Nonnull; import javax.annotation.Nullable; public interface DrawingProxy { - // TODO: Remove this method. - public void invalidateKey(@Nullable Key key); - - // TODO: Rename this method to onKeyPressed. - public void showKeyPreview(@Nonnull Key key); - - // TODO: Rename this method to onKeyReleased. - public void dismissKeyPreview(@Nonnull Key key); + /** + * Called when a key is being pressed. + * @param key the {@link Key} that is being pressed. + * @param withPreview true if key popup preview should be displayed. + */ + public void onKeyPressed(@Nonnull Key key, boolean withPreview); /** - * Dismiss a key preview visual without delay. - * @param key the key whose preview visual should be dismissed. + * Called when a key is being released. + * @param key the {@link Key} that is being released. + * @param withAnimation when true, key popup preview should be dismissed with animation. */ - public void dismissKeyPreviewWithoutDelay(@Nonnull Key key); + public void onKeyReleased(@Nonnull Key key, boolean withAnimation); - // TODO: Rename this method to onKeyLongPressed. - public void onLongPress(@Nonnull PointerTracker tracker); + /** + * Start showing more keys keyboard of a key that is being long pressed. + * @param key the {@link Key} that is being long pressed and showing more keys keyboard. + * @param tracker the {@link PointerTracker} that detects this long pressing. + * @return {@link MoreKeysPanel} that is being shown. null if there is no need to show more keys + * keyboard. + */ + @Nullable + public MoreKeysPanel showMoreKeysKeyboard(@Nonnull Key key, @Nonnull PointerTracker tracker); /** * Start a while-typing-animation. diff --git a/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java b/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java index 8068427bc..91f3558eb 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java +++ b/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java @@ -66,7 +66,7 @@ public final class TimerHandler extends LeakGuardHandlerWrapper<DrawingProxy> case MSG_LONGPRESS_SHIFT_KEY: cancelLongPressTimers(); final PointerTracker tracker2 = (PointerTracker) msg.obj; - drawingProxy.onLongPress(tracker2); + tracker2.onLongPressed(); break; case MSG_UPDATE_BATCH_INPUT: final PointerTracker tracker3 = (PointerTracker) msg.obj; @@ -74,8 +74,7 @@ public final class TimerHandler extends LeakGuardHandlerWrapper<DrawingProxy> startUpdateBatchInputTimer(tracker3); break; case MSG_DISMISS_KEY_PREVIEW: - final Key key = (Key) msg.obj; - drawingProxy.dismissKeyPreviewWithoutDelay(key); + drawingProxy.onKeyReleased((Key) msg.obj, false /* withAnimation */); break; case MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT: drawingProxy.dismissGestureFloatingPreviewTextWithoutDelay(); diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java index b24fdea55..2ee4068b6 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java @@ -138,6 +138,10 @@ public class DictionaryFacilitator { public final Locale mLocale; private Dictionary mMainDict; + // Confidence that the most probable language is actually the language the user is + // typing in. For now, this is simply the number of times a word from this language + // has been committed in a row. + private int mConfidence = 0; public float mWeightForTypingInLocale = WEIGHT_FOR_MOST_PROBABLE_LANGUAGE; public float mWeightForGesturingInLocale = WEIGHT_FOR_MOST_PROBABLE_LANGUAGE; public final ConcurrentHashMap<String, ExpandableBinaryDictionary> mSubDictMap = @@ -260,8 +264,9 @@ public class DictionaryFacilitator { public void switchMostProbableLanguage(final Locale locale) { if (null == locale) { // In many cases, there is no locale to a committed word. For example, a typed word - // that does not auto-correct has no locale. In this case we simply do not change - // the most probable language. + // that is in none of the currently active dictionaries but still does not + // auto-correct to anything has no locale. In this case we simply do not change + // the most probable language and do not touch confidence. return; } final DictionaryGroup newMostProbableDictionaryGroup = @@ -272,15 +277,20 @@ public class DictionaryFacilitator { // facilitator any more. In this case, just not changing things is fine. return; } - mMostProbableDictionaryGroup.mWeightForTypingInLocale = - DictionaryGroup.WEIGHT_FOR_TYPING_IN_NOT_MOST_PROBABLE_LANGUAGE; - mMostProbableDictionaryGroup.mWeightForGesturingInLocale = - DictionaryGroup.WEIGHT_FOR_GESTURING_IN_NOT_MOST_PROBABLE_LANGUAGE; - newMostProbableDictionaryGroup.mWeightForTypingInLocale = - DictionaryGroup.WEIGHT_FOR_MOST_PROBABLE_LANGUAGE; - newMostProbableDictionaryGroup.mWeightForGesturingInLocale = - DictionaryGroup.WEIGHT_FOR_MOST_PROBABLE_LANGUAGE; - mMostProbableDictionaryGroup = newMostProbableDictionaryGroup; + if (newMostProbableDictionaryGroup == mMostProbableDictionaryGroup) { + ++newMostProbableDictionaryGroup.mConfidence; + } else { + mMostProbableDictionaryGroup.mWeightForTypingInLocale = + DictionaryGroup.WEIGHT_FOR_TYPING_IN_NOT_MOST_PROBABLE_LANGUAGE; + mMostProbableDictionaryGroup.mWeightForGesturingInLocale = + DictionaryGroup.WEIGHT_FOR_GESTURING_IN_NOT_MOST_PROBABLE_LANGUAGE; + mMostProbableDictionaryGroup.mConfidence = 0; + newMostProbableDictionaryGroup.mWeightForTypingInLocale = + DictionaryGroup.WEIGHT_FOR_MOST_PROBABLE_LANGUAGE; + newMostProbableDictionaryGroup.mWeightForGesturingInLocale = + DictionaryGroup.WEIGHT_FOR_MOST_PROBABLE_LANGUAGE; + mMostProbableDictionaryGroup = newMostProbableDictionaryGroup; + } } @Nullable diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java index a1ac55a20..686c3a4b2 100644 --- a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java +++ b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java @@ -110,7 +110,7 @@ public class RichInputMethodManager { // Initialize additional subtypes. SubtypeLocaleUtils.init(context); - final InputMethodSubtype[] additionalSubtypes = getAdditionalSubtypes(context); + final InputMethodSubtype[] additionalSubtypes = getAdditionalSubtypes(); setAdditionalInputMethodSubtypes(additionalSubtypes); final ConnectivityManager connectivityManager = @@ -119,11 +119,10 @@ public class RichInputMethodManager { mIsNetworkConnected = (info != null && info.isConnected()); } - public InputMethodSubtype[] getAdditionalSubtypes(final Context context) { - SubtypeLocaleUtils.init(context); - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + public InputMethodSubtype[] getAdditionalSubtypes() { + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); final String prefAdditionalSubtypes = Settings.readPrefAdditionalSubtypes( - prefs, context.getResources()); + prefs, mContext.getResources()); return AdditionalSubtypeUtils.createAdditionalSubtypesArray(prefAdditionalSubtypes); } diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 4df1d6505..2d0ec42a6 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -32,6 +32,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Locale; +import javax.annotation.Nullable; + /** * This class loads a dictionary and provides a list of suggestions for a given sequence of * characters. This includes corrections and completions. @@ -143,14 +145,16 @@ public final class Suggest { final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults( wordComposer, ngramContext, proximityInfo.getNativeProximityInfo(), settingsValuesForSuggestion, SESSION_ID_TYPING); + final Locale mostProbableLocale = mDictionaryFacilitator.getMostProbableLocale(); final ArrayList<SuggestedWordInfo> suggestionsContainer = getTransformedSuggestedWordInfoList(wordComposer, suggestionResults, trailingSingleQuotesCount, // For transforming suggestions that don't come for any dictionary, we // use the currently most probable locale as it's our best bet. - mDictionaryFacilitator.getMostProbableLocale()); - final boolean didRemoveTypedWord = - SuggestedWordInfo.removeDups(wordComposer.getTypedWord(), suggestionsContainer); + mostProbableLocale); + @Nullable final Dictionary sourceDictionaryOfRemovedWord = + SuggestedWordInfo.removeDupsAndReturnSourceOfTypedWord(wordComposer.getTypedWord(), + mostProbableLocale /* preferredLocale */, suggestionsContainer); final String whitelistedWord = getWhitelistedWordOrNull(suggestionsContainer); final boolean resultsArePredictions = !wordComposer.isComposingWord(); @@ -158,7 +162,7 @@ public final class Suggest { // We allow auto-correction if we have a whitelisted word, or if the word had more than // one char and was not suggested. final boolean allowsToBeAutoCorrected = (null != whitelistedWord) - || (consideredWord.length() > 1 && !didRemoveTypedWord); + || (consideredWord.length() > 1 && (null == sourceDictionaryOfRemovedWord)); final boolean hasAutoCorrection; // If correction is not enabled, we never auto-correct. This is for example for when @@ -209,7 +213,8 @@ public final class Suggest { final SuggestedWordInfo typedWordInfo = new SuggestedWordInfo(typedWordString, SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_TYPED, - Dictionary.DICTIONARY_USER_TYPED, + null == sourceDictionaryOfRemovedWord ? Dictionary.DICTIONARY_USER_TYPED + : sourceDictionaryOfRemovedWord, SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */, SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */); if (!TextUtils.isEmpty(typedWordString)) { @@ -275,7 +280,8 @@ public final class Suggest { final SuggestedWordInfo rejected = suggestionsContainer.remove(0); suggestionsContainer.add(1, rejected); } - SuggestedWordInfo.removeDups(null /* typedWord */, suggestionsContainer); + SuggestedWordInfo.removeDupsAndReturnSourceOfTypedWord(null /* typedWord */, + null /* preferredLocale */, suggestionsContainer); // For some reason some suggestions with MIN_VALUE are making their way here. // TODO: Find a more robust way to detect distracters. diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index 49153d261..cbf48f0c0 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -27,6 +27,7 @@ import com.android.inputmethod.latin.define.DebugFlags; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; +import java.util.Locale; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -355,37 +356,53 @@ public class SuggestedWords { } // This will always remove the higher index if a duplicate is found. - public static boolean removeDups(final String typedWord, - ArrayList<SuggestedWordInfo> candidates) { + // Returns null if the typed word is not found. Always return the dictionary for the + // highest suggestion matching the locale if found, otherwise return the dictionary for + // the highest suggestion. + @Nullable + public static Dictionary removeDupsAndReturnSourceOfTypedWord( + @Nullable final String typedWord, + @Nullable final Locale preferredLocale, + @Nonnull ArrayList<SuggestedWordInfo> candidates) { if (candidates.isEmpty()) { - return false; + return null; } - final boolean didRemoveTypedWord; + final Dictionary sourceDictionaryOfTypedWord; if (!TextUtils.isEmpty(typedWord)) { - didRemoveTypedWord = removeSuggestedWordInfoFrom(typedWord, candidates, - -1 /* startIndexExclusive */); + sourceDictionaryOfTypedWord = + removeSuggestedWordInfoFromListAndReturnSourceDictionary(typedWord, + preferredLocale, candidates, -1 /* startIndexExclusive */); } else { - didRemoveTypedWord = false; + sourceDictionaryOfTypedWord = null; } for (int i = 0; i < candidates.size(); ++i) { - removeSuggestedWordInfoFrom(candidates.get(i).mWord, candidates, - i /* startIndexExclusive */); + removeSuggestedWordInfoFromListAndReturnSourceDictionary(candidates.get(i).mWord, + null /* preferredLocale */, candidates, i /* startIndexExclusive */); } - return didRemoveTypedWord; + return sourceDictionaryOfTypedWord; } - private static boolean removeSuggestedWordInfoFrom(final String word, - final ArrayList<SuggestedWordInfo> candidates, final int startIndexExclusive) { - boolean didRemove = false; + @Nullable + private static Dictionary removeSuggestedWordInfoFromListAndReturnSourceDictionary( + @Nonnull final String word, @Nullable final Locale preferredLocale, + @Nonnull final ArrayList<SuggestedWordInfo> candidates, + final int startIndexExclusive) { + Dictionary sourceDictionaryOfTypedWord = null; for (int i = startIndexExclusive + 1; i < candidates.size(); ++i) { final SuggestedWordInfo previous = candidates.get(i); if (word.equals(previous.mWord)) { - didRemove = true; + if (null == sourceDictionaryOfTypedWord + || (null != preferredLocale + && preferredLocale.equals(previous.mSourceDict.mLocale))) { + if (Dictionary.TYPE_USER_HISTORY != previous.mSourceDict.mDictType) { + sourceDictionaryOfTypedWord = previous.mSourceDict; + } + } candidates.remove(i); --i; } } - return didRemove; + return sourceDictionaryOfTypedWord; } } diff --git a/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java b/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java index 123ab208c..982d4c690 100644 --- a/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java +++ b/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java @@ -69,7 +69,7 @@ public final class SystemBroadcastReceiver extends BroadcastReceiver { // subtypes when the package is replaced. RichInputMethodManager.init(context); final RichInputMethodManager richImm = RichInputMethodManager.getInstance(); - final InputMethodSubtype[] additionalSubtypes = richImm.getAdditionalSubtypes(context); + final InputMethodSubtype[] additionalSubtypes = richImm.getAdditionalSubtypes(); richImm.setAdditionalInputMethodSubtypes(additionalSubtypes); LauncherIconVisibilityManager.updateSetupWizardIconVisibility(context); } else if (Intent.ACTION_BOOT_COMPLETED.equals(intentAction)) { |