diff options
Diffstat (limited to 'java/src/com/android/inputmethod/latin/LatinIME.java')
-rw-r--r-- | java/src/com/android/inputmethod/latin/LatinIME.java | 499 |
1 files changed, 246 insertions, 253 deletions
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 5ce1b7e95..6e76cadf2 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -18,7 +18,6 @@ package com.android.inputmethod.latin; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardActionListener; -import com.android.inputmethod.keyboard.KeyboardId; import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.KeyboardView; import com.android.inputmethod.keyboard.LatinKeyboard; @@ -40,6 +39,7 @@ import android.media.AudioManager; import android.net.ConnectivityManager; import android.os.Debug; import android.os.Handler; +import android.os.IBinder; import android.os.Message; import android.os.SystemClock; import android.os.Vibrator; @@ -81,13 +81,34 @@ import java.util.Locale; /** * Input method implementation for Qwerty'ish keyboard. */ -public class LatinIME extends InputMethodService implements KeyboardActionListener, - SharedPreferences.OnSharedPreferenceChangeListener { - private static final String TAG = "LatinIME"; +public class LatinIME extends InputMethodService implements KeyboardActionListener { + private static final String TAG = LatinIME.class.getSimpleName(); private static final boolean PERF_DEBUG = false; private static final boolean TRACE = false; private static boolean DEBUG = LatinImeLogger.sDBG; + /** + * The private IME option used to indicate that no microphone should be + * shown for a given text field. For instance, this is specified by the + * search dialog when the dialog is already showing a voice search button. + * + * @deprecated Use {@link LatinIME#IME_OPTION_NO_MICROPHONE} with package name prefixed. + */ + public static final String IME_OPTION_NO_MICROPHONE_COMPAT = "nm"; + + /** + * The private IME option used to indicate that no microphone should be + * shown for a given text field. For instance, this is specified by the + * search dialog when the dialog is already showing a voice search button. + */ + public static final String IME_OPTION_NO_MICROPHONE = "noMicrophoneKey"; + + /** + * The private IME option used to indicate that no settings key should be + * shown for a given text field. + */ + public static final String IME_OPTION_NO_SETTINGS_KEY = "noSettingsKey"; + private static final int DELAY_UPDATE_SUGGESTIONS = 180; private static final int DELAY_UPDATE_OLD_SUGGESTIONS = 300; private static final int DELAY_UPDATE_SHIFT_STATE = 300; @@ -138,6 +159,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private boolean mIsSettingsSuggestionStripOn; private boolean mApplicationSpecifiedCompletionOn; + private AccessibilityUtils mAccessibilityUtils; + private final StringBuilder mComposing = new StringBuilder(); private WordComposer mWord = new WordComposer(); private CharSequence mBestWord; @@ -145,7 +168,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private boolean mHasDictionary; private boolean mJustAddedAutoSpace; private boolean mAutoCorrectEnabled; - private boolean mReCorrectionEnabled; + private boolean mRecorrectionEnabled; private boolean mBigramSuggestionEnabled; private boolean mAutoCorrectOn; private boolean mVibrateOn; @@ -158,6 +181,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private int mConfigDelayBeforeFadeoutLanguageOnSpacebar; private int mConfigDurationOfFadeoutLanguageOnSpacebar; private float mConfigFinalFadeoutFactorOfLanguageOnSpacebar; + private long mConfigDoubleSpacesTurnIntoPeriodTimeout; private int mCorrectionMode; private int mCommittedLength; @@ -169,7 +193,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // Indicates whether the suggestion strip is to be on in landscape private boolean mJustAccepted; - private boolean mJustReverted; private int mDeleteCount; private long mLastKeyTime; @@ -186,7 +209,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // Keeps track of most recently inserted text (multi-character key) for reverting private CharSequence mEnteredText; - private boolean mRefreshKeyboardRequired; private final ArrayList<WordAlternatives> mWordHistory = new ArrayList<WordAlternatives>(); @@ -247,6 +269,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private static final int MSG_VOICE_RESULTS = 3; private static final int MSG_FADEOUT_LANGUAGE_ON_SPACEBAR = 4; private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 5; + private static final int MSG_SPACE_TYPED = 6; @Override public void handleMessage(Message msg) { @@ -323,7 +346,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen removeMessages(MSG_DISMISS_LANGUAGE_ON_SPACEBAR); final LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); if (inputView != null) { - final LatinKeyboard keyboard = inputView.getLatinKeyboard(); + final LatinKeyboard keyboard = mKeyboardSwitcher.getLatinKeyboard(); // The language is never displayed when the delay is zero. if (mConfigDelayBeforeFadeoutLanguageOnSpacebar != 0) inputView.setSpacebarTextFadeFactor(localeChanged ? 1.0f @@ -335,6 +358,20 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } } + + public void startDoubleSpacesTimer() { + removeMessages(MSG_SPACE_TYPED); + sendMessageDelayed(obtainMessage(MSG_SPACE_TYPED), + mConfigDoubleSpacesTurnIntoPeriodTimeout); + } + + public void cancelDoubleSpacesTimer() { + removeMessages(MSG_SPACE_TYPED); + } + + public boolean isAcceptingDoubleSpaces() { + return hasMessages(MSG_SPACE_TYPED); + } } @Override @@ -344,13 +381,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen LatinImeLogger.init(this, prefs); SubtypeSwitcher.init(this, prefs); KeyboardSwitcher.init(this, prefs); + AccessibilityUtils.init(this, prefs); super.onCreate(); mImm = ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)); - mInputMethodId = Utils.getInputMethodId(mImm, getApplicationInfo().packageName); + mInputMethodId = Utils.getInputMethodId(mImm, getPackageName()); mSubtypeSwitcher = SubtypeSwitcher.getInstance(); mKeyboardSwitcher = KeyboardSwitcher.getInstance(); + mAccessibilityUtils = AccessibilityUtils.getInstance(); final Resources res = getResources(); mResources = res; @@ -358,10 +397,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // If the option should not be shown, do not read the recorrection preference // but always use the default setting defined in the resources. if (res.getBoolean(R.bool.config_enable_show_recorrection_option)) { - mReCorrectionEnabled = prefs.getBoolean(Settings.PREF_RECORRECTION_ENABLED, - res.getBoolean(R.bool.default_recorrection_enabled)); + mRecorrectionEnabled = prefs.getBoolean(Settings.PREF_RECORRECTION_ENABLED, + res.getBoolean(R.bool.config_default_recorrection_enabled)); } else { - mReCorrectionEnabled = res.getBoolean(R.bool.default_recorrection_enabled); + mRecorrectionEnabled = res.getBoolean(R.bool.config_default_recorrection_enabled); } mConfigEnableShowSubtypeSettings = res.getBoolean( @@ -374,6 +413,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen R.integer.config_duration_of_fadeout_language_on_spacebar); mConfigFinalFadeoutFactorOfLanguageOnSpacebar = res.getInteger( R.integer.config_final_fadeout_percentage_of_language_on_spacebar) / 100.0f; + mConfigDoubleSpacesTurnIntoPeriodTimeout = res.getInteger( + R.integer.config_double_spaces_turn_into_period_timeout); Utils.GCUtils.getInstance().reset(); boolean tryGC = true; @@ -395,21 +436,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); registerReceiver(mReceiver, filter); mVoiceConnector = VoiceIMEConnector.init(this, prefs, mHandler); - prefs.registerOnSharedPreferenceChangeListener(this); - } - - /** - * Returns a main dictionary resource id - * @return main dictionary resource id - */ - public static int getMainDictionaryResourceId(Resources res) { - final String MAIN_DIC_NAME = "main"; - String packageName = LatinIME.class.getPackage().getName(); - return res.getIdentifier(MAIN_DIC_NAME, "raw", packageName); } private void initSuggest() { - updateAutoTextEnabled(); String locale = mSubtypeSwitcher.getInputLocaleStr(); Locale savedLocale = mSubtypeSwitcher.changeSystemLocale(new Locale(locale)); @@ -420,9 +449,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mQuickFixes = isQuickFixesEnabled(prefs); final Resources res = mResources; - int mainDicResId = getMainDictionaryResourceId(res); + int mainDicResId = Utils.getMainDictionaryResourceId(res); mSuggest = new Suggest(this, mainDicResId); loadAndSetAutoCorrectionThreshold(prefs); + updateAutoTextEnabled(); mUserDictionary = new UserDictionary(this, locale); mSuggest.setUserDictionary(mUserDictionary); @@ -497,17 +527,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen return container; } - private static boolean isPasswordVariation(int variation) { - return variation == InputType.TYPE_TEXT_VARIATION_PASSWORD - || variation == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD - || variation == InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD; - } - - private static boolean isEmailVariation(int variation) { - return variation == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS - || variation == InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS; - } - @Override public void onStartInputView(EditorInfo attribute, boolean restarting) { final KeyboardSwitcher switcher = mKeyboardSwitcher; @@ -523,20 +542,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mSubtypeSwitcher.updateParametersOnStartInputView(); - if (mRefreshKeyboardRequired) { - mRefreshKeyboardRequired = false; - onRefreshKeyboard(); - } - - TextEntryState.newSession(this); + TextEntryState.reset(); // Most such things we decide below in initializeInputAttributesAndGetMode, but we need to // know now whether this is a password text field, because we need to know now whether we // want to enable the voice button. - mVoiceConnector.resetVoiceStates(isPasswordVariation( - attribute.inputType & InputType.TYPE_MASK_VARIATION)); + final VoiceIMEConnector voiceIme = mVoiceConnector; + voiceIme.resetVoiceStates(Utils.isPasswordInputType(attribute.inputType) + || Utils.isVisiblePasswordInputType(attribute.inputType)); - final int mode = initializeInputAttributesAndGetMode(attribute.inputType); + initializeInputAttributes(attribute); inputView.closing(); mEnteredText = null; @@ -547,9 +562,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen loadSettings(attribute); if (mSubtypeSwitcher.isKeyboardMode()) { - switcher.loadKeyboard(mode, attribute.imeOptions, - mVoiceConnector.isVoiceButtonEnabled(), - mVoiceConnector.isVoiceButtonOnPrimary()); + switcher.loadKeyboard(attribute, + mSubtypeSwitcher.isShortcutImeEnabled() && voiceIme.isVoiceButtonEnabled(), + voiceIme.isVoiceButtonOnPrimary()); switcher.updateShiftState(); } @@ -560,18 +575,24 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen updateCorrectionMode(); + final boolean accessibilityEnabled = mAccessibilityUtils.isAccessibilityEnabled(); + inputView.setPreviewEnabled(mPopupOn); inputView.setProximityCorrectionEnabled(true); + inputView.setAccessibilityEnabled(accessibilityEnabled); // If we just entered a text field, maybe it has some old text that requires correction - checkReCorrectionOnStart(); + checkRecorrectionOnStart(); inputView.setForeground(true); - mVoiceConnector.onStartInputView(inputView.getWindowToken()); + voiceIme.onStartInputView(inputView.getWindowToken()); if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); } - private int initializeInputAttributesAndGetMode(int inputType) { + private void initializeInputAttributes(EditorInfo attribute) { + if (attribute == null) + return; + final int inputType = attribute.inputType; final int variation = inputType & InputType.TYPE_MASK_VARIATION; mAutoSpace = false; mInputTypeNoAutoCorrect = false; @@ -579,73 +600,52 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mApplicationSpecifiedCompletionOn = false; mApplicationSpecifiedCompletions = null; - final int mode; - switch (inputType & InputType.TYPE_MASK_CLASS) { - case InputType.TYPE_CLASS_NUMBER: - case InputType.TYPE_CLASS_DATETIME: - mode = KeyboardId.MODE_NUMBER; - break; - case InputType.TYPE_CLASS_PHONE: - mode = KeyboardId.MODE_PHONE; - break; - case InputType.TYPE_CLASS_TEXT: - mIsSettingsSuggestionStripOn = true; - // Make sure that passwords are not displayed in candidate view - if (isPasswordVariation(variation)) { - mIsSettingsSuggestionStripOn = false; - } - if (isEmailVariation(variation) - || variation == InputType.TYPE_TEXT_VARIATION_PERSON_NAME) { - mAutoSpace = false; - } else { - mAutoSpace = true; - } - if (isEmailVariation(variation)) { - mIsSettingsSuggestionStripOn = false; - mode = KeyboardId.MODE_EMAIL; - } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) { - mIsSettingsSuggestionStripOn = false; - mode = KeyboardId.MODE_URL; - } else if (variation == InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE) { - mode = KeyboardId.MODE_IM; - } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) { - mIsSettingsSuggestionStripOn = false; - mode = KeyboardId.MODE_TEXT; - } else if (variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) { - mode = KeyboardId.MODE_WEB; - // If it's a browser edit field and auto correct is not ON explicitly, then - // disable auto correction, but keep suggestions on. - if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) { - mInputTypeNoAutoCorrect = true; - } - } else { - mode = KeyboardId.MODE_TEXT; - } - - // If NO_SUGGESTIONS is set, don't do prediction. - if ((inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) { - mIsSettingsSuggestionStripOn = false; - mInputTypeNoAutoCorrect = true; - } - // If it's not multiline and the autoCorrect flag is not set, then don't correct - if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 && - (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) == 0) { + if ((inputType & InputType.TYPE_MASK_CLASS) == InputType.TYPE_CLASS_TEXT) { + mIsSettingsSuggestionStripOn = true; + // Make sure that passwords are not displayed in candidate view + if (Utils.isPasswordInputType(inputType) + || Utils.isVisiblePasswordInputType(inputType)) { + mIsSettingsSuggestionStripOn = false; + } + if (Utils.isEmailVariation(variation) + || variation == InputType.TYPE_TEXT_VARIATION_PERSON_NAME) { + mAutoSpace = false; + } else { + mAutoSpace = true; + } + if (Utils.isEmailVariation(variation)) { + mIsSettingsSuggestionStripOn = false; + } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) { + mIsSettingsSuggestionStripOn = false; + } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) { + mIsSettingsSuggestionStripOn = false; + } else if (variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) { + // If it's a browser edit field and auto correct is not ON explicitly, then + // disable auto correction, but keep suggestions on. + if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) { mInputTypeNoAutoCorrect = true; } - if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { - mIsSettingsSuggestionStripOn = false; - mApplicationSpecifiedCompletionOn = isFullscreenMode(); - } - break; - default: - mode = KeyboardId.MODE_TEXT; - break; + } + + // If NO_SUGGESTIONS is set, don't do prediction. + if ((inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) { + mIsSettingsSuggestionStripOn = false; + mInputTypeNoAutoCorrect = true; + } + // If it's not multiline and the autoCorrect flag is not set, then don't correct + if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 + && (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) == 0) { + mInputTypeNoAutoCorrect = true; + } + if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { + mIsSettingsSuggestionStripOn = false; + mApplicationSpecifiedCompletionOn = isFullscreenMode(); + } } - return mode; } - private void checkReCorrectionOnStart() { - if (!mReCorrectionEnabled) return; + private void checkRecorrectionOnStart() { + if (!mRecorrectionEnabled) return; final InputConnection ic = getCurrentInputConnection(); if (ic == null) return; @@ -713,6 +713,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (DEBUG) { Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart + ", ose=" + oldSelEnd + + ", lss=" + mLastSelectionStart + + ", lse=" + mLastSelectionEnd + ", nss=" + newSelStart + ", nse=" + newSelEnd + ", cs=" + candidatesStart @@ -723,9 +725,18 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // If the current selection in the text view changes, we should // clear whatever candidate text we have. - if ((((mComposing.length() > 0 && mHasValidSuggestions) - || mVoiceConnector.isVoiceInputHighlighted()) && (newSelStart != candidatesEnd - || newSelEnd != candidatesEnd) && mLastSelectionStart != newSelStart)) { + final boolean selectionChanged = (newSelStart != candidatesEnd + || newSelEnd != candidatesEnd) && mLastSelectionStart != newSelStart; + final boolean candidatesCleared = candidatesStart == -1 && candidatesEnd == -1; + if (((mComposing.length() > 0 && mHasValidSuggestions) + || mVoiceConnector.isVoiceInputHighlighted()) + && (selectionChanged || candidatesCleared)) { + if (candidatesCleared) { + // If the composing span has been cleared, save the typed word in the history for + // recorrection before we reset the candidate strip. Then, we'll be able to show + // suggestions for recorrection right away. + saveWordInHistory(mComposing); + } mComposing.setLength(0); mHasValidSuggestions = false; mHandler.postUpdateSuggestions(); @@ -736,15 +747,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } mVoiceConnector.setVoiceInputHighlighted(false); } else if (!mHasValidSuggestions && !mJustAccepted) { - switch (TextEntryState.getState()) { - case ACCEPTED_DEFAULT: - TextEntryState.reset(); - // $FALL-THROUGH$ - case SPACE_AFTER_PICKED: + if (TextEntryState.isAcceptedDefault() || TextEntryState.isSpaceAfterPicked()) { + if (TextEntryState.isAcceptedDefault()) + TextEntryState.reset(); mJustAddedAutoSpace = false; // The user moved the cursor. - break; - default: - break; } } mJustAccepted = false; @@ -754,18 +760,18 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mLastSelectionStart = newSelStart; mLastSelectionEnd = newSelEnd; - if (mReCorrectionEnabled && isShowingSuggestionsStrip()) { + if (mRecorrectionEnabled && isShowingSuggestionsStrip()) { // Don't look for corrections if the keyboard is not visible if (mKeyboardSwitcher.isInputViewShown()) { // Check if we should go in or out of correction mode. - if (isSuggestionsRequested() && !mJustReverted + if (isSuggestionsRequested() && (candidatesStart == candidatesEnd || newSelStart != oldSelStart - || TextEntryState.isCorrecting()) + || TextEntryState.isRecorrecting()) && (newSelStart < newSelEnd - 1 || !mHasValidSuggestions)) { if (isCursorTouchingWord() || mLastSelectionStart < mLastSelectionEnd) { mHandler.postUpdateOldSuggestions(); } else { - abortCorrection(false); + abortRecorrection(false); // Show the punctuation suggestions list if the current one is not // and if not showing "Touch again to save". if (mCandidateView != null && !isShowingPunctuationList() @@ -788,7 +794,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen */ @Override public void onExtractedTextClicked() { - if (mReCorrectionEnabled && isSuggestionsRequested()) return; + if (mRecorrectionEnabled && isSuggestionsRequested()) return; super.onExtractedTextClicked(); } @@ -804,7 +810,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen */ @Override public void onExtractedCursorMovement(int dx, int dy) { - if (mReCorrectionEnabled && isSuggestionsRequested()) return; + if (mRecorrectionEnabled && isSuggestionsRequested()) return; super.onExtractedCursorMovement(dx, dy); } @@ -822,17 +828,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mVoiceConnector.hideVoiceWindow(mConfigurationChanging); mWordHistory.clear(); super.hideWindow(); - TextEntryState.endSession(); } @Override public void onDisplayCompletions(CompletionInfo[] applicationSpecifiedCompletions) { if (DEBUG) { Log.i(TAG, "Received completions:"); - final int count = (applicationSpecifiedCompletions != null) - ? applicationSpecifiedCompletions.length : 0; - for (int i = 0; i < count; i++) { - Log.i(TAG, " #" + i + ": " + applicationSpecifiedCompletions[i]); + if (applicationSpecifiedCompletions != null) { + for (int i = 0; i < applicationSpecifiedCompletions.length; i++) { + Log.i(TAG, " #" + i + ": " + applicationSpecifiedCompletions[i]); + } } } if (mApplicationSpecifiedCompletionOn) { @@ -963,7 +968,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } mCommittedLength = mComposing.length(); TextEntryState.acceptedTyped(mComposing); - addToDictionaries(mComposing, AutoDictionary.FREQUENCY_FOR_TYPED); + addToAutoAndUserBigramDictionaries(mComposing, AutoDictionary.FREQUENCY_FOR_TYPED); } updateSuggestions(); } @@ -1011,7 +1016,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } private void doubleSpace() { - //if (!mAutoPunctuate) return; if (mCorrectionMode == Suggest.CORRECTION_NONE) return; final InputConnection ic = getCurrentInputConnection(); if (ic == null) return; @@ -1019,13 +1023,17 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (lastThree != null && lastThree.length() == 3 && Character.isLetterOrDigit(lastThree.charAt(0)) && lastThree.charAt(1) == Keyboard.CODE_SPACE - && lastThree.charAt(2) == Keyboard.CODE_SPACE) { + && lastThree.charAt(2) == Keyboard.CODE_SPACE + && mHandler.isAcceptingDoubleSpaces()) { + mHandler.cancelDoubleSpacesTimer(); ic.beginBatchEdit(); ic.deleteSurroundingText(2, 0); ic.commitText(". ", 1); ic.endBatchEdit(); mKeyboardSwitcher.updateShiftState(); mJustAddedAutoSpace = true; + } else { + mHandler.startDoubleSpacesTimer(); } } @@ -1105,6 +1113,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } mLastKeyTime = when; KeyboardSwitcher switcher = mKeyboardSwitcher; + final boolean accessibilityEnabled = switcher.isAccessibilityEnabled(); final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); switch (primaryCode) { case Keyboard.CODE_DELETE: @@ -1114,12 +1123,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen break; case Keyboard.CODE_SHIFT: // Shift key is handled in onPress() when device has distinct multi-touch panel. - if (!distinctMultiTouch) + if (!distinctMultiTouch || accessibilityEnabled) switcher.toggleShift(); break; case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: // Symbol key is handled in onPress() when device has distinct multi-touch panel. - if (!distinctMultiTouch) + if (!distinctMultiTouch || accessibilityEnabled) switcher.changeKeyboardMode(); break; case Keyboard.CODE_CANCEL: @@ -1157,10 +1166,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (isWordSeparator(primaryCode)) { handleSeparator(primaryCode); } else { - handleCharacter(primaryCode, keyCodes); + handleCharacter(primaryCode, keyCodes, x, y); } - // Cancel the just reverted state - mJustReverted = false; } switcher.onKey(primaryCode); // Reset after any single keystroke @@ -1172,7 +1179,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mVoiceConnector.commitVoiceInput(); InputConnection ic = getCurrentInputConnection(); if (ic == null) return; - abortCorrection(false); + abortRecorrection(false); ic.beginBatchEdit(); commitTyped(ic); maybeRemovePreviousPeriod(text); @@ -1180,7 +1187,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen ic.endBatchEdit(); mKeyboardSwitcher.updateShiftState(); mKeyboardSwitcher.onKey(Keyboard.CODE_DUMMY); - mJustReverted = false; mJustAddedAutoSpace = false; mEnteredText = text; } @@ -1220,7 +1226,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mHandler.postUpdateShiftKeyState(); TextEntryState.backspace(); - if (TextEntryState.getState() == TextEntryState.State.UNDO_COMMIT) { + if (TextEntryState.isUndoCommit()) { revertLastWord(deleteChar); ic.endBatchEdit(); return; @@ -1245,7 +1251,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } } - mJustReverted = false; ic.endBatchEdit(); } @@ -1273,20 +1278,20 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } - private void abortCorrection(boolean force) { - if (force || TextEntryState.isCorrecting()) { - TextEntryState.onAbortCorrection(); + private void abortRecorrection(boolean force) { + if (force || TextEntryState.isRecorrecting()) { + TextEntryState.onAbortRecorrection(); setCandidatesViewShown(isCandidateStripVisible()); getCurrentInputConnection().finishComposingText(); clearSuggestions(); } } - private void handleCharacter(int primaryCode, int[] keyCodes) { + private void handleCharacter(int primaryCode, int[] keyCodes, int x, int y) { mVoiceConnector.handleCharacter(); - if (mLastSelectionStart == mLastSelectionEnd && TextEntryState.isCorrecting()) { - abortCorrection(false); + if (mLastSelectionStart == mLastSelectionEnd && TextEntryState.isRecorrecting()) { + abortRecorrection(false); } int code = primaryCode; @@ -1296,6 +1301,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mComposing.setLength(0); saveWordInHistory(mBestWord); mWord.reset(); + clearSuggestions(); } } KeyboardSwitcher switcher = mKeyboardSwitcher; @@ -1323,7 +1329,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mWord.setFirstCharCapitalized(true); } mComposing.append((char) code); - mWord.add(code, keyCodes); + mWord.add(code, keyCodes, x, y); InputConnection ic = getCurrentInputConnection(); if (ic != null) { // If it's the first letter, make note of auto-caps state @@ -1354,14 +1360,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final InputConnection ic = getCurrentInputConnection(); if (ic != null) { ic.beginBatchEdit(); - abortCorrection(false); + abortRecorrection(false); } if (mHasValidSuggestions) { // In certain languages where single quote is a separator, it's better // not to auto correct, but accept the typed word. For instance, // in Italian dov' should not be expanded to dove' because the elision // requires the last vowel to be removed. - if (mAutoCorrectOn && primaryCode != '\'' && !mJustReverted) { + if (mAutoCorrectOn && primaryCode != '\'') { pickedDefault = pickDefaultSuggestion(); // Picked the suggestion by the space key. We consider this // as "added an auto space". @@ -1380,14 +1386,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // Handle the case of ". ." -> " .." with auto-space if necessary // before changing the TextEntryState. - if (TextEntryState.getState() == TextEntryState.State.PUNCTUATION_AFTER_ACCEPTED - && primaryCode == Keyboard.CODE_PERIOD) { + if (TextEntryState.isPunctuationAfterAccepted() && primaryCode == Keyboard.CODE_PERIOD) { reswapPeriodAndSpace(); } TextEntryState.typedCharacter((char) primaryCode, true); - if (TextEntryState.getState() == TextEntryState.State.PUNCTUATION_AFTER_ACCEPTED - && primaryCode != Keyboard.CODE_ENTER) { + if (TextEntryState.isPunctuationAfterAccepted() && primaryCode != Keyboard.CODE_ENTER) { swapPunctuationAndSpace(); } else if (isSuggestionsRequested() && primaryCode == Keyboard.CODE_SPACE) { doubleSpace(); @@ -1419,12 +1423,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); if (inputView != null) inputView.closing(); - TextEntryState.endSession(); } private void saveWordInHistory(CharSequence result) { if (mWord.size() <= 1) { - mWord.reset(); return; } // Skip if result is null. It happens in some edge case. @@ -1457,7 +1459,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private boolean isCandidateStripVisible() { if (mCandidateView == null) return false; - if (mCandidateView.isShowingAddToDictionaryHint() || TextEntryState.isCorrecting()) + if (mCandidateView.isShowingAddToDictionaryHint() || TextEntryState.isRecorrecting()) return true; if (!isShowingSuggestionsStrip()) return false; @@ -1467,26 +1469,21 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } public void switchToKeyboardView() { - mHandler.post(new Runnable() { - @Override - public void run() { - if (DEBUG) { - Log.d(TAG, "Switch to keyboard view."); - } - View v = mKeyboardSwitcher.getInputView(); - 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); - } - setCandidatesViewShown(isCandidateStripVisible()); - updateInputViewShown(); - mHandler.postUpdateSuggestions(); + if (DEBUG) { + Log.d(TAG, "Switch to keyboard view."); + } + View v = mKeyboardSwitcher.getInputView(); + 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); + } + setCandidatesViewShown(isCandidateStripVisible()); + updateInputViewShown(); + mHandler.postUpdateSuggestions(); } public void clearSuggestions() { @@ -1508,8 +1505,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } public void updateSuggestions() { - mKeyboardSwitcher.setPreferredLetters(null); - // Check if we have a suggestion engine attached. if ((mSuggest == null || !isSuggestionsRequested()) && !mVoiceConnector.isVoiceInputHighlighted()) { @@ -1528,36 +1523,30 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } private void showCorrections(WordAlternatives alternatives) { - mKeyboardSwitcher.setPreferredLetters(null); SuggestedWords.Builder builder = alternatives.getAlternatives(); builder.setTypedWordValid(false).setHasMinimalSuggestion(false); showSuggestions(builder.build(), alternatives.getOriginalWord()); } private void showSuggestions(WordComposer word) { - // TODO Maybe need better way of retrieving previous word + // TODO: May need a better way of retrieving previous word CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(), mWordSeparators); SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder( mKeyboardSwitcher.getInputView(), word, prevWord); - int[] nextLettersFrequencies = mSuggest.getNextLettersFrequencies(); - mKeyboardSwitcher.setPreferredLetters(nextLettersFrequencies); - - boolean correctionAvailable = !mInputTypeNoAutoCorrect && !mJustReverted - && mSuggest.hasAutoCorrection(); + boolean correctionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasAutoCorrection(); final CharSequence typedWord = word.getTypedWord(); - // If we're in basic correct - final boolean typedWordValid = mSuggest.isValidWord(typedWord) || - (preferCapitalization() - && mSuggest.isValidWord(typedWord.toString().toLowerCase())); + // Here, we want to promote a whitelisted word if exists. + final boolean typedWordValid = AutoCorrection.isValidWordForAutoCorrection( + mSuggest.getUnigramDictionaries(), typedWord, preferCapitalization()); if (mCorrectionMode == Suggest.CORRECTION_FULL || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) { correctionAvailable |= typedWordValid; } // Don't auto-correct words with multiple capital letter correctionAvailable &= !word.isMostlyCaps(); - correctionAvailable &= !TextEntryState.isCorrecting(); + correctionAvailable &= !TextEntryState.isRecorrecting(); // Basically, we update the suggestion strip only when suggestion count > 1. However, // there is an exception: We update the suggestion strip whenever typed word's length @@ -1604,7 +1593,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mJustAccepted = true; pickSuggestion(mBestWord); // Add the word to the auto dictionary if it's not a known word - addToDictionaries(mBestWord, AutoDictionary.FREQUENCY_FOR_TYPED); + addToAutoAndUserBigramDictionaries(mBestWord, AutoDictionary.FREQUENCY_FOR_TYPED); return true; } @@ -1615,7 +1604,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen SuggestedWords suggestions = mCandidateView.getSuggestions(); mVoiceConnector.flushAndLogAllTextModificationCounters(index, suggestion, mWordSeparators); - final boolean correcting = TextEntryState.isCorrecting(); + final boolean recorrecting = TextEntryState.isRecorrecting(); InputConnection ic = getCurrentInputConnection(); if (ic != null) { ic.beginBatchEdit(); @@ -1657,24 +1646,35 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen pickSuggestion(suggestion); // Add the word to the auto dictionary if it's not a known word if (index == 0) { - addToDictionaries(suggestion, AutoDictionary.FREQUENCY_FOR_PICKED); + addToAutoAndUserBigramDictionaries(suggestion, AutoDictionary.FREQUENCY_FOR_PICKED); } else { - addToBigramDictionary(suggestion, 1); + addToOnlyBigramDictionary(suggestion, 1); } LatinImeLogger.logOnManualSuggestion(mComposing.toString(), suggestion.toString(), index, suggestions.mWords); TextEntryState.acceptedSuggestion(mComposing.toString(), suggestion); // Follow it with a space - if (mAutoSpace && !correcting) { + if (mAutoSpace && !recorrecting) { sendSpace(); mJustAddedAutoSpace = true; } - final boolean showingAddToDictionaryHint = index == 0 && mCorrectionMode > 0 - && !mSuggest.isValidWord(suggestion) - && !mSuggest.isValidWord(suggestion.toString().toLowerCase()); - - if (!correcting) { + // We should show the hint if the user pressed the first entry AND either: + // - There is no dictionary (we know that because we tried to load it => null != mSuggest + // AND mHasDictionary is false) + // - There is a dictionary and the word is not in it + // Please note that if mSuggest is null, it means that everything is off: suggestion + // and correction, so we shouldn't try to show the hint + // We used to look at mCorrectionMode here, but showing the hint should have nothing + // to do with the autocorrection setting. + final boolean showingAddToDictionaryHint = index == 0 && mSuggest != null + // If there is no dictionary the hint should be shown. + && (!mHasDictionary + // If "suggestion" is not in the dictionary, the hint should be shown. + || !AutoCorrection.isValidWord( + mSuggest.getUnigramDictionaries(), suggestion, true)); + + if (!recorrecting) { // Fool the state watcher so that a subsequent backspace will not do a revert, unless // we just did a correction, in which case we need to stay in // TextEntryState.State.PICKED_SUGGESTION state. @@ -1712,7 +1712,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen saveWordInHistory(suggestion); mHasValidSuggestions = false; mCommittedLength = suggestion.length(); - switcher.setPreferredLetters(null); } /** @@ -1725,6 +1724,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // If we didn't find a match, search for result in typed word history WordComposer foundWord = null; WordAlternatives alternatives = null; + // Search old suggestions to suggest re-corrected suggestions. for (WordAlternatives entry : mWordHistory) { if (TextUtils.equals(entry.getChosenWord(), touching.mWord)) { if (entry instanceof TypedWordAlternatives) { @@ -1734,15 +1734,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen break; } } - // If we didn't find a match, at least suggest corrections. + // If we didn't find a match, at least suggest corrections as re-corrected suggestions. if (foundWord == null - && (mSuggest.isValidWord(touching.mWord) - || mSuggest.isValidWord(touching.mWord.toString().toLowerCase()))) { + && (AutoCorrection.isValidWord( + mSuggest.getUnigramDictionaries(), touching.mWord, true))) { foundWord = new WordComposer(); for (int i = 0; i < touching.mWord.length(); i++) { foundWord.add(touching.mWord.charAt(i), new int[] { touching.mWord.charAt(i) - }); + }, WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); } foundWord.setFirstCharCapitalized(Character.isUpperCase(touching.mWord.charAt(0))); } @@ -1779,19 +1779,19 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (!mVoiceConnector.applyVoiceAlternatives(touching) && !applyTypedAlternatives(touching)) { - abortCorrection(true); + abortRecorrection(true); } else { - TextEntryState.selectedForCorrection(); + TextEntryState.selectedForRecorrection(); EditingUtils.underlineWord(ic, touching); } ic.endBatchEdit(); } else { - abortCorrection(true); + abortRecorrection(true); setPunctuationSuggestions(); // Show the punctuation suggestions list } } else { - abortCorrection(true); + abortRecorrection(true); } } @@ -1800,21 +1800,22 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen setCandidatesViewShown(isCandidateStripVisible()); } - private void addToDictionaries(CharSequence suggestion, int frequencyDelta) { + private void addToAutoAndUserBigramDictionaries(CharSequence suggestion, int frequencyDelta) { checkAddToDictionary(suggestion, frequencyDelta, false); } - private void addToBigramDictionary(CharSequence suggestion, int frequencyDelta) { + private void addToOnlyBigramDictionary(CharSequence suggestion, int frequencyDelta) { checkAddToDictionary(suggestion, frequencyDelta, true); } /** * Adds to the UserBigramDictionary and/or AutoDictionary - * @param addToBigramDictionary true if it should be added to bigram dictionary if possible + * @param selectedANotTypedWord true if it should be added to bigram dictionary if possible */ private void checkAddToDictionary(CharSequence suggestion, int frequencyDelta, - boolean addToBigramDictionary) { + boolean selectedANotTypedWord) { if (suggestion == null || suggestion.length() < 1) return; + // Only auto-add to dictionary if auto-correct is ON. Otherwise we'll be // adding words in situations where the user or application really didn't // want corrections enabled or learned. @@ -1822,9 +1823,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM)) { return; } - if (!addToBigramDictionary && mAutoDictionary.isValidWord(suggestion) - || (!mSuggest.isValidWord(suggestion.toString()) - && !mSuggest.isValidWord(suggestion.toString().toLowerCase()))) { + + final boolean selectedATypedWordAndItsInAutoDic = + !selectedANotTypedWord && mAutoDictionary.isValidWord(suggestion); + final boolean isValidWord = AutoCorrection.isValidWord( + mSuggest.getUnigramDictionaries(), suggestion, true); + final boolean needsToAddToAutoDictionary = selectedATypedWordAndItsInAutoDic + || !isValidWord; + if (needsToAddToAutoDictionary) { mAutoDictionary.addWord(suggestion.toString(), frequencyDelta); } @@ -1864,7 +1870,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final int length = mComposing.length(); if (!mHasValidSuggestions && length > 0) { final InputConnection ic = getCurrentInputConnection(); - mJustReverted = true; final CharSequence punctuation = ic.getTextBeforeCursor(1, 0); if (deleteChar) ic.deleteSurroundingText(1, 0); int toDelete = mCommittedLength; @@ -1892,7 +1897,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mHandler.postUpdateSuggestions(); } else { sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); - mJustReverted = false; } } @@ -1930,28 +1934,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mSubtypeSwitcher.toggleLanguage(reset, next); } // Reload keyboard because the current language has been changed. - KeyboardSwitcher switcher = mKeyboardSwitcher; - final EditorInfo attribute = getCurrentInputEditorInfo(); - final int mode = initializeInputAttributesAndGetMode((attribute != null) - ? attribute.inputType : 0); - final int imeOptions = (attribute != null) ? attribute.imeOptions : 0; - switcher.loadKeyboard(mode, imeOptions, mVoiceConnector.isVoiceButtonEnabled(), + mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), + mSubtypeSwitcher.isShortcutImeEnabled() && mVoiceConnector.isVoiceButtonEnabled(), mVoiceConnector.isVoiceButtonOnPrimary()); initSuggest(); - switcher.updateShiftState(); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, - String key) { - mSubtypeSwitcher.onSharedPreferenceChanged(sharedPreferences, key); - if (Settings.PREF_SELECTED_LANGUAGES.equals(key)) { - mRefreshKeyboardRequired = true; - } else if (Settings.PREF_RECORRECTION_ENABLED.equals(key)) { - mReCorrectionEnabled = sharedPreferences.getBoolean( - Settings.PREF_RECORRECTION_ENABLED, - mResources.getBoolean(R.bool.default_recorrection_enabled)); - } + mKeyboardSwitcher.updateShiftState(); } @Override @@ -1961,7 +1948,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } @Override - public void onPress(int primaryCode) { + public void onPress(int primaryCode, boolean withSliding) { if (mKeyboardSwitcher.isVibrateAndSoundFeedbackRequired()) { vibrate(); playKeyClick(primaryCode); @@ -1969,25 +1956,27 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen KeyboardSwitcher switcher = mKeyboardSwitcher; final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { - switcher.onPressShift(); + switcher.onPressShift(withSliding); } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { switcher.onPressSymbol(); } else { switcher.onOtherKeyPressed(); } + mAccessibilityUtils.onPress(primaryCode, switcher); } @Override - public void onRelease(int primaryCode) { + public void onRelease(int primaryCode, boolean withSliding) { KeyboardSwitcher switcher = mKeyboardSwitcher; // Reset any drag flags in the keyboard switcher.keyReleased(); final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { - switcher.onReleaseShift(); + switcher.onReleaseShift(withSliding); } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { switcher.onReleaseSymbol(); } + mAccessibilityUtils.onRelease(primaryCode, switcher); } @@ -2067,6 +2056,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } private void updateCorrectionMode() { + // TODO: cleanup messy flags mHasDictionary = mSuggest != null ? mSuggest.hasMainDictionary() : false; mAutoCorrectOn = (mAutoCorrectEnabled || mQuickFixes) && !mInputTypeNoAutoCorrect && mHasDictionary; @@ -2082,7 +2072,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private void updateAutoTextEnabled() { if (mSuggest == null) return; - mSuggest.setAutoTextEnabled(mQuickFixes + mSuggest.setQuickFixesEnabled(mQuickFixes && SubtypeSwitcher.getInstance().isSystemLanguageSameAsInputLanguage()); } @@ -2121,7 +2111,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); mVibrateOn = vibrator != null && vibrator.hasVibrator() && prefs.getBoolean(Settings.PREF_VIBRATE_ON, false); - mSoundOn = prefs.getBoolean(Settings.PREF_SOUND_ON, false); + mSoundOn = prefs.getBoolean(Settings.PREF_SOUND_ON, + mResources.getBoolean(R.bool.config_default_sound_enabled)); mPopupOn = isPopupEnabled(prefs); mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true); @@ -2272,10 +2263,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen di.dismiss(); switch (position) { case 0: - launchSettings(); + mImm.showInputMethodPicker(); break; case 1: - mImm.showInputMethodPicker(); + launchSettings(); break; } } @@ -2285,6 +2276,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private void showOptionsMenuInternal(CharSequence title, CharSequence[] items, DialogInterface.OnClickListener listener) { + final IBinder windowToken = mKeyboardSwitcher.getInputView().getWindowToken(); + if (windowToken == null) return; AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setCancelable(true); builder.setIcon(R.drawable.ic_dialog_keyboard); @@ -2295,7 +2288,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mOptionsDialog.setCanceledOnTouchOutside(true); Window window = mOptionsDialog.getWindow(); WindowManager.LayoutParams lp = window.getAttributes(); - lp.token = mKeyboardSwitcher.getInputView().getWindowToken(); + lp.token = windowToken; lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; window.setAttributes(lp); window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); |