LatinIME.java revision 728115493e14f84d5f02a4812c8086a378813364
1923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/* 2443c360d0afdbab091994244f045f4756feaf2b4Jean-Baptiste Queru * Copyright (C) 2008 The Android Open Source Project 3c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * 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 195a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokaimport com.android.inputmethod.keyboard.Keyboard; 205a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardActionListener; 215a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardId; 22571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardSwitcher; 235a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardView; 24de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaokaimport com.android.inputmethod.keyboard.LatinKeyboard; 255a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokaimport com.android.inputmethod.keyboard.LatinKeyboardView; 269502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaokaimport com.android.inputmethod.latin.Utils.RingCharBuffer; 27409220583333bdf06290dd9fd42f91b5c0d1b11asatokimport com.android.inputmethod.voice.VoiceIMEConnector; 28388ce92ab8a635c5ad44620dad59baf05dfea510Amith Yamasani 29923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.app.AlertDialog; 30923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.BroadcastReceiver; 31923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Context; 32923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.DialogInterface; 33923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Intent; 34923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.IntentFilter; 35923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.SharedPreferences; 36923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.res.Configuration; 3736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasaniimport android.content.res.Resources; 38923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.inputmethodservice.InputMethodService; 39923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.media.AudioManager; 40123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaokaimport android.net.ConnectivityManager; 41923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Debug; 42923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Handler; 43923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Message; 44923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.SystemClock; 454174655e23734563775acb9e1e644b31b9e72fa5Ken Wakasaimport android.os.Vibrator; 46bf96661d33d0126adb60a48880ceba1ff055d4a4satokimport android.preference.PreferenceActivity; 47923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.preference.PreferenceManager; 48e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaokaimport android.text.InputType; 49923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.text.TextUtils; 50979f8690967ff5409fe18f5085858ccdb8e0ccf1satokimport android.util.DisplayMetrics; 51923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Log; 52923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.PrintWriterPrinter; 53923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Printer; 54e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaokaimport android.view.Gravity; 5566a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasaniimport android.view.HapticFeedbackConstants; 56923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.KeyEvent; 57e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaokaimport android.view.LayoutInflater; 58923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.View; 598e09172df1bb176cc899940862c56bed9b9aec4esatokimport android.view.ViewGroup; 608e09172df1bb176cc899940862c56bed9b9aec4esatokimport android.view.ViewParent; 61923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.Window; 62923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.WindowManager; 63923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.CompletionInfo; 641b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaokaimport android.view.inputmethod.CorrectionInfo; 65923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.EditorInfo; 66466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport android.view.inputmethod.ExtractedText; 67466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport android.view.inputmethod.ExtractedTextRequest; 68923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.InputConnection; 69923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.InputMethodManager; 700ed7191b4d1013a0b9d2fd1f26733dee7364871dsatokimport android.view.inputmethod.InputMethodSubtype; 719e347d3d448e48229c46aad394ec9bd60cd5807bsatokimport android.widget.FrameLayout; 72e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaokaimport android.widget.HorizontalScrollView; 7340ac45ebdcd71940394dda00371d4847f7db0f26Ken Wakasaimport android.widget.LinearLayout; 74923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 75466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.FileDescriptor; 76466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.PrintWriter; 77466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.util.ArrayList; 78b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimodaimport java.util.Arrays; 79466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.util.Locale; 80466741d8a78965b8509bf527344f289e50873092Mike LeBeau 81923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/** 82923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Input method implementation for Qwerty'ish keyboard. 83923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 8455b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaokapublic class LatinIME extends InputMethodService implements KeyboardActionListener, 85e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka SharedPreferences.OnSharedPreferenceChangeListener { 86466741d8a78965b8509bf527344f289e50873092Mike LeBeau private static final String TAG = "LatinIME"; 87979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private static final boolean PERF_DEBUG = false; 88409220583333bdf06290dd9fd42f91b5c0d1b11asatok private static final boolean TRACE = false; 89910b73127fa207dd26ec8124000262523b0aac0csatok private static boolean DEBUG = LatinImeLogger.sDBG; 90a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 91fd0bd57deb53c4cce32810a61133fa44b45dbb7bKen Wakasa private static final int DELAY_UPDATE_SUGGESTIONS = 180; 92fd0bd57deb53c4cce32810a61133fa44b45dbb7bKen Wakasa private static final int DELAY_UPDATE_OLD_SUGGESTIONS = 300; 93d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int DELAY_UPDATE_SHIFT_STATE = 300; 949e347d3d448e48229c46aad394ec9bd60cd5807bsatok private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100; 95fd0bd57deb53c4cce32810a61133fa44b45dbb7bKen Wakasa 96923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // How many continuous deletes at which to start deleting at a higher speed. 97923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int DELETE_ACCELERATE_AT = 20; 98923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Key events coming any faster than this are long-presses. 99d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani private static final int QUICK_PRESS = 200; 100a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1017599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private int mSuggestionVisibility; 1027599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_SHOW_VALUE 1037599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_show_value; 1047599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE 1057599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_show_only_portrait_value; 1067599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_HIDE_VALUE 1077599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_hide_value; 1087599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 1097599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int[] SUGGESTION_VISIBILITY_VALUE_ARRAY = new int[] { 1107599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_SHOW_VALUE, 1117599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE, 1127599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_HIDE_VALUE 1137599cfea4a2d56f4779452ec8e8742f7b9629cc0satok }; 1147599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 115e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka private View mCandidateViewContainer; 116923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private CandidateView mCandidateView; 117923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private Suggest mSuggest; 1181b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka private CompletionInfo[] mApplicationSpecifiedCompletions; 119a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 120923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private AlertDialog mOptionsDialog; 121a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 12279efbed76f638be298493107fa2d0cd1b5eb529esatok private InputMethodManager mImm; 1232fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private Resources mResources; 1242fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private SharedPreferences mPrefs; 1252fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private String mInputMethodId; 12671c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka private KeyboardSwitcher mKeyboardSwitcher; 1270ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private SubtypeSwitcher mSubtypeSwitcher; 128409220583333bdf06290dd9fd42f91b5c0d1b11asatok private VoiceIMEConnector mVoiceConnector; 129a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 130923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private UserDictionary mUserDictionary; 131979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private UserBigramDictionary mUserBigramDictionary; 1322bed1531c2c9bd48096bfa97dd1a39e04bd15e7bEric Fischer private ContactsDictionary mContactsDictionary; 1334ff60be170872503cca0275ef3488b7379b5311bAmith Yamasani private AutoDictionary mAutoDictionary; 13436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 135c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // These variables are initialized according to the {@link EditorInfo#inputType}. 136c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mAutoSpace; 137c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mInputTypeNoAutoCorrect; 138c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mIsSettingsSuggestionStripOn; 139c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mApplicationSpecifiedCompletionOn; 140c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 14171c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka private final StringBuilder mComposing = new StringBuilder(); 142923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private WordComposer mWord = new WordComposer(); 143923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private CharSequence mBestWord; 1449fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka private boolean mHasValidSuggestions; 145e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private boolean mHasDictionary; 1469a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa private boolean mJustAddedAutoSpace; 147e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private boolean mAutoCorrectEnabled; 14866b42a1c2d38813be104a7f0435ec6e6ec1c6e65satok private boolean mReCorrectionEnabled; 149979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private boolean mBigramSuggestionEnabled; 150923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mAutoCorrectOn; 151923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mVibrateOn; 152923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mSoundOn; 153979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private boolean mPopupOn; 154923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mAutoCap; 1556e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani private boolean mQuickFixes; 1562fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private boolean mConfigEnableShowSubtypeSettings; 157363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka private boolean mConfigSwipeDownDismissKeyboardEnabled; 158de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka private int mConfigDelayBeforeFadeoutLanguageOnSpacebar; 159de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka private int mConfigDurationOfFadeoutLanguageOnSpacebar; 160d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka private float mConfigFinalFadeoutFactorOfLanguageOnSpacebar; 161409220583333bdf06290dd9fd42f91b5c0d1b11asatok 16279efbed76f638be298493107fa2d0cd1b5eb529esatok private int mCorrectionMode; 16379efbed76f638be298493107fa2d0cd1b5eb529esatok private int mCommittedLength; 16479efbed76f638be298493107fa2d0cd1b5eb529esatok private int mOrientation; 165979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Keep track of the last selection range to decide if we need to show word alternatives 16679efbed76f638be298493107fa2d0cd1b5eb529esatok private int mLastSelectionStart; 16779efbed76f638be298493107fa2d0cd1b5eb529esatok private int mLastSelectionEnd; 1687e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka private SuggestedWords mSuggestPuncList; 169979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 170923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Indicates whether the suggestion strip is to be on in landscape 171923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mJustAccepted; 172c1e2e827b5d1bba59eb99d322dc101657ec28768Ken Wakasa private boolean mJustReverted; 173923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mDeleteCount; 174923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long mLastKeyTime; 175a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 176923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private AudioManager mAudioManager; 1772296317b8f0209789f797ac8a2fcb70e03f6d001Eric Laurent // Align sound effect volume on music volume 17871c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka private static final float FX_VOLUME = -1.0f; 179923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mSilentMode; 180923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 181979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /* package */ String mWordSeparators; 182923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private String mSentenceSeparators; 183979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private String mSuggestPuncs; 184409220583333bdf06290dd9fd42f91b5c0d1b11asatok // TODO: Move this flag to VoiceIMEConnector 18581c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani private boolean mConfigurationChanging; 186466741d8a78965b8509bf527344f289e50873092Mike LeBeau 187dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani // Keeps track of most recently inserted text (multi-character key) for reverting 188dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani private CharSequence mEnteredText; 189979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private boolean mRefreshKeyboardRequired; 190dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 19171c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka private final ArrayList<WordAlternatives> mWordHistory = new ArrayList<WordAlternatives>(); 192979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 193979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public abstract static class WordAlternatives { 194979f8690967ff5409fe18f5085858ccdb8e0ccf1satok protected CharSequence mChosenWord; 1954f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 196979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public WordAlternatives() { 197979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Nothing 198979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 199979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 200979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public WordAlternatives(CharSequence chosenWord) { 201979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mChosenWord = chosenWord; 202979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 203979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 204979f8690967ff5409fe18f5085858ccdb8e0ccf1satok @Override 205979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public int hashCode() { 206979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return mChosenWord.hashCode(); 207979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 208979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 209979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public abstract CharSequence getOriginalWord(); 210979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 211979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public CharSequence getChosenWord() { 212979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return mChosenWord; 213979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 214979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2157e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka public abstract SuggestedWords.Builder getAlternatives(); 216979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 217979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 218979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public class TypedWordAlternatives extends WordAlternatives { 219979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private WordComposer word; 220979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 221979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public TypedWordAlternatives() { 222979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Nothing 223979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 224979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 225979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public TypedWordAlternatives(CharSequence chosenWord, WordComposer wordComposer) { 226979f8690967ff5409fe18f5085858ccdb8e0ccf1satok super(chosenWord); 227979f8690967ff5409fe18f5085858ccdb8e0ccf1satok word = wordComposer; 228979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 229979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 230979f8690967ff5409fe18f5085858ccdb8e0ccf1satok @Override 231979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public CharSequence getOriginalWord() { 232979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return word.getTypedWord(); 233979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 234979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 235979f8690967ff5409fe18f5085858ccdb8e0ccf1satok @Override 2367e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka public SuggestedWords.Builder getAlternatives() { 237979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return getTypedSuggestions(word); 238979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 239979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 24036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 241571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka public final UIHandler mHandler = new UIHandler(); 242d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 243409220583333bdf06290dd9fd42f91b5c0d1b11asatok public class UIHandler extends Handler { 244d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_UPDATE_SUGGESTIONS = 0; 245d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_UPDATE_OLD_SUGGESTIONS = 1; 246d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_UPDATE_SHIFT_STATE = 2; 247d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_VOICE_RESULTS = 3; 248de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka private static final int MSG_FADEOUT_LANGUAGE_ON_SPACEBAR = 4; 249de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 5; 250d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 251923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 252923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void handleMessage(Message msg) { 253de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 254de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka final LatinKeyboardView inputView = switcher.getInputView(); 255923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (msg.what) { 256d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SUGGESTIONS: 257d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka updateSuggestions(); 258d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 259d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_OLD_SUGGESTIONS: 260d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka setOldSuggestions(); 261d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 262d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SHIFT_STATE: 263de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka switcher.updateShiftState(); 264d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 265d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_VOICE_RESULTS: 266e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mVoiceConnector.handleVoiceResults(preferCapitalization() 267de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka || (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked())); 268de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka break; 269de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka case MSG_FADEOUT_LANGUAGE_ON_SPACEBAR: 270de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka if (inputView != null) 27166432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka inputView.setSpacebarTextFadeFactor( 272d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka (1.0f + mConfigFinalFadeoutFactorOfLanguageOnSpacebar) / 2, 27366432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka (LatinKeyboard)msg.obj); 274de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_DISMISS_LANGUAGE_ON_SPACEBAR, msg.obj), 275de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka mConfigDurationOfFadeoutLanguageOnSpacebar); 276de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka break; 277de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka case MSG_DISMISS_LANGUAGE_ON_SPACEBAR: 278de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka if (inputView != null) 27966432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka inputView.setSpacebarTextFadeFactor( 280d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka mConfigFinalFadeoutFactorOfLanguageOnSpacebar, (LatinKeyboard)msg.obj); 281d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 282923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 283923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 284d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 285d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateSuggestions() { 286d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 287d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTIONS), DELAY_UPDATE_SUGGESTIONS); 288d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 289d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 290d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateSuggestions() { 291d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 292d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 293d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 294d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public boolean hasPendingUpdateSuggestions() { 295d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka return hasMessages(MSG_UPDATE_SUGGESTIONS); 296d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 297d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 298d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateOldSuggestions() { 299d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_OLD_SUGGESTIONS); 300d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_UPDATE_OLD_SUGGESTIONS), 301d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka DELAY_UPDATE_OLD_SUGGESTIONS); 302d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 303d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 304d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateOldSuggestions() { 305d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_OLD_SUGGESTIONS); 306d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 307d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 308d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateShiftKeyState() { 309d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 310d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_UPDATE_SHIFT_STATE), DELAY_UPDATE_SHIFT_STATE); 311d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 312d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 313d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateShiftState() { 314d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 315d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 316d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 317d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void updateVoiceResults() { 318d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka sendMessage(obtainMessage(MSG_VOICE_RESULTS)); 319d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 320de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka 321d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka public void startDisplayLanguageOnSpacebar(boolean localeChanged) { 322de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka removeMessages(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR); 323de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka removeMessages(MSG_DISMISS_LANGUAGE_ON_SPACEBAR); 324de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka final LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); 325de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka if (inputView != null) { 326de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka final LatinKeyboard keyboard = inputView.getLatinKeyboard(); 327de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka // The language is never displayed when the delay is zero. 328de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka if (mConfigDelayBeforeFadeoutLanguageOnSpacebar != 0) 329d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka inputView.setSpacebarTextFadeFactor(localeChanged ? 1.0f 330d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka : mConfigFinalFadeoutFactorOfLanguageOnSpacebar, keyboard); 331de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka // The language is always displayed when the delay is negative. 332d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka if (localeChanged && mConfigDelayBeforeFadeoutLanguageOnSpacebar > 0) { 333de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR, keyboard), 334de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka mConfigDelayBeforeFadeoutLanguageOnSpacebar); 335de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 336de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 337de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 338d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 339923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 3407e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 3417e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka public void onCreate() { 34227d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 34327d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa mPrefs = prefs; 34427d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa LatinImeLogger.init(this, prefs); 34527d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa SubtypeSwitcher.init(this, prefs); 34627d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa KeyboardSwitcher.init(this, prefs); 347363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 348923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onCreate(); 349363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 35079efbed76f638be298493107fa2d0cd1b5eb529esatok mImm = ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)); 3512fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka mInputMethodId = Utils.getInputMethodId(mImm, getApplicationInfo().packageName); 3520ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mSubtypeSwitcher = SubtypeSwitcher.getInstance(); 3530ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mKeyboardSwitcher = KeyboardSwitcher.getInstance(); 354363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 355363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka final Resources res = getResources(); 356363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka mResources = res; 357fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard 358fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard // If the option should not be shown, do not read the recorrection preference 359fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard // but always use the default setting defined in the resources. 360fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard if (res.getBoolean(R.bool.config_enable_show_recorrection_option)) { 361fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard mReCorrectionEnabled = prefs.getBoolean(Settings.PREF_RECORRECTION_ENABLED, 362fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard res.getBoolean(R.bool.default_recorrection_enabled)); 363fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard } else { 364fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard mReCorrectionEnabled = res.getBoolean(R.bool.default_recorrection_enabled); 365fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard } 366fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard 3672fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka mConfigEnableShowSubtypeSettings = res.getBoolean( 3682fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka R.bool.config_enable_show_subtype_settings); 369363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka mConfigSwipeDownDismissKeyboardEnabled = res.getBoolean( 370363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka R.bool.config_swipe_down_dismiss_keyboard_enabled); 371de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka mConfigDelayBeforeFadeoutLanguageOnSpacebar = res.getInteger( 372de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka R.integer.config_delay_before_fadeout_language_on_spacebar); 373de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka mConfigDurationOfFadeoutLanguageOnSpacebar = res.getInteger( 374de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka R.integer.config_duration_of_fadeout_language_on_spacebar); 375d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka mConfigFinalFadeoutFactorOfLanguageOnSpacebar = res.getInteger( 37666432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka R.integer.config_final_fadeout_percentage_of_language_on_spacebar) / 100.0f; 377979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 3789502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka Utils.GCUtils.getInstance().reset(); 379979f8690967ff5409fe18f5085858ccdb8e0ccf1satok boolean tryGC = true; 3809502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { 381979f8690967ff5409fe18f5085858ccdb8e0ccf1satok try { 3820ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 383979f8690967ff5409fe18f5085858ccdb8e0ccf1satok tryGC = false; 384979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } catch (OutOfMemoryError e) { 3859502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka tryGC = Utils.GCUtils.getInstance().tryGCOrWait("InitSuggest", e); 386979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 387979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 388979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 389363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka mOrientation = res.getConfiguration().orientation; 3906a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani initSuggestPuncList(); 391b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 392123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka // register to receive ringer mode change and network state change. 393123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final IntentFilter filter = new IntentFilter(); 394123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); 395123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 396923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project registerReceiver(mReceiver, filter); 39727d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa mVoiceConnector = VoiceIMEConnector.init(this, prefs, mHandler); 3983f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani prefs.registerOnSharedPreferenceChangeListener(this); 399923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 40036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 401979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 402458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa * Returns a main dictionary resource id 403458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa * @return main dictionary resource id 404979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 405458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa public static int getMainDictionaryResourceId(Resources res) { 406458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa final String MAIN_DIC_NAME = "main"; 407979f8690967ff5409fe18f5085858ccdb8e0ccf1satok String packageName = LatinIME.class.getPackage().getName(); 408458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa return res.getIdentifier(MAIN_DIC_NAME, "raw", packageName); 409979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 410979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 4110ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private void initSuggest() { 4120ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok updateAutoTextEnabled(); 4134ab730dbd34fad323063f2ffd31ce33de746668dsatok String locale = mSubtypeSwitcher.getInputLocaleStr(); 41436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 4150ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok Locale savedLocale = mSubtypeSwitcher.changeSystemLocale(new Locale(locale)); 41636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani if (mSuggest != null) { 41736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mSuggest.close(); 41836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 41927d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa final SharedPreferences prefs = mPrefs; 42089764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard mQuickFixes = isQuickFixesEnabled(prefs); 421979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 422458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa final Resources res = mResources; 423458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa int mainDicResId = getMainDictionaryResourceId(res); 424458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa mSuggest = new Suggest(this, mainDicResId); 4251b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka loadAndSetAutoCorrectionThreshold(prefs); 426e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 4270ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mUserDictionary = new UserDictionary(this, locale); 428923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mSuggest.setUserDictionary(mUserDictionary); 429e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 430e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mContactsDictionary = new ContactsDictionary(this, Suggest.DIC_CONTACTS); 4312bed1531c2c9bd48096bfa97dd1a39e04bd15e7bEric Fischer mSuggest.setContactsDictionary(mContactsDictionary); 432e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 433e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mAutoDictionary = new AutoDictionary(this, this, locale, Suggest.DIC_AUTO); 43434386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani mSuggest.setAutoDictionary(mAutoDictionary); 435e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 436e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mUserBigramDictionary = new UserBigramDictionary(this, this, locale, Suggest.DIC_USER); 437e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest.setUserBigramDictionary(mUserBigramDictionary); 438e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 439e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani updateCorrectionMode(); 440458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa mWordSeparators = res.getString(R.string.word_separators); 441458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa mSentenceSeparators = res.getString(R.string.sentence_separators); 44236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 4430ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mSubtypeSwitcher.changeSystemLocale(savedLocale); 444923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 44536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 446466741d8a78965b8509bf527344f289e50873092Mike LeBeau @Override 447466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onDestroy() { 448e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa if (mSuggest != null) { 449e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest.close(); 450e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest = null; 451979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 452923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project unregisterReceiver(mReceiver); 453409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.destroy(); 454979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 455979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.onDestroy(); 456923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onDestroy(); 457923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 458923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 459923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 460923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onConfigurationChanged(Configuration conf) { 461dc64b138b5e3fb3706c0818d0a308fe6e36985b0Tadashi G. Takaoka mSubtypeSwitcher.onConfigurationChanged(conf); 462b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani // If orientation changed while predicting, commit the change 463b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani if (conf.orientation != mOrientation) { 464466741d8a78965b8509bf527344f289e50873092Mike LeBeau InputConnection ic = getCurrentInputConnection(); 465466741d8a78965b8509bf527344f289e50873092Mike LeBeau commitTyped(ic); 466466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (ic != null) ic.finishComposingText(); // For voice input 467b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani mOrientation = conf.orientation; 4682fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka if (isShowingOptionDialog()) 4692fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka mOptionsDialog.dismiss(); 470b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 4718b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka 47281c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani mConfigurationChanging = true; 473923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onConfigurationChanged(conf); 474bbd651a00898dabf6b2ae0e715d99953ea81063fLuca Zanolin mVoiceConnector.onConfigurationChanged(conf); 47581c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani mConfigurationChanging = false; 476923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 477b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 478923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 479923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public View onCreateInputView() { 4808d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka return mKeyboardSwitcher.onCreateInputView(); 481923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 482923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 483923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 484923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public View onCreateCandidatesView() { 485e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka LayoutInflater inflater = getLayoutInflater(); 486e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka LinearLayout container = (LinearLayout)inflater.inflate(R.layout.candidates, null); 487e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka mCandidateViewContainer = container; 488e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka if (container.getPaddingRight() != 0) { 489e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka HorizontalScrollView scrollView = 490e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka (HorizontalScrollView) container.findViewById(R.id.candidates_scroll_view); 491e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka scrollView.setOverScrollMode(View.OVER_SCROLL_NEVER); 492e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka container.setGravity(Gravity.CENTER_HORIZONTAL); 493e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka } 494e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka mCandidateView = (CandidateView) container.findViewById(R.id.candidates); 495923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCandidateView.setService(this); 496923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project setCandidatesViewShown(true); 497e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka return container; 498923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 499923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 50047f795dc8709f95b35888fbcca80c0c18dbe63edLeon Scroggins private static boolean isPasswordVariation(int variation) { 501e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka return variation == InputType.TYPE_TEXT_VARIATION_PASSWORD 502e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka || variation == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD 503e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka || variation == InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD; 50447f795dc8709f95b35888fbcca80c0c18dbe63edLeon Scroggins } 50547f795dc8709f95b35888fbcca80c0c18dbe63edLeon Scroggins 50647f795dc8709f95b35888fbcca80c0c18dbe63edLeon Scroggins private static boolean isEmailVariation(int variation) { 507e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka return variation == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS 508e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka || variation == InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS; 50947f795dc8709f95b35888fbcca80c0c18dbe63edLeon Scroggins } 51047f795dc8709f95b35888fbcca80c0c18dbe63edLeon Scroggins 511a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker @Override 512923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onStartInputView(EditorInfo attribute, boolean restarting) { 51345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 51445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka LatinKeyboardView inputView = switcher.getInputView(); 5158e09172df1bb176cc899940862c56bed9b9aec4esatok 516910b73127fa207dd26ec8124000262523b0aac0csatok if(DEBUG) { 517910b73127fa207dd26ec8124000262523b0aac0csatok Log.d(TAG, "onStartInputView: " + inputView); 518910b73127fa207dd26ec8124000262523b0aac0csatok } 519923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In landscape mode, this method gets called without the input view being created. 520979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (inputView == null) { 521923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 522923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 523923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 5248d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka mSubtypeSwitcher.updateParametersOnStartInputView(); 5254ab730dbd34fad323063f2ffd31ce33de746668dsatok 52636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani if (mRefreshKeyboardRequired) { 52736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mRefreshKeyboardRequired = false; 528c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka onRefreshKeyboard(); 52936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 53036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 531923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.newSession(this); 5326c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani 533c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // Most such things we decide below in initializeInputAttributesAndGetMode, but we need to 534c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // know now whether this is a password text field, because we need to know now whether we 535c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // want to enable the voice button. 536c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mVoiceConnector.resetVoiceStates(isPasswordVariation( 537c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka attribute.inputType & InputType.TYPE_MASK_VARIATION)); 538c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 539c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka final int mode = initializeInputAttributesAndGetMode(attribute.inputType); 540c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 541c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.closing(); 542c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mEnteredText = null; 543c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mComposing.setLength(0); 544c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mHasValidSuggestions = false; 545c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mDeleteCount = 0; 546c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mJustAddedAutoSpace = false; 547c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 548c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka loadSettings(attribute); 549c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if (mSubtypeSwitcher.isKeyboardMode()) { 550c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka switcher.loadKeyboard(mode, attribute.imeOptions, 551c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mVoiceConnector.isVoiceButtonEnabled(), 552c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mVoiceConnector.isVoiceButtonOnPrimary()); 553c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka switcher.updateShiftState(); 554c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka } 555c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 556c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka setCandidatesViewShownInternal(isCandidateStripVisible(), 557c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka false /* needsInputViewShown */ ); 558c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // Delay updating suggestions because keyboard input view may not be shown at this point. 559c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mHandler.postUpdateSuggestions(); 560c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 561c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka updateCorrectionMode(); 562c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 563c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.setPreviewEnabled(mPopupOn); 564c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.setProximityCorrectionEnabled(true); 565c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // If we just entered a text field, maybe it has some old text that requires correction 566c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka checkReCorrectionOnStart(); 567c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.setForeground(true); 568c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 569c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mVoiceConnector.onStartInputView(inputView.getWindowToken()); 570c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 571c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); 572c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka } 573c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 574c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private int initializeInputAttributesAndGetMode(int inputType) { 575c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka final int variation = inputType & InputType.TYPE_MASK_VARIATION; 576c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mAutoSpace = false; 577e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mInputTypeNoAutoCorrect = false; 5789fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 5791b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletionOn = false; 5801b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletions = null; 581dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 582f8e30a91537b8b4920887d0d4f0771de3a23c4cbTadashi G. Takaoka final int mode; 583c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka switch (inputType & InputType.TYPE_MASK_CLASS) { 584e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case InputType.TYPE_CLASS_NUMBER: 585e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case InputType.TYPE_CLASS_DATETIME: 5865a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka mode = KeyboardId.MODE_NUMBER; 5872c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka break; 588e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case InputType.TYPE_CLASS_PHONE: 5895a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka mode = KeyboardId.MODE_PHONE; 590923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 591e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case InputType.TYPE_CLASS_TEXT: 5929fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mIsSettingsSuggestionStripOn = true; 593923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Make sure that passwords are not displayed in candidate view 59447f795dc8709f95b35888fbcca80c0c18dbe63edLeon Scroggins if (isPasswordVariation(variation)) { 5959fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 596923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 59747f795dc8709f95b35888fbcca80c0c18dbe63edLeon Scroggins if (isEmailVariation(variation) 598e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka || variation == InputType.TYPE_TEXT_VARIATION_PERSON_NAME) { 599923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAutoSpace = false; 600923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 601923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAutoSpace = true; 602923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 60347f795dc8709f95b35888fbcca80c0c18dbe63edLeon Scroggins if (isEmailVariation(variation)) { 6049fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 6055a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka mode = KeyboardId.MODE_EMAIL; 606e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) { 6079fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 6085a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka mode = KeyboardId.MODE_URL; 609e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } else if (variation == InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE) { 6105a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka mode = KeyboardId.MODE_IM; 611e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) { 6129fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 6135a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka mode = KeyboardId.MODE_TEXT; 614e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } else if (variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) { 6155a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka mode = KeyboardId.MODE_WEB; 6166c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani // If it's a browser edit field and auto correct is not ON explicitly, then 6176c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani // disable auto correction, but keep suggestions on. 618c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) { 619e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mInputTypeNoAutoCorrect = true; 6206c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani } 621f8e30a91537b8b4920887d0d4f0771de3a23c4cbTadashi G. Takaoka } else { 6225a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka mode = KeyboardId.MODE_TEXT; 623923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 62436ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani 62536ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani // If NO_SUGGESTIONS is set, don't do prediction. 626c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) { 6279fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 628e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mInputTypeNoAutoCorrect = true; 62936ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani } 63036ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani // If it's not multiline and the autoCorrect flag is not set, then don't correct 631c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 && 632c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) == 0) { 633e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mInputTypeNoAutoCorrect = true; 63436ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani } 635c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { 6369fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 6371b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletionOn = isFullscreenMode(); 638923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 639923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 640923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project default: 6415a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka mode = KeyboardId.MODE_TEXT; 642f8e30a91537b8b4920887d0d4f0771de3a23c4cbTadashi G. Takaoka break; 643923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 644c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka return mode; 645923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 646923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 647b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani private void checkReCorrectionOnStart() { 648d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa if (!mReCorrectionEnabled) return; 649d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa 650d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 651d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa if (ic == null) return; 652d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa // There could be a pending composing span. Clean it up first. 653d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa ic.finishComposingText(); 654d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa 6559fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (isShowingSuggestionsStrip() && isSuggestionsRequested()) { 656b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani // First get the cursor position. This is required by setOldSuggestions(), so that 657b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani // it can pass the correct range to setComposingRegion(). At this point, we don't 6584ca16dbd65150359c3884da7cb59a30f19abd4b7Tadashi G. Takaoka // have valid values for mLastSelectionStart/End because onUpdateSelection() has 659b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani // not been called yet. 660b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani ExtractedTextRequest etr = new ExtractedTextRequest(); 661b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani etr.token = 0; // anything is fine here 662b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani ExtractedText et = ic.getExtractedText(etr, 0); 663b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani if (et == null) return; 664b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani 665b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani mLastSelectionStart = et.startOffset + et.selectionStart; 666b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani mLastSelectionEnd = et.startOffset + et.selectionEnd; 667b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani 668b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani // Then look for possible corrections in a delayed fashion 66955b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa if (!TextUtils.isEmpty(et.text) && isCursorTouchingWord()) { 670d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateOldSuggestions(); 67155b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa } 672b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani } 673b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani } 674b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani 675923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 676923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onFinishInput() { 677923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onFinishInput(); 678a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 679979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 6801b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mKeyboardSwitcher.onAutoCorrectionStateChanged(false); 681979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 682409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.flushVoiceInputLogs(mConfigurationChanging); 683409220583333bdf06290dd9fd42f91b5c0d1b11asatok 6845a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getInputView(); 685d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa if (inputView != null) inputView.closing(); 6864ff60be170872503cca0275ef3488b7379b5311bAmith Yamasani if (mAutoDictionary != null) mAutoDictionary.flushPendingWrites(); 687979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mUserBigramDictionary != null) mUserBigramDictionary.flushPendingWrites(); 688466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 689466741d8a78965b8509bf527344f289e50873092Mike LeBeau 690466741d8a78965b8509bf527344f289e50873092Mike LeBeau @Override 6916495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa public void onFinishInputView(boolean finishingInput) { 6926495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa super.onFinishInputView(finishingInput); 6935a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getInputView(); 694d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa if (inputView != null) inputView.setForeground(false); 695d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka // Remove pending messages related to update suggestions 696d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 697d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateOldSuggestions(); 6986495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa } 6996495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa 7006495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa @Override 701466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onUpdateExtractedText(int token, ExtractedText text) { 702466741d8a78965b8509bf527344f289e50873092Mike LeBeau super.onUpdateExtractedText(token, text); 703409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.showPunctuationHintIfNecessary(); 704923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 705923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 706923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 707923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onUpdateSelection(int oldSelStart, int oldSelEnd, 708923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int newSelStart, int newSelEnd, 709923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int candidatesStart, int candidatesEnd) { 710923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, 711923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project candidatesStart, candidatesEnd); 712466741d8a78965b8509bf527344f289e50873092Mike LeBeau 713466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (DEBUG) { 714466741d8a78965b8509bf527344f289e50873092Mike LeBeau Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart 715466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", ose=" + oldSelEnd 716466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nss=" + newSelStart 717466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nse=" + newSelEnd 718466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", cs=" + candidatesStart 719466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", ce=" + candidatesEnd); 720466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 721466741d8a78965b8509bf527344f289e50873092Mike LeBeau 722409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.setCursorAndSelection(newSelEnd, newSelStart); 7234f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 724923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // If the current selection in the text view changes, we should 725923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // clear whatever candidate text we have. 7269fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if ((((mComposing.length() > 0 && mHasValidSuggestions) 7278e09172df1bb176cc899940862c56bed9b9aec4esatok || mVoiceConnector.isVoiceInputHighlighted()) && (newSelStart != candidatesEnd 7288e09172df1bb176cc899940862c56bed9b9aec4esatok || newSelEnd != candidatesEnd) && mLastSelectionStart != newSelStart)) { 729923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mComposing.setLength(0); 7309fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mHasValidSuggestions = false; 731d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 732923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.reset(); 733923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 734923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 735923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.finishComposingText(); 736923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 737409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.setVoiceInputHighlighted(false); 7389fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka } else if (!mHasValidSuggestions && !mJustAccepted) { 7399a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa switch (TextEntryState.getState()) { 740e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case ACCEPTED_DEFAULT: 741e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka TextEntryState.reset(); 742e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka // $FALL-THROUGH$ 743e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case SPACE_AFTER_PICKED: 744e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mJustAddedAutoSpace = false; // The user moved the cursor. 745e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 746e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka default: 747e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 7489a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 749923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 750923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mJustAccepted = false; 751d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateShiftKeyState(); 752466741d8a78965b8509bf527344f289e50873092Mike LeBeau 753979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Make a note of the cursor position 754979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionStart = newSelStart; 755979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionEnd = newSelEnd; 756466741d8a78965b8509bf527344f289e50873092Mike LeBeau 7579fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (mReCorrectionEnabled && isShowingSuggestionsStrip()) { 75866b42a1c2d38813be104a7f0435ec6e6ec1c6e65satok // Don't look for corrections if the keyboard is not visible 7591679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka if (mKeyboardSwitcher.isInputViewShown()) { 76066b42a1c2d38813be104a7f0435ec6e6ec1c6e65satok // Check if we should go in or out of correction mode. 7619fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (isSuggestionsRequested() && !mJustReverted 76266b42a1c2d38813be104a7f0435ec6e6ec1c6e65satok && (candidatesStart == candidatesEnd || newSelStart != oldSelStart 76366b42a1c2d38813be104a7f0435ec6e6ec1c6e65satok || TextEntryState.isCorrecting()) 7649fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka && (newSelStart < newSelEnd - 1 || !mHasValidSuggestions)) { 76566b42a1c2d38813be104a7f0435ec6e6ec1c6e65satok if (isCursorTouchingWord() || mLastSelectionStart < mLastSelectionEnd) { 766d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateOldSuggestions(); 76766b42a1c2d38813be104a7f0435ec6e6ec1c6e65satok } else { 76866b42a1c2d38813be104a7f0435ec6e6ec1c6e65satok abortCorrection(false); 76955b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // Show the punctuation suggestions list if the current one is not 770364da8c618303a7764595d2c15ee034a7671365dKen Wakasa // and if not showing "Touch again to save". 7717599cfea4a2d56f4779452ec8e8742f7b9629cc0satok if (mCandidateView != null && !isShowingPunctuationList() 7727599cfea4a2d56f4779452ec8e8742f7b9629cc0satok && !mCandidateView.isShowingAddToDictionaryHint()) { 773ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setPunctuationSuggestions(); 77455b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa } 77566b42a1c2d38813be104a7f0435ec6e6ec1c6e65satok } 776b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 777466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 778466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 779923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 780923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 781c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 782c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has clicked on the extracted text view, 783c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * when running in fullscreen mode. The default implementation hides 784c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * the candidates view when this happens, but only if the extracted text 785c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * editor has a vertical scroll bar because its text doesn't fit. 786c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * Here we override the behavior due to the possibility that a re-correction could 787c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * cause the candidate strip to disappear and re-appear. 788c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani */ 789c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani @Override 790c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani public void onExtractedTextClicked() { 7919fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (mReCorrectionEnabled && isSuggestionsRequested()) return; 792c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 793c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedTextClicked(); 794c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 795c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 796c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 797c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has performed a cursor movement in the 798c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * extracted text view, when it is running in fullscreen mode. The default 799c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * implementation hides the candidates view when a vertical movement 800c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * happens, but only if the extracted text editor has a vertical scroll bar 801c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * because its text doesn't fit. 802c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * Here we override the behavior due to the possibility that a re-correction could 803c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * cause the candidate strip to disappear and re-appear. 804c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani */ 805c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani @Override 806c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani public void onExtractedCursorMovement(int dx, int dy) { 8079fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (mReCorrectionEnabled && isSuggestionsRequested()) return; 808c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 809c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedCursorMovement(dx, dy); 810c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 811c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 812923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 813923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void hideWindow() { 814979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 8151b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mKeyboardSwitcher.onAutoCorrectionStateChanged(false); 816979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 817923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (TRACE) Debug.stopMethodTracing(); 8186e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (mOptionsDialog != null && mOptionsDialog.isShowing()) { 8196e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog.dismiss(); 8206e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog = null; 8216e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 822409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.hideVoiceWindow(mConfigurationChanging); 823979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mWordHistory.clear(); 824923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.hideWindow(); 825923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.endSession(); 826923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 827923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 828923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 8291b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka public void onDisplayCompletions(CompletionInfo[] applicationSpecifiedCompletions) { 830979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (DEBUG) { 831a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa Log.i(TAG, "Received completions:"); 8321b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final int count = (applicationSpecifiedCompletions != null) 8331b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka ? applicationSpecifiedCompletions.length : 0; 8341b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka for (int i = 0; i < count; i++) { 835a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa Log.i(TAG, " #" + i + ": " + applicationSpecifiedCompletions[i]); 836923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 837923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 8381b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (mApplicationSpecifiedCompletionOn) { 8391b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletions = applicationSpecifiedCompletions; 8401b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (applicationSpecifiedCompletions == null) { 841b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani clearSuggestions(); 842923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 843923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 844a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 8457e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords.Builder builder = new SuggestedWords.Builder() 8461b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka .setApplicationSpecifiedCompletions(applicationSpecifiedCompletions) 8477e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka .setTypedWordValid(true) 8487e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka .setHasMinimalSuggestion(true); 849979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // When in fullscreen mode, show completions generated by the application 8507e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(builder.build()); 851923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = null; 852543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa setCandidatesViewShown(true); 853923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 854923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 855923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 856543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa private void setCandidatesViewShownInternal(boolean shown, boolean needsInputViewShown) { 857923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // TODO: Remove this if we support candidates with hard keyboard 858923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (onEvaluateInputViewShown()) { 8591679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka super.setCandidatesViewShown(shown 8601679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka && (needsInputViewShown ? mKeyboardSwitcher.isInputViewShown() : true)); 861923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 862923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 863a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 864923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 865543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa public void setCandidatesViewShown(boolean shown) { 866543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa setCandidatesViewShownInternal(shown, true /* needsInputViewShown */ ); 867543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa } 868543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa 869543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa @Override 870923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onComputeInsets(InputMethodService.Insets outInsets) { 871923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onComputeInsets(outInsets); 872264b19a6853ab3d13d26270e99a13dc015b01bebThe Android Open Source Project if (!isFullscreenMode()) { 873264b19a6853ab3d13d26270e99a13dc015b01bebThe Android Open Source Project outInsets.contentTopInsets = outInsets.visibleTopInsets; 874264b19a6853ab3d13d26270e99a13dc015b01bebThe Android Open Source Project } 8759e347d3d448e48229c46aad394ec9bd60cd5807bsatok KeyboardView inputView = mKeyboardSwitcher.getInputView(); 8769e347d3d448e48229c46aad394ec9bd60cd5807bsatok // Need to set touchable region only if input view is being shown 8779e347d3d448e48229c46aad394ec9bd60cd5807bsatok if (inputView != null && mKeyboardSwitcher.isInputViewShown()) { 8789e347d3d448e48229c46aad394ec9bd60cd5807bsatok final int x = 0; 8799e347d3d448e48229c46aad394ec9bd60cd5807bsatok int y = 0; 8809e347d3d448e48229c46aad394ec9bd60cd5807bsatok final int width = inputView.getWidth(); 8819e347d3d448e48229c46aad394ec9bd60cd5807bsatok int height = inputView.getHeight() + EXTENDED_TOUCHABLE_REGION_HEIGHT; 8829e347d3d448e48229c46aad394ec9bd60cd5807bsatok if (mCandidateViewContainer != null) { 8839e347d3d448e48229c46aad394ec9bd60cd5807bsatok ViewParent candidateParent = mCandidateViewContainer.getParent(); 8849e347d3d448e48229c46aad394ec9bd60cd5807bsatok if (candidateParent instanceof FrameLayout) { 88500eb3658734078df46b6fe88b8b6aa8b79d327c9Tadashi G. Takaoka FrameLayout fl = (FrameLayout) candidateParent; 88600eb3658734078df46b6fe88b8b6aa8b79d327c9Tadashi G. Takaoka if (fl != null) { 88700eb3658734078df46b6fe88b8b6aa8b79d327c9Tadashi G. Takaoka // Check frame layout's visibility 88800eb3658734078df46b6fe88b8b6aa8b79d327c9Tadashi G. Takaoka if (fl.getVisibility() == View.INVISIBLE) { 88900eb3658734078df46b6fe88b8b6aa8b79d327c9Tadashi G. Takaoka y = fl.getHeight(); 89000eb3658734078df46b6fe88b8b6aa8b79d327c9Tadashi G. Takaoka height += y; 89100eb3658734078df46b6fe88b8b6aa8b79d327c9Tadashi G. Takaoka } else if (fl.getVisibility() == View.VISIBLE) { 89200eb3658734078df46b6fe88b8b6aa8b79d327c9Tadashi G. Takaoka height += fl.getHeight(); 89300eb3658734078df46b6fe88b8b6aa8b79d327c9Tadashi G. Takaoka } 8949e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 8959e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 8969e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 8979e347d3d448e48229c46aad394ec9bd60cd5807bsatok if (DEBUG) { 8989e347d3d448e48229c46aad394ec9bd60cd5807bsatok Log.d(TAG, "Touchable region " + x + ", " + y + ", " + width + ", " + height); 8999e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 9006845da8d7b940018c4ef77646f0028d131ed2753satok outInsets.touchableInsets = InputMethodService.Insets.TOUCHABLE_INSETS_REGION; 9019e347d3d448e48229c46aad394ec9bd60cd5807bsatok outInsets.touchableRegion.set(x, y, width, height); 9029e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 903923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 904a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 905923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 906979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public boolean onEvaluateFullscreenMode() { 907458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa final Resources res = mResources; 908458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa DisplayMetrics dm = res.getDisplayMetrics(); 909979f8690967ff5409fe18f5085858ccdb8e0ccf1satok float displayHeight = dm.heightPixels; 910979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // If the display is more than X inches high, don't go to fullscreen mode 911458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa float dimen = res.getDimension(R.dimen.max_height_for_fullscreen); 912979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (displayHeight > dimen) { 913979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return false; 914979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } else { 915979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return super.onEvaluateFullscreenMode(); 916979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 917979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 918979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 919979f8690967ff5409fe18f5085858ccdb8e0ccf1satok @Override 920923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 921923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 922e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_BACK: 923e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (event.getRepeatCount() == 0 && mKeyboardSwitcher.getInputView() != null) { 924e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mKeyboardSwitcher.getInputView().handleBack()) { 9256e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani return true; 9266e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 927e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 928e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 929923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 930923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyDown(keyCode, event); 931923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 932923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 933923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 934923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 935923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 936e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_DOWN: 937e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_UP: 938e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_LEFT: 939e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_RIGHT: 940e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka // Enable shift key and DPAD to do selections 941e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mKeyboardSwitcher.isInputViewShown() 942e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka && mKeyboardSwitcher.isShiftedOrShiftLocked()) { 943e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka KeyEvent newEvent = new KeyEvent(event.getDownTime(), event.getEventTime(), 944e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka event.getAction(), event.getKeyCode(), event.getRepeatCount(), 945e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka event.getDeviceId(), event.getScanCode(), 946e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON); 947e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka InputConnection ic = getCurrentInputConnection(); 948e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (ic != null) 949e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka ic.sendKeyEvent(newEvent); 950e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka return true; 951e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 952e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 953923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 954923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyUp(keyCode, event); 955923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 956923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 957409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void commitTyped(InputConnection inputConnection) { 9589fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (mHasValidSuggestions) { 9599fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mHasValidSuggestions = false; 960923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mComposing.length() > 0) { 961923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (inputConnection != null) { 962923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project inputConnection.commitText(mComposing, 1); 963923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 964923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCommittedLength = mComposing.length(); 965923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.acceptedTyped(mComposing); 966979f8690967ff5409fe18f5085858ccdb8e0ccf1satok addToDictionaries(mComposing, AutoDictionary.FREQUENCY_FOR_TYPED); 967923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 968923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateSuggestions(); 969923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 970923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 971923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 972b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public boolean getCurrentAutoCapsState() { 973923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 9741c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani EditorInfo ei = getCurrentInputEditorInfo(); 975e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mAutoCap && ic != null && ei != null && ei.inputType != InputType.TYPE_NULL) { 976b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return ic.getCursorCapsMode(ei.inputType) != 0; 9771c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 978b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return false; 9791c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 9801c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 981923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void swapPunctuationAndSpace() { 982923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final InputConnection ic = getCurrentInputConnection(); 983923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 984923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence lastTwo = ic.getTextBeforeCursor(2, 0); 985923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastTwo != null && lastTwo.length() == 2 986571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastTwo.charAt(0) == Keyboard.CODE_SPACE 987571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && isSentenceSeparator(lastTwo.charAt(1))) { 988923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 989923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 990923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(lastTwo.charAt(1) + " ", 1); 991923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 992b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 9939a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa mJustAddedAutoSpace = true; 994923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 995923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 9961c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 9974ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa private void reswapPeriodAndSpace() { 9984ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa final InputConnection ic = getCurrentInputConnection(); 9994ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa if (ic == null) return; 10004ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa CharSequence lastThree = ic.getTextBeforeCursor(3, 0); 10014ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa if (lastThree != null && lastThree.length() == 3 1002571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastThree.charAt(0) == Keyboard.CODE_PERIOD 1003571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastThree.charAt(1) == Keyboard.CODE_SPACE 1004571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastThree.charAt(2) == Keyboard.CODE_PERIOD) { 10054ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa ic.beginBatchEdit(); 10064ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa ic.deleteSurroundingText(3, 0); 10074ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa ic.commitText(" ..", 1); 10084ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa ic.endBatchEdit(); 1009b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 10104ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 10114ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 10124ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1013923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void doubleSpace() { 1014923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project //if (!mAutoPunctuate) return; 1015923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mCorrectionMode == Suggest.CORRECTION_NONE) return; 1016923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final InputConnection ic = getCurrentInputConnection(); 1017923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 1018923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence lastThree = ic.getTextBeforeCursor(3, 0); 1019923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastThree != null && lastThree.length() == 3 1020923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project && Character.isLetterOrDigit(lastThree.charAt(0)) 1021571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastThree.charAt(1) == Keyboard.CODE_SPACE 1022571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastThree.charAt(2) == Keyboard.CODE_SPACE) { 1023923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 1024923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 1025923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(". ", 1); 1026923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1027b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 10289a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa mJustAddedAutoSpace = true; 1029923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1030923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1031a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 103241a519729505a877844f2c57a33509c302dddbceKen Wakasa private void maybeRemovePreviousPeriod(CharSequence text) { 103341a519729505a877844f2c57a33509c302dddbceKen Wakasa final InputConnection ic = getCurrentInputConnection(); 103441a519729505a877844f2c57a33509c302dddbceKen Wakasa if (ic == null) return; 103541a519729505a877844f2c57a33509c302dddbceKen Wakasa 103641a519729505a877844f2c57a33509c302dddbceKen Wakasa // When the text's first character is '.', remove the previous period 103741a519729505a877844f2c57a33509c302dddbceKen Wakasa // if there is one. 103841a519729505a877844f2c57a33509c302dddbceKen Wakasa CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 10394ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa if (lastOne != null && lastOne.length() == 1 1040571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastOne.charAt(0) == Keyboard.CODE_PERIOD 1041571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && text.charAt(0) == Keyboard.CODE_PERIOD) { 104241a519729505a877844f2c57a33509c302dddbceKen Wakasa ic.deleteSurroundingText(1, 0); 104341a519729505a877844f2c57a33509c302dddbceKen Wakasa } 104441a519729505a877844f2c57a33509c302dddbceKen Wakasa } 104541a519729505a877844f2c57a33509c302dddbceKen Wakasa 10469a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa private void removeTrailingSpace() { 10479a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa final InputConnection ic = getCurrentInputConnection(); 10489a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic == null) return; 10499a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa 10509a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 10519a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (lastOne != null && lastOne.length() == 1 1052571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastOne.charAt(0) == Keyboard.CODE_SPACE) { 10539a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.deleteSurroundingText(1, 0); 10549a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 10559a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 10569a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa 1057923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean addWordToDictionary(String word) { 1058923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mUserDictionary.addWord(word, 128); 10596558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // Suggestion strip should be updated after the operation of adding word to the 10606558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // user dictionary 1061d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1062923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1063923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1064923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1065923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean isAlphabet(int code) { 1066923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (Character.isLetter(code)) { 1067923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1068923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1069923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return false; 1070923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1071923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1072a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1073e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka private void onSettingsKeyPressed() { 10749a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok if (!isShowingOptionDialog()) { 10752fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka if (!mConfigEnableShowSubtypeSettings) { 10762fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka showSubtypeSelectorAndSettings(); 10772fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } else if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm)) { 10789a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok showOptionsMenu(); 10799a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } else { 10809a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok launchSettings(); 10819a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10829a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10839a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10849a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 1085e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka private void onSettingsKeyLongPressed() { 10869a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok if (!isShowingOptionDialog()) { 10879502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm)) { 108879efbed76f638be298493107fa2d0cd1b5eb529esatok mImm.showInputMethodPicker(); 10899a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } else { 10909a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok launchSettings(); 10919a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10929a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10939a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10949a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 10959a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok private boolean isShowingOptionDialog() { 10969a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok return mOptionsDialog != null && mOptionsDialog.isShowing(); 10979a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10989a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 10995f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // Implementation of {@link KeyboardActionListener}. 11005a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 11018aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { 1102923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long when = SystemClock.uptimeMillis(); 1103571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (primaryCode != Keyboard.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) { 1104923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mDeleteCount = 0; 1105923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1106923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mLastKeyTime = when; 1107b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 1108b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); 1109923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 1110571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_DELETE: 11114189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka handleBackspace(); 11124189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka mDeleteCount++; 11134189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka LatinImeLogger.logOnDelete(); 11144189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1115571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_SHIFT: 11164189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka // Shift key is handled in onPress() when device has distinct multi-touch panel. 11174189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka if (!distinctMultiTouch) 1118b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.toggleShift(); 11194189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1120e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: 11214189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka // Symbol key is handled in onPress() when device has distinct multi-touch panel. 11224189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka if (!distinctMultiTouch) 1123b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.changeKeyboardMode(); 11244189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1125571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_CANCEL: 11264189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka if (!isShowingOptionDialog()) { 11274189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka handleClose(); 11284189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } 11294189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1130e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SETTINGS: 1131e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka onSettingsKeyPressed(); 11324189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1133e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SETTINGS_LONGPRESS: 1134e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka onSettingsKeyLongPressed(); 11354189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1136571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_NEXT_LANGUAGE: 11374189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka toggleLanguage(false, true); 11384189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1139571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_PREV_LANGUAGE: 11404189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka toggleLanguage(false, false); 11414189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1142571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_CAPSLOCK: 1143b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.toggleCapsLock(); 11444189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 114520cdb37bd062ae6cb6d42ad6229a19733476cd55satok case Keyboard.CODE_VOICE: 114620cdb37bd062ae6cb6d42ad6229a19733476cd55satok mSubtypeSwitcher.switchToShortcutIME(); 11474189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1148571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_TAB: 114945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka handleTab(); 11504189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 11514189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka default: 1152571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (primaryCode != Keyboard.CODE_ENTER) { 11534189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka mJustAddedAutoSpace = false; 11544189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } 11554189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka RingCharBuffer.getInstance().push((char)primaryCode, x, y); 11564189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka LatinImeLogger.logOnInputChar(); 11574189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka if (isWordSeparator(primaryCode)) { 11584189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka handleSeparator(primaryCode); 11594189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } else { 11604189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka handleCharacter(primaryCode, keyCodes); 11614189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } 11624189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka // Cancel the just reverted state 1163c1e2e827b5d1bba59eb99d322dc101657ec28768Ken Wakasa mJustReverted = false; 1164923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1165b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.onKey(primaryCode); 1166dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani // Reset after any single keystroke 1167dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = null; 1168923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1169a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 11705a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 11718aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onTextInput(CharSequence text) { 1172409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.commitVoiceInput(); 1173923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1174923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 1175979f8690967ff5409fe18f5085858ccdb8e0ccf1satok abortCorrection(false); 1176923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 117755b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka commitTyped(ic); 117841a519729505a877844f2c57a33509c302dddbceKen Wakasa maybeRemovePreviousPeriod(text); 1179923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(text, 1); 1180923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1181b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 11825f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka mKeyboardSwitcher.onKey(Keyboard.CODE_DUMMY); 1183c1e2e827b5d1bba59eb99d322dc101657ec28768Ken Wakasa mJustReverted = false; 11849a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa mJustAddedAutoSpace = false; 1185dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = text; 1186923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1187923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 11885a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 11898aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onCancelInput() { 119083e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka // User released a finger outside any key 11915f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka mKeyboardSwitcher.onCancelInput(); 119283e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka } 119383e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka 1194923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleBackspace() { 1195409220583333bdf06290dd9fd42f91b5c0d1b11asatok if (mVoiceConnector.logAndRevertVoiceInput()) return; 11964f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1197504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1198504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka if (ic == null) return; 1199979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.beginBatchEdit(); 1200979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1201409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.handleBackspace(); 12024f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1203504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka boolean deleteChar = false; 12049fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (mHasValidSuggestions) { 1205923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final int length = mComposing.length(); 1206923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (length > 0) { 1207923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mComposing.delete(length - 1, length); 1208923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mWord.deleteLast(); 1209923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.setComposingText(mComposing, 1); 1210923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mComposing.length() == 0) { 12119fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mHasValidSuggestions = false; 1212923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1213d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1214923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1215923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(1, 0); 1216923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1217923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1218923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project deleteChar = true; 1219923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1220d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateShiftKeyState(); 1221504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka 1222923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.backspace(); 1223979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (TextEntryState.getState() == TextEntryState.State.UNDO_COMMIT) { 1224923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project revertLastWord(deleteChar); 1225979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.endBatchEdit(); 1226923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1227504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka } 1228504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka 1229504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) { 1230dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani ic.deleteSurroundingText(mEnteredText.length(), 0); 1231923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else if (deleteChar) { 12326558253160e2039c87f424bd814f402ecd31de3bKen Wakasa if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) { 12336558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // Go back to the suggestion mode if the user canceled the 123455b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // "Touch again to save". 12356558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // NOTE: In gerenal, we don't revert the word when backspacing 12366558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // from a manual suggestion pick. We deliberately chose a 12376558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // different behavior only in the case of picking the first 12386558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // suggestion (typed word). It's intentional to have made this 12396558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // inconsistent with backspacing after selecting other suggestions. 12406558253160e2039c87f424bd814f402ecd31de3bKen Wakasa revertLastWord(deleteChar); 12416558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } else { 1242923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 12436558253160e2039c87f424bd814f402ecd31de3bKen Wakasa if (mDeleteCount > DELETE_ACCELERATE_AT) { 12446558253160e2039c87f424bd814f402ecd31de3bKen Wakasa sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 12456558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 1246923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1247923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1248c1e2e827b5d1bba59eb99d322dc101657ec28768Ken Wakasa mJustReverted = false; 1249979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.endBatchEdit(); 1250923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1251923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 125245911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka private void handleTab() { 125345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final int imeOptions = getCurrentInputEditorInfo().imeOptions; 125445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final int navigationFlags = 125545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka EditorInfo.IME_FLAG_NAVIGATE_NEXT | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS; 125645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if ((imeOptions & navigationFlags) == 0) { 125745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB); 125845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka return; 125945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 126045911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 126145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 126245911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (ic == null) 126345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka return; 126445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 126545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka // True if keyboard is in either chording shift or manual temporary upper case mode. 126645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final boolean isManualTemporaryUpperCase = mKeyboardSwitcher.isManualTemporaryUpperCase(); 126745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if ((imeOptions & EditorInfo.IME_FLAG_NAVIGATE_NEXT) != 0 126845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka && !isManualTemporaryUpperCase) { 126945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka ic.performEditorAction(EditorInfo.IME_ACTION_NEXT); 127045911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } else if ((imeOptions & EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS) != 0 127145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka && isManualTemporaryUpperCase) { 127245911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka ic.performEditorAction(EditorInfo.IME_ACTION_PREVIOUS); 127345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 127445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 127545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 1276979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void abortCorrection(boolean force) { 1277979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (force || TextEntryState.isCorrecting()) { 1278ca26f20fa4903de46e374babbfba8c8a1a5cac93satok TextEntryState.onAbortCorrection(); 1279ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setCandidatesViewShown(isCandidateStripVisible()); 1280979f8690967ff5409fe18f5085858ccdb8e0ccf1satok getCurrentInputConnection().finishComposingText(); 1281b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani clearSuggestions(); 1282923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1283923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1284a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1285923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleCharacter(int primaryCode, int[] keyCodes) { 1286409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.handleCharacter(); 12874f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1288b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani if (mLastSelectionStart == mLastSelectionEnd && TextEntryState.isCorrecting()) { 1289b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani abortCorrection(false); 1290b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 12914f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1292e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka int code = primaryCode; 12939fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (isAlphabet(code) && isSuggestionsRequested() && !isCursorTouchingWord()) { 12949fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (!mHasValidSuggestions) { 12959fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mHasValidSuggestions = true; 1296923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mComposing.setLength(0); 1297979f8690967ff5409fe18f5085858ccdb8e0ccf1satok saveWordInHistory(mBestWord); 1298923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mWord.reset(); 1299923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1300923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 13011679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 1302f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (switcher.isShiftedOrShiftLocked()) { 1303eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT 1304eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani || keyCodes[0] > Character.MAX_CODE_POINT) { 1305eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani return; 1306eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani } 1307e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka code = keyCodes[0]; 1308e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (switcher.isAlphabetMode() && Character.isLowerCase(code)) { 1309e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka int upperCaseCode = Character.toUpperCase(code); 1310e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (upperCaseCode != code) { 1311e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka code = upperCaseCode; 131212a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka } else { 131312a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka // Some keys, such as [eszett], have upper case as multi-characters. 1314e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka String upperCase = new String(new int[] {code}, 0, 1).toUpperCase(); 13158aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka onTextInput(upperCase); 131612a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka return; 131712a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka } 1318979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1319923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 13209fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (mHasValidSuggestions) { 1321f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (mComposing.length() == 0 && switcher.isAlphabetMode() 1322f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka && switcher.isShiftedOrShiftLocked()) { 13230b4ae1f578e768eec4ada90aeb81d11acb10eb2eKen Wakasa mWord.setFirstCharCapitalized(true); 1324923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1325e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mComposing.append((char) code); 1326e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mWord.add(code, keyCodes); 1327923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1328923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 13291c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani // If it's the first letter, make note of auto-caps state 13301c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani if (mWord.size() == 1) { 1331b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mWord.setAutoCapitalized(getCurrentAutoCapsState()); 13321c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 1333923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.setComposingText(mComposing, 1); 1334923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1335d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1336923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1337e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka sendKeyChar((char)code); 1338923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1339b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.updateShiftState(); 1340979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (LatinIME.PERF_DEBUG) measureCps(); 1341e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka TextEntryState.typedCharacter((char) code, isWordSeparator(code)); 1342923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1343923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1344923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleSeparator(int primaryCode) { 1345409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.handleSeparator(); 13464f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 134755b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // Should dismiss the "Touch again to save" message when handling separator 13486558253160e2039c87f424bd814f402ecd31de3bKen Wakasa if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) { 1349d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 13506558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 13516558253160e2039c87f424bd814f402ecd31de3bKen Wakasa 1352923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project boolean pickedDefault = false; 1353923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Handle separator 13541b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1355923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1356923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 1357979f8690967ff5409fe18f5085858ccdb8e0ccf1satok abortCorrection(false); 1358923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 13599fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (mHasValidSuggestions) { 1360923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In certain languages where single quote is a separator, it's better 1361a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker // not to auto correct, but accept the typed word. For instance, 1362923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // in Italian dov' should not be expanded to dove' because the elision 1363923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // requires the last vowel to be removed. 1364c1e2e827b5d1bba59eb99d322dc101657ec28768Ken Wakasa if (mAutoCorrectOn && primaryCode != '\'' && !mJustReverted) { 1365979f8690967ff5409fe18f5085858ccdb8e0ccf1satok pickedDefault = pickDefaultSuggestion(); 13669a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa // Picked the suggestion by the space key. We consider this 13679a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa // as "added an auto space". 1368571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (primaryCode == Keyboard.CODE_SPACE) { 13699a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa mJustAddedAutoSpace = true; 13709a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1371923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1372923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project commitTyped(ic); 1373923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1374923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1375571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (mJustAddedAutoSpace && primaryCode == Keyboard.CODE_ENTER) { 13769a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa removeTrailingSpace(); 13779a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa mJustAddedAutoSpace = false; 13789a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1379923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendKeyChar((char)primaryCode); 13804ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 13814ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa // Handle the case of ". ." -> " .." with auto-space if necessary 13824ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa // before changing the TextEntryState. 1383979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (TextEntryState.getState() == TextEntryState.State.PUNCTUATION_AFTER_ACCEPTED 1384571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && primaryCode == Keyboard.CODE_PERIOD) { 13854ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa reswapPeriodAndSpace(); 13864ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 13874ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1388923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.typedCharacter((char) primaryCode, true); 1389979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (TextEntryState.getState() == TextEntryState.State.PUNCTUATION_AFTER_ACCEPTED 1390571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && primaryCode != Keyboard.CODE_ENTER) { 1391923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project swapPunctuationAndSpace(); 13929fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka } else if (isSuggestionsRequested() && primaryCode == Keyboard.CODE_SPACE) { 1393923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project doubleSpace(); 1394923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1395979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (pickedDefault) { 139655b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka CharSequence typedWord = mWord.getTypedWord(); 139755b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka TextEntryState.backToAcceptedDefault(typedWord); 139855b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka if (!TextUtils.isEmpty(typedWord) && !typedWord.equals(mBestWord)) { 13994ca16dbd65150359c3884da7cb59a30f19abd4b7Tadashi G. Takaoka if (ic != null) { 14004ca16dbd65150359c3884da7cb59a30f19abd4b7Tadashi G. Takaoka CorrectionInfo correctionInfo = new CorrectionInfo( 14014ca16dbd65150359c3884da7cb59a30f19abd4b7Tadashi G. Takaoka mLastSelectionEnd - typedWord.length(), typedWord, mBestWord); 14024ca16dbd65150359c3884da7cb59a30f19abd4b7Tadashi G. Takaoka ic.commitCorrection(correctionInfo); 14034ca16dbd65150359c3884da7cb59a30f19abd4b7Tadashi G. Takaoka } 140455b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka if (mCandidateView != null) 140555b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka mCandidateView.onAutoCorrectionInverted(mBestWord); 140655b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka } 140755b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka setPunctuationSuggestions(); 1408923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1409b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 1410923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1411923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1412923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1413923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1414466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1415923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleClose() { 1416923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project commitTyped(getCurrentInputConnection()); 1417409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.handleClose(); 1418923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project requestHideSelf(0); 14191679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); 14201679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka if (inputView != null) 14211679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka inputView.closing(); 1422923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.endSession(); 1423923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1424923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1425979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void saveWordInHistory(CharSequence result) { 1426979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mWord.size() <= 1) { 1427979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mWord.reset(); 1428979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return; 1429923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1430979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Skip if result is null. It happens in some edge case. 1431979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (TextUtils.isEmpty(result)) { 1432979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return; 1433923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1434979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1435979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Make a copy of the CharSequence, since it is/could be a mutable CharSequence 1436979f8690967ff5409fe18f5085858ccdb8e0ccf1satok final String resultCopy = result.toString(); 1437979f8690967ff5409fe18f5085858ccdb8e0ccf1satok TypedWordAlternatives entry = new TypedWordAlternatives(resultCopy, 1438979f8690967ff5409fe18f5085858ccdb8e0ccf1satok new WordComposer(mWord)); 1439979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mWordHistory.add(entry); 1440923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1441923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 14429fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka private boolean isSuggestionsRequested() { 1443c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka return mIsSettingsSuggestionStripOn 1444c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka && (mCorrectionMode > 0 || isShowingSuggestionsStrip()); 1445923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1446a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 14477599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private boolean isShowingPunctuationList() { 14487e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka return mSuggestPuncList == mCandidateView.getSuggestions(); 14497599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 14507599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 14519fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka private boolean isShowingSuggestionsStrip() { 14527599cfea4a2d56f4779452ec8e8742f7b9629cc0satok return (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_VALUE) 14537599cfea4a2d56f4779452ec8e8742f7b9629cc0satok || (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE 14547599cfea4a2d56f4779452ec8e8742f7b9629cc0satok && mOrientation == Configuration.ORIENTATION_PORTRAIT); 14557599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 14567599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 1457923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean isCandidateStripVisible() { 1458b5e00d5841b946de8970875231456228ae0eb6b1Ken Wakasa if (mCandidateView == null) 1459b5e00d5841b946de8970875231456228ae0eb6b1Ken Wakasa return false; 14609fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (mCandidateView.isShowingAddToDictionaryHint() || TextEntryState.isCorrecting()) 14619fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 14629fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (!isShowingSuggestionsStrip()) 14639fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return false; 14649fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (mApplicationSpecifiedCompletionOn) 14659fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 14669fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return isSuggestionsRequested(); 1467923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1468923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1469409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void switchToKeyboardView() { 14705a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka mHandler.post(new Runnable() { 14715a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 14725a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka public void run() { 14735a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka if (DEBUG) { 14745a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka Log.d(TAG, "Switch to keyboard view."); 14755a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka } 14765a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka View v = mKeyboardSwitcher.getInputView(); 14775a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka if (v != null) { 14785a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka // Confirms that the keyboard view doesn't have parent view. 14795a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka ViewParent p = v.getParent(); 14805a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka if (p != null && p instanceof ViewGroup) { 14815a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka ((ViewGroup) p).removeView(v); 14825a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka } 14835a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka setInputView(v); 14845a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka } 14855a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka setCandidatesViewShown(isCandidateStripVisible()); 14865a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka updateInputViewShown(); 14875a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 14885a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka } 14895a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka }); 1490466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1491466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1492409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void clearSuggestions() { 14937e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(SuggestedWords.EMPTY); 1494466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1495466741d8a78965b8509bf527344f289e50873092Mike LeBeau 14967e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka public void setSuggestions(SuggestedWords words) { 1497409220583333bdf06290dd9fd42f91b5c0d1b11asatok if (mVoiceConnector.getAndResetIsShowingHint()) { 1498466741d8a78965b8509bf527344f289e50873092Mike LeBeau setCandidatesView(mCandidateViewContainer); 1499466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1500466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1501466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mCandidateView != null) { 15027e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka mCandidateView.setSuggestions(words); 15039ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka if (mCandidateView.isConfigCandidateHighlightFontColorEnabled()) { 15049ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka mKeyboardSwitcher.onAutoCorrectionStateChanged( 15059ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka words.hasWordAboveAutoCorrectionScoreThreshold()); 15069ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka } 1507466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1508466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1509466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1510409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void updateSuggestions() { 15111679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka mKeyboardSwitcher.setPreferredLetters(null); 15121b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani 1513923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Check if we have a suggestion engine attached. 15149fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if ((mSuggest == null || !isSuggestionsRequested()) 1515409220583333bdf06290dd9fd42f91b5c0d1b11asatok && !mVoiceConnector.isVoiceInputHighlighted()) { 1516923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1517923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1518466741d8a78965b8509bf527344f289e50873092Mike LeBeau 15199fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (!mHasValidSuggestions) { 1520ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setPunctuationSuggestions(); 1521923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1522923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1523979f8690967ff5409fe18f5085858ccdb8e0ccf1satok showSuggestions(mWord); 1524979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1525979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 15267e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka private SuggestedWords.Builder getTypedSuggestions(WordComposer word) { 15279ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka return mSuggest.getSuggestedWordBuilder(mKeyboardSwitcher.getInputView(), word, null); 1528979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1529979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1530979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void showCorrections(WordAlternatives alternatives) { 15311679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka mKeyboardSwitcher.setPreferredLetters(null); 15327e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords.Builder builder = alternatives.getAlternatives(); 15337e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka builder.setTypedWordValid(false).setHasMinimalSuggestion(false); 15347e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka showSuggestions(builder.build(), alternatives.getOriginalWord()); 1535979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1536979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1537979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void showSuggestions(WordComposer word) { 1538979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // TODO Maybe need better way of retrieving previous word 1539e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(), 1540979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mWordSeparators); 15417e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder( 15429ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka mKeyboardSwitcher.getInputView(), word, prevWord); 1543923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 15441b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani int[] nextLettersFrequencies = mSuggest.getNextLettersFrequencies(); 15451679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka mKeyboardSwitcher.setPreferredLetters(nextLettersFrequencies); 15461b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani 1547378a1b516d867671d292900c5d42aef3a0dc1556Ken Wakasa boolean correctionAvailable = !mInputTypeNoAutoCorrect && !mJustReverted 15486f7218627eda110a8454053f8ecb7b80edfdc8cesatok && mSuggest.hasAutoCorrection(); 1549a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa final CharSequence typedWord = word.getTypedWord(); 1550923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // If we're in basic correct 1551a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa final boolean typedWordValid = mSuggest.isValidWord(typedWord) || 1552979f8690967ff5409fe18f5085858ccdb8e0ccf1satok (preferCapitalization() 1553979f8690967ff5409fe18f5085858ccdb8e0ccf1satok && mSuggest.isValidWord(typedWord.toString().toLowerCase())); 1554979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mCorrectionMode == Suggest.CORRECTION_FULL 1555979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) { 1556923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project correctionAvailable |= typedWordValid; 1557923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 15584a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani // Don't auto-correct words with multiple capital letter 1559979f8690967ff5409fe18f5085858ccdb8e0ccf1satok correctionAvailable &= !word.isMostlyCaps(); 1560979f8690967ff5409fe18f5085858ccdb8e0ccf1satok correctionAvailable &= !TextEntryState.isCorrecting(); 1561979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1562a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // Basically, we update the suggestion strip only when suggestion count > 1. However, 1563a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // there is an exception: We update the suggestion strip whenever typed word's length 1564f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // is 1 or typed word is found in dictionary, regardless of suggestion count. Actually, 1565f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // in most cases, suggestion count is 1 when typed word's length is 1, but we do always 1566f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // need to clear the previous state when the user starts typing a word (i.e. typed word's 1567f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // length == 1). 1568f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka if (builder.size() > 1 || typedWord.length() == 1 || typedWordValid 1569a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa || mCandidateView.isShowingAddToDictionaryHint()) { 15709fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka builder.setTypedWordValid(typedWordValid).setHasMinimalSuggestion(correctionAvailable); 15719fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka } else { 15729fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka final SuggestedWords previousSuggestions = mCandidateView.getSuggestions(); 15739fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (previousSuggestions == mSuggestPuncList) 15749fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return; 15759fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka builder.addTypedWordAndPreviousSuggestions(typedWord, previousSuggestions); 15769fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka } 15777e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka showSuggestions(builder.build(), typedWord); 1578979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 15794a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani 15807e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka private void showSuggestions(SuggestedWords suggestedWords, CharSequence typedWord) { 15817e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(suggestedWords); 15827e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka if (suggestedWords.size() > 0) { 158314e427d5bb13d59d23fb317ef90a6c44ae279425satok if (Utils.shouldBlockedBySafetyNetForAutoCorrection(suggestedWords, mSuggest)) { 158482411d47ba7e8133ed2390c6920945e139a738cesatok mBestWord = typedWord; 158582411d47ba7e8133ed2390c6920945e139a738cesatok } else if (suggestedWords.hasAutoCorrectionWord()) { 15867e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka mBestWord = suggestedWords.getWord(1); 1587923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1588923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = typedWord; 1589923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1590923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1591923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = null; 1592923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1593ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setCandidatesViewShown(isCandidateStripVisible()); 1594923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1595923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1596979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private boolean pickDefaultSuggestion() { 1597923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Complete any pending candidate query first 1598d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka if (mHandler.hasPendingUpdateSuggestions()) { 1599d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 1600923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateSuggestions(); 1601923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 16026780b898ec2647a21319601a03ae1c393c0e1b29Amith Yamasani if (mBestWord != null && mBestWord.length() > 0) { 1603923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.acceptedDefault(mWord.getTypedWord(), mBestWord); 1604923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mJustAccepted = true; 160555b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka pickSuggestion(mBestWord); 16069468335a06d2b0e3ef15f4f57f8c1b0857b34ebeAmith Yamasani // Add the word to the auto dictionary if it's not a known word 1607979f8690967ff5409fe18f5085858ccdb8e0ccf1satok addToDictionaries(mBestWord, AutoDictionary.FREQUENCY_FOR_TYPED); 1608979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return true; 1609979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1610923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1611979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return false; 1612923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1613923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1614923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void pickSuggestionManually(int index, CharSequence suggestion) { 16157e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords suggestions = mCandidateView.getSuggestions(); 1616409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.flushAndLogAllTextModificationCounters(index, suggestion, mWordSeparators); 16174f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1618979f8690967ff5409fe18f5085858ccdb8e0ccf1satok final boolean correcting = TextEntryState.isCorrecting(); 16199a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa InputConnection ic = getCurrentInputConnection(); 16209a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 16219a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.beginBatchEdit(); 16229a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 16231b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (mApplicationSpecifiedCompletionOn && mApplicationSpecifiedCompletions != null 16241b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka && index >= 0 && index < mApplicationSpecifiedCompletions.length) { 16251b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka CompletionInfo ci = mApplicationSpecifiedCompletions[index]; 1626923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1627923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitCompletion(ci); 1628923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1629923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCommittedLength = suggestion.length(); 1630923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mCandidateView != null) { 1631923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCandidateView.clear(); 1632923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1633b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 16349a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 16359a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 16369a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1637923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1638923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 16396a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 16406a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani // If this is a punctuation, apply it through the normal key press 1641979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (suggestion.length() == 1 && (isWordSeparator(suggestion.charAt(0)) 1642979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || isSuggestedPunctuation(suggestion.charAt(0)))) { 1643979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Word separators are suggested before the user inputs something. 1644979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // So, LatinImeLogger logs "" as a user's input. 1645979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.logOnManualSuggestion( 16467e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka "", suggestion.toString(), index, suggestions.mWords); 164755b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa final char primaryCode = suggestion.charAt(0); 1648a96574fdd5e38a237a35b21a2b7c20a29138c648Tadashi G. Takaoka onCodeInput(primaryCode, new int[] { primaryCode }, 1649a96574fdd5e38a237a35b21a2b7c20a29138c648Tadashi G. Takaoka KeyboardActionListener.NOT_A_TOUCH_COORDINATE, 1650a96574fdd5e38a237a35b21a2b7c20a29138c648Tadashi G. Takaoka KeyboardActionListener.NOT_A_TOUCH_COORDINATE); 16519a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 16529a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 16539a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 16546a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani return; 16556a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 16569a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa mJustAccepted = true; 165755b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka pickSuggestion(suggestion); 16589468335a06d2b0e3ef15f4f57f8c1b0857b34ebeAmith Yamasani // Add the word to the auto dictionary if it's not a known word 16590c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani if (index == 0) { 1660979f8690967ff5409fe18f5085858ccdb8e0ccf1satok addToDictionaries(suggestion, AutoDictionary.FREQUENCY_FOR_PICKED); 1661979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } else { 1662979f8690967ff5409fe18f5085858ccdb8e0ccf1satok addToBigramDictionary(suggestion, 1); 16630c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani } 1664979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.logOnManualSuggestion(mComposing.toString(), suggestion.toString(), 16657e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka index, suggestions.mWords); 1666923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.acceptedSuggestion(mComposing.toString(), suggestion); 1667923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Follow it with a space 1668979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mAutoSpace && !correcting) { 1669923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendSpace(); 16709a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa mJustAddedAutoSpace = true; 1671923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1672979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1673b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani final boolean showingAddToDictionaryHint = index == 0 && mCorrectionMode > 0 1674b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani && !mSuggest.isValidWord(suggestion) 1675b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani && !mSuggest.isValidWord(suggestion.toString().toLowerCase()); 1676b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani 1677979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (!correcting) { 1678b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // Fool the state watcher so that a subsequent backspace will not do a revert, unless 1679b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // we just did a correction, in which case we need to stay in 1680b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // TextEntryState.State.PICKED_SUGGESTION state. 1681571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka TextEntryState.typedCharacter((char) Keyboard.CODE_SPACE, true); 1682ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setPunctuationSuggestions(); 1683b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } else if (!showingAddToDictionaryHint) { 1684364da8c618303a7764595d2c15ee034a7671365dKen Wakasa // If we're not showing the "Touch again to save", then show corrections again. 1685979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // In case the cursor position doesn't change, make sure we show the suggestions again. 1686b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani clearSuggestions(); 1687d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateOldSuggestions(); 1688979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1689b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani if (showingAddToDictionaryHint) { 169066a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani mCandidateView.showAddToDictionaryHint(suggestion); 169166a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani } 16929a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 16939a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 16949a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1695923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1696a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1697979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 1698979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * Commits the chosen word to the text field and saves it for later 1699979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * retrieval. 1700979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * @param suggestion the suggestion picked by the user to be committed to 1701979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * the text field 1702979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 170355b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka private void pickSuggestion(CharSequence suggestion) { 1704b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 1705b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (!switcher.isKeyboardAvailable()) 17061679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka return; 1707923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1708923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1709409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.rememberReplacedWord(suggestion, mWordSeparators); 1710979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.commitText(suggestion, 1); 1711923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1712979f8690967ff5409fe18f5085858ccdb8e0ccf1satok saveWordInHistory(suggestion); 17139fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mHasValidSuggestions = false; 1714923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCommittedLength = suggestion.length(); 1715b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.setPreferredLetters(null); 1716923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1717923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1718b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani /** 1719b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani * Tries to apply any typed alternatives for the word if we have any cached alternatives, 1720b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani * otherwise tries to find new corrections and completions for the word. 1721b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani * @param touching The word that the cursor is touching, with position information 1722b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani * @return true if an alternative was found, false otherwise. 1723b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani */ 1724e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka private boolean applyTypedAlternatives(EditingUtils.SelectedWord touching) { 1725b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // If we didn't find a match, search for result in typed word history 1726b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani WordComposer foundWord = null; 1727b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani WordAlternatives alternatives = null; 1728b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani for (WordAlternatives entry : mWordHistory) { 1729e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (TextUtils.equals(entry.getChosenWord(), touching.mWord)) { 1730b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani if (entry instanceof TypedWordAlternatives) { 1731b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani foundWord = ((TypedWordAlternatives) entry).word; 1732b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 1733b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani alternatives = entry; 1734b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani break; 1735b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 1736b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 17371b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka // If we didn't find a match, at least suggest corrections. 1738b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani if (foundWord == null 1739e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka && (mSuggest.isValidWord(touching.mWord) 1740e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka || mSuggest.isValidWord(touching.mWord.toString().toLowerCase()))) { 1741b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani foundWord = new WordComposer(); 1742e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka for (int i = 0; i < touching.mWord.length(); i++) { 1743e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka foundWord.add(touching.mWord.charAt(i), new int[] { 1744e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka touching.mWord.charAt(i) 1745b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani }); 1746b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 1747e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka foundWord.setFirstCharCapitalized(Character.isUpperCase(touching.mWord.charAt(0))); 1748b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 1749b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // Found a match, show suggestions 1750b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani if (foundWord != null || alternatives != null) { 1751b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani if (alternatives == null) { 1752e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka alternatives = new TypedWordAlternatives(touching.mWord, foundWord); 1753b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 1754b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani showCorrections(alternatives); 1755b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani if (foundWord != null) { 1756b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani mWord = new WordComposer(foundWord); 1757b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } else { 1758b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani mWord.reset(); 1759b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 1760b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani return true; 1761b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 1762b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani return false; 1763b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 1764b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani 1765979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void setOldSuggestions() { 1766409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.setShowingVoiceSuggestions(false); 1767b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani if (mCandidateView != null && mCandidateView.isShowingAddToDictionaryHint()) { 1768b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani return; 1769b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 1770979f8690967ff5409fe18f5085858ccdb8e0ccf1satok InputConnection ic = getCurrentInputConnection(); 1771979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (ic == null) return; 17729fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (!mHasValidSuggestions) { 1773b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // Extract the selected or touching text 1774e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka EditingUtils.SelectedWord touching = EditingUtils.getWordAtCursorOrSelection(ic, 1775b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani mLastSelectionStart, mLastSelectionEnd, mWordSeparators); 1776979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1777e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (touching != null && touching.mWord.length() > 1) { 1778b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani ic.beginBatchEdit(); 1779979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1780409220583333bdf06290dd9fd42f91b5c0d1b11asatok if (!mVoiceConnector.applyVoiceAlternatives(touching) 1781409220583333bdf06290dd9fd42f91b5c0d1b11asatok && !applyTypedAlternatives(touching)) { 1782b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani abortCorrection(true); 1783b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } else { 1784979f8690967ff5409fe18f5085858ccdb8e0ccf1satok TextEntryState.selectedForCorrection(); 1785e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka EditingUtils.underlineWord(ic, touching); 1786979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1787b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani 1788b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani ic.endBatchEdit(); 1789979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } else { 1790979f8690967ff5409fe18f5085858ccdb8e0ccf1satok abortCorrection(true); 1791ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setPunctuationSuggestions(); // Show the punctuation suggestions list 1792979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1793979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } else { 1794979f8690967ff5409fe18f5085858ccdb8e0ccf1satok abortCorrection(true); 1795979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1796979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1797979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1798ca26f20fa4903de46e374babbfba8c8a1a5cac93satok private void setPunctuationSuggestions() { 17997e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(mSuggestPuncList); 18009fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka setCandidatesViewShown(isCandidateStripVisible()); 18016a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 18026a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 1803979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void addToDictionaries(CharSequence suggestion, int frequencyDelta) { 1804979f8690967ff5409fe18f5085858ccdb8e0ccf1satok checkAddToDictionary(suggestion, frequencyDelta, false); 1805979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1806979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1807979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void addToBigramDictionary(CharSequence suggestion, int frequencyDelta) { 1808979f8690967ff5409fe18f5085858ccdb8e0ccf1satok checkAddToDictionary(suggestion, frequencyDelta, true); 1809979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1810979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1811979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 1812979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * Adds to the UserBigramDictionary and/or AutoDictionary 1813979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * @param addToBigramDictionary true if it should be added to bigram dictionary if possible 1814979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 1815979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void checkAddToDictionary(CharSequence suggestion, int frequencyDelta, 1816979f8690967ff5409fe18f5085858ccdb8e0ccf1satok boolean addToBigramDictionary) { 1817979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (suggestion == null || suggestion.length() < 1) return; 18180c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // Only auto-add to dictionary if auto-correct is ON. Otherwise we'll be 18190c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // adding words in situations where the user or application really didn't 18200c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // want corrections enabled or learned. 1821979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (!(mCorrectionMode == Suggest.CORRECTION_FULL 1822979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM)) { 1823979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return; 1824979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1825e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (!addToBigramDictionary && mAutoDictionary.isValidWord(suggestion) 1826e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka || (!mSuggest.isValidWord(suggestion.toString()) 1827e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka && !mSuggest.isValidWord(suggestion.toString().toLowerCase()))) { 1828e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mAutoDictionary.addWord(suggestion.toString(), frequencyDelta); 1829e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 1830979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1831e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mUserBigramDictionary != null) { 1832e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(), 1833e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mSentenceSeparators); 1834e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (!TextUtils.isEmpty(prevWord)) { 1835e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mUserBigramDictionary.addBigrams(prevWord.toString(), suggestion.toString()); 1836979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 183732e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 183832e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 183932e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani 1840923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean isCursorTouchingWord() { 1841923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1842923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return false; 1843923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence toLeft = ic.getTextBeforeCursor(1, 0); 1844923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence toRight = ic.getTextAfterCursor(1, 0); 1845923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (!TextUtils.isEmpty(toLeft) 184655b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa && !isWordSeparator(toLeft.charAt(0)) 184755b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa && !isSuggestedPunctuation(toLeft.charAt(0))) { 1848923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1849923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1850a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker if (!TextUtils.isEmpty(toRight) 185155b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa && !isWordSeparator(toRight.charAt(0)) 185255b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa && !isSuggestedPunctuation(toRight.charAt(0))) { 1853923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1854923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1855923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return false; 1856923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1857a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1858dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani private boolean sameAsTextBeforeCursor(InputConnection ic, CharSequence text) { 1859dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani CharSequence beforeText = ic.getTextBeforeCursor(text.length(), 0); 1860dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani return TextUtils.equals(text, beforeText); 1861dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani } 1862dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 1863923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void revertLastWord(boolean deleteChar) { 1864923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final int length = mComposing.length(); 18659fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (!mHasValidSuggestions && length > 0) { 1866923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final InputConnection ic = getCurrentInputConnection(); 1867c1e2e827b5d1bba59eb99d322dc101657ec28768Ken Wakasa mJustReverted = true; 1868504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka final CharSequence punctuation = ic.getTextBeforeCursor(1, 0); 1869923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (deleteChar) ic.deleteSurroundingText(1, 0); 1870923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int toDelete = mCommittedLength; 1871504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka final CharSequence toTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0); 1872504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka if (!TextUtils.isEmpty(toTheLeft) && isWordSeparator(toTheLeft.charAt(0))) { 1873923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project toDelete--; 1874923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1875923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(toDelete, 0); 187630be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka // Re-insert punctuation only when the deleted character was word separator and the 187730be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka // composing text wasn't equal to the auto-corrected text. 187830be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka if (deleteChar 187930be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka && !TextUtils.isEmpty(punctuation) && isWordSeparator(punctuation.charAt(0)) 188030be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka && !TextUtils.equals(mComposing, toTheLeft)) { 1881504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka ic.commitText(mComposing, 1); 1882504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka TextEntryState.acceptedTyped(mComposing); 188330be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka ic.commitText(punctuation, 1); 188430be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka TextEntryState.typedCharacter(punctuation.charAt(0), true); 188530be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka // Clear composing text 188630be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka mComposing.setLength(0); 1887504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka } else { 188830be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka mHasValidSuggestions = true; 1889504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka ic.setComposingText(mComposing, 1); 1890504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka TextEntryState.backspace(); 1891504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka } 1892d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1893923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1894923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 1895c1e2e827b5d1bba59eb99d322dc101657ec28768Ken Wakasa mJustReverted = false; 1896923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1897923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1898923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1899923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project protected String getWordSeparators() { 1900923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return mWordSeparators; 1901923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1902a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1903923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean isWordSeparator(int code) { 1904923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project String separators = getWordSeparators(); 1905923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return separators.contains(String.valueOf((char)code)); 1906923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1907923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1908979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private boolean isSentenceSeparator(int code) { 1909923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return mSentenceSeparators.contains(String.valueOf((char)code)); 1910923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1911923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1912923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void sendSpace() { 1913571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka sendKeyChar((char)Keyboard.CODE_SPACE); 1914b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 1915923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1916923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1917923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean preferCapitalization() { 19180b4ae1f578e768eec4ada90aeb81d11acb10eb2eKen Wakasa return mWord.isFirstCharCapitalized(); 1919923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1920923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1921c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // Notify that language or mode have been changed and toggleLanguage will update KeyboaredID 1922c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // according to new language or mode. 1923c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka public void onRefreshKeyboard() { 19244ab730dbd34fad323063f2ffd31ce33de746668dsatok toggleLanguage(true, true); 19254ab730dbd34fad323063f2ffd31ce33de746668dsatok } 19264ab730dbd34fad323063f2ffd31ce33de746668dsatok 19274ab730dbd34fad323063f2ffd31ce33de746668dsatok // "reset" and "next" are used only for USE_SPACEBAR_LANGUAGE_SWITCHER. 19283f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani private void toggleLanguage(boolean reset, boolean next) { 1929de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka if (mSubtypeSwitcher.useSpacebarLanguageSwitcher()) { 19304ab730dbd34fad323063f2ffd31ce33de746668dsatok mSubtypeSwitcher.toggleLanguage(reset, next); 19314ab730dbd34fad323063f2ffd31ce33de746668dsatok } 19324ab730dbd34fad323063f2ffd31ce33de746668dsatok // Reload keyboard because the current language has been changed. 1933b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 19348b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka final EditorInfo attribute = getCurrentInputEditorInfo(); 1935c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka final int mode = initializeInputAttributesAndGetMode((attribute != null) 1936c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka ? attribute.inputType : 0); 1937d98c20b036ff02f99406dabb8cc4fdf4a51cd6c4Tadashi G. Takaoka final int imeOptions = (attribute != null) ? attribute.imeOptions : 0; 1938409220583333bdf06290dd9fd42f91b5c0d1b11asatok switcher.loadKeyboard(mode, imeOptions, mVoiceConnector.isVoiceButtonEnabled(), 1939409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.isVoiceButtonOnPrimary()); 19400ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 1941b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.updateShiftState(); 194236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 194336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 19445a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 194536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, 194636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani String key) { 19470ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mSubtypeSwitcher.onSharedPreferenceChanged(sharedPreferences, key); 19489502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka if (Settings.PREF_SELECTED_LANGUAGES.equals(key)) { 194936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mRefreshKeyboardRequired = true; 19509502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka } else if (Settings.PREF_RECORRECTION_ENABLED.equals(key)) { 19519502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka mReCorrectionEnabled = sharedPreferences.getBoolean( 19529502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka Settings.PREF_RECORRECTION_ENABLED, 1953458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa mResources.getBoolean(R.bool.default_recorrection_enabled)); 195436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 195536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 195636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 19575a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 19588aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onSwipeDown() { 1959363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka if (mConfigSwipeDownDismissKeyboardEnabled) 1960363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka handleClose(); 1961923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1962923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 19635a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 1964923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onPress(int primaryCode) { 1965cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka if (mKeyboardSwitcher.isVibrateAndSoundFeedbackRequired()) { 1966cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka vibrate(); 1967cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka playKeyClick(primaryCode); 1968cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka } 19691679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 19701679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); 1971571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { 1972b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.onPressShift(); 1973e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { 19746c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka switcher.onPressSymbol(); 197540a05f62edc6cdedb4365a722b48a72826ef2bf6Tadashi G. Takaoka } else { 19766c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka switcher.onOtherKeyPressed(); 1977681b102a492b7d5301c1ca87985b4c391eb5eb14Tadashi G. Takaoka } 1978923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1979923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 19805a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 1981923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onRelease(int primaryCode) { 19821679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 19833f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani // Reset any drag flags in the keyboard 19841679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka switcher.keyReleased(); 19851679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); 1986571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { 1987889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka switcher.onReleaseShift(); 1988e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { 19896c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka switcher.onReleaseSymbol(); 199040a05f62edc6cdedb4365a722b48a72826ef2bf6Tadashi G. Takaoka } 1991923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1992a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1993a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1994123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka // receive ringer mode change and network state change. 1995923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private BroadcastReceiver mReceiver = new BroadcastReceiver() { 1996923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 1997923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onReceive(Context context, Intent intent) { 1998123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final String action = intent.getAction(); 1999123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { 2000123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka updateRingerMode(); 2001123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 2002123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka mSubtypeSwitcher.onNetworkStateChanged(intent); 2003123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka } 2004923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2005923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project }; 2006923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2007923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // update flags for silent mode 2008923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void updateRingerMode() { 2009923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager == null) { 2010923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 2011923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2012923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager != null) { 2013923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mSilentMode = (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL); 2014923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2015923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2016923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2017923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void playKeyClick(int primaryCode) { 2018923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // if mAudioManager is null, we don't have the ringer state yet 2019923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // mAudioManager will be set by updateRingerMode 2020923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager == null) { 2021979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mKeyboardSwitcher.getInputView() != null) { 2022923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateRingerMode(); 2023923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2024923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2025923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mSoundOn && !mSilentMode) { 2026923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // FIXME: Volume and enable should come from UI settings 2027923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // FIXME: These should be triggered after auto-repeat logic 2028923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int sound = AudioManager.FX_KEYPRESS_STANDARD; 2029923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 2030571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_DELETE: 2031923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sound = AudioManager.FX_KEYPRESS_DELETE; 2032923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 2033571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_ENTER: 2034923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sound = AudioManager.FX_KEYPRESS_RETURN; 2035923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 2036571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_SPACE: 2037923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sound = AudioManager.FX_KEYPRESS_SPACEBAR; 2038923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 2039923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2040923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAudioManager.playSoundEffect(sound, FX_VOLUME); 2041923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2042923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2043923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2044409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void vibrate() { 2045923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (!mVibrateOn) { 2046923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 2047923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 20481679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); 20491679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka if (inputView != null) { 20501679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka inputView.performHapticFeedback( 2051979f8690967ff5409fe18f5085858ccdb8e0ccf1satok HapticFeedbackConstants.KEYBOARD_TAP, 205266a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); 2053923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2054923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2055923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 205671c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka public void promoteToUserDictionary(String word, int frequency) { 205734386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani if (mUserDictionary.isValidWord(word)) return; 205834386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani mUserDictionary.addWord(word, frequency); 205934386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani } 206034386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani 206171c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka public WordComposer getCurrentWord() { 20626516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani return mWord; 20636516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani } 20646516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani 206571c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka public boolean getPopupOn() { 2066979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return mPopupOn; 2067979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 2068979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2069e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private void updateCorrectionMode() { 2070e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mHasDictionary = mSuggest != null ? mSuggest.hasMainDictionary() : false; 2071e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mAutoCorrectOn = (mAutoCorrectEnabled || mQuickFixes) 2072e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani && !mInputTypeNoAutoCorrect && mHasDictionary; 207332e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani mCorrectionMode = (mAutoCorrectOn && mAutoCorrectEnabled) 2074e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani ? Suggest.CORRECTION_FULL 207532e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani : (mAutoCorrectOn ? Suggest.CORRECTION_BASIC : Suggest.CORRECTION_NONE); 2076979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mCorrectionMode = (mBigramSuggestionEnabled && mAutoCorrectOn && mAutoCorrectEnabled) 2077979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ? Suggest.CORRECTION_FULL_BIGRAM : mCorrectionMode; 2078e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani if (mSuggest != null) { 2079e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mSuggest.setCorrectionMode(mCorrectionMode); 2080e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani } 2081e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani } 2082e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani 20830ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private void updateAutoTextEnabled() { 208432e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani if (mSuggest == null) return; 20850ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mSuggest.setAutoTextEnabled(mQuickFixes 20864ab730dbd34fad323063f2ffd31ce33de746668dsatok && SubtypeSwitcher.getInstance().isSystemLanguageSameAsInputLanguage()); 208732e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 208832e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani 20897599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private void updateSuggestionVisibility(SharedPreferences prefs) { 2090458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa final Resources res = mResources; 20917599cfea4a2d56f4779452ec8e8742f7b9629cc0satok final String suggestionVisiblityStr = prefs.getString( 20929502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka Settings.PREF_SHOW_SUGGESTIONS_SETTING, 2093458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa res.getString(R.string.prefs_suggestion_visibility_default_value)); 20947599cfea4a2d56f4779452ec8e8742f7b9629cc0satok for (int visibility : SUGGESTION_VISIBILITY_VALUE_ARRAY) { 2095458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa if (suggestionVisiblityStr.equals(res.getString(visibility))) { 20967599cfea4a2d56f4779452ec8e8742f7b9629cc0satok mSuggestionVisibility = visibility; 20977599cfea4a2d56f4779452ec8e8742f7b9629cc0satok break; 20987599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 20997599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 21007599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 21017599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 2102466741d8a78965b8509bf527344f289e50873092Mike LeBeau protected void launchSettings() { 21039502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka launchSettings(Settings.class); 2104466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 2105466741d8a78965b8509bf527344f289e50873092Mike LeBeau 2106bf96661d33d0126adb60a48880ceba1ff055d4a4satok public void launchDebugSettings() { 21079502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka launchSettings(DebugSettings.class); 2108bf96661d33d0126adb60a48880ceba1ff055d4a4satok } 2109bf96661d33d0126adb60a48880ceba1ff055d4a4satok 2110507495efd57074994fdc2fda78db9d5345f4a3a8Tadashi G. Takaoka protected void launchSettings(Class<? extends PreferenceActivity> settingsClass) { 2111923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project handleClose(); 2112923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Intent intent = new Intent(); 2113466741d8a78965b8509bf527344f289e50873092Mike LeBeau intent.setClass(LatinIME.this, settingsClass); 2114923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2115923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project startActivity(intent); 2116923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2117923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2118507495efd57074994fdc2fda78db9d5345f4a3a8Tadashi G. Takaoka private void loadSettings(EditorInfo attribute) { 2119923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Get the settings preferences 212027d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa final SharedPreferences prefs = mPrefs; 21214174655e23734563775acb9e1e644b31b9e72fa5Ken Wakasa Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); 21224174655e23734563775acb9e1e644b31b9e72fa5Ken Wakasa mVibrateOn = vibrator != null && vibrator.hasVibrator() 21239502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka && prefs.getBoolean(Settings.PREF_VIBRATE_ON, false); 21249502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka mSoundOn = prefs.getBoolean(Settings.PREF_SOUND_ON, false); 2125728115493e14f84d5f02a4812c8086a378813364Jean Chalard 2126728115493e14f84d5f02a4812c8086a378813364Jean Chalard mPopupOn = isPopupEnabled(prefs); 21279502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true); 212889764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard mQuickFixes = isQuickFixesEnabled(prefs); 2129a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 213027d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa mAutoCorrectEnabled = isAutoCorrectEnabled(prefs); 213127d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa mBigramSuggestionEnabled = mAutoCorrectEnabled && isBigramSuggestionEnabled(prefs); 21321b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka loadAndSetAutoCorrectionThreshold(prefs); 2133466741d8a78965b8509bf527344f289e50873092Mike LeBeau 213427d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa mVoiceConnector.loadSettings(attribute, prefs); 2135409220583333bdf06290dd9fd42f91b5c0d1b11asatok 2136e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani updateCorrectionMode(); 21370ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok updateAutoTextEnabled(); 213827d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa updateSuggestionVisibility(prefs); 213927d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa SubtypeSwitcher.getInstance().loadSettings(); 214036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 214136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 2142b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda /** 21431b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka * Load Auto correction threshold from SharedPreferences, and modify mSuggest's threshold. 2144b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda */ 21451b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka private void loadAndSetAutoCorrectionThreshold(SharedPreferences sp) { 2146b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda // When mSuggest is not initialized, cannnot modify mSuggest's threshold. 2147b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda if (mSuggest == null) return; 21481b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka // When auto correction setting is turned off, the threshold is ignored. 2149b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda if (!isAutoCorrectEnabled(sp)) return; 2150b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda 21511b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final String currentAutoCorrectionSetting = sp.getString( 21521b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka Settings.PREF_AUTO_CORRECTION_THRESHOLD, 21539ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka mResources.getString(R.string.auto_correction_threshold_mode_index_modest)); 21541b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final String[] autoCorrectionThresholdValues = mResources.getStringArray( 21559ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka R.array.auto_correction_threshold_values); 21561b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka // When autoCrrectionThreshold is greater than 1.0, auto correction is virtually turned off. 21571b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka double autoCorrectionThreshold = Double.MAX_VALUE; 2158b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda try { 21591b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final int arrayIndex = Integer.valueOf(currentAutoCorrectionSetting); 21601b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (arrayIndex >= 0 && arrayIndex < autoCorrectionThresholdValues.length) { 21611b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka autoCorrectionThreshold = Double.parseDouble( 21621b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka autoCorrectionThresholdValues[arrayIndex]); 2163b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda } 2164b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda } catch (NumberFormatException e) { 21651b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka // Whenever the threshold settings are correct, never come here. 21661b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka autoCorrectionThreshold = Double.MAX_VALUE; 21671b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka Log.w(TAG, "Cannot load auto correction threshold setting." 21681b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka + " currentAutoCorrectionSetting: " + currentAutoCorrectionSetting 21691b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka + ", autoCorrectionThresholdValues: " 21701b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka + Arrays.toString(autoCorrectionThresholdValues)); 2171b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda } 2172b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda // TODO: This should be refactored : 21731b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka // setAutoCorrectionThreshold should be called outside of this method. 21741b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mSuggest.setAutoCorrectionThreshold(autoCorrectionThreshold); 2175b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda } 2176b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda 2177728115493e14f84d5f02a4812c8086a378813364Jean Chalard private boolean isPopupEnabled(SharedPreferences sp) { 2178728115493e14f84d5f02a4812c8086a378813364Jean Chalard final boolean showPopupOption = getResources().getBoolean( 2179728115493e14f84d5f02a4812c8086a378813364Jean Chalard R.bool.config_enable_show_popup_on_keypress_option); 2180728115493e14f84d5f02a4812c8086a378813364Jean Chalard if (!showPopupOption) return mResources.getBoolean(R.bool.config_default_popup_preview); 2181728115493e14f84d5f02a4812c8086a378813364Jean Chalard return sp.getBoolean(Settings.PREF_POPUP_ON, 2182728115493e14f84d5f02a4812c8086a378813364Jean Chalard mResources.getBoolean(R.bool.config_default_popup_preview)); 2183728115493e14f84d5f02a4812c8086a378813364Jean Chalard } 2184728115493e14f84d5f02a4812c8086a378813364Jean Chalard 218589764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard private boolean isQuickFixesEnabled(SharedPreferences sp) { 218689764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard final boolean showQuickFixesOption = mResources.getBoolean( 218789764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard R.bool.config_enable_quick_fixes_option); 218889764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard if (!showQuickFixesOption) { 218989764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard return isAutoCorrectEnabled(sp); 219089764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard } 219189764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard return sp.getBoolean(Settings.PREF_QUICK_FIXES, mResources.getBoolean( 219289764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard R.bool.config_default_quick_fixes)); 219389764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard } 219489764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard 2195b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda private boolean isAutoCorrectEnabled(SharedPreferences sp) { 21961b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final String currentAutoCorrectionSetting = sp.getString( 21971b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka Settings.PREF_AUTO_CORRECTION_THRESHOLD, 21989ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka mResources.getString(R.string.auto_correction_threshold_mode_index_modest)); 21991b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final String autoCorrectionOff = mResources.getString( 22009ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka R.string.auto_correction_threshold_mode_index_off); 22011b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka return !currentAutoCorrectionSetting.equals(autoCorrectionOff); 2202b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda } 2203b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda 2204b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda private boolean isBigramSuggestionEnabled(SharedPreferences sp) { 220589764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard final boolean showBigramSuggestionsOption = mResources.getBoolean( 220689764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard R.bool.config_enable_bigram_suggestions_option); 220789764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard if (!showBigramSuggestionsOption) { 220889764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard return isAutoCorrectEnabled(sp); 220989764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard } 221089764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard return sp.getBoolean(Settings.PREF_BIGRAM_SUGGESTIONS, mResources.getBoolean( 221189764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard R.bool.config_default_bigram_suggestions)); 2212b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda } 2213b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda 22146a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani private void initSuggestPuncList() { 22157e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka if (mSuggestPuncs != null || mSuggestPuncList != null) 22167e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka return; 22177e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords.Builder builder = new SuggestedWords.Builder(); 22187e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka String puncs = mResources.getString(R.string.suggested_punctuations); 22197e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka if (puncs != null) { 22207e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka for (int i = 0; i < puncs.length(); i++) { 22217e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka builder.addWord(puncs.subSequence(i, i + 1)); 22226a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 22236a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 22247e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka mSuggestPuncList = builder.build(); 22257e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka mSuggestPuncs = puncs; 22266a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 22276a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 2228979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private boolean isSuggestedPunctuation(int code) { 2229979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return mSuggestPuncs.contains(String.valueOf((char)code)); 2230979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 2231979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 22322fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private void showSubtypeSelectorAndSettings() { 223385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence title = getString(R.string.english_ime_input_options); 223485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence[] items = new CharSequence[] { 223585996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka // TODO: Should use new string "Select active input modes". 223685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.language_selection_title), 223785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.english_ime_settings), 223885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 223985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 22402fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka @Override 22412fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka public void onClick(DialogInterface di, int position) { 22422fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka di.dismiss(); 22432fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka switch (position) { 224485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 0: 22452fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka Intent intent = new Intent( 22462fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka android.provider.Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS); 22472fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 22482fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 22492fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_CLEAR_TOP); 22502fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka intent.putExtra(android.provider.Settings.EXTRA_INPUT_METHOD_ID, 22512fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka mInputMethodId); 22522fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka startActivity(intent); 22532fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 2254aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa case 1: 2255aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa launchSettings(); 2256aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa break; 22572fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 22582fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 225985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 226085996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka showOptionsMenuInternal(title, items, listener); 22612fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 2262923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 22632fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private void showOptionsMenu() { 226485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence title = getString(R.string.english_ime_input_options); 226585996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence[] items = new CharSequence[] { 226685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.selectInputMethod), 226785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.english_ime_settings), 226885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 226985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 22705a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 2271923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onClick(DialogInterface di, int position) { 2272923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project di.dismiss(); 2273923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (position) { 227485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 0: 22752fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka launchSettings(); 22762fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 227785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 1: 22782fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka mImm.showInputMethodPicker(); 22792fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 2280923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2281923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 228285996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 228385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka showOptionsMenuInternal(title, items, listener); 22842fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 22852fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka 228685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka private void showOptionsMenuInternal(CharSequence title, CharSequence[] items, 228785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka DialogInterface.OnClickListener listener) { 22882fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka AlertDialog.Builder builder = new AlertDialog.Builder(this); 22892fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka builder.setCancelable(true); 22902fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka builder.setIcon(R.drawable.ic_dialog_keyboard); 22912fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka builder.setNegativeButton(android.R.string.cancel, null); 229285996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka builder.setItems(items, listener); 229385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka builder.setTitle(title); 2294923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mOptionsDialog = builder.create(); 2295a2ad96d95986eb61c3d2d5abce154fb4c3803cacTadashi G. Takaoka mOptionsDialog.setCanceledOnTouchOutside(true); 2296923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Window window = mOptionsDialog.getWindow(); 2297923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project WindowManager.LayoutParams lp = window.getAttributes(); 2298979f8690967ff5409fe18f5085858ccdb8e0ccf1satok lp.token = mKeyboardSwitcher.getInputView().getWindowToken(); 2299923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 2300923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project window.setAttributes(lp); 2301923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 2302923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mOptionsDialog.show(); 2303923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2304923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 23057e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 23067e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { 2307923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.dump(fd, fout, args); 2308a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2309923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final Printer p = new PrintWriterPrinter(fout); 2310923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println("LatinIME state :"); 2311923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" Keyboard mode = " + mKeyboardSwitcher.getKeyboardMode()); 2312923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mComposing=" + mComposing.toString()); 23139fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka p.println(" mIsSuggestionsRequested=" + mIsSettingsSuggestionStripOn); 2314923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mCorrectionMode=" + mCorrectionMode); 23159fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka p.println(" mHasValidSuggestions=" + mHasValidSuggestions); 2316923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mAutoCorrectOn=" + mAutoCorrectOn); 2317923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mAutoSpace=" + mAutoSpace); 23181b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka p.println(" mApplicationSpecifiedCompletionOn=" + mApplicationSpecifiedCompletionOn); 2319923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" TextEntryState.state=" + TextEntryState.getState()); 2320923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mSoundOn=" + mSoundOn); 2321923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mVibrateOn=" + mVibrateOn); 2322979f8690967ff5409fe18f5085858ccdb8e0ccf1satok p.println(" mPopupOn=" + mPopupOn); 2323923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 23246e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani 2325923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Characters per second measurement 2326a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2327923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long mLastCpsTime; 2328923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int CPS_BUFFER_SIZE = 16; 2329923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long[] mCpsIntervals = new long[CPS_BUFFER_SIZE]; 2330923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mCpsIndex; 2331a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2332923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void measureCps() { 2333923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long now = System.currentTimeMillis(); 2334923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mLastCpsTime == 0) mLastCpsTime = now - 100; // Initial 2335923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCpsIntervals[mCpsIndex] = now - mLastCpsTime; 2336923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mLastCpsTime = now; 2337923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCpsIndex = (mCpsIndex + 1) % CPS_BUFFER_SIZE; 2338923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long total = 0; 2339923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project for (int i = 0; i < CPS_BUFFER_SIZE; i++) total += mCpsIntervals[i]; 2340923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project System.out.println("CPS = " + ((CPS_BUFFER_SIZE * 1000f) / total)); 2341923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 234234386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani 23430ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok @Override 23440ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) { 23454ab730dbd34fad323063f2ffd31ce33de746668dsatok SubtypeSwitcher.getInstance().updateSubtype(subtype); 23460ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok } 2347923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 2348