Merge "Fix a bug where the caps mode would not be changed"
diff --git a/java/res/xml-sw600dp/key_styles_common.xml b/java/res/xml-sw600dp/key_styles_common.xml
index a1b2eb4..bf2e76a 100644
--- a/java/res/xml-sw600dp/key_styles_common.xml
+++ b/java/res/xml-sw600dp/key_styles_common.xml
@@ -133,6 +133,17 @@
                 latin:keyIconPreview="!icon/tab_key_preview"
                 latin:backgroundType="functional" />
         </case>
+        <case
+            latin:keyboardLayoutSetElement="alphabet|alphabetAutomaticShifted|alphabetShiftLocked"
+            latin:navigateNext="true"
+        >
+            <key-style
+                latin:styleName="tabKeyStyle"
+                latin:code="!code/key_action_next"
+                latin:keyIcon="!icon/tab_key"
+                latin:keyIconPreview="!icon/tab_key_preview"
+                latin:backgroundType="functional" />
+        </case>
         <default>
             <key-style
                 latin:styleName="tabKeyStyle"
diff --git a/java/res/xml-sw768dp/key_styles_common.xml b/java/res/xml-sw768dp/key_styles_common.xml
index 40082ac..7afe584 100644
--- a/java/res/xml-sw768dp/key_styles_common.xml
+++ b/java/res/xml-sw768dp/key_styles_common.xml
@@ -117,6 +117,17 @@
                 latin:keyLabelFlags="fontNormal|preserveCase"
                 latin:backgroundType="functional" />
         </case>
+        <case
+            latin:keyboardLayoutSetElement="alphabet|alphabetAutomaticShifted|alphabetShiftLocked"
+            latin:navigateNext="true"
+        >
+            <key-style
+                latin:styleName="tabKeyStyle"
+                latin:code="!code/key_action_next"
+                latin:keyLabel="!text/label_tab_key"
+                latin:keyLabelFlags="fontNormal|preserveCase"
+                latin:backgroundType="functional" />
+        </case>
         <default>
             <key-style
                 latin:styleName="tabKeyStyle"
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 1b4cea2..1aec001 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -185,19 +185,21 @@
         if (code == CODE_UNSPECIFIED) {
             return null;
         }
-        final int index = mKeyCache.indexOfKey(code);
-        if (index >= 0) {
-            return mKeyCache.valueAt(index);
-        }
-
-        for (final Key key : mKeys) {
-            if (key.mCode == code) {
-                mKeyCache.put(code, key);
-                return key;
+        synchronized (mKeyCache) {
+            final int index = mKeyCache.indexOfKey(code);
+            if (index >= 0) {
+                return mKeyCache.valueAt(index);
             }
+
+            for (final Key key : mKeys) {
+                if (key.mCode == code) {
+                    mKeyCache.put(code, key);
+                    return key;
+                }
+            }
+            mKeyCache.put(code, null);
+            return null;
         }
-        mKeyCache.put(code, null);
-        return null;
     }
 
     public boolean hasKey(Key aKey) {
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
index 233716a..b54c726 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
@@ -137,11 +137,13 @@
     }
 
     public boolean navigateNext() {
-        return (mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NAVIGATE_NEXT) != 0;
+        return (mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NAVIGATE_NEXT) != 0
+                || imeAction() == EditorInfo.IME_ACTION_NEXT;
     }
 
     public boolean navigatePrevious() {
-        return (mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS) != 0;
+        return (mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS) != 0
+                || imeAction() == EditorInfo.IME_ACTION_PREVIOUS;
     }
 
     public boolean passwordInput() {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
index c4452a5..5326120 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
@@ -68,12 +68,20 @@
 
         public MoreKeySpec(final String moreKeySpec, boolean needsToUpperCase, Locale locale,
                 final KeyboardCodesSet codesSet) {
-            mCode = toUpperCaseOfCodeForLocale(getCode(moreKeySpec, codesSet),
-                    needsToUpperCase, locale);
             mLabel = toUpperCaseOfStringForLocale(getLabel(moreKeySpec),
                     needsToUpperCase, locale);
-            mOutputText = toUpperCaseOfStringForLocale(getOutputText(moreKeySpec),
+            final int code = toUpperCaseOfCodeForLocale(getCode(moreKeySpec, codesSet),
                     needsToUpperCase, locale);
+            if (code == Keyboard.CODE_UNSPECIFIED) {
+                // Some letter, for example German Eszett (U+00DF: "ß"), has multiple characters
+                // upper case representation ("SS").
+                mCode = Keyboard.CODE_OUTPUT_TEXT;
+                mOutputText = mLabel;
+            } else {
+                mCode = code;
+                mOutputText = toUpperCaseOfStringForLocale(getOutputText(moreKeySpec),
+                        needsToUpperCase, locale);
+            }
             mIconId = getIconId(moreKeySpec);
         }
     }
diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java
index 229ae2f..9c32f94 100644
--- a/java/src/com/android/inputmethod/latin/InputAttributes.java
+++ b/java/src/com/android/inputmethod/latin/InputAttributes.java
@@ -29,7 +29,6 @@
     final public boolean mInputTypeNoAutoCorrect;
     final public boolean mIsSettingsSuggestionStripOn;
     final public boolean mApplicationSpecifiedCompletionOn;
-    final public int mEditorAction;
 
     public InputAttributes(final EditorInfo editorInfo, final boolean isFullscreenMode) {
         final int inputType = null != editorInfo ? editorInfo.inputType : 0;
@@ -92,8 +91,6 @@
 
             mApplicationSpecifiedCompletionOn = flagAutoComplete && isFullscreenMode;
         }
-        mEditorAction = (editorInfo == null) ? EditorInfo.IME_ACTION_UNSPECIFIED
-                : editorInfo.imeOptions & EditorInfo.IME_MASK_ACTION;
     }
 
     @SuppressWarnings("unused")
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 3abdbf9..80dda9c 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -48,9 +48,7 @@
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
-import android.view.ViewParent;
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.inputmethod.CompletionInfo;
@@ -208,24 +206,25 @@
             final KeyboardSwitcher switcher = latinIme.mKeyboardSwitcher;
             switch (msg.what) {
             case MSG_UPDATE_SUGGESTIONS:
-                latinIme.updateSuggestions();
+                latinIme.updateSuggestionsOrPredictions(false /* isPredictions */);
                 break;
             case MSG_UPDATE_SHIFT_STATE:
                 switcher.updateShiftState();
                 break;
             case MSG_SET_BIGRAM_PREDICTIONS:
-                latinIme.updateBigramPredictions();
+                latinIme.updateSuggestionsOrPredictions(true /* isPredictions */);
                 break;
             }
         }
 
         public void postUpdateSuggestions() {
-            removeMessages(MSG_UPDATE_SUGGESTIONS);
+            cancelUpdateSuggestionStrip();
             sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTIONS), mDelayUpdateSuggestions);
         }
 
-        public void cancelUpdateSuggestions() {
+        public void cancelUpdateSuggestionStrip() {
             removeMessages(MSG_UPDATE_SUGGESTIONS);
+            removeMessages(MSG_SET_BIGRAM_PREDICTIONS);
         }
 
         public boolean hasPendingUpdateSuggestions() {
@@ -242,14 +241,10 @@
         }
 
         public void postUpdateBigramPredictions() {
-            removeMessages(MSG_SET_BIGRAM_PREDICTIONS);
+            cancelUpdateSuggestionStrip();
             sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_PREDICTIONS), mDelayUpdateSuggestions);
         }
 
-        public void cancelUpdateBigramPredictions() {
-            removeMessages(MSG_SET_BIGRAM_PREDICTIONS);
-        }
-
         public void startDoubleSpacesTimer() {
             mDoubleSpaceTimerStart = SystemClock.uptimeMillis();
         }
@@ -739,7 +734,7 @@
         KeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
         if (inputView != null) inputView.cancelAllMessages();
         // Remove pending messages related to update suggestions
-        mHandler.cancelUpdateSuggestions();
+        mHandler.cancelUpdateSuggestionStrip();
     }
 
     @Override
@@ -1003,7 +998,7 @@
     // the composing word, reset the last composed word, tell the inputconnection about it.
     private void resetEntireInputState() {
         resetComposingState(true /* alsoResetLastComposedWord */);
-        updateSuggestions();
+        clearSuggestions();
         mConnection.finishComposingText();
     }
 
@@ -1026,7 +1021,7 @@
                     LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, typedWord.toString(),
                     separatorCode, prevWord);
         }
-        updateSuggestions();
+        updateSuggestionsOrPredictions(false /* isPredictions */);
     }
 
     public int getCurrentAutoCapsState() {
@@ -1105,7 +1100,7 @@
     }
 
     @Override
-    public boolean addWordToDictionary(String word) {
+    public boolean addWordToUserDictionary(String word) {
         mUserDictionary.addWordToUserDictionary(word, 128);
         // Suggestion strip should be updated after the operation of adding word to the
         // user dictionary
@@ -1276,10 +1271,6 @@
             }
             break;
         default:
-            if (primaryCode == Keyboard.CODE_TAB && mCurrentSettings.isEditorActionNext()) {
-                performEditorAction(EditorInfo.IME_ACTION_NEXT);
-                break;
-            }
             mSpaceState = SPACE_STATE_NONE;
             if (mCurrentSettings.isWordSeparator(primaryCode)) {
                 didAutoCorrect = handleSeparator(primaryCode, x, y, spaceState);
@@ -1553,7 +1544,6 @@
             final int spaceState) {
         // Should dismiss the "Touch again to save" message when handling separator
         if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) {
-            mHandler.cancelUpdateBigramPredictions();
             mHandler.postUpdateSuggestions();
         }
 
@@ -1592,7 +1582,6 @@
 
             mHandler.startDoubleSpacesTimer();
             if (!mConnection.isCursorTouchingWord(mCurrentSettings)) {
-                mHandler.cancelUpdateSuggestions();
                 mHandler.postUpdateBigramPredictions();
             }
         } else {
@@ -1650,27 +1639,6 @@
         return mCurrentSettings.isSuggestionsRequested(mDisplayOrientation);
     }
 
-    public void switchToKeyboardView() {
-        if (DEBUG) {
-            Log.d(TAG, "Switch to keyboard view.");
-        }
-        if (ProductionFlag.IS_EXPERIMENTAL) {
-            ResearchLogger.latinIME_switchToKeyboardView();
-        }
-        View v = mKeyboardSwitcher.getKeyboardView();
-        if (v != null) {
-            // Confirms that the keyboard view doesn't have parent view.
-            ViewParent p = v.getParent();
-            if (p != null && p instanceof ViewGroup) {
-                ((ViewGroup) p).removeView(v);
-            }
-            setInputView(v);
-        }
-        setSuggestionStripShown(isSuggestionsStripVisible());
-        updateInputViewShown();
-        mHandler.postUpdateSuggestions();
-    }
-
     public void clearSuggestions() {
         setSuggestions(SuggestedWords.EMPTY, false);
         setAutoCorrectionIndicator(false);
@@ -1694,28 +1662,43 @@
         }
     }
 
-    public void updateSuggestions() {
-        mHandler.cancelUpdateSuggestions();
-        mHandler.cancelUpdateBigramPredictions();
+    public void updateSuggestionsOrPredictions(final boolean isPredictions) {
+        mHandler.cancelUpdateSuggestionStrip();
 
         // Check if we have a suggestion engine attached.
-        if ((mSuggest == null || !mCurrentSettings.isSuggestionsRequested(mDisplayOrientation))) {
+        if (mSuggest == null || !mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) {
             if (mWordComposer.isComposingWord()) {
-                Log.w(TAG, "Called updateSuggestions but suggestions were not requested!");
+                Log.w(TAG, "Called updateSuggestionsOrPredictions but suggestions were not "
+                        + "requested!");
                 mWordComposer.setAutoCorrection(mWordComposer.getTypedWord());
             }
             return;
         }
 
-        if (!mWordComposer.isComposingWord()) {
-            // This is dead code: we can't come here with an empty word composer.
-            setPunctuationSuggestions();
-            return;
+        final CharSequence typedWord;
+        final SuggestedWords suggestions;
+        if (isPredictions || !mWordComposer.isComposingWord()) {
+            if (!mCurrentSettings.mBigramPredictionEnabled) {
+                setPunctuationSuggestions();
+                return;
+            }
+            typedWord = "";
+            suggestions = updateBigramPredictions(typedWord);
+        } else {
+            typedWord = mWordComposer.getTypedWord();
+            suggestions = updateSuggestions(typedWord);
         }
 
+        if (null != suggestions && suggestions.size() > 0) {
+            showSuggestions(suggestions, typedWord);
+        } else {
+            clearSuggestions();
+        }
+    }
+
+    private SuggestedWords updateSuggestions(final CharSequence typedWord) {
         // TODO: May need a better way of retrieving previous word
         final CharSequence prevWord = mConnection.getPreviousWord(mCurrentSettings.mWordSeparators);
-        final CharSequence typedWord = mWordComposer.getTypedWord();
         // getSuggestedWords handles gracefully a null value of prevWord
         final SuggestedWords suggestedWords = mSuggest.getSuggestedWords(mWordComposer,
                 prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(),
@@ -1730,7 +1713,7 @@
         if (suggestedWords.size() > 1 || typedWord.length() == 1
                 || !suggestedWords.mTypedWordValid
                 || mSuggestionsView.isShowingAddToDictionaryHint()) {
-            showSuggestions(suggestedWords, typedWord);
+            return suggestedWords;
         } else {
             SuggestedWords previousSuggestions = mSuggestionsView.getSuggestions();
             if (previousSuggestions == mCurrentSettings.mSuggestPuncList) {
@@ -1739,18 +1722,18 @@
             final ArrayList<SuggestedWords.SuggestedWordInfo> typedWordAndPreviousSuggestions =
                     SuggestedWords.getTypedWordAndPreviousSuggestions(
                             typedWord, previousSuggestions);
-            final SuggestedWords obsoleteSuggestedWords =
-                    new SuggestedWords(typedWordAndPreviousSuggestions,
+            return new SuggestedWords(typedWordAndPreviousSuggestions,
                             false /* typedWordValid */,
                             false /* hasAutoCorrectionCandidate */,
                             false /* isPunctuationSuggestions */,
                             true /* isObsoleteSuggestions */,
                             false /* isPrediction */);
-            showSuggestions(obsoleteSuggestedWords, typedWord);
         }
     }
 
-    public void showSuggestions(final SuggestedWords suggestedWords, final CharSequence typedWord) {
+    private void showSuggestions(final SuggestedWords suggestedWords,
+            final CharSequence typedWord) {
+        // This method is only ever called by updateSuggestions or updateBigramPredictions.
         final CharSequence autoCorrection;
         if (suggestedWords.size() > 0) {
             if (suggestedWords.mWillAutoCorrect) {
@@ -1771,8 +1754,8 @@
     private void commitCurrentAutoCorrection(final int separatorCodePoint) {
         // Complete any pending suggestions query first
         if (mHandler.hasPendingUpdateSuggestions()) {
-            mHandler.cancelUpdateSuggestions();
-            updateSuggestions();
+            mHandler.cancelUpdateSuggestionStrip();
+            updateSuggestionsOrPredictions(false /* isPredictions */);
         }
         final CharSequence autoCorrection = mWordComposer.getAutoCorrectionOrNull();
         if (autoCorrection != null) {
@@ -1882,7 +1865,7 @@
         if (!showingAddToDictionaryHint) {
             // If we're not showing the "Touch again to save", then show corrections again.
             // In case the cursor position doesn't change, make sure we show the suggestions again.
-            updateBigramPredictions();
+            updateSuggestionsOrPredictions(true /* isPredictions */);
             // Updating the predictions right away may be slow and feel unresponsive on slower
             // terminals. On the other hand if we just postUpdateBigramPredictions() it will
             // take a noticeable delay to update them which may feel uneasy.
@@ -1917,44 +1900,11 @@
                 separatorCode, prevWord);
     }
 
-    public void updateBigramPredictions() {
-        mHandler.cancelUpdateSuggestions();
-        mHandler.cancelUpdateBigramPredictions();
-
-        if (mSuggest == null || !mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) {
-            if (mWordComposer.isComposingWord()) {
-                Log.w(TAG, "Called updateBigramPredictions but suggestions were not requested!");
-                mWordComposer.setAutoCorrection(mWordComposer.getTypedWord());
-            }
-            return;
-        }
-
-        if (!mCurrentSettings.mBigramPredictionEnabled) {
-            setPunctuationSuggestions();
-            return;
-        }
-
-        final SuggestedWords suggestedWords;
-        if (mCurrentSettings.mCorrectionEnabled) {
-            final CharSequence prevWord = mConnection.getThisWord(mCurrentSettings.mWordSeparators);
-            if (!TextUtils.isEmpty(prevWord)) {
-                suggestedWords = mSuggest.getSuggestedWords(mWordComposer,
-                        prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(),
-                        mCurrentSettings.mCorrectionEnabled, true);
-            } else {
-                suggestedWords = null;
-            }
-        } else {
-            suggestedWords = null;
-        }
-
-        if (null != suggestedWords && suggestedWords.size() > 0) {
-            // Explicitly supply an empty typed word (the no-second-arg version of
-            // showSuggestions will retrieve the word near the cursor, we don't want that here)
-            showSuggestions(suggestedWords, "");
-        } else {
-            clearSuggestions();
-        }
+    private SuggestedWords updateBigramPredictions(final CharSequence typedWord) {
+        final CharSequence prevWord = mConnection.getThisWord(mCurrentSettings.mWordSeparators);
+        return mSuggest.getSuggestedWords(mWordComposer,
+                prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(),
+                mCurrentSettings.mCorrectionEnabled, true);
     }
 
     public void setPunctuationSuggestions() {
@@ -2068,7 +2018,6 @@
             // separator.
         }
         mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
-        mHandler.cancelUpdateBigramPredictions();
         mHandler.postUpdateSuggestions();
     }
 
diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java
index e83d7c8..2de0194 100644
--- a/java/src/com/android/inputmethod/latin/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java
@@ -933,13 +933,6 @@
                 EVENTKEYS_NULLVALUES);
     }
 
-    private static final String[] EVENTKEYS_LATINIME_SWITCHTOKEYBOARDVIEW = {
-        "LatinIMESwitchToKeyboardView"
-    };
-    public static void latinIME_switchToKeyboardView() {
-        getInstance().enqueueEvent(EVENTKEYS_LATINIME_SWITCHTOKEYBOARDVIEW, EVENTKEYS_NULLVALUES);
-    }
-
     private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_ONLONGPRESS = {
         "LatinKeyboardViewOnLongPress"
     };
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 4c89a6e..70acdc7 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -111,6 +111,10 @@
         final Resources res = getResources();
         final Context context = getActivity();
 
+        // When we are called from the Settings application but we are not already running, the
+        // {@link SubtypeLocale} class may not have been initialized. It is safe to call
+        // {@link SubtypeLocale#init(Context)} multiple times.
+        SubtypeLocale.init(context);
         mVoicePreference = (ListPreference) findPreference(PREF_VOICE_MODE);
         mShowCorrectionSuggestionsPreference =
                 (ListPreference) findPreference(PREF_SHOW_SUGGESTIONS_SETTING);
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index aab84fc..10025da 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -224,10 +224,6 @@
         return mInputAttributes.mApplicationSpecifiedCompletionOn;
     }
 
-    public boolean isEditorActionNext() {
-        return mInputAttributes.mEditorAction == EditorInfo.IME_ACTION_NEXT;
-    }
-
     public boolean isSuggestionsRequested(final int displayOrientation) {
         return mInputAttributes.mIsSettingsSuggestionStripOn
                 && (mCorrectionEnabled
diff --git a/java/src/com/android/inputmethod/latin/SubtypeLocale.java b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
index acc17ef..21c9c0d 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeLocale.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
@@ -41,6 +41,7 @@
     public static final String QWERTY = "qwerty";
     public static final int UNKNOWN_KEYBOARD_LAYOUT = R.string.subtype_generic;
 
+    private static boolean sInitialized = false;
     private static String[] sPredefinedKeyboardLayoutSet;
     // Keyboard layout to its display name map.
     private static final HashMap<String, String> sKeyboardLayoutToDisplayNameMap =
@@ -69,7 +70,10 @@
         // Intentional empty constructor for utility class.
     }
 
-    public static void init(Context context) {
+    // Note that this initialization method can be called multiple times.
+    public static synchronized void init(Context context) {
+        if (sInitialized) return;
+
         final Resources res = context.getResources();
 
         final String[] predefinedLayoutSet = res.getStringArray(R.array.predefined_layouts);
@@ -109,6 +113,8 @@
             final String keyboardLayoutSet = keyboardLayoutSetMap[i + 1];
             sLocaleAndExtraValueToKeyboardLayoutSetMap.put(key, keyboardLayoutSet);
         }
+
+        sInitialized = true;
     }
 
     public static String[] getPredefinedKeyboardLayoutSet() {
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java
index 642a551..4d33f4b 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java
@@ -71,7 +71,7 @@
 public class SuggestionsView extends RelativeLayout implements OnClickListener,
         OnLongClickListener {
     public interface Listener {
-        public boolean addWordToDictionary(String word);
+        public boolean addWordToUserDictionary(String word);
         public void pickSuggestionManually(int index, CharSequence word, int x, int y);
     }
 
@@ -718,10 +718,6 @@
         mPreviewPopup.dismiss();
     }
 
-    private void addToDictionary(CharSequence word) {
-        mListener.addWordToDictionary(word.toString());
-    }
-
     private final KeyboardActionListener mMoreSuggestionsListener =
             new KeyboardActionListener.Adapter() {
         @Override
@@ -863,7 +859,7 @@
     @Override
     public void onClick(View view) {
         if (mParams.isAddToDictionaryShowing(view)) {
-            addToDictionary(mParams.getAddToDictionaryWord());
+            mListener.addWordToUserDictionary(mParams.getAddToDictionaryWord().toString());
             clear();
             return;
         }