LatinIME.java revision 66a787b953d703201c6b827abbee74e8cd9bb063
1923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/* 2923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Copyright (C) 2008-2009 Google Inc. 3a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker * 4923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * use this file except in compliance with the License. You may obtain a copy of 6923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License at 7a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker * 8923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker * 10923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * License for the specific language governing permissions and limitations under 14923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License. 15923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 16923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 17923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectpackage com.android.inputmethod.latin; 18923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 19960ea65f3f2162e7f8f387380924162d42fef4dcValentin Kravtsovimport com.android.inputmethod.voice.EditingUtil; 20960ea65f3f2162e7f8f387380924162d42fef4dcValentin Kravtsovimport com.android.inputmethod.voice.FieldContext; 21960ea65f3f2162e7f8f387380924162d42fef4dcValentin Kravtsovimport com.android.inputmethod.voice.SettingsUtil; 22960ea65f3f2162e7f8f387380924162d42fef4dcValentin Kravtsovimport com.android.inputmethod.voice.VoiceInput; 23466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport com.google.android.collect.Lists; 24388ce92ab8a635c5ad44620dad59baf05dfea510Amith Yamasani 25923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.app.AlertDialog; 26923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.BroadcastReceiver; 27923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Context; 28923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.DialogInterface; 29923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Intent; 30923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.IntentFilter; 31923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.SharedPreferences; 32923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.res.Configuration; 3336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasaniimport android.content.res.Resources; 34923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.inputmethodservice.InputMethodService; 35923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.inputmethodservice.Keyboard; 36923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.inputmethodservice.KeyboardView; 37923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.media.AudioManager; 38923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Debug; 39923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Handler; 40923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Message; 41923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.SystemClock; 42923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Vibrator; 43923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.preference.PreferenceManager; 44960ea65f3f2162e7f8f387380924162d42fef4dcValentin Kravtsovimport android.speech.RecognitionManager; 456e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasaniimport android.text.AutoText; 46923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.text.ClipboardManager; 47923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.text.TextUtils; 48923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Log; 49923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.PrintWriterPrinter; 50923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Printer; 5166a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasaniimport android.view.HapticFeedbackConstants; 52923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.KeyEvent; 53466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport android.view.LayoutInflater; 54923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.View; 55923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.Window; 56923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.WindowManager; 57923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.CompletionInfo; 58923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.EditorInfo; 59466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport android.view.inputmethod.ExtractedText; 60466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport android.view.inputmethod.ExtractedTextRequest; 61923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.InputConnection; 62923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.InputMethodManager; 63923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 64466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.FileDescriptor; 65466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.PrintWriter; 66466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.util.ArrayList; 67466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.util.HashMap; 68466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.util.List; 69466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.util.Locale; 70466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.util.Map; 71466741d8a78965b8509bf527344f289e50873092Mike LeBeau 72923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/** 73923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Input method implementation for Qwerty'ish keyboard. 74923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 75466741d8a78965b8509bf527344f289e50873092Mike LeBeaupublic class LatinIME extends InputMethodService 7636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani implements KeyboardView.OnKeyboardActionListener, 77466741d8a78965b8509bf527344f289e50873092Mike LeBeau VoiceInput.UiListener, 78466741d8a78965b8509bf527344f289e50873092Mike LeBeau SharedPreferences.OnSharedPreferenceChangeListener { 79466741d8a78965b8509bf527344f289e50873092Mike LeBeau private static final String TAG = "LatinIME"; 80923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project static final boolean DEBUG = false; 81923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project static final boolean TRACE = false; 82466741d8a78965b8509bf527344f289e50873092Mike LeBeau static final boolean VOICE_INSTALLED = true; 83466741d8a78965b8509bf527344f289e50873092Mike LeBeau static final boolean ENABLE_VOICE_BUTTON = true; 84a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 85923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final String PREF_VIBRATE_ON = "vibrate_on"; 86923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final String PREF_SOUND_ON = "sound_on"; 87923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final String PREF_AUTO_CAP = "auto_cap"; 886e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani private static final String PREF_QUICK_FIXES = "quick_fixes"; 896e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani private static final String PREF_SHOW_SUGGESTIONS = "show_suggestions"; 906e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani private static final String PREF_AUTO_COMPLETE = "auto_complete"; 91457fdffce4550b5597435f030483dcafffecf714Amith Yamasani private static final String PREF_VOICE_MODE = "voice_mode"; 92b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani 93466741d8a78965b8509bf527344f289e50873092Mike LeBeau // Whether or not the user has used voice input before (and thus, whether to show the 94a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker // first-run warning dialog or not). 95466741d8a78965b8509bf527344f289e50873092Mike LeBeau private static final String PREF_HAS_USED_VOICE_INPUT = "has_used_voice_input"; 96a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 97466741d8a78965b8509bf527344f289e50873092Mike LeBeau // Whether or not the user has used voice input from an unsupported locale UI before. 98466741d8a78965b8509bf527344f289e50873092Mike LeBeau // For example, the user has a Chinese UI but activates voice input. 99466741d8a78965b8509bf527344f289e50873092Mike LeBeau private static final String PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE = 100466741d8a78965b8509bf527344f289e50873092Mike LeBeau "has_used_voice_input_unsupported_locale"; 101466741d8a78965b8509bf527344f289e50873092Mike LeBeau 102466741d8a78965b8509bf527344f289e50873092Mike LeBeau // A list of locales which are supported by default for voice input, unless we get a 103466741d8a78965b8509bf527344f289e50873092Mike LeBeau // different list from Gservices. 104466741d8a78965b8509bf527344f289e50873092Mike LeBeau public static final String DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES = 105466741d8a78965b8509bf527344f289e50873092Mike LeBeau "en " + 106466741d8a78965b8509bf527344f289e50873092Mike LeBeau "en_US " + 107466741d8a78965b8509bf527344f289e50873092Mike LeBeau "en_GB " + 108466741d8a78965b8509bf527344f289e50873092Mike LeBeau "en_AU " + 109466741d8a78965b8509bf527344f289e50873092Mike LeBeau "en_CA " + 110466741d8a78965b8509bf527344f289e50873092Mike LeBeau "en_IE " + 111466741d8a78965b8509bf527344f289e50873092Mike LeBeau "en_IN " + 112466741d8a78965b8509bf527344f289e50873092Mike LeBeau "en_NZ " + 113466741d8a78965b8509bf527344f289e50873092Mike LeBeau "en_SG " + 114466741d8a78965b8509bf527344f289e50873092Mike LeBeau "en_ZA "; 115a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 116466741d8a78965b8509bf527344f289e50873092Mike LeBeau // The private IME option used to indicate that no microphone should be shown for a 117466741d8a78965b8509bf527344f289e50873092Mike LeBeau // given text field. For instance this is specified by the search dialog when the 118466741d8a78965b8509bf527344f289e50873092Mike LeBeau // dialog is already showing a voice search button. 119466741d8a78965b8509bf527344f289e50873092Mike LeBeau private static final String IME_OPTION_NO_MICROPHONE = "nm"; 120a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 12136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani public static final String PREF_SELECTED_LANGUAGES = "selected_languages"; 12236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani public static final String PREF_INPUT_LANGUAGE = "input_language"; 123923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 124923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int MSG_UPDATE_SUGGESTIONS = 0; 1256e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani private static final int MSG_START_TUTORIAL = 1; 1264a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani private static final int MSG_UPDATE_SHIFT_STATE = 2; 127466741d8a78965b8509bf527344f289e50873092Mike LeBeau private static final int MSG_VOICE_RESULTS = 3; 128466741d8a78965b8509bf527344f289e50873092Mike LeBeau private static final int MSG_START_LISTENING_AFTER_SWIPE = 4; 129466741d8a78965b8509bf527344f289e50873092Mike LeBeau 130466741d8a78965b8509bf527344f289e50873092Mike LeBeau // If we detect a swipe gesture within N ms of typing, then swipe is 131466741d8a78965b8509bf527344f289e50873092Mike LeBeau // ignored, since it may in fact be two key presses in quick succession. 132466741d8a78965b8509bf527344f289e50873092Mike LeBeau private static final long MIN_MILLIS_AFTER_TYPING_BEFORE_SWIPE = 1000; 133466741d8a78965b8509bf527344f289e50873092Mike LeBeau 134466741d8a78965b8509bf527344f289e50873092Mike LeBeau // If we detect a swipe gesture, and the user types N ms later, cancel the 135466741d8a78965b8509bf527344f289e50873092Mike LeBeau // swipe since it was probably a false trigger. 136466741d8a78965b8509bf527344f289e50873092Mike LeBeau private static final long MIN_MILLIS_AFTER_SWIPE_TO_WAIT_FOR_TYPING = 500; 137a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 138923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // How many continuous deletes at which to start deleting at a higher speed. 139923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int DELETE_ACCELERATE_AT = 20; 140923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Key events coming any faster than this are long-presses. 141d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani private static final int QUICK_PRESS = 200; 142d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani // Weight added to a user picking a new word from the suggestion strip 143d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani static final int FREQUENCY_FOR_PICKED = 3; 144d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani // Weight added to a user typing a new word that doesn't get corrected (or is reverted) 145d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani static final int FREQUENCY_FOR_TYPED = 1; 146d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani // A word that is frequently typed and get's promoted to the user dictionary, uses this 147d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani // frequency. 148d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani static final int FREQUENCY_FOR_AUTO_ADD = 250; 149a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 150d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani static final int KEYCODE_ENTER = '\n'; 151d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani static final int KEYCODE_SPACE = ' '; 152923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 153923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Contextual menu positions 154923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int POS_SETTINGS = 0; 155923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int POS_METHOD = 1; 156466741d8a78965b8509bf527344f289e50873092Mike LeBeau 157923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private LatinKeyboardView mInputView; 158923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private CandidateViewContainer mCandidateViewContainer; 159923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private CandidateView mCandidateView; 160923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private Suggest mSuggest; 161923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private CompletionInfo[] mCompletions; 162a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 163923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private AlertDialog mOptionsDialog; 164466741d8a78965b8509bf527344f289e50873092Mike LeBeau private AlertDialog mVoiceWarningDialog; 165a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1666e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani KeyboardSwitcher mKeyboardSwitcher; 167a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 168923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private UserDictionary mUserDictionary; 1692bed1531c2c9bd48096bfa97dd1a39e04bd15e7bEric Fischer private ContactsDictionary mContactsDictionary; 17034386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani private ExpandableDictionary mAutoDictionary; 17136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 172466741d8a78965b8509bf527344f289e50873092Mike LeBeau private Hints mHints; 173a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 17436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani Resources mResources; 17536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 176923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private String mLocale; 1773f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani private LanguageSwitcher mLanguageSwitcher; 178923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 179923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private StringBuilder mComposing = new StringBuilder(); 180923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private WordComposer mWord = new WordComposer(); 181923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mCommittedLength; 182923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mPredicting; 183466741d8a78965b8509bf527344f289e50873092Mike LeBeau private boolean mRecognizing; 184466741d8a78965b8509bf527344f289e50873092Mike LeBeau private boolean mAfterVoiceInput; 185466741d8a78965b8509bf527344f289e50873092Mike LeBeau private boolean mImmediatelyAfterVoiceInput; 186466741d8a78965b8509bf527344f289e50873092Mike LeBeau private boolean mShowingVoiceSuggestions; 187466741d8a78965b8509bf527344f289e50873092Mike LeBeau private boolean mImmediatelyAfterVoiceSuggestions; 188466741d8a78965b8509bf527344f289e50873092Mike LeBeau private boolean mVoiceInputHighlighted; 189466741d8a78965b8509bf527344f289e50873092Mike LeBeau private boolean mEnableVoiceButton; 190923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private CharSequence mBestWord; 191923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mPredictionOn; 192923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mCompletionOn; 193e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private boolean mHasDictionary; 194923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mAutoSpace; 195e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private boolean mAutoCorrectEnabled; 196923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mAutoCorrectOn; 197923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mCapsLock; 198466741d8a78965b8509bf527344f289e50873092Mike LeBeau private boolean mPasswordText; 199466741d8a78965b8509bf527344f289e50873092Mike LeBeau private boolean mEmailText; 200923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mVibrateOn; 201923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mSoundOn; 202923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mAutoCap; 2036e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani private boolean mQuickFixes; 204466741d8a78965b8509bf527344f289e50873092Mike LeBeau private boolean mHasUsedVoiceInput; 205466741d8a78965b8509bf527344f289e50873092Mike LeBeau private boolean mHasUsedVoiceInputUnsupportedLocale; 206466741d8a78965b8509bf527344f289e50873092Mike LeBeau private boolean mLocaleSupportedForVoiceInput; 2076e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani private boolean mShowSuggestions; 208466741d8a78965b8509bf527344f289e50873092Mike LeBeau private boolean mSuggestionShouldReplaceCurrentWord; 209466741d8a78965b8509bf527344f289e50873092Mike LeBeau private boolean mIsShowingHint; 2106e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani private int mCorrectionMode; 211466741d8a78965b8509bf527344f289e50873092Mike LeBeau private boolean mEnableVoice = true; 212b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani private boolean mVoiceOnPrimary; 213b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani private int mOrientation; 2146a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani private List<CharSequence> mSuggestPuncList; 215a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 216923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Indicates whether the suggestion strip is to be on in landscape 217923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mJustAccepted; 218923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private CharSequence mJustRevertedSeparator; 219923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mDeleteCount; 220923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long mLastKeyTime; 221a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 222923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private Tutorial mTutorial; 223923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 224923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private AudioManager mAudioManager; 2252296317b8f0209789f797ac8a2fcb70e03f6d001Eric Laurent // Align sound effect volume on music volume 2262296317b8f0209789f797ac8a2fcb70e03f6d001Eric Laurent private final float FX_VOLUME = -1.0f; 227923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mSilentMode; 228923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 229923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private String mWordSeparators; 230923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private String mSentenceSeparators; 231466741d8a78965b8509bf527344f289e50873092Mike LeBeau private VoiceInput mVoiceInput; 232466741d8a78965b8509bf527344f289e50873092Mike LeBeau private VoiceResults mVoiceResults = new VoiceResults(); 233466741d8a78965b8509bf527344f289e50873092Mike LeBeau private long mSwipeTriggerTimeMillis; 234466741d8a78965b8509bf527344f289e50873092Mike LeBeau 235466741d8a78965b8509bf527344f289e50873092Mike LeBeau // For each word, a list of potential replacements, usually from voice. 23666a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani private Map<String, List<CharSequence>> mWordToSuggestions = 23766a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani new HashMap<String, List<CharSequence>>(); 238466741d8a78965b8509bf527344f289e50873092Mike LeBeau 239466741d8a78965b8509bf527344f289e50873092Mike LeBeau private class VoiceResults { 240466741d8a78965b8509bf527344f289e50873092Mike LeBeau List<String> candidates; 241466741d8a78965b8509bf527344f289e50873092Mike LeBeau Map<String, List<CharSequence>> alternatives; 242466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 24336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani private boolean mRefreshKeyboardRequired; 24436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 245923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Handler mHandler = new Handler() { 246923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 247923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void handleMessage(Message msg) { 248923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (msg.what) { 249923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case MSG_UPDATE_SUGGESTIONS: 250923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateSuggestions(); 251923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 2526e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani case MSG_START_TUTORIAL: 2536e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (mTutorial == null) { 2546e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (mInputView.isShown()) { 2556e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mTutorial = new Tutorial(LatinIME.this, mInputView); 2566e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mTutorial.start(); 2576e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } else { 2586e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani // Try again soon if the view is not yet showing 2596e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani sendMessageDelayed(obtainMessage(MSG_START_TUTORIAL), 100); 2606e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 261923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 262923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 2634a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani case MSG_UPDATE_SHIFT_STATE: 2644a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani updateShiftKeyState(getCurrentInputEditorInfo()); 2654a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani break; 266466741d8a78965b8509bf527344f289e50873092Mike LeBeau case MSG_VOICE_RESULTS: 267466741d8a78965b8509bf527344f289e50873092Mike LeBeau handleVoiceResults(); 268466741d8a78965b8509bf527344f289e50873092Mike LeBeau break; 269466741d8a78965b8509bf527344f289e50873092Mike LeBeau case MSG_START_LISTENING_AFTER_SWIPE: 270466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mLastKeyTime < mSwipeTriggerTimeMillis) { 271466741d8a78965b8509bf527344f289e50873092Mike LeBeau startListening(true); 272466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 273923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 274923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 275923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project }; 276923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 277923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override public void onCreate() { 278923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onCreate(); 279923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project //setStatusIcon(R.drawable.ime_qwerty); 28036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mResources = getResources(); 28136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani final Configuration conf = mResources.getConfiguration(); 2823f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 2833f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani mLanguageSwitcher = new LanguageSwitcher(this); 2843f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani mLanguageSwitcher.loadLocales(prefs); 2853f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani mKeyboardSwitcher = new KeyboardSwitcher(this, this); 2863f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani mKeyboardSwitcher.setLanguageSwitcher(mLanguageSwitcher); 2873f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani boolean enableMultipleLanguages = mLanguageSwitcher.getLocaleCount() > 0; 2883f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani String inputLanguage = mLanguageSwitcher.getInputLanguage(); 2893f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani if (inputLanguage == null) { 2903f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani inputLanguage = conf.locale.toString(); 2913f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani } 2923f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani initSuggest(inputLanguage); 293b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani mOrientation = conf.orientation; 2946a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani initSuggestPuncList(); 295b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 296923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // register to receive ringer mode changes for silent mode 297923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION); 298923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project registerReceiver(mReceiver, filter); 299466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (VOICE_INSTALLED) { 300466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceInput = new VoiceInput(this, this); 301466741d8a78965b8509bf527344f289e50873092Mike LeBeau mHints = new Hints(this, new Hints.Display() { 302466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void showHint(int viewResource) { 303466741d8a78965b8509bf527344f289e50873092Mike LeBeau LayoutInflater inflater = (LayoutInflater) getSystemService( 304466741d8a78965b8509bf527344f289e50873092Mike LeBeau Context.LAYOUT_INFLATER_SERVICE); 305466741d8a78965b8509bf527344f289e50873092Mike LeBeau View view = inflater.inflate(viewResource, null); 306466741d8a78965b8509bf527344f289e50873092Mike LeBeau setCandidatesView(view); 307466741d8a78965b8509bf527344f289e50873092Mike LeBeau setCandidatesViewShown(true); 308466741d8a78965b8509bf527344f289e50873092Mike LeBeau mIsShowingHint = true; 309466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 310466741d8a78965b8509bf527344f289e50873092Mike LeBeau }); 311466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 3123f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani prefs.registerOnSharedPreferenceChangeListener(this); 313923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 31436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 315923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void initSuggest(String locale) { 316923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mLocale = locale; 31736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 31836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani Resources orig = getResources(); 31936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani Configuration conf = orig.getConfiguration(); 32036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani Locale saveLocale = conf.locale; 32136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani conf.locale = new Locale(locale); 32236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani orig.updateConfiguration(conf, orig.getDisplayMetrics()); 32336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani if (mSuggest != null) { 32436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mSuggest.close(); 32536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 326923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mSuggest = new Suggest(this, R.raw.main); 327d8564506124fe6a683ef0adf8ca5cf5348756f8dMike LeBeau if (mUserDictionary != null) mUserDictionary.close(); 328923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mUserDictionary = new UserDictionary(this); 32936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani if (mContactsDictionary == null) { 33036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mContactsDictionary = new ContactsDictionary(this); 33136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 33236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani // TODO: Save and restore the dictionary for the current input language. 33336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani if (mAutoDictionary == null) { 33436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mAutoDictionary = new AutoDictionary(this); 33536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 336923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mSuggest.setUserDictionary(mUserDictionary); 3372bed1531c2c9bd48096bfa97dd1a39e04bd15e7bEric Fischer mSuggest.setContactsDictionary(mContactsDictionary); 33834386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani mSuggest.setAutoDictionary(mAutoDictionary); 339e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani updateCorrectionMode(); 34036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mWordSeparators = mResources.getString(R.string.word_separators); 34136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mSentenceSeparators = mResources.getString(R.string.sentence_separators); 34236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 34336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani conf.locale = saveLocale; 34436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani orig.updateConfiguration(conf, orig.getDisplayMetrics()); 345923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 34636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 347466741d8a78965b8509bf527344f289e50873092Mike LeBeau @Override 348466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onDestroy() { 349923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mUserDictionary.close(); 3502bed1531c2c9bd48096bfa97dd1a39e04bd15e7bEric Fischer mContactsDictionary.close(); 351923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project unregisterReceiver(mReceiver); 352466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (VOICE_INSTALLED) { 353466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceInput.destroy(); 354466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 355923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onDestroy(); 356923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 357923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 358923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 359923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onConfigurationChanged(Configuration conf) { 360923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (!TextUtils.equals(conf.locale.toString(), mLocale)) { 361923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project initSuggest(conf.locale.toString()); 362923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 363b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani // If orientation changed while predicting, commit the change 364b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani if (conf.orientation != mOrientation) { 365466741d8a78965b8509bf527344f289e50873092Mike LeBeau InputConnection ic = getCurrentInputConnection(); 366466741d8a78965b8509bf527344f289e50873092Mike LeBeau commitTyped(ic); 367466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (ic != null) ic.finishComposingText(); // For voice input 368b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani mOrientation = conf.orientation; 369b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 37036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani reloadKeyboards(); 371923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onConfigurationChanged(conf); 372923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 373b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 374923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 375923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public View onCreateInputView() { 376923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mInputView = (LatinKeyboardView) getLayoutInflater().inflate( 377923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project R.layout.input, null); 378923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mKeyboardSwitcher.setInputView(mInputView); 37912e582c79c4e8028bb03971377633440aa95cefbAmith Yamasani mKeyboardSwitcher.makeKeyboards(true); 380923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mInputView.setOnKeyboardActionListener(this); 381466741d8a78965b8509bf527344f289e50873092Mike LeBeau mKeyboardSwitcher.setKeyboardMode( 382466741d8a78965b8509bf527344f289e50873092Mike LeBeau KeyboardSwitcher.MODE_TEXT, 0, 383466741d8a78965b8509bf527344f289e50873092Mike LeBeau shouldShowVoiceButton(makeFieldContext(), getCurrentInputEditorInfo())); 384923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return mInputView; 385923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 386923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 387923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 388466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onInitializeInterface() { 389466741d8a78965b8509bf527344f289e50873092Mike LeBeau // Create a new view associated with voice input if the old 390466741d8a78965b8509bf527344f289e50873092Mike LeBeau // view is stuck in another layout (e.g. if switching from 391466741d8a78965b8509bf527344f289e50873092Mike LeBeau // portrait to landscape while speaking) 392466741d8a78965b8509bf527344f289e50873092Mike LeBeau // NOTE: This must be done here because for some reason 393466741d8a78965b8509bf527344f289e50873092Mike LeBeau // onCreateInputView isn't called after an orientation change while 394466741d8a78965b8509bf527344f289e50873092Mike LeBeau // speech rec is in progress. 395466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mVoiceInput != null && mVoiceInput.getView().getParent() != null) { 396466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceInput.newView(); 397466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 398466741d8a78965b8509bf527344f289e50873092Mike LeBeau 399466741d8a78965b8509bf527344f289e50873092Mike LeBeau super.onInitializeInterface(); 400466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 401466741d8a78965b8509bf527344f289e50873092Mike LeBeau 402466741d8a78965b8509bf527344f289e50873092Mike LeBeau @Override 403923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public View onCreateCandidatesView() { 40412e582c79c4e8028bb03971377633440aa95cefbAmith Yamasani mKeyboardSwitcher.makeKeyboards(true); 405923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCandidateViewContainer = (CandidateViewContainer) getLayoutInflater().inflate( 406923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project R.layout.candidates, null); 407923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCandidateViewContainer.initViews(); 408923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCandidateView = (CandidateView) mCandidateViewContainer.findViewById(R.id.candidates); 409923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCandidateView.setService(this); 410923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project setCandidatesViewShown(true); 411923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return mCandidateViewContainer; 412923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 413923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 414a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker @Override 415923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onStartInputView(EditorInfo attribute, boolean restarting) { 416923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In landscape mode, this method gets called without the input view being created. 417923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mInputView == null) { 418923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 419923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 420923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 42136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani if (mRefreshKeyboardRequired) { 42236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mRefreshKeyboardRequired = false; 4233f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani toggleLanguage(true, true); 42436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 42536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 42612e582c79c4e8028bb03971377633440aa95cefbAmith Yamasani mKeyboardSwitcher.makeKeyboards(false); 4276c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani 428923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.newSession(this); 4296c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani 430466741d8a78965b8509bf527344f289e50873092Mike LeBeau // Most such things we decide below in the switch statement, but we need to know 431466741d8a78965b8509bf527344f289e50873092Mike LeBeau // now whether this is a password text field, because we need to know now (before 432466741d8a78965b8509bf527344f289e50873092Mike LeBeau // the switch statement) whether we want to enable the voice button. 433466741d8a78965b8509bf527344f289e50873092Mike LeBeau mPasswordText = false; 434466741d8a78965b8509bf527344f289e50873092Mike LeBeau int variation = attribute.inputType & EditorInfo.TYPE_MASK_VARIATION; 435466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (variation == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD || 436466741d8a78965b8509bf527344f289e50873092Mike LeBeau variation == EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) { 437466741d8a78965b8509bf527344f289e50873092Mike LeBeau mPasswordText = true; 438466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 439a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 440466741d8a78965b8509bf527344f289e50873092Mike LeBeau mEnableVoiceButton = shouldShowVoiceButton(makeFieldContext(), attribute); 441b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani final boolean enableVoiceButton = mEnableVoiceButton && mEnableVoice; 442466741d8a78965b8509bf527344f289e50873092Mike LeBeau 443466741d8a78965b8509bf527344f289e50873092Mike LeBeau mAfterVoiceInput = false; 444466741d8a78965b8509bf527344f289e50873092Mike LeBeau mImmediatelyAfterVoiceInput = false; 445466741d8a78965b8509bf527344f289e50873092Mike LeBeau mShowingVoiceSuggestions = false; 446466741d8a78965b8509bf527344f289e50873092Mike LeBeau mImmediatelyAfterVoiceSuggestions = false; 447466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceInputHighlighted = false; 448466741d8a78965b8509bf527344f289e50873092Mike LeBeau boolean disableAutoCorrect = false; 449466741d8a78965b8509bf527344f289e50873092Mike LeBeau mWordToSuggestions.clear(); 450e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mInputTypeNoAutoCorrect = false; 451923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPredictionOn = false; 452923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCompletionOn = false; 453923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCompletions = null; 454923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCapsLock = false; 455466741d8a78965b8509bf527344f289e50873092Mike LeBeau mEmailText = false; 456466741d8a78965b8509bf527344f289e50873092Mike LeBeau switch (attribute.inputType & EditorInfo.TYPE_MASK_CLASS) { 457923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case EditorInfo.TYPE_CLASS_NUMBER: 458923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case EditorInfo.TYPE_CLASS_DATETIME: 459e3803800c53cc813e27dd1e7c31bdb4d075f0252Amith Yamasani mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_SYMBOLS, 460b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani attribute.imeOptions, enableVoiceButton); 461923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 462923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case EditorInfo.TYPE_CLASS_PHONE: 463923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_PHONE, 464b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani attribute.imeOptions, enableVoiceButton); 465923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 466923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case EditorInfo.TYPE_CLASS_TEXT: 467923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_TEXT, 468b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani attribute.imeOptions, enableVoiceButton); 469923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project //startPrediction(); 470923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPredictionOn = true; 471923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Make sure that passwords are not displayed in candidate view 472923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (variation == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD || 473923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project variation == EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD ) { 474923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPredictionOn = false; 475923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 476466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS) { 477466741d8a78965b8509bf527344f289e50873092Mike LeBeau mEmailText = true; 478466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 479923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS 480923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project || variation == EditorInfo.TYPE_TEXT_VARIATION_PERSON_NAME) { 481923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAutoSpace = false; 482923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 483923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAutoSpace = true; 484923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 485923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS) { 486923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPredictionOn = false; 487923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_EMAIL, 488b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani attribute.imeOptions, enableVoiceButton); 489923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else if (variation == EditorInfo.TYPE_TEXT_VARIATION_URI) { 490923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPredictionOn = false; 491923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_URL, 492b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani attribute.imeOptions, enableVoiceButton); 493923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else if (variation == EditorInfo.TYPE_TEXT_VARIATION_SHORT_MESSAGE) { 494923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_IM, 495b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani attribute.imeOptions, enableVoiceButton); 496923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else if (variation == EditorInfo.TYPE_TEXT_VARIATION_FILTER) { 497923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPredictionOn = false; 4986c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani } else if (variation == EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) { 499cf02653097893b06f24551b790b0f7ec288e704dAmith Yamasani mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_WEB, 500b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani attribute.imeOptions, enableVoiceButton); 5016c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani // If it's a browser edit field and auto correct is not ON explicitly, then 5026c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani // disable auto correction, but keep suggestions on. 5036c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) { 504e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mInputTypeNoAutoCorrect = true; 5056c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani } 506923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 50736ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani 50836ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani // If NO_SUGGESTIONS is set, don't do prediction. 50936ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) { 51036ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani mPredictionOn = false; 511e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mInputTypeNoAutoCorrect = true; 51236ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani } 51336ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani // If it's not multiline and the autoCorrect flag is not set, then don't correct 51436ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 && 51536ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani (attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE) == 0) { 516e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mInputTypeNoAutoCorrect = true; 51736ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani } 518923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if ((attribute.inputType&EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { 519923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPredictionOn = false; 520923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCompletionOn = true && isFullscreenMode(); 521923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 522923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateShiftKeyState(attribute); 523923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 524923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project default: 525923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_TEXT, 526b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani attribute.imeOptions, enableVoiceButton); 527923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateShiftKeyState(attribute); 528923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 529923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mInputView.closing(); 530923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mComposing.setLength(0); 531923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPredicting = false; 532923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mDeleteCount = 0; 533923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project loadSettings(); 534e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani 535466741d8a78965b8509bf527344f289e50873092Mike LeBeau setCandidatesViewShown(false); 536466741d8a78965b8509bf527344f289e50873092Mike LeBeau setSuggestions(null, false, false, false); 537466741d8a78965b8509bf527344f289e50873092Mike LeBeau 538466741d8a78965b8509bf527344f289e50873092Mike LeBeau // Override auto correct 539466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (disableAutoCorrect) { 540466741d8a78965b8509bf527344f289e50873092Mike LeBeau mAutoCorrectOn = false; 541466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mCorrectionMode == Suggest.CORRECTION_FULL) { 542466741d8a78965b8509bf527344f289e50873092Mike LeBeau mCorrectionMode = Suggest.CORRECTION_BASIC; 543466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 544466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 545e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani // If the dictionary is not big enough, don't auto correct 546e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mHasDictionary = mSuggest.hasMainDictionary(); 547e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani 548e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani updateCorrectionMode(); 549e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani 5506e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mInputView.setProximityCorrectionEnabled(true); 551a200a9bff75130b1d79d505c6770f3132f8499bdAmith Yamasani mPredictionOn = mPredictionOn && mCorrectionMode > 0; 5526e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani checkTutorial(attribute.privateImeOptions); 5534a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); 554923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 555923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 556923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 557923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onFinishInput() { 558923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onFinishInput(); 559a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 5601322b7f899e9d3ccfb91d9e3ede99b3ad336c354Kristian Monsen if (VOICE_INSTALLED && mAfterVoiceInput) { 5611322b7f899e9d3ccfb91d9e3ede99b3ad336c354Kristian Monsen mVoiceInput.logInputEnded(); 5621322b7f899e9d3ccfb91d9e3ede99b3ad336c354Kristian Monsen } 563a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 5641322b7f899e9d3ccfb91d9e3ede99b3ad336c354Kristian Monsen if (VOICE_INSTALLED) { 5651322b7f899e9d3ccfb91d9e3ede99b3ad336c354Kristian Monsen mVoiceInput.flushLogs(); 5661322b7f899e9d3ccfb91d9e3ede99b3ad336c354Kristian Monsen } 567a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 568923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mInputView != null) { 569923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mInputView.closing(); 570923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 5711322b7f899e9d3ccfb91d9e3ede99b3ad336c354Kristian Monsen if (VOICE_INSTALLED && mRecognizing) { 572466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceInput.cancel(); 573466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 574466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 575466741d8a78965b8509bf527344f289e50873092Mike LeBeau 576466741d8a78965b8509bf527344f289e50873092Mike LeBeau @Override 577466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onUpdateExtractedText(int token, ExtractedText text) { 578466741d8a78965b8509bf527344f289e50873092Mike LeBeau super.onUpdateExtractedText(token, text); 579466741d8a78965b8509bf527344f289e50873092Mike LeBeau InputConnection ic = getCurrentInputConnection(); 580466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (!mImmediatelyAfterVoiceInput && mAfterVoiceInput && ic != null) { 581466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceInput.logTextModified(); 582466741d8a78965b8509bf527344f289e50873092Mike LeBeau 583466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mHints.showPunctuationHintIfNecessary(ic)) { 584466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceInput.logPunctuationHintDisplayed(); 585466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 586466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 587466741d8a78965b8509bf527344f289e50873092Mike LeBeau mImmediatelyAfterVoiceInput = false; 588923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 589923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 590923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 591923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onUpdateSelection(int oldSelStart, int oldSelEnd, 592923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int newSelStart, int newSelEnd, 593923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int candidatesStart, int candidatesEnd) { 594923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, 595923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project candidatesStart, candidatesEnd); 596466741d8a78965b8509bf527344f289e50873092Mike LeBeau 597466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (DEBUG) { 598466741d8a78965b8509bf527344f289e50873092Mike LeBeau Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart 599466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", ose=" + oldSelEnd 600466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nss=" + newSelStart 601466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nse=" + newSelEnd 602466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", cs=" + candidatesStart 603466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", ce=" + candidatesEnd); 604466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 605466741d8a78965b8509bf527344f289e50873092Mike LeBeau 606466741d8a78965b8509bf527344f289e50873092Mike LeBeau mSuggestionShouldReplaceCurrentWord = false; 607923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // If the current selection in the text view changes, we should 608923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // clear whatever candidate text we have. 609466741d8a78965b8509bf527344f289e50873092Mike LeBeau if ((((mComposing.length() > 0 && mPredicting) || mVoiceInputHighlighted) 610466741d8a78965b8509bf527344f289e50873092Mike LeBeau && (newSelStart != candidatesEnd 611466741d8a78965b8509bf527344f289e50873092Mike LeBeau || newSelEnd != candidatesEnd))) { 612923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mComposing.setLength(0); 613923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPredicting = false; 614923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateSuggestions(); 615923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.reset(); 616923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 617923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 618923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.finishComposingText(); 619923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 620466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceInputHighlighted = false; 621923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else if (!mPredicting && !mJustAccepted 622923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project && TextEntryState.getState() == TextEntryState.STATE_ACCEPTED_DEFAULT) { 623923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.reset(); 624923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 625923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mJustAccepted = false; 6263263841911dc3dbbf4ffe26d2f046e38a1896f72Amith Yamasani postUpdateShiftKeyState(); 627466741d8a78965b8509bf527344f289e50873092Mike LeBeau 628466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (VOICE_INSTALLED) { 629466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mShowingVoiceSuggestions) { 630466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mImmediatelyAfterVoiceSuggestions) { 631466741d8a78965b8509bf527344f289e50873092Mike LeBeau mImmediatelyAfterVoiceSuggestions = false; 632466741d8a78965b8509bf527344f289e50873092Mike LeBeau } else { 633466741d8a78965b8509bf527344f289e50873092Mike LeBeau updateSuggestions(); 634466741d8a78965b8509bf527344f289e50873092Mike LeBeau mShowingVoiceSuggestions = false; 635466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 636466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 637466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (VoiceInput.ENABLE_WORD_CORRECTIONS) { 638466741d8a78965b8509bf527344f289e50873092Mike LeBeau // If we have alternatives for the current word, then show them. 639466741d8a78965b8509bf527344f289e50873092Mike LeBeau String word = EditingUtil.getWordAtCursor( 640466741d8a78965b8509bf527344f289e50873092Mike LeBeau getCurrentInputConnection(), getWordSeparators()); 641466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (word != null && mWordToSuggestions.containsKey(word.trim())) { 642466741d8a78965b8509bf527344f289e50873092Mike LeBeau mSuggestionShouldReplaceCurrentWord = true; 643466741d8a78965b8509bf527344f289e50873092Mike LeBeau final List<CharSequence> suggestions = mWordToSuggestions.get(word.trim()); 644466741d8a78965b8509bf527344f289e50873092Mike LeBeau 645466741d8a78965b8509bf527344f289e50873092Mike LeBeau setSuggestions(suggestions, false, true, true); 646466741d8a78965b8509bf527344f289e50873092Mike LeBeau setCandidatesViewShown(true); 647466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 648466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 649466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 650923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 651923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 652923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 653923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void hideWindow() { 654466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mAfterVoiceInput) mVoiceInput.logInputEnded(); 655923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (TRACE) Debug.stopMethodTracing(); 6566e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (mOptionsDialog != null && mOptionsDialog.isShowing()) { 6576e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog.dismiss(); 6586e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog = null; 6596e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 660466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) { 661466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceInput.logKeyboardWarningDialogDismissed(); 662466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceWarningDialog.dismiss(); 663466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceWarningDialog = null; 664466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 6656e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (mTutorial != null) { 6666e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mTutorial.close(); 667a200a9bff75130b1d79d505c6770f3132f8499bdAmith Yamasani mTutorial = null; 668a200a9bff75130b1d79d505c6770f3132f8499bdAmith Yamasani } 669466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (VOICE_INSTALLED & mRecognizing) { 670466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceInput.cancel(); 671466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 672923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.hideWindow(); 673923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.endSession(); 674923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 675923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 676923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 677923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onDisplayCompletions(CompletionInfo[] completions) { 678923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (false) { 679923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Log.i("foo", "Received completions:"); 680923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project for (int i=0; i<(completions != null ? completions.length : 0); i++) { 681923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Log.i("foo", " #" + i + ": " + completions[i]); 682923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 683923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 684923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mCompletionOn) { 685923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCompletions = completions; 686923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (completions == null) { 687466741d8a78965b8509bf527344f289e50873092Mike LeBeau setSuggestions(null, false, false, false); 688923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 689923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 690a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 691923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project List<CharSequence> stringList = new ArrayList<CharSequence>(); 692923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project for (int i=0; i<(completions != null ? completions.length : 0); i++) { 693923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CompletionInfo ci = completions[i]; 694923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ci != null) stringList.add(ci.getText()); 695923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 696923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project //CharSequence typedWord = mWord.getTypedWord(); 697466741d8a78965b8509bf527344f289e50873092Mike LeBeau setSuggestions(stringList, true, true, true); 698923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = null; 699923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project setCandidatesViewShown(isCandidateStripVisible() || mCompletionOn); 700923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 701923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 702923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 703923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 704923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void setCandidatesViewShown(boolean shown) { 705923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // TODO: Remove this if we support candidates with hard keyboard 706923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (onEvaluateInputViewShown()) { 707923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.setCandidatesViewShown(shown); 708923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 709923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 710a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 711923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 712923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onComputeInsets(InputMethodService.Insets outInsets) { 713923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onComputeInsets(outInsets); 714264b19a6853ab3d13d26270e99a13dc015b01bebThe Android Open Source Project if (!isFullscreenMode()) { 715264b19a6853ab3d13d26270e99a13dc015b01bebThe Android Open Source Project outInsets.contentTopInsets = outInsets.visibleTopInsets; 716264b19a6853ab3d13d26270e99a13dc015b01bebThe Android Open Source Project } 717923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 718a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 719923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 720923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 721923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 722923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case KeyEvent.KEYCODE_BACK: 723923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (event.getRepeatCount() == 0 && mInputView != null) { 724923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mInputView.handleBack()) { 725923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 7266e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } else if (mTutorial != null) { 7276e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mTutorial.close(); 7286e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mTutorial = null; 729923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 730923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 731923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 7326e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani case KeyEvent.KEYCODE_DPAD_DOWN: 7336e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani case KeyEvent.KEYCODE_DPAD_UP: 7346e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani case KeyEvent.KEYCODE_DPAD_LEFT: 7356e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani case KeyEvent.KEYCODE_DPAD_RIGHT: 7366e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani // If tutorial is visible, don't allow dpad to work 7376e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (mTutorial != null) { 7386e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani return true; 7396e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 7406e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani break; 741923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 742923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyDown(keyCode, event); 743923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 744923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 745923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 746923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 747923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 748923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case KeyEvent.KEYCODE_DPAD_DOWN: 749923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case KeyEvent.KEYCODE_DPAD_UP: 750923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case KeyEvent.KEYCODE_DPAD_LEFT: 751923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case KeyEvent.KEYCODE_DPAD_RIGHT: 7526e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani // If tutorial is visible, don't allow dpad to work 7536e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (mTutorial != null) { 7546e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani return true; 7556e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 756923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Enable shift key and DPAD to do selections 757923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mInputView != null && mInputView.isShown() && mInputView.isShifted()) { 758a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker event = new KeyEvent(event.getDownTime(), event.getEventTime(), 759923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project event.getAction(), event.getKeyCode(), event.getRepeatCount(), 760923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project event.getDeviceId(), event.getScanCode(), 761923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON); 762923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 763923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) ic.sendKeyEvent(event); 764923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 765923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 766923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 767923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 768923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyUp(keyCode, event); 769923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 770923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 771466741d8a78965b8509bf527344f289e50873092Mike LeBeau private void revertVoiceInput() { 772466741d8a78965b8509bf527344f289e50873092Mike LeBeau InputConnection ic = getCurrentInputConnection(); 773466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (ic != null) ic.commitText("", 1); 774466741d8a78965b8509bf527344f289e50873092Mike LeBeau updateSuggestions(); 775466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceInputHighlighted = false; 776466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 777466741d8a78965b8509bf527344f289e50873092Mike LeBeau 778466741d8a78965b8509bf527344f289e50873092Mike LeBeau private void commitVoiceInput() { 779466741d8a78965b8509bf527344f289e50873092Mike LeBeau InputConnection ic = getCurrentInputConnection(); 780466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (ic != null) ic.finishComposingText(); 781466741d8a78965b8509bf527344f289e50873092Mike LeBeau updateSuggestions(); 782466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceInputHighlighted = false; 783466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 784466741d8a78965b8509bf527344f289e50873092Mike LeBeau 78536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani private void reloadKeyboards() { 78636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani if (mKeyboardSwitcher == null) { 78736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mKeyboardSwitcher = new KeyboardSwitcher(this, this); 78836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 7893f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani mKeyboardSwitcher.setLanguageSwitcher(mLanguageSwitcher); 790b8f98ad014ac6f1d453128f902dba67ebebff1d3Amith Yamasani if (mInputView != null) { 791b8f98ad014ac6f1d453128f902dba67ebebff1d3Amith Yamasani mKeyboardSwitcher.setVoiceMode(mEnableVoice, mVoiceOnPrimary); 792b8f98ad014ac6f1d453128f902dba67ebebff1d3Amith Yamasani } 79336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mKeyboardSwitcher.makeKeyboards(true); 79436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 79536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 796923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void commitTyped(InputConnection inputConnection) { 797923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mPredicting) { 798923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPredicting = false; 799923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mComposing.length() > 0) { 800923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (inputConnection != null) { 801923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project inputConnection.commitText(mComposing, 1); 802923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 803923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCommittedLength = mComposing.length(); 804923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.acceptedTyped(mComposing); 805d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani mAutoDictionary.addWord(mComposing.toString(), FREQUENCY_FOR_TYPED); 806923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 807923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateSuggestions(); 808923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 809923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 810923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 8113263841911dc3dbbf4ffe26d2f046e38a1896f72Amith Yamasani private void postUpdateShiftKeyState() { 8123263841911dc3dbbf4ffe26d2f046e38a1896f72Amith Yamasani mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE); 8133263841911dc3dbbf4ffe26d2f046e38a1896f72Amith Yamasani mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_UPDATE_SHIFT_STATE), 300); 8143263841911dc3dbbf4ffe26d2f046e38a1896f72Amith Yamasani } 8153263841911dc3dbbf4ffe26d2f046e38a1896f72Amith Yamasani 816923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void updateShiftKeyState(EditorInfo attr) { 817923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 818923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (attr != null && mInputView != null && mKeyboardSwitcher.isAlphabetMode() 819923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project && ic != null) { 8201c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani mInputView.setShifted(mCapsLock || getCursorCapsMode(ic, attr) != 0); 821923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 822923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 8231c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 8241c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani private int getCursorCapsMode(InputConnection ic, EditorInfo attr) { 8251c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani int caps = 0; 8261c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani EditorInfo ei = getCurrentInputEditorInfo(); 8271c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani if (mAutoCap && ei != null && ei.inputType != EditorInfo.TYPE_NULL) { 8281c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani caps = ic.getCursorCapsMode(attr.inputType); 8291c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 8301c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani return caps; 8311c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 8321c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 833923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void swapPunctuationAndSpace() { 834923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final InputConnection ic = getCurrentInputConnection(); 835923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 836923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence lastTwo = ic.getTextBeforeCursor(2, 0); 837923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastTwo != null && lastTwo.length() == 2 838923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project && lastTwo.charAt(0) == KEYCODE_SPACE && isSentenceSeparator(lastTwo.charAt(1))) { 839923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 840923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 841923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(lastTwo.charAt(1) + " ", 1); 842923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 843923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateShiftKeyState(getCurrentInputEditorInfo()); 844923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 845923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 8461c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 847923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void doubleSpace() { 848923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project //if (!mAutoPunctuate) return; 849923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mCorrectionMode == Suggest.CORRECTION_NONE) return; 850923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final InputConnection ic = getCurrentInputConnection(); 851923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 852923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence lastThree = ic.getTextBeforeCursor(3, 0); 853923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastThree != null && lastThree.length() == 3 854923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project && Character.isLetterOrDigit(lastThree.charAt(0)) 855923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project && lastThree.charAt(1) == KEYCODE_SPACE && lastThree.charAt(2) == KEYCODE_SPACE) { 856923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 857923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 858923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(". ", 1); 859923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 860923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateShiftKeyState(getCurrentInputEditorInfo()); 861923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 862923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 863a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 86441a519729505a877844f2c57a33509c302dddbceKen Wakasa private void maybeRemovePreviousPeriod(CharSequence text) { 86541a519729505a877844f2c57a33509c302dddbceKen Wakasa final InputConnection ic = getCurrentInputConnection(); 86641a519729505a877844f2c57a33509c302dddbceKen Wakasa if (ic == null) return; 86741a519729505a877844f2c57a33509c302dddbceKen Wakasa 86841a519729505a877844f2c57a33509c302dddbceKen Wakasa // When the text's first character is '.', remove the previous period 86941a519729505a877844f2c57a33509c302dddbceKen Wakasa // if there is one. 87041a519729505a877844f2c57a33509c302dddbceKen Wakasa CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 87141a519729505a877844f2c57a33509c302dddbceKen Wakasa if (lastOne != null && lastOne.length() == 1 && lastOne.charAt(0) == '.' 87241a519729505a877844f2c57a33509c302dddbceKen Wakasa && text.charAt(0) == '.') { 87341a519729505a877844f2c57a33509c302dddbceKen Wakasa ic.deleteSurroundingText(1, 0); 87441a519729505a877844f2c57a33509c302dddbceKen Wakasa } 87541a519729505a877844f2c57a33509c302dddbceKen Wakasa } 87641a519729505a877844f2c57a33509c302dddbceKen Wakasa 877923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean addWordToDictionary(String word) { 878923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mUserDictionary.addWord(word, 128); 879923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 880923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 881923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 882923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean isAlphabet(int code) { 883923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (Character.isLetter(code)) { 884923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 885923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 886923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return false; 887923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 888923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 889a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 890923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Implementation of KeyboardViewListener 891923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 892923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onKey(int primaryCode, int[] keyCodes) { 893923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long when = SystemClock.uptimeMillis(); 894a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker if (primaryCode != Keyboard.KEYCODE_DELETE || 895923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project when > mLastKeyTime + QUICK_PRESS) { 896923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mDeleteCount = 0; 897923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 898923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mLastKeyTime = when; 899923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 900923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case Keyboard.KEYCODE_DELETE: 901923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project handleBackspace(); 902923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mDeleteCount++; 903923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 904923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case Keyboard.KEYCODE_SHIFT: 905923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project handleShift(); 906923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 907923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case Keyboard.KEYCODE_CANCEL: 908923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mOptionsDialog == null || !mOptionsDialog.isShowing()) { 909923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project handleClose(); 910923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 911923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 912923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case LatinKeyboardView.KEYCODE_OPTIONS: 913923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project showOptionsMenu(); 914923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 9158eb2e34d5b2def57c9548f88e37e5c9e5a0bea59Amith Yamasani case LatinKeyboardView.KEYCODE_NEXT_LANGUAGE: 9163f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani toggleLanguage(false, true); 9173f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani break; 9183f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani case LatinKeyboardView.KEYCODE_PREV_LANGUAGE: 9193f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani toggleLanguage(false, false); 92036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani break; 921923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case LatinKeyboardView.KEYCODE_SHIFT_LONGPRESS: 922923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mCapsLock) { 923923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project handleShift(); 924923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 925923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project toggleCapsLock(); 926923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 927923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 928923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case Keyboard.KEYCODE_MODE_CHANGE: 929923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project changeKeyboardMode(); 930923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 931466741d8a78965b8509bf527344f289e50873092Mike LeBeau case LatinKeyboardView.KEYCODE_VOICE: 932466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (VOICE_INSTALLED) { 933466741d8a78965b8509bf527344f289e50873092Mike LeBeau startListening(false /* was a button press, was not a swipe */); 934466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 935466741d8a78965b8509bf527344f289e50873092Mike LeBeau break; 936cf02653097893b06f24551b790b0f7ec288e704dAmith Yamasani case 9 /*Tab*/: 9378fa317a61a2152347c59dda7eb1b8e2979f6cc1dLeon Scroggins sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB); 938cf02653097893b06f24551b790b0f7ec288e704dAmith Yamasani break; 939923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project default: 940923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (isWordSeparator(primaryCode)) { 941923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project handleSeparator(primaryCode); 942923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 943923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project handleCharacter(primaryCode, keyCodes); 944923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 945923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Cancel the just reverted state 946923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mJustRevertedSeparator = null; 947923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 948b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani if (mKeyboardSwitcher.onKey(primaryCode)) { 949b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani changeKeyboardMode(); 950b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 951923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 952a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 953923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onText(CharSequence text) { 954923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 955923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 956923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 957923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mPredicting) { 958923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project commitTyped(ic); 959923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 96041a519729505a877844f2c57a33509c302dddbceKen Wakasa maybeRemovePreviousPeriod(text); 961923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(text, 1); 962923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 963923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateShiftKeyState(getCurrentInputEditorInfo()); 964923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mJustRevertedSeparator = null; 965923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 966923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 967923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleBackspace() { 968466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (VOICE_INSTALLED && mVoiceInputHighlighted) { 969466741d8a78965b8509bf527344f289e50873092Mike LeBeau revertVoiceInput(); 970466741d8a78965b8509bf527344f289e50873092Mike LeBeau return; 971466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 972923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project boolean deleteChar = false; 973923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 974923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 975923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mPredicting) { 976923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final int length = mComposing.length(); 977923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (length > 0) { 978923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mComposing.delete(length - 1, length); 979923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mWord.deleteLast(); 980923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.setComposingText(mComposing, 1); 981923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mComposing.length() == 0) { 982923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPredicting = false; 983923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 984923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project postUpdateSuggestions(); 985923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 986923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(1, 0); 987923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 988923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 989923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project deleteChar = true; 990923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 9913263841911dc3dbbf4ffe26d2f046e38a1896f72Amith Yamasani postUpdateShiftKeyState(); 992923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.backspace(); 993923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (TextEntryState.getState() == TextEntryState.STATE_UNDO_COMMIT) { 994923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project revertLastWord(deleteChar); 995923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 996923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else if (deleteChar) { 997923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 998923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mDeleteCount > DELETE_ACCELERATE_AT) { 999923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 1000923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1001923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1002923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mJustRevertedSeparator = null; 1003923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1004923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1005923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleShift() { 100682c68bfbfc9442ebb7d8be842aaf8dedf5ffc76eAmith Yamasani mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE); 1007923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mKeyboardSwitcher.isAlphabetMode()) { 1008923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Alphabet keyboard 1009923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project checkToggleCapsLock(); 1010923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mInputView.setShifted(mCapsLock || !mInputView.isShifted()); 1011923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1012923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mKeyboardSwitcher.toggleShift(); 1013923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1014923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1015a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1016923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleCharacter(int primaryCode, int[] keyCodes) { 1017466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (VOICE_INSTALLED && mVoiceInputHighlighted) { 1018466741d8a78965b8509bf527344f289e50873092Mike LeBeau commitVoiceInput(); 1019466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1020923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (isAlphabet(primaryCode) && isPredictionOn() && !isCursorTouchingWord()) { 1021923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (!mPredicting) { 1022923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPredicting = true; 1023923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mComposing.setLength(0); 1024923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mWord.reset(); 1025923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1026923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1027923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mInputView.isShifted()) { 102856f96fe05b2b01c488ce569eb2eefc13ee917fd3Amith Yamasani // TODO: This doesn't work with ß, need to fix it in the next release. 1029eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT 1030eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani || keyCodes[0] > Character.MAX_CODE_POINT) { 1031eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani return; 1032eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani } 103356f96fe05b2b01c488ce569eb2eefc13ee917fd3Amith Yamasani primaryCode = new String(keyCodes, 0, 1).toUpperCase().charAt(0); 1034923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1035923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mPredicting) { 1036923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mInputView.isShifted() && mComposing.length() == 0) { 1037923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mWord.setCapitalized(true); 1038923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1039923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mComposing.append((char) primaryCode); 1040923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mWord.add(primaryCode, keyCodes); 1041923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1042923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 10431c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani // If it's the first letter, make note of auto-caps state 10441c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani if (mWord.size() == 1) { 10451c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani mWord.setAutoCapitalized( 10461c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani getCursorCapsMode(ic, getCurrentInputEditorInfo()) != 0); 10471c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 1048923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.setComposingText(mComposing, 1); 1049923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1050923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project postUpdateSuggestions(); 1051923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1052923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendKeyChar((char)primaryCode); 1053923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 10548850bdc7e4c1da7049231bc1e21f17213562f9b6Amith Yamasani updateShiftKeyState(getCurrentInputEditorInfo()); 1055923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project measureCps(); 1056923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.typedCharacter((char) primaryCode, isWordSeparator(primaryCode)); 1057923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1058923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1059923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleSeparator(int primaryCode) { 1060466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (VOICE_INSTALLED && mVoiceInputHighlighted) { 1061466741d8a78965b8509bf527344f289e50873092Mike LeBeau commitVoiceInput(); 1062466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1063923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project boolean pickedDefault = false; 1064923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Handle separator 1065923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1066923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1067923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 1068923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1069923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mPredicting) { 1070923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In certain languages where single quote is a separator, it's better 1071a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker // not to auto correct, but accept the typed word. For instance, 1072923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // in Italian dov' should not be expanded to dove' because the elision 1073923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // requires the last vowel to be removed. 1074a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker if (mAutoCorrectOn && primaryCode != '\'' && 1075a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker (mJustRevertedSeparator == null 1076a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker || mJustRevertedSeparator.length() == 0 1077923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project || mJustRevertedSeparator.charAt(0) != primaryCode)) { 1078923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project pickDefaultSuggestion(); 1079923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project pickedDefault = true; 1080923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1081923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project commitTyped(ic); 1082923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1083923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1084923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendKeyChar((char)primaryCode); 1085923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.typedCharacter((char) primaryCode, true); 1086a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker if (TextEntryState.getState() == TextEntryState.STATE_PUNCTUATION_AFTER_ACCEPTED 1087923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project && primaryCode != KEYCODE_ENTER) { 1088923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project swapPunctuationAndSpace(); 1089a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker } else if (isPredictionOn() && primaryCode == ' ') { 1090923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project //else if (TextEntryState.STATE_SPACE_AFTER_ACCEPTED) { 1091923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project doubleSpace(); 1092923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1093923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (pickedDefault && mBestWord != null) { 1094923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.acceptedDefault(mWord.getTypedWord(), mBestWord); 1095923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1096923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateShiftKeyState(getCurrentInputEditorInfo()); 1097923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1098923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1099923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1100923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1101466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1102923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleClose() { 1103923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project commitTyped(getCurrentInputConnection()); 1104466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (VOICE_INSTALLED & mRecognizing) { 1105466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceInput.cancel(); 1106466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1107923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project requestHideSelf(0); 1108923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mInputView.closing(); 1109923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.endSession(); 1110923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1111923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1112923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void checkToggleCapsLock() { 1113923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mInputView.getKeyboard().isShifted()) { 1114923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project toggleCapsLock(); 1115923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1116923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1117a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1118923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void toggleCapsLock() { 1119923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCapsLock = !mCapsLock; 1120923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mKeyboardSwitcher.isAlphabetMode()) { 1121923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ((LatinKeyboard) mInputView.getKeyboard()).setShiftLocked(mCapsLock); 1122923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1123923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1124923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1125923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void postUpdateSuggestions() { 1126923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mHandler.removeMessages(MSG_UPDATE_SUGGESTIONS); 1127923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_UPDATE_SUGGESTIONS), 100); 1128923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1129a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1130923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean isPredictionOn() { 1131923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project boolean predictionOn = mPredictionOn; 1132923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project //if (isFullscreenMode()) predictionOn &= mPredictionLandscape; 1133923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return predictionOn; 1134923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1135a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1136923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean isCandidateStripVisible() { 11376e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani return isPredictionOn() && mShowSuggestions; 1138923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1139923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1140466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onCancelVoice() { 1141466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mRecognizing) { 1142466741d8a78965b8509bf527344f289e50873092Mike LeBeau switchToKeyboardView(); 1143466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1144466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1145466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1146466741d8a78965b8509bf527344f289e50873092Mike LeBeau private void switchToKeyboardView() { 1147466741d8a78965b8509bf527344f289e50873092Mike LeBeau mHandler.post(new Runnable() { 1148466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void run() { 1149466741d8a78965b8509bf527344f289e50873092Mike LeBeau mRecognizing = false; 1150466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mInputView != null) { 1151466741d8a78965b8509bf527344f289e50873092Mike LeBeau setInputView(mInputView); 1152466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1153466741d8a78965b8509bf527344f289e50873092Mike LeBeau updateInputViewShown(); 1154466741d8a78965b8509bf527344f289e50873092Mike LeBeau }}); 1155466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1156466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1157466741d8a78965b8509bf527344f289e50873092Mike LeBeau private void switchToRecognitionStatusView() { 1158466741d8a78965b8509bf527344f289e50873092Mike LeBeau mHandler.post(new Runnable() { 1159466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void run() { 1160466741d8a78965b8509bf527344f289e50873092Mike LeBeau mRecognizing = true; 1161466741d8a78965b8509bf527344f289e50873092Mike LeBeau setInputView(mVoiceInput.getView()); 1162466741d8a78965b8509bf527344f289e50873092Mike LeBeau updateInputViewShown(); 1163466741d8a78965b8509bf527344f289e50873092Mike LeBeau }}); 1164466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1165466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1166466741d8a78965b8509bf527344f289e50873092Mike LeBeau private void startListening(boolean swipe) { 1167466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (!mHasUsedVoiceInput || 1168466741d8a78965b8509bf527344f289e50873092Mike LeBeau (!mLocaleSupportedForVoiceInput && !mHasUsedVoiceInputUnsupportedLocale)) { 1169466741d8a78965b8509bf527344f289e50873092Mike LeBeau // Calls reallyStartListening if user clicks OK, does nothing if user clicks Cancel. 1170466741d8a78965b8509bf527344f289e50873092Mike LeBeau showVoiceWarningDialog(swipe); 1171466741d8a78965b8509bf527344f289e50873092Mike LeBeau } else { 1172466741d8a78965b8509bf527344f289e50873092Mike LeBeau reallyStartListening(swipe); 1173466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1174466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1175a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1176466741d8a78965b8509bf527344f289e50873092Mike LeBeau private void reallyStartListening(boolean swipe) { 1177466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (!mHasUsedVoiceInput) { 1178466741d8a78965b8509bf527344f289e50873092Mike LeBeau // The user has started a voice input, so remember that in the 1179466741d8a78965b8509bf527344f289e50873092Mike LeBeau // future (so we don't show the warning dialog after the first run). 1180466741d8a78965b8509bf527344f289e50873092Mike LeBeau SharedPreferences.Editor editor = 1181466741d8a78965b8509bf527344f289e50873092Mike LeBeau PreferenceManager.getDefaultSharedPreferences(this).edit(); 1182466741d8a78965b8509bf527344f289e50873092Mike LeBeau editor.putBoolean(PREF_HAS_USED_VOICE_INPUT, true); 1183466741d8a78965b8509bf527344f289e50873092Mike LeBeau editor.commit(); 1184466741d8a78965b8509bf527344f289e50873092Mike LeBeau mHasUsedVoiceInput = true; 1185466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1186a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1187466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (!mLocaleSupportedForVoiceInput && !mHasUsedVoiceInputUnsupportedLocale) { 1188466741d8a78965b8509bf527344f289e50873092Mike LeBeau // The user has started a voice input from an unsupported locale, so remember that 1189466741d8a78965b8509bf527344f289e50873092Mike LeBeau // in the future (so we don't show the warning dialog the next time they do this). 1190466741d8a78965b8509bf527344f289e50873092Mike LeBeau SharedPreferences.Editor editor = 1191466741d8a78965b8509bf527344f289e50873092Mike LeBeau PreferenceManager.getDefaultSharedPreferences(this).edit(); 1192466741d8a78965b8509bf527344f289e50873092Mike LeBeau editor.putBoolean(PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE, true); 1193466741d8a78965b8509bf527344f289e50873092Mike LeBeau editor.commit(); 1194466741d8a78965b8509bf527344f289e50873092Mike LeBeau mHasUsedVoiceInputUnsupportedLocale = true; 1195466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1196a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1197466741d8a78965b8509bf527344f289e50873092Mike LeBeau // Clear N-best suggestions 1198466741d8a78965b8509bf527344f289e50873092Mike LeBeau setSuggestions(null, false, false, true); 1199466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1200466741d8a78965b8509bf527344f289e50873092Mike LeBeau FieldContext context = new FieldContext( 12012e3aa86cf389236c085ab4758239b01e80c3b2dcMike LeBeau getCurrentInputConnection(), 12022e3aa86cf389236c085ab4758239b01e80c3b2dcMike LeBeau getCurrentInputEditorInfo(), 12032e3aa86cf389236c085ab4758239b01e80c3b2dcMike LeBeau mLanguageSwitcher.getInputLanguage(), 12042e3aa86cf389236c085ab4758239b01e80c3b2dcMike LeBeau mLanguageSwitcher.getEnabledLanguages()); 1205466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceInput.startListening(context, swipe); 1206466741d8a78965b8509bf527344f289e50873092Mike LeBeau switchToRecognitionStatusView(); 1207466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1208a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1209466741d8a78965b8509bf527344f289e50873092Mike LeBeau private void showVoiceWarningDialog(final boolean swipe) { 1210466741d8a78965b8509bf527344f289e50873092Mike LeBeau AlertDialog.Builder builder = new AlertDialog.Builder(this); 1211466741d8a78965b8509bf527344f289e50873092Mike LeBeau builder.setCancelable(true); 1212466741d8a78965b8509bf527344f289e50873092Mike LeBeau builder.setIcon(R.drawable.ic_mic_dialog); 1213466741d8a78965b8509bf527344f289e50873092Mike LeBeau builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 1214466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onClick(DialogInterface dialog, int whichButton) { 1215466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceInput.logKeyboardWarningDialogOk(); 1216466741d8a78965b8509bf527344f289e50873092Mike LeBeau reallyStartListening(swipe); 1217466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1218466741d8a78965b8509bf527344f289e50873092Mike LeBeau }); 1219466741d8a78965b8509bf527344f289e50873092Mike LeBeau builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { 1220466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onClick(DialogInterface dialog, int whichButton) { 1221466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceInput.logKeyboardWarningDialogCancel(); 1222466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1223466741d8a78965b8509bf527344f289e50873092Mike LeBeau }); 1224a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1225466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mLocaleSupportedForVoiceInput) { 1226466741d8a78965b8509bf527344f289e50873092Mike LeBeau String message = getString(R.string.voice_warning_may_not_understand) + "\n\n" + 1227466741d8a78965b8509bf527344f289e50873092Mike LeBeau getString(R.string.voice_warning_how_to_turn_off); 1228466741d8a78965b8509bf527344f289e50873092Mike LeBeau builder.setMessage(message); 1229466741d8a78965b8509bf527344f289e50873092Mike LeBeau } else { 1230466741d8a78965b8509bf527344f289e50873092Mike LeBeau String message = getString(R.string.voice_warning_locale_not_supported) + "\n\n" + 1231466741d8a78965b8509bf527344f289e50873092Mike LeBeau getString(R.string.voice_warning_may_not_understand) + "\n\n" + 1232466741d8a78965b8509bf527344f289e50873092Mike LeBeau getString(R.string.voice_warning_how_to_turn_off); 1233466741d8a78965b8509bf527344f289e50873092Mike LeBeau builder.setMessage(message); 1234466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1235a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1236466741d8a78965b8509bf527344f289e50873092Mike LeBeau builder.setTitle(R.string.voice_warning_title); 1237466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceWarningDialog = builder.create(); 1238a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1239466741d8a78965b8509bf527344f289e50873092Mike LeBeau Window window = mVoiceWarningDialog.getWindow(); 1240466741d8a78965b8509bf527344f289e50873092Mike LeBeau WindowManager.LayoutParams lp = window.getAttributes(); 1241466741d8a78965b8509bf527344f289e50873092Mike LeBeau lp.token = mInputView.getWindowToken(); 1242466741d8a78965b8509bf527344f289e50873092Mike LeBeau lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 1243466741d8a78965b8509bf527344f289e50873092Mike LeBeau window.setAttributes(lp); 1244466741d8a78965b8509bf527344f289e50873092Mike LeBeau window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 1245466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceInput.logKeyboardWarningDialogShown(); 1246466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceWarningDialog.show(); 1247466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1248466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1249466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onVoiceResults(List<String> candidates, 1250466741d8a78965b8509bf527344f289e50873092Mike LeBeau Map<String, List<CharSequence>> alternatives) { 1251466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (!mRecognizing) { 1252466741d8a78965b8509bf527344f289e50873092Mike LeBeau return; 1253466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1254466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceResults.candidates = candidates; 1255466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceResults.alternatives = alternatives; 1256466741d8a78965b8509bf527344f289e50873092Mike LeBeau mHandler.sendMessage(mHandler.obtainMessage(MSG_VOICE_RESULTS)); 1257466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1258466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1259466741d8a78965b8509bf527344f289e50873092Mike LeBeau private void handleVoiceResults() { 1260466741d8a78965b8509bf527344f289e50873092Mike LeBeau mAfterVoiceInput = true; 1261466741d8a78965b8509bf527344f289e50873092Mike LeBeau mImmediatelyAfterVoiceInput = true; 1262466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1263466741d8a78965b8509bf527344f289e50873092Mike LeBeau InputConnection ic = getCurrentInputConnection(); 1264466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (!isFullscreenMode()) { 1265466741d8a78965b8509bf527344f289e50873092Mike LeBeau // Start listening for updates to the text from typing, etc. 1266466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (ic != null) { 1267466741d8a78965b8509bf527344f289e50873092Mike LeBeau ExtractedTextRequest req = new ExtractedTextRequest(); 1268466741d8a78965b8509bf527344f289e50873092Mike LeBeau ic.getExtractedText(req, InputConnection.GET_EXTRACTED_TEXT_MONITOR); 1269466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1270466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1271466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1272466741d8a78965b8509bf527344f289e50873092Mike LeBeau vibrate(); 1273466741d8a78965b8509bf527344f289e50873092Mike LeBeau switchToKeyboardView(); 1274466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1275466741d8a78965b8509bf527344f289e50873092Mike LeBeau final List<CharSequence> nBest = new ArrayList<CharSequence>(); 1276466741d8a78965b8509bf527344f289e50873092Mike LeBeau boolean capitalizeFirstWord = preferCapitalization() 1277466741d8a78965b8509bf527344f289e50873092Mike LeBeau || (mKeyboardSwitcher.isAlphabetMode() && mInputView.isShifted()); 1278466741d8a78965b8509bf527344f289e50873092Mike LeBeau for (String c : mVoiceResults.candidates) { 1279466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (capitalizeFirstWord) { 1280466741d8a78965b8509bf527344f289e50873092Mike LeBeau c = Character.toUpperCase(c.charAt(0)) + c.substring(1, c.length()); 1281466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1282466741d8a78965b8509bf527344f289e50873092Mike LeBeau nBest.add(c); 1283466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1284466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1285466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (nBest.size() == 0) { 1286466741d8a78965b8509bf527344f289e50873092Mike LeBeau return; 1287466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1288466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1289466741d8a78965b8509bf527344f289e50873092Mike LeBeau String bestResult = nBest.get(0).toString(); 1290466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1291466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceInput.logVoiceInputDelivered(); 1292466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1293466741d8a78965b8509bf527344f289e50873092Mike LeBeau mHints.registerVoiceResult(bestResult); 1294466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1295466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (ic != null) ic.beginBatchEdit(); // To avoid extra updates on committing older text 1296466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1297466741d8a78965b8509bf527344f289e50873092Mike LeBeau commitTyped(ic); 1298466741d8a78965b8509bf527344f289e50873092Mike LeBeau EditingUtil.appendText(ic, bestResult); 1299466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1300466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (ic != null) ic.endBatchEdit(); 1301466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1302466741d8a78965b8509bf527344f289e50873092Mike LeBeau // Show N-Best alternates, if there is more than one choice. 1303466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (nBest.size() > 1) { 1304466741d8a78965b8509bf527344f289e50873092Mike LeBeau mImmediatelyAfterVoiceSuggestions = true; 1305466741d8a78965b8509bf527344f289e50873092Mike LeBeau mShowingVoiceSuggestions = true; 1306466741d8a78965b8509bf527344f289e50873092Mike LeBeau setSuggestions(nBest.subList(1, nBest.size()), false, true, true); 1307466741d8a78965b8509bf527344f289e50873092Mike LeBeau setCandidatesViewShown(true); 1308466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1309466741d8a78965b8509bf527344f289e50873092Mike LeBeau mVoiceInputHighlighted = true; 1310466741d8a78965b8509bf527344f289e50873092Mike LeBeau mWordToSuggestions.putAll(mVoiceResults.alternatives); 1311466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1312466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1313466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1314466741d8a78965b8509bf527344f289e50873092Mike LeBeau private void setSuggestions( 1315466741d8a78965b8509bf527344f289e50873092Mike LeBeau List<CharSequence> suggestions, 1316466741d8a78965b8509bf527344f289e50873092Mike LeBeau boolean completions, 1317466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1318466741d8a78965b8509bf527344f289e50873092Mike LeBeau boolean typedWordValid, 1319466741d8a78965b8509bf527344f289e50873092Mike LeBeau boolean haveMinimalSuggestion) { 1320466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1321466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mIsShowingHint) { 1322466741d8a78965b8509bf527344f289e50873092Mike LeBeau setCandidatesView(mCandidateViewContainer); 1323466741d8a78965b8509bf527344f289e50873092Mike LeBeau mIsShowingHint = false; 1324466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1325466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1326466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mCandidateView != null) { 1327466741d8a78965b8509bf527344f289e50873092Mike LeBeau mCandidateView.setSuggestions( 1328466741d8a78965b8509bf527344f289e50873092Mike LeBeau suggestions, completions, typedWordValid, haveMinimalSuggestion); 1329466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1330466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1331466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1332923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void updateSuggestions() { 1333466741d8a78965b8509bf527344f289e50873092Mike LeBeau mSuggestionShouldReplaceCurrentWord = false; 1334466741d8a78965b8509bf527344f289e50873092Mike LeBeau 13351b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani ((LatinKeyboard) mInputView.getKeyboard()).setPreferredLetters(null); 13361b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani 1337923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Check if we have a suggestion engine attached. 1338466741d8a78965b8509bf527344f289e50873092Mike LeBeau if ((mSuggest == null || !isPredictionOn()) && !mVoiceInputHighlighted) { 1339923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1340923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1341466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1342923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (!mPredicting) { 13436a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani setNextSuggestions(); 1344923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1345923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1346923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1347923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project List<CharSequence> stringList = mSuggest.getSuggestions(mInputView, mWord, false); 13481b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani int[] nextLettersFrequencies = mSuggest.getNextLettersFrequencies(); 13491b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani 13501b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani ((LatinKeyboard) mInputView.getKeyboard()).setPreferredLetters(nextLettersFrequencies); 13511b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani 1352923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project boolean correctionAvailable = mSuggest.hasMinimalCorrection(); 1353923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project //|| mCorrectionMode == mSuggest.CORRECTION_FULL; 1354923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence typedWord = mWord.getTypedWord(); 1355923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // If we're in basic correct 1356f590a497393eb77875017010e9a36cf33b095e3cAmith Yamasani boolean typedWordValid = mSuggest.isValidWord(typedWord) || 1357f590a497393eb77875017010e9a36cf33b095e3cAmith Yamasani (preferCapitalization() && mSuggest.isValidWord(typedWord.toString().toLowerCase())); 1358923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mCorrectionMode == Suggest.CORRECTION_FULL) { 1359923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project correctionAvailable |= typedWordValid; 1360923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 13614a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani // Don't auto-correct words with multiple capital letter 13624a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani correctionAvailable &= !mWord.isMostlyCaps(); 13634a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani 1364466741d8a78965b8509bf527344f289e50873092Mike LeBeau setSuggestions(stringList, false, typedWordValid, correctionAvailable); 1365923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (stringList.size() > 0) { 1366923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (correctionAvailable && !typedWordValid && stringList.size() > 1) { 1367923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = stringList.get(1); 1368923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1369923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = typedWord; 1370923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1371923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1372923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = null; 1373923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1374923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project setCandidatesViewShown(isCandidateStripVisible() || mCompletionOn); 1375923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1376923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1377923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void pickDefaultSuggestion() { 1378923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Complete any pending candidate query first 1379923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mHandler.hasMessages(MSG_UPDATE_SUGGESTIONS)) { 1380923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mHandler.removeMessages(MSG_UPDATE_SUGGESTIONS); 1381923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateSuggestions(); 1382923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1383923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mBestWord != null) { 1384923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.acceptedDefault(mWord.getTypedWord(), mBestWord); 1385923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mJustAccepted = true; 1386923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project pickSuggestion(mBestWord); 1387923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1388923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1389923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1390923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void pickSuggestionManually(int index, CharSequence suggestion) { 1391466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mAfterVoiceInput && mShowingVoiceSuggestions) mVoiceInput.logNBestChoose(index); 1392466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1393923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mCompletionOn && mCompletions != null && index >= 0 1394923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project && index < mCompletions.length) { 1395923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CompletionInfo ci = mCompletions[index]; 1396923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1397923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1398923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitCompletion(ci); 1399923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1400923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCommittedLength = suggestion.length(); 1401923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mCandidateView != null) { 1402923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCandidateView.clear(); 1403923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1404923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateShiftKeyState(getCurrentInputEditorInfo()); 1405923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1406923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 14076a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 14086a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani // If this is a punctuation, apply it through the normal key press 14096a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani if (suggestion.length() == 1 && isWordSeparator(suggestion.charAt(0))) { 14106a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani onKey(suggestion.charAt(0), null); 14116a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani return; 14126a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 1413923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project pickSuggestion(suggestion); 1414923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.acceptedSuggestion(mComposing.toString(), suggestion); 1415923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Follow it with a space 1416923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAutoSpace) { 1417923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendSpace(); 1418923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1419923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Fool the state watcher so that a subsequent backspace will not do a revert 1420923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.typedCharacter((char) KEYCODE_SPACE, true); 142166a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani if (index == 0 && !mSuggest.isValidWord(suggestion)) { 142266a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani mCandidateView.showAddToDictionaryHint(suggestion); 142366a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani } 1424923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1425a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1426923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void pickSuggestion(CharSequence suggestion) { 1427923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mCapsLock) { 1428923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project suggestion = suggestion.toString().toUpperCase(); 1429a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker } else if (preferCapitalization() 1430923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project || (mKeyboardSwitcher.isAlphabetMode() && mInputView.isShifted())) { 143156f96fe05b2b01c488ce569eb2eefc13ee917fd3Amith Yamasani suggestion = suggestion.toString().toUpperCase().charAt(0) 1432923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project + suggestion.subSequence(1, suggestion.length()).toString(); 1433923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1434923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1435923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1436466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mSuggestionShouldReplaceCurrentWord) { 1437466741d8a78965b8509bf527344f289e50873092Mike LeBeau EditingUtil.deleteWordAtCursor(ic, getWordSeparators()); 1438466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1439466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (!VoiceInput.DELETE_SYMBOL.equals(suggestion)) { 1440466741d8a78965b8509bf527344f289e50873092Mike LeBeau ic.commitText(suggestion, 1); 1441466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1442923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 144334386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani // Add the word to the auto dictionary if it's not a known word 144434386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani if (mAutoDictionary.isValidWord(suggestion) || !mSuggest.isValidWord(suggestion)) { 1445d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani mAutoDictionary.addWord(suggestion.toString(), FREQUENCY_FOR_PICKED); 144634386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani } 1447923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPredicting = false; 1448923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCommittedLength = suggestion.length(); 14496a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani setNextSuggestions(); 1450923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateShiftKeyState(getCurrentInputEditorInfo()); 1451923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1452923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 14536a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani private void setNextSuggestions() { 14546a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani setSuggestions(mSuggestPuncList, false, false, false); 14556a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 14566a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 1457923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean isCursorTouchingWord() { 1458923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1459923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return false; 1460923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence toLeft = ic.getTextBeforeCursor(1, 0); 1461923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence toRight = ic.getTextAfterCursor(1, 0); 1462923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (!TextUtils.isEmpty(toLeft) 1463923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project && !isWordSeparator(toLeft.charAt(0))) { 1464923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1465923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1466a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker if (!TextUtils.isEmpty(toRight) 1467923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project && !isWordSeparator(toRight.charAt(0))) { 1468923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1469923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1470923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return false; 1471923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1472a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1473923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void revertLastWord(boolean deleteChar) { 1474923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final int length = mComposing.length(); 1475923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (!mPredicting && length > 0) { 1476923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final InputConnection ic = getCurrentInputConnection(); 1477923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPredicting = true; 1478923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 1479923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mJustRevertedSeparator = ic.getTextBeforeCursor(1, 0); 1480923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (deleteChar) ic.deleteSurroundingText(1, 0); 1481923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int toDelete = mCommittedLength; 1482923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence toTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0); 1483a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker if (toTheLeft != null && toTheLeft.length() > 0 1484923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project && isWordSeparator(toTheLeft.charAt(0))) { 1485923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project toDelete--; 1486923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1487923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(toDelete, 0); 1488923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.setComposingText(mComposing, 1); 1489923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.backspace(); 1490923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1491923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project postUpdateSuggestions(); 1492923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1493923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 1494923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mJustRevertedSeparator = null; 1495923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1496923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1497923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1498923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project protected String getWordSeparators() { 1499923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return mWordSeparators; 1500923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1501a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1502923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean isWordSeparator(int code) { 1503923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project String separators = getWordSeparators(); 1504923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return separators.contains(String.valueOf((char)code)); 1505923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1506923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1507923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean isSentenceSeparator(int code) { 1508923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return mSentenceSeparators.contains(String.valueOf((char)code)); 1509923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1510923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1511923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void sendSpace() { 1512923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendKeyChar((char)KEYCODE_SPACE); 1513923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateShiftKeyState(getCurrentInputEditorInfo()); 1514923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project //onKey(KEY_SPACE[0], KEY_SPACE); 1515923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1516923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1517923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean preferCapitalization() { 1518923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return mWord.isCapitalized(); 1519923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1520923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1521923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void swipeRight() { 1522466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (userHasNotTypedRecently() && VOICE_INSTALLED && mEnableVoice && 1523466741d8a78965b8509bf527344f289e50873092Mike LeBeau fieldCanDoVoice(makeFieldContext())) { 1524466741d8a78965b8509bf527344f289e50873092Mike LeBeau startListening(true /* was a swipe */); 1525466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1526466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1527923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (LatinKeyboardView.DEBUG_AUTO_PLAY) { 1528923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ClipboardManager cm = ((ClipboardManager)getSystemService(CLIPBOARD_SERVICE)); 1529923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence text = cm.getText(); 1530923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (!TextUtils.isEmpty(text)) { 1531923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mInputView.startPlaying(text.toString()); 1532923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1533923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1534923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 153536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 15363f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani private void toggleLanguage(boolean reset, boolean next) { 15373f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani if (reset) { 15383f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani mLanguageSwitcher.reset(); 15393f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani } else { 15403f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani if (next) { 15413f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani mLanguageSwitcher.next(); 15423f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani } else { 15433f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani mLanguageSwitcher.prev(); 15443f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani } 15453f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani } 154636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani int currentKeyboardMode = mKeyboardSwitcher.getKeyboardMode(); 154736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani reloadKeyboards(); 154836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mKeyboardSwitcher.makeKeyboards(true); 1549b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani mKeyboardSwitcher.setKeyboardMode(currentKeyboardMode, 0, 1550b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani mEnableVoiceButton && mEnableVoice); 15513f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani initSuggest(mLanguageSwitcher.getInputLanguage()); 15523f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani mLanguageSwitcher.persist(); 155336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani updateShiftKeyState(getCurrentInputEditorInfo()); 155436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 155536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 155636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, 155736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani String key) { 155836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani if (PREF_SELECTED_LANGUAGES.equals(key)) { 15593f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani mLanguageSwitcher.loadLocales(sharedPreferences); 156036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mRefreshKeyboardRequired = true; 156136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 156236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 156336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 1564923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void swipeLeft() { 1565923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1566923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1567923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void swipeDown() { 15685d11ccc27d9e06a174b5f027109e29b34eea751eAmith Yamasani handleClose(); 1569923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1570923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1571923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void swipeUp() { 1572923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project //launchSettings(); 1573923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1574923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1575923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onPress(int primaryCode) { 1576923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project vibrate(); 1577923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project playKeyClick(primaryCode); 1578923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1579923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1580923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onRelease(int primaryCode) { 15813f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani // Reset any drag flags in the keyboard 15823f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani ((LatinKeyboard) mInputView.getKeyboard()).keyReleased(); 1583923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project //vibrate(); 1584923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1585a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1586466741d8a78965b8509bf527344f289e50873092Mike LeBeau private FieldContext makeFieldContext() { 15872e3aa86cf389236c085ab4758239b01e80c3b2dcMike LeBeau return new FieldContext( 15882e3aa86cf389236c085ab4758239b01e80c3b2dcMike LeBeau getCurrentInputConnection(), 15892e3aa86cf389236c085ab4758239b01e80c3b2dcMike LeBeau getCurrentInputEditorInfo(), 15902e3aa86cf389236c085ab4758239b01e80c3b2dcMike LeBeau mLanguageSwitcher.getInputLanguage(), 15912e3aa86cf389236c085ab4758239b01e80c3b2dcMike LeBeau mLanguageSwitcher.getEnabledLanguages()); 1592466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1593a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1594466741d8a78965b8509bf527344f289e50873092Mike LeBeau private boolean fieldCanDoVoice(FieldContext fieldContext) { 1595466741d8a78965b8509bf527344f289e50873092Mike LeBeau return !mPasswordText 1596466741d8a78965b8509bf527344f289e50873092Mike LeBeau && mVoiceInput != null 1597466741d8a78965b8509bf527344f289e50873092Mike LeBeau && !mVoiceInput.isBlacklistedField(fieldContext); 1598466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1599466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1600466741d8a78965b8509bf527344f289e50873092Mike LeBeau private boolean fieldIsRecommendedForVoice(FieldContext fieldContext) { 1601466741d8a78965b8509bf527344f289e50873092Mike LeBeau // TODO: Move this logic into the VoiceInput method. 1602466741d8a78965b8509bf527344f289e50873092Mike LeBeau return !mPasswordText && !mEmailText && mVoiceInput.isRecommendedField(fieldContext); 1603466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1604923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1605466741d8a78965b8509bf527344f289e50873092Mike LeBeau private boolean shouldShowVoiceButton(FieldContext fieldContext, EditorInfo attribute) { 1606960ea65f3f2162e7f8f387380924162d42fef4dcValentin Kravtsov return ENABLE_VOICE_BUTTON && fieldCanDoVoice(fieldContext) 1607466741d8a78965b8509bf527344f289e50873092Mike LeBeau && !(attribute != null && attribute.privateImeOptions != null 1608960ea65f3f2162e7f8f387380924162d42fef4dcValentin Kravtsov && attribute.privateImeOptions.equals(IME_OPTION_NO_MICROPHONE)) 1609960ea65f3f2162e7f8f387380924162d42fef4dcValentin Kravtsov && RecognitionManager.isRecognitionAvailable(this); 1610466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1611a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1612923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // receive ringer mode changes to detect silent mode 1613923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private BroadcastReceiver mReceiver = new BroadcastReceiver() { 1614923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 1615923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onReceive(Context context, Intent intent) { 1616923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateRingerMode(); 1617923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1618923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project }; 1619923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1620923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // update flags for silent mode 1621923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void updateRingerMode() { 1622923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager == null) { 1623923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 1624923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1625923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager != null) { 1626923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mSilentMode = (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL); 1627923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1628923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1629923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1630466741d8a78965b8509bf527344f289e50873092Mike LeBeau private boolean userHasNotTypedRecently() { 1631466741d8a78965b8509bf527344f289e50873092Mike LeBeau return (SystemClock.uptimeMillis() - mLastKeyTime) 1632466741d8a78965b8509bf527344f289e50873092Mike LeBeau > MIN_MILLIS_AFTER_TYPING_BEFORE_SWIPE; 1633466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1634466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1635466741d8a78965b8509bf527344f289e50873092Mike LeBeau /* 1636466741d8a78965b8509bf527344f289e50873092Mike LeBeau * Only trigger a swipe action if the user hasn't typed X millis before 1637466741d8a78965b8509bf527344f289e50873092Mike LeBeau * now, and if they don't type Y millis after the swipe is detected. This 1638466741d8a78965b8509bf527344f289e50873092Mike LeBeau * delays the onset of the swipe action by Y millis. 1639466741d8a78965b8509bf527344f289e50873092Mike LeBeau */ 1640466741d8a78965b8509bf527344f289e50873092Mike LeBeau private void conservativelyTriggerSwipeAction(final Runnable action) { 1641466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (userHasNotTypedRecently()) { 1642466741d8a78965b8509bf527344f289e50873092Mike LeBeau mSwipeTriggerTimeMillis = System.currentTimeMillis(); 1643466741d8a78965b8509bf527344f289e50873092Mike LeBeau mHandler.sendMessageDelayed( 1644466741d8a78965b8509bf527344f289e50873092Mike LeBeau mHandler.obtainMessage(MSG_START_LISTENING_AFTER_SWIPE), 1645466741d8a78965b8509bf527344f289e50873092Mike LeBeau MIN_MILLIS_AFTER_SWIPE_TO_WAIT_FOR_TYPING); 1646466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1647466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1648466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1649466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1650923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void playKeyClick(int primaryCode) { 1651923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // if mAudioManager is null, we don't have the ringer state yet 1652923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // mAudioManager will be set by updateRingerMode 1653923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager == null) { 1654923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mInputView != null) { 1655923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateRingerMode(); 1656923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1657923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1658923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mSoundOn && !mSilentMode) { 1659923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // FIXME: Volume and enable should come from UI settings 1660923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // FIXME: These should be triggered after auto-repeat logic 1661923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int sound = AudioManager.FX_KEYPRESS_STANDARD; 1662923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 1663923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case Keyboard.KEYCODE_DELETE: 1664923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sound = AudioManager.FX_KEYPRESS_DELETE; 1665923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 1666923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case KEYCODE_ENTER: 1667923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sound = AudioManager.FX_KEYPRESS_RETURN; 1668923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 1669923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case KEYCODE_SPACE: 1670923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sound = AudioManager.FX_KEYPRESS_SPACEBAR; 1671923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 1672923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1673923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAudioManager.playSoundEffect(sound, FX_VOLUME); 1674923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1675923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1676923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1677923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void vibrate() { 1678923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (!mVibrateOn) { 1679923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1680923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 168166a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani if (mInputView != null) { 168266a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani mInputView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, 168366a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); 1684923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1685923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1686923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 16876e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani private void checkTutorial(String privateImeOptions) { 16886e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (privateImeOptions == null) return; 16896e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (privateImeOptions.equals("com.android.setupwizard:ShowTutorial")) { 16906e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (mTutorial == null) startTutorial(); 16916e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } else if (privateImeOptions.equals("com.android.setupwizard:HideTutorial")) { 16926e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (mTutorial != null) { 16936e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (mTutorial.close()) { 16946e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mTutorial = null; 16956e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 16966e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 16976e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 16986e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 1699a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 17006e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani private void startTutorial() { 17016e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_TUTORIAL), 500); 17026e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 17036e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani 17046e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani void tutorialDone() { 17056e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mTutorial = null; 17066e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 170734386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani 170834386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani void promoteToUserDictionary(String word, int frequency) { 170934386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani if (mUserDictionary.isValidWord(word)) return; 171034386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani mUserDictionary.addWord(word, frequency); 171134386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani } 171234386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani 1713e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private void updateCorrectionMode() { 1714e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mHasDictionary = mSuggest != null ? mSuggest.hasMainDictionary() : false; 1715e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mAutoCorrectOn = (mAutoCorrectEnabled || mQuickFixes) 1716e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani && !mInputTypeNoAutoCorrect && mHasDictionary; 1717e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mCorrectionMode = mAutoCorrectOn 1718e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani ? Suggest.CORRECTION_FULL 1719e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani : (mQuickFixes ? Suggest.CORRECTION_BASIC : Suggest.CORRECTION_NONE); 1720e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani if (mSuggest != null) { 1721e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mSuggest.setCorrectionMode(mCorrectionMode); 1722e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani } 1723e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani } 1724e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani 1725466741d8a78965b8509bf527344f289e50873092Mike LeBeau protected void launchSettings() { 1726466741d8a78965b8509bf527344f289e50873092Mike LeBeau launchSettings(LatinIMESettings.class); 1727466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1728466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1729466741d8a78965b8509bf527344f289e50873092Mike LeBeau protected void launchSettings(Class settingsClass) { 1730923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project handleClose(); 1731923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Intent intent = new Intent(); 1732466741d8a78965b8509bf527344f289e50873092Mike LeBeau intent.setClass(LatinIME.this, settingsClass); 1733923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1734923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project startActivity(intent); 1735923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1736923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1737923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void loadSettings() { 1738923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Get the settings preferences 1739923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); 17405ff5160ff89231ceb55d4d248fb529743d3f8e16Amith Yamasani mVibrateOn = sp.getBoolean(PREF_VIBRATE_ON, false); 1741923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mSoundOn = sp.getBoolean(PREF_SOUND_ON, false); 1742923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAutoCap = sp.getBoolean(PREF_AUTO_CAP, true); 17436e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mQuickFixes = sp.getBoolean(PREF_QUICK_FIXES, true); 1744466741d8a78965b8509bf527344f289e50873092Mike LeBeau mHasUsedVoiceInput = sp.getBoolean(PREF_HAS_USED_VOICE_INPUT, false); 1745466741d8a78965b8509bf527344f289e50873092Mike LeBeau mHasUsedVoiceInputUnsupportedLocale = 1746466741d8a78965b8509bf527344f289e50873092Mike LeBeau sp.getBoolean(PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE, false); 1747a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1748466741d8a78965b8509bf527344f289e50873092Mike LeBeau // Get the current list of supported locales and check the current locale against that 1749466741d8a78965b8509bf527344f289e50873092Mike LeBeau // list. We cache this value so as not to check it every time the user starts a voice 1750466741d8a78965b8509bf527344f289e50873092Mike LeBeau // input. Because this method is called by onStartInputView, this should mean that as 1751466741d8a78965b8509bf527344f289e50873092Mike LeBeau // long as the locale doesn't change while the user is keeping the IME open, the 1752466741d8a78965b8509bf527344f289e50873092Mike LeBeau // value should never be stale. 1753a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker String supportedLocalesString = SettingsUtil.getSettingsString( 1754466741d8a78965b8509bf527344f289e50873092Mike LeBeau getContentResolver(), 1755a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker SettingsUtil.LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES, 1756466741d8a78965b8509bf527344f289e50873092Mike LeBeau DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES); 1757466741d8a78965b8509bf527344f289e50873092Mike LeBeau ArrayList<String> voiceInputSupportedLocales = 1758466741d8a78965b8509bf527344f289e50873092Mike LeBeau Lists.newArrayList(supportedLocalesString.split("\\s+")); 1759a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1760466741d8a78965b8509bf527344f289e50873092Mike LeBeau mLocaleSupportedForVoiceInput = voiceInputSupportedLocales.contains(mLocale); 1761a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 17626e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani // If there is no auto text data, then quickfix is forced to "on", so that the other options 17636e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani // will continue to work 1764466741d8a78965b8509bf527344f289e50873092Mike LeBeau 17656e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (AutoText.getSize(mInputView) < 1) mQuickFixes = true; 17666e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mShowSuggestions = sp.getBoolean(PREF_SHOW_SUGGESTIONS, true) & mQuickFixes; 1767466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1768466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (VOICE_INSTALLED) { 1769457fdffce4550b5597435f030483dcafffecf714Amith Yamasani final String voiceMode = sp.getString(PREF_VOICE_MODE, ""); 1770457fdffce4550b5597435f030483dcafffecf714Amith Yamasani boolean enableVoice = !voiceMode.equals(getString(R.string.voice_mode_off)); 1771457fdffce4550b5597435f030483dcafffecf714Amith Yamasani boolean voiceOnPrimary = voiceMode.equals(getString(R.string.voice_mode_main)); 1772b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani if (mKeyboardSwitcher != null && 1773b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani (enableVoice != mEnableVoice || voiceOnPrimary != mVoiceOnPrimary)) { 1774b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani mKeyboardSwitcher.setVoiceMode(enableVoice, voiceOnPrimary); 1775466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1776466741d8a78965b8509bf527344f289e50873092Mike LeBeau mEnableVoice = enableVoice; 1777b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani mVoiceOnPrimary = voiceOnPrimary; 1778466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1779e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mAutoCorrectEnabled = sp.getBoolean(PREF_AUTO_COMPLETE, 178036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mResources.getBoolean(R.bool.enable_autocorrect)) & mShowSuggestions; 1781e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani updateCorrectionMode(); 17823f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani mLanguageSwitcher.loadLocales(sp); 178336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 178436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 17856a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani private void initSuggestPuncList() { 17866a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani mSuggestPuncList = new ArrayList<CharSequence>(); 17876a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani String suggestPuncs = mResources.getString(R.string.suggested_punctuations); 17886a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani if (suggestPuncs != null) { 17896a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani for (int i = 0; i < suggestPuncs.length(); i++) { 17906a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani mSuggestPuncList.add(suggestPuncs.subSequence(i, i + 1)); 17916a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 17926a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 17936a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 17946a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 1795923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void showOptionsMenu() { 1796923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project AlertDialog.Builder builder = new AlertDialog.Builder(this); 1797923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project builder.setCancelable(true); 1798923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project builder.setIcon(R.drawable.ic_dialog_keyboard); 1799923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project builder.setNegativeButton(android.R.string.cancel, null); 1800923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence itemSettings = getString(R.string.english_ime_settings); 1801466741d8a78965b8509bf527344f289e50873092Mike LeBeau CharSequence itemInputMethod = getString(R.string.inputMethod); 1802923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project builder.setItems(new CharSequence[] { 1803923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project itemSettings, itemInputMethod}, 1804923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project new DialogInterface.OnClickListener() { 1805923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1806923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onClick(DialogInterface di, int position) { 1807923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project di.dismiss(); 1808923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (position) { 1809923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case POS_SETTINGS: 1810923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project launchSettings(); 1811923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 1812923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project case POS_METHOD: 181371351469e3af45a2ee89b017089f9e850e973a19Brandon Ballinger ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)) 181471351469e3af45a2ee89b017089f9e850e973a19Brandon Ballinger .showInputMethodPicker(); 1815923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 1816923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1817923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1818923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project }); 181936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani builder.setTitle(mResources.getString(R.string.english_ime_name)); 1820923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mOptionsDialog = builder.create(); 1821923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Window window = mOptionsDialog.getWindow(); 1822923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project WindowManager.LayoutParams lp = window.getAttributes(); 1823923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project lp.token = mInputView.getWindowToken(); 1824923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 1825923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project window.setAttributes(lp); 1826923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 1827923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mOptionsDialog.show(); 1828923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1829923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1830923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void changeKeyboardMode() { 1831923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mKeyboardSwitcher.toggleSymbols(); 1832923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mCapsLock && mKeyboardSwitcher.isAlphabetMode()) { 1833923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ((LatinKeyboard) mInputView.getKeyboard()).setShiftLocked(mCapsLock); 1834923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1835923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1836923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateShiftKeyState(getCurrentInputEditorInfo()); 1837923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 183836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 1839923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { 1840923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.dump(fd, fout, args); 1841a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1842923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final Printer p = new PrintWriterPrinter(fout); 1843923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println("LatinIME state :"); 1844923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" Keyboard mode = " + mKeyboardSwitcher.getKeyboardMode()); 1845923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mCapsLock=" + mCapsLock); 1846923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mComposing=" + mComposing.toString()); 1847923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mPredictionOn=" + mPredictionOn); 1848923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mCorrectionMode=" + mCorrectionMode); 1849923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mPredicting=" + mPredicting); 1850923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mAutoCorrectOn=" + mAutoCorrectOn); 1851923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mAutoSpace=" + mAutoSpace); 1852923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mCompletionOn=" + mCompletionOn); 1853923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" TextEntryState.state=" + TextEntryState.getState()); 1854923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mSoundOn=" + mSoundOn); 1855923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mVibrateOn=" + mVibrateOn); 1856923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 18576e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani 1858923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Characters per second measurement 1859a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1860923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final boolean PERF_DEBUG = false; 1861923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long mLastCpsTime; 1862923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int CPS_BUFFER_SIZE = 16; 1863923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long[] mCpsIntervals = new long[CPS_BUFFER_SIZE]; 1864923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mCpsIndex; 1865e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private boolean mInputTypeNoAutoCorrect; 1866a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1867923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void measureCps() { 1868923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (!LatinIME.PERF_DEBUG) return; 1869923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long now = System.currentTimeMillis(); 1870923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mLastCpsTime == 0) mLastCpsTime = now - 100; // Initial 1871923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCpsIntervals[mCpsIndex] = now - mLastCpsTime; 1872923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mLastCpsTime = now; 1873923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCpsIndex = (mCpsIndex + 1) % CPS_BUFFER_SIZE; 1874923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long total = 0; 1875923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project for (int i = 0; i < CPS_BUFFER_SIZE; i++) total += mCpsIntervals[i]; 1876923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project System.out.println("CPS = " + ((CPS_BUFFER_SIZE * 1000f) / total)); 1877923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 187834386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani 187934386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani class AutoDictionary extends ExpandableDictionary { 1880d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani // If the user touches a typed word 2 times or more, it will become valid. 1881d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani private static final int VALIDITY_THRESHOLD = 2 * FREQUENCY_FOR_PICKED; 1882d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani // If the user touches a typed word 5 times or more, it will be added to the user dict. 18836a442663d600fa1d8cc0b7a77f313b0a13a4b809Amith Yamasani private static final int PROMOTION_THRESHOLD = 4 * FREQUENCY_FOR_PICKED; 188434386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani 188534386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani public AutoDictionary(Context context) { 188634386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani super(context); 188734386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani } 188834386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani 188934386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani @Override 189034386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani public boolean isValidWord(CharSequence word) { 189134386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani final int frequency = getWordFrequency(word); 18926a442663d600fa1d8cc0b7a77f313b0a13a4b809Amith Yamasani return frequency >= VALIDITY_THRESHOLD; 189334386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani } 189434386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani 189534386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani @Override 1896d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani public void addWord(String word, int addFrequency) { 189781115075d28e7df6b43fd2252b83211ba2a827deAmith Yamasani final int length = word.length(); 189881115075d28e7df6b43fd2252b83211ba2a827deAmith Yamasani // Don't add very short or very long words. 189981115075d28e7df6b43fd2252b83211ba2a827deAmith Yamasani if (length < 2 || length > getMaxWordLength()) return; 19001c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani if (mWord.isAutoCapitalized()) { 19011c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani // Remove caps before adding 19021c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani word = Character.toLowerCase(word.charAt(0)) 19031c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani + word.substring(1); 19041c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 19056a442663d600fa1d8cc0b7a77f313b0a13a4b809Amith Yamasani int freq = getWordFrequency(word); 19066a442663d600fa1d8cc0b7a77f313b0a13a4b809Amith Yamasani freq = freq < 0 ? addFrequency : freq + addFrequency; 19076a442663d600fa1d8cc0b7a77f313b0a13a4b809Amith Yamasani super.addWord(word, freq); 19086a442663d600fa1d8cc0b7a77f313b0a13a4b809Amith Yamasani if (freq >= PROMOTION_THRESHOLD) { 1909d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani LatinIME.this.promoteToUserDictionary(word, FREQUENCY_FOR_AUTO_ADD); 191034386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani } 191134386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani } 191234386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani } 1913923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 1914