LatinIME.java revision 7e99a28dfcc14f5b19220442db972ca8d786b4fe
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; 21571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardSwitcher; 225a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardView; 23de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaokaimport com.android.inputmethod.keyboard.LatinKeyboard; 245a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokaimport com.android.inputmethod.keyboard.LatinKeyboardView; 259502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaokaimport com.android.inputmethod.latin.Utils.RingCharBuffer; 26409220583333bdf06290dd9fd42f91b5c0d1b11asatokimport com.android.inputmethod.voice.VoiceIMEConnector; 27388ce92ab8a635c5ad44620dad59baf05dfea510Amith Yamasani 28923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.app.AlertDialog; 29923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.BroadcastReceiver; 30923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Context; 31923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.DialogInterface; 32923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Intent; 33923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.IntentFilter; 34923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.SharedPreferences; 35923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.res.Configuration; 3636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasaniimport android.content.res.Resources; 37923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.inputmethodservice.InputMethodService; 38923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.media.AudioManager; 39123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaokaimport android.net.ConnectivityManager; 40923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Debug; 41923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Handler; 4218e15a1e5e30cf200e935e43a73edef25682de27Ken Wakasaimport android.os.IBinder; 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 */ 849a5d2ba03e7c8caf82cce64aa254d2177a72a8cfJean Chalardpublic class LatinIME extends InputMethodService implements KeyboardActionListener { 858efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka private static final String TAG = LatinIME.class.getSimpleName(); 86979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private static final boolean PERF_DEBUG = false; 87409220583333bdf06290dd9fd42f91b5c0d1b11asatok private static final boolean TRACE = false; 88910b73127fa207dd26ec8124000262523b0aac0csatok private static boolean DEBUG = LatinImeLogger.sDBG; 89a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 908efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka /** 918efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * The private IME option used to indicate that no microphone should be 928efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * shown for a given text field. For instance, this is specified by the 938efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * search dialog when the dialog is already showing a voice search button. 948efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * 958efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * @deprecated Use {@link LatinIME#IME_OPTION_NO_MICROPHONE} with package name prefixed. 968efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka */ 978efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka public static final String IME_OPTION_NO_MICROPHONE_COMPAT = "nm"; 988efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka 998efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka /** 1008efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * The private IME option used to indicate that no microphone should be 1018efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * shown for a given text field. For instance, this is specified by the 1028efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * search dialog when the dialog is already showing a voice search button. 1038efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka */ 1044199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka public static final String IME_OPTION_NO_MICROPHONE = "noMicrophoneKey"; 1054199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka 1064199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka /** 1074199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka * The private IME option used to indicate that no settings key should be 1084199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka * shown for a given text field. 1094199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka */ 1104199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka public static final String IME_OPTION_NO_SETTINGS_KEY = "noSettingsKey"; 1118efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka 112fd0bd57deb53c4cce32810a61133fa44b45dbb7bKen Wakasa private static final int DELAY_UPDATE_SUGGESTIONS = 180; 113fd0bd57deb53c4cce32810a61133fa44b45dbb7bKen Wakasa private static final int DELAY_UPDATE_OLD_SUGGESTIONS = 300; 114d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int DELAY_UPDATE_SHIFT_STATE = 300; 1159e347d3d448e48229c46aad394ec9bd60cd5807bsatok private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100; 116fd0bd57deb53c4cce32810a61133fa44b45dbb7bKen Wakasa 117923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // How many continuous deletes at which to start deleting at a higher speed. 118923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int DELETE_ACCELERATE_AT = 20; 119923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Key events coming any faster than this are long-presses. 120d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani private static final int QUICK_PRESS = 200; 121a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1227599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private int mSuggestionVisibility; 1237599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_SHOW_VALUE 1247599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_show_value; 1257599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE 1267599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_show_only_portrait_value; 1277599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_HIDE_VALUE 1287599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_hide_value; 1297599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 1307599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int[] SUGGESTION_VISIBILITY_VALUE_ARRAY = new int[] { 1317599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_SHOW_VALUE, 1327599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE, 1337599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_HIDE_VALUE 1347599cfea4a2d56f4779452ec8e8742f7b9629cc0satok }; 1357599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 136e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka private View mCandidateViewContainer; 137923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private CandidateView mCandidateView; 138923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private Suggest mSuggest; 1391b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka private CompletionInfo[] mApplicationSpecifiedCompletions; 140a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 141923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private AlertDialog mOptionsDialog; 142a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 14379efbed76f638be298493107fa2d0cd1b5eb529esatok private InputMethodManager mImm; 1442fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private Resources mResources; 1452fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private SharedPreferences mPrefs; 1462fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private String mInputMethodId; 14771c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka private KeyboardSwitcher mKeyboardSwitcher; 1480ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private SubtypeSwitcher mSubtypeSwitcher; 149409220583333bdf06290dd9fd42f91b5c0d1b11asatok private VoiceIMEConnector mVoiceConnector; 150a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 151923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private UserDictionary mUserDictionary; 152979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private UserBigramDictionary mUserBigramDictionary; 1532bed1531c2c9bd48096bfa97dd1a39e04bd15e7bEric Fischer private ContactsDictionary mContactsDictionary; 1544ff60be170872503cca0275ef3488b7379b5311bAmith Yamasani private AutoDictionary mAutoDictionary; 15536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 156c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // These variables are initialized according to the {@link EditorInfo#inputType}. 157c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mAutoSpace; 158c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mInputTypeNoAutoCorrect; 159c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mIsSettingsSuggestionStripOn; 160c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mApplicationSpecifiedCompletionOn; 161c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 162dcade18113286a132a2f5fb508fdba836470c3fbAlan Viverette private AccessibilityUtils mAccessibilityUtils; 163dcade18113286a132a2f5fb508fdba836470c3fbAlan Viverette 16471c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka private final StringBuilder mComposing = new StringBuilder(); 165923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private WordComposer mWord = new WordComposer(); 166923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private CharSequence mBestWord; 1679fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka private boolean mHasValidSuggestions; 168e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private boolean mHasDictionary; 1699a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa private boolean mJustAddedAutoSpace; 170e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private boolean mAutoCorrectEnabled; 171952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa private boolean mRecorrectionEnabled; 172979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private boolean mBigramSuggestionEnabled; 173923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mAutoCorrectOn; 174923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mVibrateOn; 175923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mSoundOn; 176979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private boolean mPopupOn; 177923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mAutoCap; 1786e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani private boolean mQuickFixes; 1792fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private boolean mConfigEnableShowSubtypeSettings; 180363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka private boolean mConfigSwipeDownDismissKeyboardEnabled; 181de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka private int mConfigDelayBeforeFadeoutLanguageOnSpacebar; 182de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka private int mConfigDurationOfFadeoutLanguageOnSpacebar; 183d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka private float mConfigFinalFadeoutFactorOfLanguageOnSpacebar; 184409220583333bdf06290dd9fd42f91b5c0d1b11asatok 18579efbed76f638be298493107fa2d0cd1b5eb529esatok private int mCorrectionMode; 18679efbed76f638be298493107fa2d0cd1b5eb529esatok private int mCommittedLength; 18779efbed76f638be298493107fa2d0cd1b5eb529esatok private int mOrientation; 188979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Keep track of the last selection range to decide if we need to show word alternatives 18979efbed76f638be298493107fa2d0cd1b5eb529esatok private int mLastSelectionStart; 19079efbed76f638be298493107fa2d0cd1b5eb529esatok private int mLastSelectionEnd; 1917e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka private SuggestedWords mSuggestPuncList; 192979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 193923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Indicates whether the suggestion strip is to be on in landscape 194923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mJustAccepted; 195c1e2e827b5d1bba59eb99d322dc101657ec28768Ken Wakasa private boolean mJustReverted; 196923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mDeleteCount; 197923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long mLastKeyTime; 198a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 199923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private AudioManager mAudioManager; 2002296317b8f0209789f797ac8a2fcb70e03f6d001Eric Laurent // Align sound effect volume on music volume 20171c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka private static final float FX_VOLUME = -1.0f; 202923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mSilentMode; 203923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 204979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /* package */ String mWordSeparators; 205923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private String mSentenceSeparators; 206979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private String mSuggestPuncs; 207409220583333bdf06290dd9fd42f91b5c0d1b11asatok // TODO: Move this flag to VoiceIMEConnector 20881c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani private boolean mConfigurationChanging; 209466741d8a78965b8509bf527344f289e50873092Mike LeBeau 210dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani // Keeps track of most recently inserted text (multi-character key) for reverting 211dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani private CharSequence mEnteredText; 212dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 21371c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka private final ArrayList<WordAlternatives> mWordHistory = new ArrayList<WordAlternatives>(); 214979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 215979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public abstract static class WordAlternatives { 216979f8690967ff5409fe18f5085858ccdb8e0ccf1satok protected CharSequence mChosenWord; 2174f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 218979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public WordAlternatives() { 219979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Nothing 220979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 221979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 222979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public WordAlternatives(CharSequence chosenWord) { 223979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mChosenWord = chosenWord; 224979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 225979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 226979f8690967ff5409fe18f5085858ccdb8e0ccf1satok @Override 227979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public int hashCode() { 228979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return mChosenWord.hashCode(); 229979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 230979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 231979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public abstract CharSequence getOriginalWord(); 232979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 233979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public CharSequence getChosenWord() { 234979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return mChosenWord; 235979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 236979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2377e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka public abstract SuggestedWords.Builder getAlternatives(); 238979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 239979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 240979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public class TypedWordAlternatives extends WordAlternatives { 241979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private WordComposer word; 242979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 243979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public TypedWordAlternatives() { 244979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Nothing 245979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 246979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 247979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public TypedWordAlternatives(CharSequence chosenWord, WordComposer wordComposer) { 248979f8690967ff5409fe18f5085858ccdb8e0ccf1satok super(chosenWord); 249979f8690967ff5409fe18f5085858ccdb8e0ccf1satok word = wordComposer; 250979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 251979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 252979f8690967ff5409fe18f5085858ccdb8e0ccf1satok @Override 253979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public CharSequence getOriginalWord() { 254979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return word.getTypedWord(); 255979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 256979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 257979f8690967ff5409fe18f5085858ccdb8e0ccf1satok @Override 2587e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka public SuggestedWords.Builder getAlternatives() { 259979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return getTypedSuggestions(word); 260979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 261979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 26236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 263571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka public final UIHandler mHandler = new UIHandler(); 264d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 265409220583333bdf06290dd9fd42f91b5c0d1b11asatok public class UIHandler extends Handler { 266d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_UPDATE_SUGGESTIONS = 0; 267d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_UPDATE_OLD_SUGGESTIONS = 1; 268d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_UPDATE_SHIFT_STATE = 2; 269d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_VOICE_RESULTS = 3; 270de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka private static final int MSG_FADEOUT_LANGUAGE_ON_SPACEBAR = 4; 271de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 5; 272d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 273923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 274923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void handleMessage(Message msg) { 275de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 276de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka final LatinKeyboardView inputView = switcher.getInputView(); 277923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (msg.what) { 278d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SUGGESTIONS: 279d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka updateSuggestions(); 280d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 281d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_OLD_SUGGESTIONS: 282d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka setOldSuggestions(); 283d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 284d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SHIFT_STATE: 285de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka switcher.updateShiftState(); 286d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 287d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_VOICE_RESULTS: 288e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mVoiceConnector.handleVoiceResults(preferCapitalization() 289de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka || (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked())); 290de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka break; 291de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka case MSG_FADEOUT_LANGUAGE_ON_SPACEBAR: 292de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka if (inputView != null) 29366432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka inputView.setSpacebarTextFadeFactor( 294d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka (1.0f + mConfigFinalFadeoutFactorOfLanguageOnSpacebar) / 2, 29566432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka (LatinKeyboard)msg.obj); 296de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_DISMISS_LANGUAGE_ON_SPACEBAR, msg.obj), 297de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka mConfigDurationOfFadeoutLanguageOnSpacebar); 298de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka break; 299de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka case MSG_DISMISS_LANGUAGE_ON_SPACEBAR: 300de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka if (inputView != null) 30166432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka inputView.setSpacebarTextFadeFactor( 302d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka mConfigFinalFadeoutFactorOfLanguageOnSpacebar, (LatinKeyboard)msg.obj); 303d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 304923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 305923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 306d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 307d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateSuggestions() { 308d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 309d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTIONS), DELAY_UPDATE_SUGGESTIONS); 310d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 311d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 312d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateSuggestions() { 313d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 314d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 315d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 316d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public boolean hasPendingUpdateSuggestions() { 317d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka return hasMessages(MSG_UPDATE_SUGGESTIONS); 318d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 319d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 320d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateOldSuggestions() { 321d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_OLD_SUGGESTIONS); 322d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_UPDATE_OLD_SUGGESTIONS), 323d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka DELAY_UPDATE_OLD_SUGGESTIONS); 324d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 325d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 326d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateOldSuggestions() { 327d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_OLD_SUGGESTIONS); 328d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 329d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 330d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateShiftKeyState() { 331d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 332d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_UPDATE_SHIFT_STATE), DELAY_UPDATE_SHIFT_STATE); 333d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 334d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 335d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateShiftState() { 336d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 337d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 338d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 339d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void updateVoiceResults() { 340d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka sendMessage(obtainMessage(MSG_VOICE_RESULTS)); 341d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 342de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka 343d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka public void startDisplayLanguageOnSpacebar(boolean localeChanged) { 344de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka removeMessages(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR); 345de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka removeMessages(MSG_DISMISS_LANGUAGE_ON_SPACEBAR); 346de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka final LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); 347de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka if (inputView != null) { 348050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka final LatinKeyboard keyboard = mKeyboardSwitcher.getLatinKeyboard(); 349de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka // The language is never displayed when the delay is zero. 350de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka if (mConfigDelayBeforeFadeoutLanguageOnSpacebar != 0) 351d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka inputView.setSpacebarTextFadeFactor(localeChanged ? 1.0f 352d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka : mConfigFinalFadeoutFactorOfLanguageOnSpacebar, keyboard); 353de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka // The language is always displayed when the delay is negative. 354d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka if (localeChanged && mConfigDelayBeforeFadeoutLanguageOnSpacebar > 0) { 355de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR, keyboard), 356de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka mConfigDelayBeforeFadeoutLanguageOnSpacebar); 357de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 358de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 359de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 360d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 361923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 3627e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 3637e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka public void onCreate() { 36427d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 36527d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa mPrefs = prefs; 36627d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa LatinImeLogger.init(this, prefs); 36727d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa SubtypeSwitcher.init(this, prefs); 36827d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa KeyboardSwitcher.init(this, prefs); 369dcade18113286a132a2f5fb508fdba836470c3fbAlan Viverette AccessibilityUtils.init(this, prefs); 370363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 371923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onCreate(); 372363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 37379efbed76f638be298493107fa2d0cd1b5eb529esatok mImm = ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)); 3748efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka mInputMethodId = Utils.getInputMethodId(mImm, getPackageName()); 3750ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mSubtypeSwitcher = SubtypeSwitcher.getInstance(); 3760ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mKeyboardSwitcher = KeyboardSwitcher.getInstance(); 377dcade18113286a132a2f5fb508fdba836470c3fbAlan Viverette mAccessibilityUtils = AccessibilityUtils.getInstance(); 378363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 379363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka final Resources res = getResources(); 380363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka mResources = res; 381fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard 382fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard // If the option should not be shown, do not read the recorrection preference 383fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard // but always use the default setting defined in the resources. 384fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard if (res.getBoolean(R.bool.config_enable_show_recorrection_option)) { 385952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa mRecorrectionEnabled = prefs.getBoolean(Settings.PREF_RECORRECTION_ENABLED, 386f0d99b8677afdde39c16d414d44bfafcaea94b50Jean Chalard res.getBoolean(R.bool.config_default_recorrection_enabled)); 387fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard } else { 388952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa mRecorrectionEnabled = res.getBoolean(R.bool.config_default_recorrection_enabled); 389fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard } 390fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard 3912fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka mConfigEnableShowSubtypeSettings = res.getBoolean( 3922fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka R.bool.config_enable_show_subtype_settings); 393363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka mConfigSwipeDownDismissKeyboardEnabled = res.getBoolean( 394363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka R.bool.config_swipe_down_dismiss_keyboard_enabled); 395de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka mConfigDelayBeforeFadeoutLanguageOnSpacebar = res.getInteger( 396de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka R.integer.config_delay_before_fadeout_language_on_spacebar); 397de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka mConfigDurationOfFadeoutLanguageOnSpacebar = res.getInteger( 398de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka R.integer.config_duration_of_fadeout_language_on_spacebar); 399d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka mConfigFinalFadeoutFactorOfLanguageOnSpacebar = res.getInteger( 40066432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka R.integer.config_final_fadeout_percentage_of_language_on_spacebar) / 100.0f; 401979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 4029502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka Utils.GCUtils.getInstance().reset(); 403979f8690967ff5409fe18f5085858ccdb8e0ccf1satok boolean tryGC = true; 4049502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { 405979f8690967ff5409fe18f5085858ccdb8e0ccf1satok try { 4060ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 407979f8690967ff5409fe18f5085858ccdb8e0ccf1satok tryGC = false; 408979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } catch (OutOfMemoryError e) { 4099502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka tryGC = Utils.GCUtils.getInstance().tryGCOrWait("InitSuggest", e); 410979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 411979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 412979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 413363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka mOrientation = res.getConfiguration().orientation; 4146a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani initSuggestPuncList(); 415b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 416123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka // register to receive ringer mode change and network state change. 417123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final IntentFilter filter = new IntentFilter(); 418123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); 419123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 420923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project registerReceiver(mReceiver, filter); 42127d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa mVoiceConnector = VoiceIMEConnector.init(this, prefs, mHandler); 422923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 42336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 4240ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private void initSuggest() { 4254ab730dbd34fad323063f2ffd31ce33de746668dsatok String locale = mSubtypeSwitcher.getInputLocaleStr(); 42636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 4270ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok Locale savedLocale = mSubtypeSwitcher.changeSystemLocale(new Locale(locale)); 42836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani if (mSuggest != null) { 42936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mSuggest.close(); 43036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 43127d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa final SharedPreferences prefs = mPrefs; 43289764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard mQuickFixes = isQuickFixesEnabled(prefs); 433979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 434458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa final Resources res = mResources; 4358efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka int mainDicResId = Utils.getMainDictionaryResourceId(res); 436458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa mSuggest = new Suggest(this, mainDicResId); 4371b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka loadAndSetAutoCorrectionThreshold(prefs); 43827023341658b4cf5430d18ddb94fd9502ecfe3cbTadashi G. Takaoka updateAutoTextEnabled(); 439e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 4400ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mUserDictionary = new UserDictionary(this, locale); 441923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mSuggest.setUserDictionary(mUserDictionary); 442e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 443e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mContactsDictionary = new ContactsDictionary(this, Suggest.DIC_CONTACTS); 4442bed1531c2c9bd48096bfa97dd1a39e04bd15e7bEric Fischer mSuggest.setContactsDictionary(mContactsDictionary); 445e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 446e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mAutoDictionary = new AutoDictionary(this, this, locale, Suggest.DIC_AUTO); 44734386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani mSuggest.setAutoDictionary(mAutoDictionary); 448e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 449e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mUserBigramDictionary = new UserBigramDictionary(this, this, locale, Suggest.DIC_USER); 450e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest.setUserBigramDictionary(mUserBigramDictionary); 451e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 452e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani updateCorrectionMode(); 453458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa mWordSeparators = res.getString(R.string.word_separators); 454458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa mSentenceSeparators = res.getString(R.string.sentence_separators); 45536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 4560ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mSubtypeSwitcher.changeSystemLocale(savedLocale); 457923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 45836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 459466741d8a78965b8509bf527344f289e50873092Mike LeBeau @Override 460466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onDestroy() { 461e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa if (mSuggest != null) { 462e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest.close(); 463e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest = null; 464979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 465923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project unregisterReceiver(mReceiver); 466409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.destroy(); 467979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 468979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.onDestroy(); 469923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onDestroy(); 470923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 471923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 472923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 473923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onConfigurationChanged(Configuration conf) { 474dc64b138b5e3fb3706c0818d0a308fe6e36985b0Tadashi G. Takaoka mSubtypeSwitcher.onConfigurationChanged(conf); 475b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani // If orientation changed while predicting, commit the change 476b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani if (conf.orientation != mOrientation) { 477466741d8a78965b8509bf527344f289e50873092Mike LeBeau InputConnection ic = getCurrentInputConnection(); 478466741d8a78965b8509bf527344f289e50873092Mike LeBeau commitTyped(ic); 479466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (ic != null) ic.finishComposingText(); // For voice input 480b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani mOrientation = conf.orientation; 4812fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka if (isShowingOptionDialog()) 4822fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka mOptionsDialog.dismiss(); 483b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 4848b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka 48581c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani mConfigurationChanging = true; 486923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onConfigurationChanged(conf); 487bbd651a00898dabf6b2ae0e715d99953ea81063fLuca Zanolin mVoiceConnector.onConfigurationChanged(conf); 48881c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani mConfigurationChanging = false; 489923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 490b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 491923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 492923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public View onCreateInputView() { 4938d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka return mKeyboardSwitcher.onCreateInputView(); 494923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 495923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 496923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 497923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public View onCreateCandidatesView() { 498e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka LayoutInflater inflater = getLayoutInflater(); 499e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka LinearLayout container = (LinearLayout)inflater.inflate(R.layout.candidates, null); 500e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka mCandidateViewContainer = container; 501e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka if (container.getPaddingRight() != 0) { 502e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka HorizontalScrollView scrollView = 503e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka (HorizontalScrollView) container.findViewById(R.id.candidates_scroll_view); 504e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka scrollView.setOverScrollMode(View.OVER_SCROLL_NEVER); 505e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka container.setGravity(Gravity.CENTER_HORIZONTAL); 506e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka } 507e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka mCandidateView = (CandidateView) container.findViewById(R.id.candidates); 508923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCandidateView.setService(this); 509923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project setCandidatesViewShown(true); 510e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka return container; 511923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 512923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 513a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker @Override 514923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onStartInputView(EditorInfo attribute, boolean restarting) { 51545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 51645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka LatinKeyboardView inputView = switcher.getInputView(); 5178e09172df1bb176cc899940862c56bed9b9aec4esatok 518910b73127fa207dd26ec8124000262523b0aac0csatok if(DEBUG) { 519910b73127fa207dd26ec8124000262523b0aac0csatok Log.d(TAG, "onStartInputView: " + inputView); 520910b73127fa207dd26ec8124000262523b0aac0csatok } 521923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In landscape mode, this method gets called without the input view being created. 522979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (inputView == null) { 523923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 524923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 525923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 5268d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka mSubtypeSwitcher.updateParametersOnStartInputView(); 5274ab730dbd34fad323063f2ffd31ce33de746668dsatok 528923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.newSession(this); 5296c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani 530c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // Most such things we decide below in initializeInputAttributesAndGetMode, but we need to 531c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // know now whether this is a password text field, because we need to know now whether we 532c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // want to enable the voice button. 5334b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka mVoiceConnector.resetVoiceStates(Utils.isPasswordInputType(attribute.inputType) 5344b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka || Utils.isVisiblePasswordInputType(attribute.inputType)); 535c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 536cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka initializeInputAttributes(attribute); 537c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 538c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.closing(); 539c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mEnteredText = null; 540c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mComposing.setLength(0); 541c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mHasValidSuggestions = false; 542c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mDeleteCount = 0; 543c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mJustAddedAutoSpace = false; 544c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 545c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka loadSettings(attribute); 546c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if (mSubtypeSwitcher.isKeyboardMode()) { 547cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka switcher.loadKeyboard(attribute, 548c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mVoiceConnector.isVoiceButtonEnabled(), 549c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mVoiceConnector.isVoiceButtonOnPrimary()); 550c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka switcher.updateShiftState(); 551c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka } 552c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 553c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka setCandidatesViewShownInternal(isCandidateStripVisible(), 554c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka false /* needsInputViewShown */ ); 555c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // Delay updating suggestions because keyboard input view may not be shown at this point. 556c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mHandler.postUpdateSuggestions(); 557c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 558c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka updateCorrectionMode(); 559c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 560dcade18113286a132a2f5fb508fdba836470c3fbAlan Viverette final boolean accessibilityEnabled = mAccessibilityUtils.isAccessibilityEnabled(); 561dcade18113286a132a2f5fb508fdba836470c3fbAlan Viverette 562c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.setPreviewEnabled(mPopupOn); 563c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.setProximityCorrectionEnabled(true); 564dcade18113286a132a2f5fb508fdba836470c3fbAlan Viverette inputView.setAccessibilityEnabled(accessibilityEnabled); 565c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // If we just entered a text field, maybe it has some old text that requires correction 566952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa 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 574cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka private void initializeInputAttributes(EditorInfo attribute) { 575cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if (attribute == null) 576cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka return; 5774b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka final int inputType = attribute.inputType; 578c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka final int variation = inputType & InputType.TYPE_MASK_VARIATION; 579c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mAutoSpace = false; 580e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mInputTypeNoAutoCorrect = false; 5819fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 5821b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletionOn = false; 5831b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletions = null; 584dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 585cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_MASK_CLASS) == InputType.TYPE_CLASS_TEXT) { 586cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = true; 587cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // Make sure that passwords are not displayed in candidate view 588cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if (Utils.isPasswordInputType(inputType) 589cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka || Utils.isVisiblePasswordInputType(inputType)) { 590cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 591cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 592cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if (Utils.isEmailVariation(variation) 593cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka || variation == InputType.TYPE_TEXT_VARIATION_PERSON_NAME) { 594cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mAutoSpace = false; 595cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else { 596cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mAutoSpace = true; 597cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 598cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if (Utils.isEmailVariation(variation)) { 599cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 600cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) { 601cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 602cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) { 603cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 604cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else if (variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) { 605cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // If it's a browser edit field and auto correct is not ON explicitly, then 606cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // disable auto correction, but keep suggestions on. 607cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) { 608e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mInputTypeNoAutoCorrect = true; 60936ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani } 610cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 611cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka 612cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // If NO_SUGGESTIONS is set, don't do prediction. 613cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) { 614cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 615cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mInputTypeNoAutoCorrect = true; 616cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 617cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // If it's not multiline and the autoCorrect flag is not set, then don't correct 618cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 619cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka && (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) == 0) { 620cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mInputTypeNoAutoCorrect = true; 621cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 622cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { 623cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 624cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mApplicationSpecifiedCompletionOn = isFullscreenMode(); 625cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 626923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 627923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 628923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 629952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa private void checkRecorrectionOnStart() { 630952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa if (!mRecorrectionEnabled) return; 631d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa 632d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 633d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa if (ic == null) return; 634d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa // There could be a pending composing span. Clean it up first. 635d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa ic.finishComposingText(); 636d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa 6379fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (isShowingSuggestionsStrip() && isSuggestionsRequested()) { 638b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani // First get the cursor position. This is required by setOldSuggestions(), so that 639b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani // it can pass the correct range to setComposingRegion(). At this point, we don't 6404ca16dbd65150359c3884da7cb59a30f19abd4b7Tadashi G. Takaoka // have valid values for mLastSelectionStart/End because onUpdateSelection() has 641b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani // not been called yet. 642b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani ExtractedTextRequest etr = new ExtractedTextRequest(); 643b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani etr.token = 0; // anything is fine here 644b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani ExtractedText et = ic.getExtractedText(etr, 0); 645b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani if (et == null) return; 646b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani 647b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani mLastSelectionStart = et.startOffset + et.selectionStart; 648b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani mLastSelectionEnd = et.startOffset + et.selectionEnd; 649b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani 650b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani // Then look for possible corrections in a delayed fashion 65155b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa if (!TextUtils.isEmpty(et.text) && isCursorTouchingWord()) { 652d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateOldSuggestions(); 65355b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa } 654b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani } 655b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani } 656b8fa10080dfac777fce7c8a7fc3180e8b540f9f5Amith Yamasani 657923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 658923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onFinishInput() { 659923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onFinishInput(); 660a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 661979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 6621b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mKeyboardSwitcher.onAutoCorrectionStateChanged(false); 663979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 664409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.flushVoiceInputLogs(mConfigurationChanging); 665409220583333bdf06290dd9fd42f91b5c0d1b11asatok 6665a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getInputView(); 667d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa if (inputView != null) inputView.closing(); 6684ff60be170872503cca0275ef3488b7379b5311bAmith Yamasani if (mAutoDictionary != null) mAutoDictionary.flushPendingWrites(); 669979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mUserBigramDictionary != null) mUserBigramDictionary.flushPendingWrites(); 670466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 671466741d8a78965b8509bf527344f289e50873092Mike LeBeau 672466741d8a78965b8509bf527344f289e50873092Mike LeBeau @Override 6736495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa public void onFinishInputView(boolean finishingInput) { 6746495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa super.onFinishInputView(finishingInput); 6755a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getInputView(); 676d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa if (inputView != null) inputView.setForeground(false); 677d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka // Remove pending messages related to update suggestions 678d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 679d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateOldSuggestions(); 6806495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa } 6816495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa 6826495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa @Override 683466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onUpdateExtractedText(int token, ExtractedText text) { 684466741d8a78965b8509bf527344f289e50873092Mike LeBeau super.onUpdateExtractedText(token, text); 685409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.showPunctuationHintIfNecessary(); 686923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 687923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 688923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 689923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onUpdateSelection(int oldSelStart, int oldSelEnd, 690923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int newSelStart, int newSelEnd, 691923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int candidatesStart, int candidatesEnd) { 692923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, 693923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project candidatesStart, candidatesEnd); 694466741d8a78965b8509bf527344f289e50873092Mike LeBeau 695466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (DEBUG) { 696466741d8a78965b8509bf527344f289e50873092Mike LeBeau Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart 697466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", ose=" + oldSelEnd 698025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa + ", lss=" + mLastSelectionStart 699025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa + ", lse=" + mLastSelectionEnd 700466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nss=" + newSelStart 701466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nse=" + newSelEnd 702466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", cs=" + candidatesStart 703466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", ce=" + candidatesEnd); 704466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 705466741d8a78965b8509bf527344f289e50873092Mike LeBeau 706409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.setCursorAndSelection(newSelEnd, newSelStart); 7074f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 708923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // If the current selection in the text view changes, we should 709923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // clear whatever candidate text we have. 710025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa final boolean selectionChanged = (newSelStart != candidatesEnd 711025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa || newSelEnd != candidatesEnd) && mLastSelectionStart != newSelStart; 712025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa final boolean candidatesCleared = candidatesStart == -1 && candidatesEnd == -1; 713025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa if (((mComposing.length() > 0 && mHasValidSuggestions) 714025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa || mVoiceConnector.isVoiceInputHighlighted()) 715025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa && (selectionChanged || candidatesCleared)) { 716025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa if (candidatesCleared) { 717025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa // If the composing span has been cleared, save the typed word in the history for 718025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa // recorrection before we reset the candidate strip. Then, we'll be able to show 719025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa // suggestions for recorrection right away. 720025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa saveWordInHistory(mComposing); 721025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa } 722923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mComposing.setLength(0); 7239fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mHasValidSuggestions = false; 724d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 725923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.reset(); 726923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 727923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 728923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.finishComposingText(); 729923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 730409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.setVoiceInputHighlighted(false); 7319fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka } else if (!mHasValidSuggestions && !mJustAccepted) { 7329a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa switch (TextEntryState.getState()) { 733e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case ACCEPTED_DEFAULT: 734e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka TextEntryState.reset(); 735e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka // $FALL-THROUGH$ 736e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case SPACE_AFTER_PICKED: 737e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mJustAddedAutoSpace = false; // The user moved the cursor. 738e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 739e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka default: 740e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 7419a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 742923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 743923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mJustAccepted = false; 744d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateShiftKeyState(); 745466741d8a78965b8509bf527344f289e50873092Mike LeBeau 746979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Make a note of the cursor position 747979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionStart = newSelStart; 748979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionEnd = newSelEnd; 749466741d8a78965b8509bf527344f289e50873092Mike LeBeau 750952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa if (mRecorrectionEnabled && isShowingSuggestionsStrip()) { 75166b42a1c2d38813be104a7f0435ec6e6ec1c6e65satok // Don't look for corrections if the keyboard is not visible 7521679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka if (mKeyboardSwitcher.isInputViewShown()) { 75366b42a1c2d38813be104a7f0435ec6e6ec1c6e65satok // Check if we should go in or out of correction mode. 7549fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (isSuggestionsRequested() && !mJustReverted 75566b42a1c2d38813be104a7f0435ec6e6ec1c6e65satok && (candidatesStart == candidatesEnd || newSelStart != oldSelStart 756952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa || TextEntryState.isRecorrecting()) 7579fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka && (newSelStart < newSelEnd - 1 || !mHasValidSuggestions)) { 75866b42a1c2d38813be104a7f0435ec6e6ec1c6e65satok if (isCursorTouchingWord() || mLastSelectionStart < mLastSelectionEnd) { 759d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateOldSuggestions(); 76066b42a1c2d38813be104a7f0435ec6e6ec1c6e65satok } else { 761952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa abortRecorrection(false); 76255b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // Show the punctuation suggestions list if the current one is not 763364da8c618303a7764595d2c15ee034a7671365dKen Wakasa // and if not showing "Touch again to save". 7647599cfea4a2d56f4779452ec8e8742f7b9629cc0satok if (mCandidateView != null && !isShowingPunctuationList() 7657599cfea4a2d56f4779452ec8e8742f7b9629cc0satok && !mCandidateView.isShowingAddToDictionaryHint()) { 766ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setPunctuationSuggestions(); 76755b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa } 76866b42a1c2d38813be104a7f0435ec6e6ec1c6e65satok } 769b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 770466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 771466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 772923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 773923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 774c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 775c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has clicked on the extracted text view, 776c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * when running in fullscreen mode. The default implementation hides 777c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * the candidates view when this happens, but only if the extracted text 778c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * editor has a vertical scroll bar because its text doesn't fit. 779c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * Here we override the behavior due to the possibility that a re-correction could 780c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * cause the candidate strip to disappear and re-appear. 781c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani */ 782c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani @Override 783c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani public void onExtractedTextClicked() { 784952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa if (mRecorrectionEnabled && isSuggestionsRequested()) return; 785c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 786c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedTextClicked(); 787c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 788c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 789c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 790c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has performed a cursor movement in the 791c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * extracted text view, when it is running in fullscreen mode. The default 792c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * implementation hides the candidates view when a vertical movement 793c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * happens, but only if the extracted text editor has a vertical scroll bar 794c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * because its text doesn't fit. 795c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * Here we override the behavior due to the possibility that a re-correction could 796c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * cause the candidate strip to disappear and re-appear. 797c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani */ 798c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani @Override 799c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani public void onExtractedCursorMovement(int dx, int dy) { 800952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa if (mRecorrectionEnabled && isSuggestionsRequested()) return; 801c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 802c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedCursorMovement(dx, dy); 803c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 804c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 805923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 806923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void hideWindow() { 807979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 8081b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mKeyboardSwitcher.onAutoCorrectionStateChanged(false); 809979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 810923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (TRACE) Debug.stopMethodTracing(); 8116e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (mOptionsDialog != null && mOptionsDialog.isShowing()) { 8126e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog.dismiss(); 8136e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog = null; 8146e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 815409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.hideVoiceWindow(mConfigurationChanging); 816979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mWordHistory.clear(); 817923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.hideWindow(); 818923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.endSession(); 819923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 820923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 821923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 8221b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka public void onDisplayCompletions(CompletionInfo[] applicationSpecifiedCompletions) { 823979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (DEBUG) { 824a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa Log.i(TAG, "Received completions:"); 8251b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final int count = (applicationSpecifiedCompletions != null) 8261b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka ? applicationSpecifiedCompletions.length : 0; 8271b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka for (int i = 0; i < count; i++) { 828a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa Log.i(TAG, " #" + i + ": " + applicationSpecifiedCompletions[i]); 829923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 830923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 8311b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (mApplicationSpecifiedCompletionOn) { 8321b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletions = applicationSpecifiedCompletions; 8331b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (applicationSpecifiedCompletions == null) { 834b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani clearSuggestions(); 835923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 836923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 837a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 8387e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords.Builder builder = new SuggestedWords.Builder() 8391b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka .setApplicationSpecifiedCompletions(applicationSpecifiedCompletions) 8407e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka .setTypedWordValid(true) 8417e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka .setHasMinimalSuggestion(true); 842979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // When in fullscreen mode, show completions generated by the application 8437e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(builder.build()); 844923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = null; 845543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa setCandidatesViewShown(true); 846923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 847923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 848923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 849543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa private void setCandidatesViewShownInternal(boolean shown, boolean needsInputViewShown) { 850923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // TODO: Remove this if we support candidates with hard keyboard 851923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (onEvaluateInputViewShown()) { 8521679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka super.setCandidatesViewShown(shown 8531679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka && (needsInputViewShown ? mKeyboardSwitcher.isInputViewShown() : true)); 854923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 855923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 856a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 857923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 858543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa public void setCandidatesViewShown(boolean shown) { 859543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa setCandidatesViewShownInternal(shown, true /* needsInputViewShown */ ); 860543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa } 861543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa 862543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa @Override 863923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onComputeInsets(InputMethodService.Insets outInsets) { 864923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onComputeInsets(outInsets); 865264b19a6853ab3d13d26270e99a13dc015b01bebThe Android Open Source Project if (!isFullscreenMode()) { 866264b19a6853ab3d13d26270e99a13dc015b01bebThe Android Open Source Project outInsets.contentTopInsets = outInsets.visibleTopInsets; 867264b19a6853ab3d13d26270e99a13dc015b01bebThe Android Open Source Project } 8689e347d3d448e48229c46aad394ec9bd60cd5807bsatok KeyboardView inputView = mKeyboardSwitcher.getInputView(); 8699e347d3d448e48229c46aad394ec9bd60cd5807bsatok // Need to set touchable region only if input view is being shown 8709e347d3d448e48229c46aad394ec9bd60cd5807bsatok if (inputView != null && mKeyboardSwitcher.isInputViewShown()) { 8719e347d3d448e48229c46aad394ec9bd60cd5807bsatok final int x = 0; 8729e347d3d448e48229c46aad394ec9bd60cd5807bsatok int y = 0; 8739e347d3d448e48229c46aad394ec9bd60cd5807bsatok final int width = inputView.getWidth(); 8749e347d3d448e48229c46aad394ec9bd60cd5807bsatok int height = inputView.getHeight() + EXTENDED_TOUCHABLE_REGION_HEIGHT; 8759e347d3d448e48229c46aad394ec9bd60cd5807bsatok if (mCandidateViewContainer != null) { 8769e347d3d448e48229c46aad394ec9bd60cd5807bsatok ViewParent candidateParent = mCandidateViewContainer.getParent(); 8779e347d3d448e48229c46aad394ec9bd60cd5807bsatok if (candidateParent instanceof FrameLayout) { 87800eb3658734078df46b6fe88b8b6aa8b79d327c9Tadashi G. Takaoka FrameLayout fl = (FrameLayout) candidateParent; 87900eb3658734078df46b6fe88b8b6aa8b79d327c9Tadashi G. Takaoka if (fl != null) { 88000eb3658734078df46b6fe88b8b6aa8b79d327c9Tadashi G. Takaoka // Check frame layout's visibility 88100eb3658734078df46b6fe88b8b6aa8b79d327c9Tadashi G. Takaoka if (fl.getVisibility() == View.INVISIBLE) { 88200eb3658734078df46b6fe88b8b6aa8b79d327c9Tadashi G. Takaoka y = fl.getHeight(); 88300eb3658734078df46b6fe88b8b6aa8b79d327c9Tadashi G. Takaoka height += y; 88400eb3658734078df46b6fe88b8b6aa8b79d327c9Tadashi G. Takaoka } else if (fl.getVisibility() == View.VISIBLE) { 88500eb3658734078df46b6fe88b8b6aa8b79d327c9Tadashi G. Takaoka height += fl.getHeight(); 88600eb3658734078df46b6fe88b8b6aa8b79d327c9Tadashi G. Takaoka } 8879e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 8889e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 8899e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 8909e347d3d448e48229c46aad394ec9bd60cd5807bsatok if (DEBUG) { 8919e347d3d448e48229c46aad394ec9bd60cd5807bsatok Log.d(TAG, "Touchable region " + x + ", " + y + ", " + width + ", " + height); 8929e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 8936845da8d7b940018c4ef77646f0028d131ed2753satok outInsets.touchableInsets = InputMethodService.Insets.TOUCHABLE_INSETS_REGION; 8949e347d3d448e48229c46aad394ec9bd60cd5807bsatok outInsets.touchableRegion.set(x, y, width, height); 8959e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 896923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 897a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 898923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 899979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public boolean onEvaluateFullscreenMode() { 900458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa final Resources res = mResources; 901458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa DisplayMetrics dm = res.getDisplayMetrics(); 902979f8690967ff5409fe18f5085858ccdb8e0ccf1satok float displayHeight = dm.heightPixels; 903979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // If the display is more than X inches high, don't go to fullscreen mode 904458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa float dimen = res.getDimension(R.dimen.max_height_for_fullscreen); 905979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (displayHeight > dimen) { 906979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return false; 907979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } else { 908979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return super.onEvaluateFullscreenMode(); 909979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 910979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 911979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 912979f8690967ff5409fe18f5085858ccdb8e0ccf1satok @Override 913923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 914923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 915e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_BACK: 916e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (event.getRepeatCount() == 0 && mKeyboardSwitcher.getInputView() != null) { 917e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mKeyboardSwitcher.getInputView().handleBack()) { 9186e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani return true; 9196e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 920e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 921e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 922923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 923923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyDown(keyCode, event); 924923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 925923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 926923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 927923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 928923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 929e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_DOWN: 930e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_UP: 931e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_LEFT: 932e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_RIGHT: 933e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka // Enable shift key and DPAD to do selections 934e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mKeyboardSwitcher.isInputViewShown() 935e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka && mKeyboardSwitcher.isShiftedOrShiftLocked()) { 936e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka KeyEvent newEvent = new KeyEvent(event.getDownTime(), event.getEventTime(), 937e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka event.getAction(), event.getKeyCode(), event.getRepeatCount(), 938e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka event.getDeviceId(), event.getScanCode(), 939e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON); 940e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka InputConnection ic = getCurrentInputConnection(); 941e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (ic != null) 942e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka ic.sendKeyEvent(newEvent); 943e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka return true; 944e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 945e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 946923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 947923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyUp(keyCode, event); 948923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 949923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 950409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void commitTyped(InputConnection inputConnection) { 9519fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (mHasValidSuggestions) { 9529fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mHasValidSuggestions = false; 953923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mComposing.length() > 0) { 954923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (inputConnection != null) { 955923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project inputConnection.commitText(mComposing, 1); 956923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 957923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCommittedLength = mComposing.length(); 958923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.acceptedTyped(mComposing); 959979f8690967ff5409fe18f5085858ccdb8e0ccf1satok addToDictionaries(mComposing, AutoDictionary.FREQUENCY_FOR_TYPED); 960923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 961923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateSuggestions(); 962923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 963923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 964923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 965b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public boolean getCurrentAutoCapsState() { 966923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 9671c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani EditorInfo ei = getCurrentInputEditorInfo(); 968e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mAutoCap && ic != null && ei != null && ei.inputType != InputType.TYPE_NULL) { 969b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return ic.getCursorCapsMode(ei.inputType) != 0; 9701c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 971b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return false; 9721c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 9731c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 974923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void swapPunctuationAndSpace() { 975923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final InputConnection ic = getCurrentInputConnection(); 976923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 977923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence lastTwo = ic.getTextBeforeCursor(2, 0); 978923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastTwo != null && lastTwo.length() == 2 979571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastTwo.charAt(0) == Keyboard.CODE_SPACE 980571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && isSentenceSeparator(lastTwo.charAt(1))) { 981923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 982923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 983923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(lastTwo.charAt(1) + " ", 1); 984923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 985b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 9869a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa mJustAddedAutoSpace = true; 987923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 988923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 9891c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 9904ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa private void reswapPeriodAndSpace() { 9914ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa final InputConnection ic = getCurrentInputConnection(); 9924ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa if (ic == null) return; 9934ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa CharSequence lastThree = ic.getTextBeforeCursor(3, 0); 9944ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa if (lastThree != null && lastThree.length() == 3 995571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastThree.charAt(0) == Keyboard.CODE_PERIOD 996571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastThree.charAt(1) == Keyboard.CODE_SPACE 997571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastThree.charAt(2) == Keyboard.CODE_PERIOD) { 9984ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa ic.beginBatchEdit(); 9994ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa ic.deleteSurroundingText(3, 0); 10004ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa ic.commitText(" ..", 1); 10014ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa ic.endBatchEdit(); 1002b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 10034ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 10044ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 10054ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1006923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void doubleSpace() { 1007923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project //if (!mAutoPunctuate) return; 1008923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mCorrectionMode == Suggest.CORRECTION_NONE) return; 1009923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final InputConnection ic = getCurrentInputConnection(); 1010923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 1011923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence lastThree = ic.getTextBeforeCursor(3, 0); 1012923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastThree != null && lastThree.length() == 3 1013923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project && Character.isLetterOrDigit(lastThree.charAt(0)) 1014571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastThree.charAt(1) == Keyboard.CODE_SPACE 1015571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastThree.charAt(2) == Keyboard.CODE_SPACE) { 1016923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 1017923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 1018923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(". ", 1); 1019923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1020b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 10219a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa mJustAddedAutoSpace = true; 1022923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1023923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1024a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 102541a519729505a877844f2c57a33509c302dddbceKen Wakasa private void maybeRemovePreviousPeriod(CharSequence text) { 102641a519729505a877844f2c57a33509c302dddbceKen Wakasa final InputConnection ic = getCurrentInputConnection(); 102741a519729505a877844f2c57a33509c302dddbceKen Wakasa if (ic == null) return; 102841a519729505a877844f2c57a33509c302dddbceKen Wakasa 102941a519729505a877844f2c57a33509c302dddbceKen Wakasa // When the text's first character is '.', remove the previous period 103041a519729505a877844f2c57a33509c302dddbceKen Wakasa // if there is one. 103141a519729505a877844f2c57a33509c302dddbceKen Wakasa CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 10324ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa if (lastOne != null && lastOne.length() == 1 1033571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastOne.charAt(0) == Keyboard.CODE_PERIOD 1034571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && text.charAt(0) == Keyboard.CODE_PERIOD) { 103541a519729505a877844f2c57a33509c302dddbceKen Wakasa ic.deleteSurroundingText(1, 0); 103641a519729505a877844f2c57a33509c302dddbceKen Wakasa } 103741a519729505a877844f2c57a33509c302dddbceKen Wakasa } 103841a519729505a877844f2c57a33509c302dddbceKen Wakasa 10399a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa private void removeTrailingSpace() { 10409a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa final InputConnection ic = getCurrentInputConnection(); 10419a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic == null) return; 10429a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa 10439a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 10449a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (lastOne != null && lastOne.length() == 1 1045571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastOne.charAt(0) == Keyboard.CODE_SPACE) { 10469a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.deleteSurroundingText(1, 0); 10479a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 10489a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 10499a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa 1050923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean addWordToDictionary(String word) { 1051923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mUserDictionary.addWord(word, 128); 10526558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // Suggestion strip should be updated after the operation of adding word to the 10536558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // user dictionary 1054d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1055923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1056923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1057923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1058923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean isAlphabet(int code) { 1059923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (Character.isLetter(code)) { 1060923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1061923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1062923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return false; 1063923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1064923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1065a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1066e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka private void onSettingsKeyPressed() { 10679a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok if (!isShowingOptionDialog()) { 10682fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka if (!mConfigEnableShowSubtypeSettings) { 10692fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka showSubtypeSelectorAndSettings(); 10702fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } else if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm)) { 10719a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok showOptionsMenu(); 10729a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } else { 10739a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok launchSettings(); 10749a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10759a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10769a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10779a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 1078e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka private void onSettingsKeyLongPressed() { 10799a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok if (!isShowingOptionDialog()) { 10809502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm)) { 108179efbed76f638be298493107fa2d0cd1b5eb529esatok mImm.showInputMethodPicker(); 10829a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } else { 10839a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok launchSettings(); 10849a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10859a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10869a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10879a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 10889a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok private boolean isShowingOptionDialog() { 10899a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok return mOptionsDialog != null && mOptionsDialog.isShowing(); 10909a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10919a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 10925f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // Implementation of {@link KeyboardActionListener}. 10935a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 10948aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { 1095923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long when = SystemClock.uptimeMillis(); 1096571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (primaryCode != Keyboard.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) { 1097923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mDeleteCount = 0; 1098923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1099923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mLastKeyTime = when; 1100b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 1101dcade18113286a132a2f5fb508fdba836470c3fbAlan Viverette final boolean accessibilityEnabled = switcher.isAccessibilityEnabled(); 1102b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); 1103923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 1104571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_DELETE: 11054189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka handleBackspace(); 11064189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka mDeleteCount++; 11074189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka LatinImeLogger.logOnDelete(); 11084189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1109571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_SHIFT: 11104189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka // Shift key is handled in onPress() when device has distinct multi-touch panel. 1111dcade18113286a132a2f5fb508fdba836470c3fbAlan Viverette if (!distinctMultiTouch || accessibilityEnabled) 1112b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.toggleShift(); 11134189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1114e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: 11154189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka // Symbol key is handled in onPress() when device has distinct multi-touch panel. 1116dcade18113286a132a2f5fb508fdba836470c3fbAlan Viverette if (!distinctMultiTouch || accessibilityEnabled) 1117b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.changeKeyboardMode(); 11184189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1119571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_CANCEL: 11204189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka if (!isShowingOptionDialog()) { 11214189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka handleClose(); 11224189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } 11234189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1124e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SETTINGS: 1125e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka onSettingsKeyPressed(); 11264189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1127e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SETTINGS_LONGPRESS: 1128e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka onSettingsKeyLongPressed(); 11294189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1130571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_NEXT_LANGUAGE: 11314189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka toggleLanguage(false, true); 11324189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1133571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_PREV_LANGUAGE: 11344189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka toggleLanguage(false, false); 11354189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1136571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_CAPSLOCK: 1137b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.toggleCapsLock(); 11384189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 113920cdb37bd062ae6cb6d42ad6229a19733476cd55satok case Keyboard.CODE_VOICE: 114020cdb37bd062ae6cb6d42ad6229a19733476cd55satok mSubtypeSwitcher.switchToShortcutIME(); 11414189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1142571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_TAB: 114345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka handleTab(); 11444189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 11454189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka default: 1146571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (primaryCode != Keyboard.CODE_ENTER) { 11474189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka mJustAddedAutoSpace = false; 11484189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } 11494189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka RingCharBuffer.getInstance().push((char)primaryCode, x, y); 11504189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka LatinImeLogger.logOnInputChar(); 11514189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka if (isWordSeparator(primaryCode)) { 11524189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka handleSeparator(primaryCode); 11534189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } else { 11548fbd55229243cb66c03d5ea1f79dfb39f596590dsatok handleCharacter(primaryCode, keyCodes, x, y); 11554189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } 11564189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka // Cancel the just reverted state 1157c1e2e827b5d1bba59eb99d322dc101657ec28768Ken Wakasa mJustReverted = false; 1158923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1159b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.onKey(primaryCode); 1160dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani // Reset after any single keystroke 1161dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = null; 1162923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1163a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 11645a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 11658aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onTextInput(CharSequence text) { 1166409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.commitVoiceInput(); 1167923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1168923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 1169952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa abortRecorrection(false); 1170923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 117155b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka commitTyped(ic); 117241a519729505a877844f2c57a33509c302dddbceKen Wakasa maybeRemovePreviousPeriod(text); 1173923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(text, 1); 1174923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1175b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 11765f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka mKeyboardSwitcher.onKey(Keyboard.CODE_DUMMY); 1177c1e2e827b5d1bba59eb99d322dc101657ec28768Ken Wakasa mJustReverted = false; 11789a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa mJustAddedAutoSpace = false; 1179dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = text; 1180923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1181923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 11825a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 11838aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onCancelInput() { 118483e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka // User released a finger outside any key 11855f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka mKeyboardSwitcher.onCancelInput(); 118683e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka } 118783e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka 1188923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleBackspace() { 1189409220583333bdf06290dd9fd42f91b5c0d1b11asatok if (mVoiceConnector.logAndRevertVoiceInput()) return; 11904f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1191504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1192504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka if (ic == null) return; 1193979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.beginBatchEdit(); 1194979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1195409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.handleBackspace(); 11964f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1197504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka boolean deleteChar = false; 11989fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (mHasValidSuggestions) { 1199923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final int length = mComposing.length(); 1200923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (length > 0) { 1201923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mComposing.delete(length - 1, length); 1202923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mWord.deleteLast(); 1203923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.setComposingText(mComposing, 1); 1204923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mComposing.length() == 0) { 12059fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mHasValidSuggestions = false; 1206923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1207d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1208923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1209923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(1, 0); 1210923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1211923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1212923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project deleteChar = true; 1213923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1214d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateShiftKeyState(); 1215504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka 1216923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.backspace(); 1217979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (TextEntryState.getState() == TextEntryState.State.UNDO_COMMIT) { 1218923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project revertLastWord(deleteChar); 1219979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.endBatchEdit(); 1220923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1221504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka } 1222504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka 1223504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) { 1224dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani ic.deleteSurroundingText(mEnteredText.length(), 0); 1225923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else if (deleteChar) { 12266558253160e2039c87f424bd814f402ecd31de3bKen Wakasa if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) { 12276558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // Go back to the suggestion mode if the user canceled the 122855b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // "Touch again to save". 12296558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // NOTE: In gerenal, we don't revert the word when backspacing 12306558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // from a manual suggestion pick. We deliberately chose a 12316558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // different behavior only in the case of picking the first 12326558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // suggestion (typed word). It's intentional to have made this 12336558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // inconsistent with backspacing after selecting other suggestions. 12346558253160e2039c87f424bd814f402ecd31de3bKen Wakasa revertLastWord(deleteChar); 12356558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } else { 1236923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 12376558253160e2039c87f424bd814f402ecd31de3bKen Wakasa if (mDeleteCount > DELETE_ACCELERATE_AT) { 12386558253160e2039c87f424bd814f402ecd31de3bKen Wakasa sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 12396558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 1240923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1241923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1242c1e2e827b5d1bba59eb99d322dc101657ec28768Ken Wakasa mJustReverted = false; 1243979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.endBatchEdit(); 1244923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1245923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 124645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka private void handleTab() { 124745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final int imeOptions = getCurrentInputEditorInfo().imeOptions; 124845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final int navigationFlags = 124945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka EditorInfo.IME_FLAG_NAVIGATE_NEXT | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS; 125045911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if ((imeOptions & navigationFlags) == 0) { 125145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB); 125245911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka return; 125345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 125445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 125545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 125645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (ic == null) 125745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka return; 125845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 125945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka // True if keyboard is in either chording shift or manual temporary upper case mode. 126045911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final boolean isManualTemporaryUpperCase = mKeyboardSwitcher.isManualTemporaryUpperCase(); 126145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if ((imeOptions & EditorInfo.IME_FLAG_NAVIGATE_NEXT) != 0 126245911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka && !isManualTemporaryUpperCase) { 126345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka ic.performEditorAction(EditorInfo.IME_ACTION_NEXT); 126445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } else if ((imeOptions & EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS) != 0 126545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka && isManualTemporaryUpperCase) { 126645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka ic.performEditorAction(EditorInfo.IME_ACTION_PREVIOUS); 126745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 126845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 126945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 1270952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa private void abortRecorrection(boolean force) { 1271952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa if (force || TextEntryState.isRecorrecting()) { 1272952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa TextEntryState.onAbortRecorrection(); 1273ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setCandidatesViewShown(isCandidateStripVisible()); 1274979f8690967ff5409fe18f5085858ccdb8e0ccf1satok getCurrentInputConnection().finishComposingText(); 1275b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani clearSuggestions(); 1276923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1277923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1278a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 12798fbd55229243cb66c03d5ea1f79dfb39f596590dsatok private void handleCharacter(int primaryCode, int[] keyCodes, int x, int y) { 1280409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.handleCharacter(); 12814f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1282952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa if (mLastSelectionStart == mLastSelectionEnd && TextEntryState.isRecorrecting()) { 1283952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa abortRecorrection(false); 1284b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 12854f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1286e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka int code = primaryCode; 12879fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (isAlphabet(code) && isSuggestionsRequested() && !isCursorTouchingWord()) { 12889fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (!mHasValidSuggestions) { 12899fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mHasValidSuggestions = true; 1290923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mComposing.setLength(0); 1291979f8690967ff5409fe18f5085858ccdb8e0ccf1satok saveWordInHistory(mBestWord); 1292923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mWord.reset(); 12937e99a28dfcc14f5b19220442db972ca8d786b4feKen Wakasa clearSuggestions(); 1294923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1295923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 12961679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 1297f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (switcher.isShiftedOrShiftLocked()) { 1298eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT 1299eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani || keyCodes[0] > Character.MAX_CODE_POINT) { 1300eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani return; 1301eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani } 1302e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka code = keyCodes[0]; 1303e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (switcher.isAlphabetMode() && Character.isLowerCase(code)) { 1304e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka int upperCaseCode = Character.toUpperCase(code); 1305e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (upperCaseCode != code) { 1306e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka code = upperCaseCode; 130712a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka } else { 130812a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka // Some keys, such as [eszett], have upper case as multi-characters. 1309e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka String upperCase = new String(new int[] {code}, 0, 1).toUpperCase(); 13108aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka onTextInput(upperCase); 131112a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka return; 131212a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka } 1313979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1314923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 13159fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (mHasValidSuggestions) { 1316f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (mComposing.length() == 0 && switcher.isAlphabetMode() 1317f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka && switcher.isShiftedOrShiftLocked()) { 13180b4ae1f578e768eec4ada90aeb81d11acb10eb2eKen Wakasa mWord.setFirstCharCapitalized(true); 1319923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1320e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mComposing.append((char) code); 13218fbd55229243cb66c03d5ea1f79dfb39f596590dsatok mWord.add(code, keyCodes, x, y); 1322923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1323923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 13241c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani // If it's the first letter, make note of auto-caps state 13251c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani if (mWord.size() == 1) { 1326b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mWord.setAutoCapitalized(getCurrentAutoCapsState()); 13271c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 1328923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.setComposingText(mComposing, 1); 1329923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1330d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1331923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1332e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka sendKeyChar((char)code); 1333923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1334b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.updateShiftState(); 1335979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (LatinIME.PERF_DEBUG) measureCps(); 1336e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka TextEntryState.typedCharacter((char) code, isWordSeparator(code)); 1337923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1338923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1339923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleSeparator(int primaryCode) { 1340409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.handleSeparator(); 13414f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 134255b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // Should dismiss the "Touch again to save" message when handling separator 13436558253160e2039c87f424bd814f402ecd31de3bKen Wakasa if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) { 1344d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 13456558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 13466558253160e2039c87f424bd814f402ecd31de3bKen Wakasa 1347923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project boolean pickedDefault = false; 1348923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Handle separator 13491b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1350923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1351923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 1352952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa abortRecorrection(false); 1353923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 13549fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (mHasValidSuggestions) { 1355923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In certain languages where single quote is a separator, it's better 1356a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker // not to auto correct, but accept the typed word. For instance, 1357923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // in Italian dov' should not be expanded to dove' because the elision 1358923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // requires the last vowel to be removed. 1359c1e2e827b5d1bba59eb99d322dc101657ec28768Ken Wakasa if (mAutoCorrectOn && primaryCode != '\'' && !mJustReverted) { 1360979f8690967ff5409fe18f5085858ccdb8e0ccf1satok pickedDefault = pickDefaultSuggestion(); 13619a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa // Picked the suggestion by the space key. We consider this 13629a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa // as "added an auto space". 1363571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (primaryCode == Keyboard.CODE_SPACE) { 13649a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa mJustAddedAutoSpace = true; 13659a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1366923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1367923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project commitTyped(ic); 1368923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1369923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1370571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (mJustAddedAutoSpace && primaryCode == Keyboard.CODE_ENTER) { 13719a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa removeTrailingSpace(); 13729a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa mJustAddedAutoSpace = false; 13739a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1374923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendKeyChar((char)primaryCode); 13754ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 13764ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa // Handle the case of ". ." -> " .." with auto-space if necessary 13774ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa // before changing the TextEntryState. 1378979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (TextEntryState.getState() == TextEntryState.State.PUNCTUATION_AFTER_ACCEPTED 1379571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && primaryCode == Keyboard.CODE_PERIOD) { 13804ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa reswapPeriodAndSpace(); 13814ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 13824ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1383923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.typedCharacter((char) primaryCode, true); 1384979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (TextEntryState.getState() == TextEntryState.State.PUNCTUATION_AFTER_ACCEPTED 1385571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && primaryCode != Keyboard.CODE_ENTER) { 1386923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project swapPunctuationAndSpace(); 13879fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka } else if (isSuggestionsRequested() && primaryCode == Keyboard.CODE_SPACE) { 1388923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project doubleSpace(); 1389923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1390979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (pickedDefault) { 139155b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka CharSequence typedWord = mWord.getTypedWord(); 139255b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka TextEntryState.backToAcceptedDefault(typedWord); 139355b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka if (!TextUtils.isEmpty(typedWord) && !typedWord.equals(mBestWord)) { 13944ca16dbd65150359c3884da7cb59a30f19abd4b7Tadashi G. Takaoka if (ic != null) { 13954ca16dbd65150359c3884da7cb59a30f19abd4b7Tadashi G. Takaoka CorrectionInfo correctionInfo = new CorrectionInfo( 13964ca16dbd65150359c3884da7cb59a30f19abd4b7Tadashi G. Takaoka mLastSelectionEnd - typedWord.length(), typedWord, mBestWord); 13974ca16dbd65150359c3884da7cb59a30f19abd4b7Tadashi G. Takaoka ic.commitCorrection(correctionInfo); 13984ca16dbd65150359c3884da7cb59a30f19abd4b7Tadashi G. Takaoka } 139955b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka if (mCandidateView != null) 140055b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka mCandidateView.onAutoCorrectionInverted(mBestWord); 140155b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka } 140255b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka setPunctuationSuggestions(); 1403923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1404b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 1405923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1406923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1407923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1408923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1409466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1410923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleClose() { 1411923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project commitTyped(getCurrentInputConnection()); 1412409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.handleClose(); 1413923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project requestHideSelf(0); 14141679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); 14151679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka if (inputView != null) 14161679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka inputView.closing(); 1417923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.endSession(); 1418923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1419923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1420979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void saveWordInHistory(CharSequence result) { 1421979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mWord.size() <= 1) { 1422979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mWord.reset(); 1423979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return; 1424923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1425979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Skip if result is null. It happens in some edge case. 1426979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (TextUtils.isEmpty(result)) { 1427979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return; 1428923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1429979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1430979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Make a copy of the CharSequence, since it is/could be a mutable CharSequence 1431979f8690967ff5409fe18f5085858ccdb8e0ccf1satok final String resultCopy = result.toString(); 1432979f8690967ff5409fe18f5085858ccdb8e0ccf1satok TypedWordAlternatives entry = new TypedWordAlternatives(resultCopy, 1433979f8690967ff5409fe18f5085858ccdb8e0ccf1satok new WordComposer(mWord)); 1434979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mWordHistory.add(entry); 1435923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1436923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 14379fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka private boolean isSuggestionsRequested() { 1438c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka return mIsSettingsSuggestionStripOn 1439c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka && (mCorrectionMode > 0 || isShowingSuggestionsStrip()); 1440923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1441a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 14427599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private boolean isShowingPunctuationList() { 14437e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka return mSuggestPuncList == mCandidateView.getSuggestions(); 14447599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 14457599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 14469fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka private boolean isShowingSuggestionsStrip() { 14477599cfea4a2d56f4779452ec8e8742f7b9629cc0satok return (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_VALUE) 14487599cfea4a2d56f4779452ec8e8742f7b9629cc0satok || (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE 14497599cfea4a2d56f4779452ec8e8742f7b9629cc0satok && mOrientation == Configuration.ORIENTATION_PORTRAIT); 14507599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 14517599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 1452923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean isCandidateStripVisible() { 1453b5e00d5841b946de8970875231456228ae0eb6b1Ken Wakasa if (mCandidateView == null) 1454b5e00d5841b946de8970875231456228ae0eb6b1Ken Wakasa return false; 1455952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa if (mCandidateView.isShowingAddToDictionaryHint() || TextEntryState.isRecorrecting()) 14569fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 14579fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (!isShowingSuggestionsStrip()) 14589fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return false; 14599fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (mApplicationSpecifiedCompletionOn) 14609fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 14619fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return isSuggestionsRequested(); 1462923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1463923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1464409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void switchToKeyboardView() { 1465060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (DEBUG) { 1466060efb6d82af1f896d90cb845c8ae07c726f85e1satok Log.d(TAG, "Switch to keyboard view."); 1467060efb6d82af1f896d90cb845c8ae07c726f85e1satok } 1468060efb6d82af1f896d90cb845c8ae07c726f85e1satok View v = mKeyboardSwitcher.getInputView(); 1469060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (v != null) { 1470060efb6d82af1f896d90cb845c8ae07c726f85e1satok // Confirms that the keyboard view doesn't have parent view. 1471060efb6d82af1f896d90cb845c8ae07c726f85e1satok ViewParent p = v.getParent(); 1472060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (p != null && p instanceof ViewGroup) { 1473060efb6d82af1f896d90cb845c8ae07c726f85e1satok ((ViewGroup) p).removeView(v); 14745a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka } 1475060efb6d82af1f896d90cb845c8ae07c726f85e1satok setInputView(v); 1476060efb6d82af1f896d90cb845c8ae07c726f85e1satok } 1477060efb6d82af1f896d90cb845c8ae07c726f85e1satok setCandidatesViewShown(isCandidateStripVisible()); 1478060efb6d82af1f896d90cb845c8ae07c726f85e1satok updateInputViewShown(); 1479060efb6d82af1f896d90cb845c8ae07c726f85e1satok mHandler.postUpdateSuggestions(); 1480466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1481466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1482409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void clearSuggestions() { 14837e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(SuggestedWords.EMPTY); 1484466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1485466741d8a78965b8509bf527344f289e50873092Mike LeBeau 14867e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka public void setSuggestions(SuggestedWords words) { 1487409220583333bdf06290dd9fd42f91b5c0d1b11asatok if (mVoiceConnector.getAndResetIsShowingHint()) { 1488466741d8a78965b8509bf527344f289e50873092Mike LeBeau setCandidatesView(mCandidateViewContainer); 1489466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1490466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1491466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mCandidateView != null) { 14927e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka mCandidateView.setSuggestions(words); 14939ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka if (mCandidateView.isConfigCandidateHighlightFontColorEnabled()) { 14949ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka mKeyboardSwitcher.onAutoCorrectionStateChanged( 14959ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka words.hasWordAboveAutoCorrectionScoreThreshold()); 14969ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka } 1497466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1498466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1499466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1500409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void updateSuggestions() { 1501923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Check if we have a suggestion engine attached. 15029fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if ((mSuggest == null || !isSuggestionsRequested()) 1503409220583333bdf06290dd9fd42f91b5c0d1b11asatok && !mVoiceConnector.isVoiceInputHighlighted()) { 1504923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1505923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1506466741d8a78965b8509bf527344f289e50873092Mike LeBeau 15079fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (!mHasValidSuggestions) { 1508ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setPunctuationSuggestions(); 1509923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1510923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1511979f8690967ff5409fe18f5085858ccdb8e0ccf1satok showSuggestions(mWord); 1512979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1513979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 15147e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka private SuggestedWords.Builder getTypedSuggestions(WordComposer word) { 15159ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka return mSuggest.getSuggestedWordBuilder(mKeyboardSwitcher.getInputView(), word, null); 1516979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1517979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1518979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void showCorrections(WordAlternatives alternatives) { 15197e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords.Builder builder = alternatives.getAlternatives(); 15207e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka builder.setTypedWordValid(false).setHasMinimalSuggestion(false); 15217e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka showSuggestions(builder.build(), alternatives.getOriginalWord()); 1522979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1523979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1524979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void showSuggestions(WordComposer word) { 1525979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // TODO Maybe need better way of retrieving previous word 1526e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(), 1527979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mWordSeparators); 15287e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder( 15299ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka mKeyboardSwitcher.getInputView(), word, prevWord); 1530923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1531378a1b516d867671d292900c5d42aef3a0dc1556Ken Wakasa boolean correctionAvailable = !mInputTypeNoAutoCorrect && !mJustReverted 15326f7218627eda110a8454053f8ecb7b80edfdc8cesatok && mSuggest.hasAutoCorrection(); 1533a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa final CharSequence typedWord = word.getTypedWord(); 1534923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // If we're in basic correct 1535a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa final boolean typedWordValid = mSuggest.isValidWord(typedWord) || 1536979f8690967ff5409fe18f5085858ccdb8e0ccf1satok (preferCapitalization() 1537979f8690967ff5409fe18f5085858ccdb8e0ccf1satok && mSuggest.isValidWord(typedWord.toString().toLowerCase())); 1538979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mCorrectionMode == Suggest.CORRECTION_FULL 1539979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) { 1540923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project correctionAvailable |= typedWordValid; 1541923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 15424a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani // Don't auto-correct words with multiple capital letter 1543979f8690967ff5409fe18f5085858ccdb8e0ccf1satok correctionAvailable &= !word.isMostlyCaps(); 1544952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa correctionAvailable &= !TextEntryState.isRecorrecting(); 1545979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1546a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // Basically, we update the suggestion strip only when suggestion count > 1. However, 1547a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // there is an exception: We update the suggestion strip whenever typed word's length 1548f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // is 1 or typed word is found in dictionary, regardless of suggestion count. Actually, 1549f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // in most cases, suggestion count is 1 when typed word's length is 1, but we do always 1550f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // need to clear the previous state when the user starts typing a word (i.e. typed word's 1551f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // length == 1). 1552f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka if (builder.size() > 1 || typedWord.length() == 1 || typedWordValid 1553a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa || mCandidateView.isShowingAddToDictionaryHint()) { 15549fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka builder.setTypedWordValid(typedWordValid).setHasMinimalSuggestion(correctionAvailable); 15559fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka } else { 15569fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka final SuggestedWords previousSuggestions = mCandidateView.getSuggestions(); 15579fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (previousSuggestions == mSuggestPuncList) 15589fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return; 15599fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka builder.addTypedWordAndPreviousSuggestions(typedWord, previousSuggestions); 15609fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka } 15617e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka showSuggestions(builder.build(), typedWord); 1562979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 15634a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani 15647e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka private void showSuggestions(SuggestedWords suggestedWords, CharSequence typedWord) { 15657e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(suggestedWords); 15667e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka if (suggestedWords.size() > 0) { 156714e427d5bb13d59d23fb317ef90a6c44ae279425satok if (Utils.shouldBlockedBySafetyNetForAutoCorrection(suggestedWords, mSuggest)) { 156882411d47ba7e8133ed2390c6920945e139a738cesatok mBestWord = typedWord; 156982411d47ba7e8133ed2390c6920945e139a738cesatok } else if (suggestedWords.hasAutoCorrectionWord()) { 15707e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka mBestWord = suggestedWords.getWord(1); 1571923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1572923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = typedWord; 1573923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1574923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1575923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = null; 1576923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1577ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setCandidatesViewShown(isCandidateStripVisible()); 1578923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1579923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1580979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private boolean pickDefaultSuggestion() { 1581923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Complete any pending candidate query first 1582d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka if (mHandler.hasPendingUpdateSuggestions()) { 1583d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 1584923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateSuggestions(); 1585923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 15866780b898ec2647a21319601a03ae1c393c0e1b29Amith Yamasani if (mBestWord != null && mBestWord.length() > 0) { 1587923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.acceptedDefault(mWord.getTypedWord(), mBestWord); 1588923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mJustAccepted = true; 158955b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka pickSuggestion(mBestWord); 15909468335a06d2b0e3ef15f4f57f8c1b0857b34ebeAmith Yamasani // Add the word to the auto dictionary if it's not a known word 1591979f8690967ff5409fe18f5085858ccdb8e0ccf1satok addToDictionaries(mBestWord, AutoDictionary.FREQUENCY_FOR_TYPED); 1592979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return true; 1593979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1594923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1595979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return false; 1596923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1597923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1598923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void pickSuggestionManually(int index, CharSequence suggestion) { 15997e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords suggestions = mCandidateView.getSuggestions(); 1600409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.flushAndLogAllTextModificationCounters(index, suggestion, mWordSeparators); 16014f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1602952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa final boolean recorrecting = TextEntryState.isRecorrecting(); 16039a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa InputConnection ic = getCurrentInputConnection(); 16049a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 16059a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.beginBatchEdit(); 16069a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 16071b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (mApplicationSpecifiedCompletionOn && mApplicationSpecifiedCompletions != null 16081b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka && index >= 0 && index < mApplicationSpecifiedCompletions.length) { 16091b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka CompletionInfo ci = mApplicationSpecifiedCompletions[index]; 1610923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1611923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitCompletion(ci); 1612923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1613923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCommittedLength = suggestion.length(); 1614923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mCandidateView != null) { 1615923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCandidateView.clear(); 1616923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1617b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 16189a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 16199a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 16209a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1621923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1622923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 16236a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 16246a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani // If this is a punctuation, apply it through the normal key press 1625979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (suggestion.length() == 1 && (isWordSeparator(suggestion.charAt(0)) 1626979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || isSuggestedPunctuation(suggestion.charAt(0)))) { 1627979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Word separators are suggested before the user inputs something. 1628979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // So, LatinImeLogger logs "" as a user's input. 1629979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.logOnManualSuggestion( 16307e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka "", suggestion.toString(), index, suggestions.mWords); 163155b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa final char primaryCode = suggestion.charAt(0); 1632a96574fdd5e38a237a35b21a2b7c20a29138c648Tadashi G. Takaoka onCodeInput(primaryCode, new int[] { primaryCode }, 1633a96574fdd5e38a237a35b21a2b7c20a29138c648Tadashi G. Takaoka KeyboardActionListener.NOT_A_TOUCH_COORDINATE, 1634a96574fdd5e38a237a35b21a2b7c20a29138c648Tadashi G. Takaoka KeyboardActionListener.NOT_A_TOUCH_COORDINATE); 16359a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 16369a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 16379a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 16386a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani return; 16396a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 16409a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa mJustAccepted = true; 164155b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka pickSuggestion(suggestion); 16429468335a06d2b0e3ef15f4f57f8c1b0857b34ebeAmith Yamasani // Add the word to the auto dictionary if it's not a known word 16430c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani if (index == 0) { 1644979f8690967ff5409fe18f5085858ccdb8e0ccf1satok addToDictionaries(suggestion, AutoDictionary.FREQUENCY_FOR_PICKED); 1645979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } else { 1646979f8690967ff5409fe18f5085858ccdb8e0ccf1satok addToBigramDictionary(suggestion, 1); 16470c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani } 1648979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.logOnManualSuggestion(mComposing.toString(), suggestion.toString(), 16497e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka index, suggestions.mWords); 1650923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.acceptedSuggestion(mComposing.toString(), suggestion); 1651923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Follow it with a space 1652952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa if (mAutoSpace && !recorrecting) { 1653923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendSpace(); 16549a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa mJustAddedAutoSpace = true; 1655923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1656979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 16577f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // We should show the hint if the user pressed the first entry AND either: 16587f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // - There is no dictionary (we know that because we tried to load it => null != mSuggest 16597f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // AND mHasDictionary is false) 16607f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // - There is a dictionary and the word is not in it 16617f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // Please note that if mSuggest is null, it means that everything is off: suggestion 16627f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // and correction, so we shouldn't try to show the hint 16637f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // We used to look at mCorrectionMode here, but showing the hint should have nothing 16647f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // to do with the autocorrection setting. 16657f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard final boolean showingAddToDictionaryHint = index == 0 && 16667f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // Test for no dictionary: 16677f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard ((!mHasDictionary && null != mSuggest) || 16687f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // Test for dictionary && word is inside: 16697f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard (mHasDictionary && null != mSuggest 1670b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani && !mSuggest.isValidWord(suggestion) 16717f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard && !mSuggest.isValidWord(suggestion.toString().toLowerCase()))); 1672b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani 1673952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa if (!recorrecting) { 1674b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // Fool the state watcher so that a subsequent backspace will not do a revert, unless 1675b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // we just did a correction, in which case we need to stay in 1676b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // TextEntryState.State.PICKED_SUGGESTION state. 1677571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka TextEntryState.typedCharacter((char) Keyboard.CODE_SPACE, true); 1678ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setPunctuationSuggestions(); 1679b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } else if (!showingAddToDictionaryHint) { 1680364da8c618303a7764595d2c15ee034a7671365dKen Wakasa // If we're not showing the "Touch again to save", then show corrections again. 1681979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // In case the cursor position doesn't change, make sure we show the suggestions again. 1682b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani clearSuggestions(); 1683d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateOldSuggestions(); 1684979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1685b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani if (showingAddToDictionaryHint) { 168666a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani mCandidateView.showAddToDictionaryHint(suggestion); 168766a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani } 16889a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 16899a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 16909a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1691923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1692a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1693979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 1694979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * Commits the chosen word to the text field and saves it for later 1695979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * retrieval. 1696979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * @param suggestion the suggestion picked by the user to be committed to 1697979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * the text field 1698979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 169955b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka private void pickSuggestion(CharSequence suggestion) { 1700b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 1701b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (!switcher.isKeyboardAvailable()) 17021679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka return; 1703923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1704923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1705409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.rememberReplacedWord(suggestion, mWordSeparators); 1706979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.commitText(suggestion, 1); 1707923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1708979f8690967ff5409fe18f5085858ccdb8e0ccf1satok saveWordInHistory(suggestion); 17099fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mHasValidSuggestions = false; 1710923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCommittedLength = suggestion.length(); 1711923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1712923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1713b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani /** 1714b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani * Tries to apply any typed alternatives for the word if we have any cached alternatives, 1715b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani * otherwise tries to find new corrections and completions for the word. 1716b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani * @param touching The word that the cursor is touching, with position information 1717b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani * @return true if an alternative was found, false otherwise. 1718b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani */ 1719e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka private boolean applyTypedAlternatives(EditingUtils.SelectedWord touching) { 1720b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // If we didn't find a match, search for result in typed word history 1721b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani WordComposer foundWord = null; 1722b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani WordAlternatives alternatives = null; 1723b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani for (WordAlternatives entry : mWordHistory) { 1724e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (TextUtils.equals(entry.getChosenWord(), touching.mWord)) { 1725b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani if (entry instanceof TypedWordAlternatives) { 1726b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani foundWord = ((TypedWordAlternatives) entry).word; 1727b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 1728b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani alternatives = entry; 1729b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani break; 1730b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 1731b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 17321b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka // If we didn't find a match, at least suggest corrections. 1733b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani if (foundWord == null 1734e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka && (mSuggest.isValidWord(touching.mWord) 1735e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka || mSuggest.isValidWord(touching.mWord.toString().toLowerCase()))) { 1736b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani foundWord = new WordComposer(); 1737e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka for (int i = 0; i < touching.mWord.length(); i++) { 1738e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka foundWord.add(touching.mWord.charAt(i), new int[] { 1739e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka touching.mWord.charAt(i) 17408fbd55229243cb66c03d5ea1f79dfb39f596590dsatok }, WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); 1741b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 1742e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka foundWord.setFirstCharCapitalized(Character.isUpperCase(touching.mWord.charAt(0))); 1743b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 1744b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // Found a match, show suggestions 1745b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani if (foundWord != null || alternatives != null) { 1746b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani if (alternatives == null) { 1747e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka alternatives = new TypedWordAlternatives(touching.mWord, foundWord); 1748b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 1749b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani showCorrections(alternatives); 1750b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani if (foundWord != null) { 1751b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani mWord = new WordComposer(foundWord); 1752b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } else { 1753b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani mWord.reset(); 1754b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 1755b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani return true; 1756b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 1757b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani return false; 1758b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 1759b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani 1760979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void setOldSuggestions() { 1761409220583333bdf06290dd9fd42f91b5c0d1b11asatok mVoiceConnector.setShowingVoiceSuggestions(false); 1762b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani if (mCandidateView != null && mCandidateView.isShowingAddToDictionaryHint()) { 1763b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani return; 1764b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 1765979f8690967ff5409fe18f5085858ccdb8e0ccf1satok InputConnection ic = getCurrentInputConnection(); 1766979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (ic == null) return; 17679fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (!mHasValidSuggestions) { 1768b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // Extract the selected or touching text 1769e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka EditingUtils.SelectedWord touching = EditingUtils.getWordAtCursorOrSelection(ic, 1770b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani mLastSelectionStart, mLastSelectionEnd, mWordSeparators); 1771979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1772e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (touching != null && touching.mWord.length() > 1) { 1773b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani ic.beginBatchEdit(); 1774979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1775409220583333bdf06290dd9fd42f91b5c0d1b11asatok if (!mVoiceConnector.applyVoiceAlternatives(touching) 1776409220583333bdf06290dd9fd42f91b5c0d1b11asatok && !applyTypedAlternatives(touching)) { 1777952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa abortRecorrection(true); 1778b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } else { 1779952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa TextEntryState.selectedForRecorrection(); 1780e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka EditingUtils.underlineWord(ic, touching); 1781979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1782b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani 1783b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani ic.endBatchEdit(); 1784979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } else { 1785952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa abortRecorrection(true); 1786ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setPunctuationSuggestions(); // Show the punctuation suggestions list 1787979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1788979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } else { 1789952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa abortRecorrection(true); 1790979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1791979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1792979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1793ca26f20fa4903de46e374babbfba8c8a1a5cac93satok private void setPunctuationSuggestions() { 17947e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(mSuggestPuncList); 17959fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka setCandidatesViewShown(isCandidateStripVisible()); 17966a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 17976a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 1798979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void addToDictionaries(CharSequence suggestion, int frequencyDelta) { 1799979f8690967ff5409fe18f5085858ccdb8e0ccf1satok checkAddToDictionary(suggestion, frequencyDelta, false); 1800979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1801979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1802979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void addToBigramDictionary(CharSequence suggestion, int frequencyDelta) { 1803979f8690967ff5409fe18f5085858ccdb8e0ccf1satok checkAddToDictionary(suggestion, frequencyDelta, true); 1804979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1805979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1806979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 1807979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * Adds to the UserBigramDictionary and/or AutoDictionary 1808979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * @param addToBigramDictionary true if it should be added to bigram dictionary if possible 1809979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 1810979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void checkAddToDictionary(CharSequence suggestion, int frequencyDelta, 1811979f8690967ff5409fe18f5085858ccdb8e0ccf1satok boolean addToBigramDictionary) { 1812979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (suggestion == null || suggestion.length() < 1) return; 18130c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // Only auto-add to dictionary if auto-correct is ON. Otherwise we'll be 18140c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // adding words in situations where the user or application really didn't 18150c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // want corrections enabled or learned. 1816979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (!(mCorrectionMode == Suggest.CORRECTION_FULL 1817979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM)) { 1818979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return; 1819979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1820e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (!addToBigramDictionary && mAutoDictionary.isValidWord(suggestion) 1821e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka || (!mSuggest.isValidWord(suggestion.toString()) 1822e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka && !mSuggest.isValidWord(suggestion.toString().toLowerCase()))) { 1823e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mAutoDictionary.addWord(suggestion.toString(), frequencyDelta); 1824e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 1825979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1826e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mUserBigramDictionary != null) { 1827e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(), 1828e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mSentenceSeparators); 1829e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (!TextUtils.isEmpty(prevWord)) { 1830e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mUserBigramDictionary.addBigrams(prevWord.toString(), suggestion.toString()); 1831979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 183232e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 183332e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 183432e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani 1835923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean isCursorTouchingWord() { 1836923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1837923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return false; 1838923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence toLeft = ic.getTextBeforeCursor(1, 0); 1839923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence toRight = ic.getTextAfterCursor(1, 0); 1840923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (!TextUtils.isEmpty(toLeft) 184155b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa && !isWordSeparator(toLeft.charAt(0)) 184255b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa && !isSuggestedPunctuation(toLeft.charAt(0))) { 1843923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1844923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1845a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker if (!TextUtils.isEmpty(toRight) 184655b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa && !isWordSeparator(toRight.charAt(0)) 184755b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa && !isSuggestedPunctuation(toRight.charAt(0))) { 1848923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1849923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1850923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return false; 1851923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1852a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1853dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani private boolean sameAsTextBeforeCursor(InputConnection ic, CharSequence text) { 1854dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani CharSequence beforeText = ic.getTextBeforeCursor(text.length(), 0); 1855dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani return TextUtils.equals(text, beforeText); 1856dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani } 1857dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 1858923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void revertLastWord(boolean deleteChar) { 1859923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final int length = mComposing.length(); 18609fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (!mHasValidSuggestions && length > 0) { 1861923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final InputConnection ic = getCurrentInputConnection(); 1862c1e2e827b5d1bba59eb99d322dc101657ec28768Ken Wakasa mJustReverted = true; 1863504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka final CharSequence punctuation = ic.getTextBeforeCursor(1, 0); 1864923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (deleteChar) ic.deleteSurroundingText(1, 0); 1865923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int toDelete = mCommittedLength; 1866504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka final CharSequence toTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0); 1867504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka if (!TextUtils.isEmpty(toTheLeft) && isWordSeparator(toTheLeft.charAt(0))) { 1868923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project toDelete--; 1869923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1870923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(toDelete, 0); 187130be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka // Re-insert punctuation only when the deleted character was word separator and the 187230be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka // composing text wasn't equal to the auto-corrected text. 187330be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka if (deleteChar 187430be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka && !TextUtils.isEmpty(punctuation) && isWordSeparator(punctuation.charAt(0)) 187530be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka && !TextUtils.equals(mComposing, toTheLeft)) { 1876504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka ic.commitText(mComposing, 1); 1877504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka TextEntryState.acceptedTyped(mComposing); 187830be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka ic.commitText(punctuation, 1); 187930be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka TextEntryState.typedCharacter(punctuation.charAt(0), true); 188030be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka // Clear composing text 188130be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka mComposing.setLength(0); 1882504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka } else { 188330be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka mHasValidSuggestions = true; 1884504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka ic.setComposingText(mComposing, 1); 1885504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka TextEntryState.backspace(); 1886504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka } 1887d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1888923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1889923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 1890c1e2e827b5d1bba59eb99d322dc101657ec28768Ken Wakasa mJustReverted = false; 1891923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1892923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1893923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1894923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project protected String getWordSeparators() { 1895923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return mWordSeparators; 1896923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1897a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1898923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean isWordSeparator(int code) { 1899923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project String separators = getWordSeparators(); 1900923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return separators.contains(String.valueOf((char)code)); 1901923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1902923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1903979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private boolean isSentenceSeparator(int code) { 1904923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return mSentenceSeparators.contains(String.valueOf((char)code)); 1905923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1906923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1907923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void sendSpace() { 1908571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka sendKeyChar((char)Keyboard.CODE_SPACE); 1909b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 1910923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1911923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1912923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean preferCapitalization() { 19130b4ae1f578e768eec4ada90aeb81d11acb10eb2eKen Wakasa return mWord.isFirstCharCapitalized(); 1914923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1915923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1916c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // Notify that language or mode have been changed and toggleLanguage will update KeyboaredID 1917c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // according to new language or mode. 1918c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka public void onRefreshKeyboard() { 19194ab730dbd34fad323063f2ffd31ce33de746668dsatok toggleLanguage(true, true); 19204ab730dbd34fad323063f2ffd31ce33de746668dsatok } 19214ab730dbd34fad323063f2ffd31ce33de746668dsatok 19224ab730dbd34fad323063f2ffd31ce33de746668dsatok // "reset" and "next" are used only for USE_SPACEBAR_LANGUAGE_SWITCHER. 19233f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani private void toggleLanguage(boolean reset, boolean next) { 1924de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka if (mSubtypeSwitcher.useSpacebarLanguageSwitcher()) { 19254ab730dbd34fad323063f2ffd31ce33de746668dsatok mSubtypeSwitcher.toggleLanguage(reset, next); 19264ab730dbd34fad323063f2ffd31ce33de746668dsatok } 19274ab730dbd34fad323063f2ffd31ce33de746668dsatok // Reload keyboard because the current language has been changed. 1928cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), 19294b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka mVoiceConnector.isVoiceButtonEnabled(), mVoiceConnector.isVoiceButtonOnPrimary()); 19300ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 19314b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 193236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 193336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 19345a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 19358aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onSwipeDown() { 1936363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka if (mConfigSwipeDownDismissKeyboardEnabled) 1937363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka handleClose(); 1938923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1939923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 19405a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 1941923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onPress(int primaryCode) { 1942cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka if (mKeyboardSwitcher.isVibrateAndSoundFeedbackRequired()) { 1943cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka vibrate(); 1944cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka playKeyClick(primaryCode); 1945cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka } 19461679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 19471679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); 1948571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { 1949b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.onPressShift(); 1950e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { 19516c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka switcher.onPressSymbol(); 195240a05f62edc6cdedb4365a722b48a72826ef2bf6Tadashi G. Takaoka } else { 19536c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka switcher.onOtherKeyPressed(); 1954681b102a492b7d5301c1ca87985b4c391eb5eb14Tadashi G. Takaoka } 1955dcade18113286a132a2f5fb508fdba836470c3fbAlan Viverette mAccessibilityUtils.onPress(primaryCode, switcher); 1956923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1957923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 19585a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 1959923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onRelease(int primaryCode) { 19601679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 19613f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani // Reset any drag flags in the keyboard 19621679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka switcher.keyReleased(); 19631679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); 1964571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { 1965889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka switcher.onReleaseShift(); 1966e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { 19676c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka switcher.onReleaseSymbol(); 196840a05f62edc6cdedb4365a722b48a72826ef2bf6Tadashi G. Takaoka } 1969dcade18113286a132a2f5fb508fdba836470c3fbAlan Viverette mAccessibilityUtils.onRelease(primaryCode, switcher); 1970923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1971a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1972a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1973123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka // receive ringer mode change and network state change. 1974923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private BroadcastReceiver mReceiver = new BroadcastReceiver() { 1975923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 1976923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onReceive(Context context, Intent intent) { 1977123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final String action = intent.getAction(); 1978123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { 1979123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka updateRingerMode(); 1980123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 1981123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka mSubtypeSwitcher.onNetworkStateChanged(intent); 1982123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka } 1983923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1984923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project }; 1985923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1986923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // update flags for silent mode 1987923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void updateRingerMode() { 1988923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager == null) { 1989923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 1990923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1991923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager != null) { 1992923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mSilentMode = (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL); 1993923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1994923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1995923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1996923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void playKeyClick(int primaryCode) { 1997923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // if mAudioManager is null, we don't have the ringer state yet 1998923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // mAudioManager will be set by updateRingerMode 1999923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager == null) { 2000979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mKeyboardSwitcher.getInputView() != null) { 2001923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateRingerMode(); 2002923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2003923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2004923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mSoundOn && !mSilentMode) { 2005923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // FIXME: Volume and enable should come from UI settings 2006923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // FIXME: These should be triggered after auto-repeat logic 2007923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int sound = AudioManager.FX_KEYPRESS_STANDARD; 2008923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 2009571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_DELETE: 2010923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sound = AudioManager.FX_KEYPRESS_DELETE; 2011923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 2012571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_ENTER: 2013923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sound = AudioManager.FX_KEYPRESS_RETURN; 2014923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 2015571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_SPACE: 2016923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sound = AudioManager.FX_KEYPRESS_SPACEBAR; 2017923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 2018923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2019923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAudioManager.playSoundEffect(sound, FX_VOLUME); 2020923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2021923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2022923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2023409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void vibrate() { 2024923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (!mVibrateOn) { 2025923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 2026923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 20271679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); 20281679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka if (inputView != null) { 20291679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka inputView.performHapticFeedback( 2030979f8690967ff5409fe18f5085858ccdb8e0ccf1satok HapticFeedbackConstants.KEYBOARD_TAP, 203166a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); 2032923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2033923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2034923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 203571c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka public void promoteToUserDictionary(String word, int frequency) { 203634386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani if (mUserDictionary.isValidWord(word)) return; 203734386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani mUserDictionary.addWord(word, frequency); 203834386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani } 203934386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani 204071c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka public WordComposer getCurrentWord() { 20416516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani return mWord; 20426516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani } 20436516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani 204471c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka public boolean getPopupOn() { 2045979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return mPopupOn; 2046979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 2047979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2048e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private void updateCorrectionMode() { 2049e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mHasDictionary = mSuggest != null ? mSuggest.hasMainDictionary() : false; 2050e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mAutoCorrectOn = (mAutoCorrectEnabled || mQuickFixes) 2051e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani && !mInputTypeNoAutoCorrect && mHasDictionary; 205232e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani mCorrectionMode = (mAutoCorrectOn && mAutoCorrectEnabled) 2053e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani ? Suggest.CORRECTION_FULL 205432e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani : (mAutoCorrectOn ? Suggest.CORRECTION_BASIC : Suggest.CORRECTION_NONE); 2055979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mCorrectionMode = (mBigramSuggestionEnabled && mAutoCorrectOn && mAutoCorrectEnabled) 2056979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ? Suggest.CORRECTION_FULL_BIGRAM : mCorrectionMode; 2057e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani if (mSuggest != null) { 2058e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mSuggest.setCorrectionMode(mCorrectionMode); 2059e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani } 2060e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani } 2061e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani 20620ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private void updateAutoTextEnabled() { 206332e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani if (mSuggest == null) return; 20645ef096f5f601c759e8a4a888aaca91ac5ccd9974Tadashi G. Takaoka mSuggest.setQuickFixesEnabled(mQuickFixes 20654ab730dbd34fad323063f2ffd31ce33de746668dsatok && SubtypeSwitcher.getInstance().isSystemLanguageSameAsInputLanguage()); 206632e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 206732e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani 20687599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private void updateSuggestionVisibility(SharedPreferences prefs) { 2069458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa final Resources res = mResources; 20707599cfea4a2d56f4779452ec8e8742f7b9629cc0satok final String suggestionVisiblityStr = prefs.getString( 20719502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka Settings.PREF_SHOW_SUGGESTIONS_SETTING, 2072458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa res.getString(R.string.prefs_suggestion_visibility_default_value)); 20737599cfea4a2d56f4779452ec8e8742f7b9629cc0satok for (int visibility : SUGGESTION_VISIBILITY_VALUE_ARRAY) { 2074458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa if (suggestionVisiblityStr.equals(res.getString(visibility))) { 20757599cfea4a2d56f4779452ec8e8742f7b9629cc0satok mSuggestionVisibility = visibility; 20767599cfea4a2d56f4779452ec8e8742f7b9629cc0satok break; 20777599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 20787599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 20797599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 20807599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 2081466741d8a78965b8509bf527344f289e50873092Mike LeBeau protected void launchSettings() { 20829502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka launchSettings(Settings.class); 2083466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 2084466741d8a78965b8509bf527344f289e50873092Mike LeBeau 2085bf96661d33d0126adb60a48880ceba1ff055d4a4satok public void launchDebugSettings() { 20869502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka launchSettings(DebugSettings.class); 2087bf96661d33d0126adb60a48880ceba1ff055d4a4satok } 2088bf96661d33d0126adb60a48880ceba1ff055d4a4satok 2089507495efd57074994fdc2fda78db9d5345f4a3a8Tadashi G. Takaoka protected void launchSettings(Class<? extends PreferenceActivity> settingsClass) { 2090923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project handleClose(); 2091923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Intent intent = new Intent(); 2092466741d8a78965b8509bf527344f289e50873092Mike LeBeau intent.setClass(LatinIME.this, settingsClass); 2093923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2094923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project startActivity(intent); 2095923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2096923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2097507495efd57074994fdc2fda78db9d5345f4a3a8Tadashi G. Takaoka private void loadSettings(EditorInfo attribute) { 2098923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Get the settings preferences 209927d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa final SharedPreferences prefs = mPrefs; 21004174655e23734563775acb9e1e644b31b9e72fa5Ken Wakasa Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); 21014174655e23734563775acb9e1e644b31b9e72fa5Ken Wakasa mVibrateOn = vibrator != null && vibrator.hasVibrator() 21029502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka && prefs.getBoolean(Settings.PREF_VIBRATE_ON, false); 2103f0d99b8677afdde39c16d414d44bfafcaea94b50Jean Chalard mSoundOn = prefs.getBoolean(Settings.PREF_SOUND_ON, 2104f0d99b8677afdde39c16d414d44bfafcaea94b50Jean Chalard mResources.getBoolean(R.bool.config_default_sound_enabled)); 2105728115493e14f84d5f02a4812c8086a378813364Jean Chalard 2106728115493e14f84d5f02a4812c8086a378813364Jean Chalard mPopupOn = isPopupEnabled(prefs); 21079502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true); 210889764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard mQuickFixes = isQuickFixesEnabled(prefs); 2109a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 211027d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa mAutoCorrectEnabled = isAutoCorrectEnabled(prefs); 211127d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa mBigramSuggestionEnabled = mAutoCorrectEnabled && isBigramSuggestionEnabled(prefs); 21121b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka loadAndSetAutoCorrectionThreshold(prefs); 2113466741d8a78965b8509bf527344f289e50873092Mike LeBeau 211427d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa mVoiceConnector.loadSettings(attribute, prefs); 2115409220583333bdf06290dd9fd42f91b5c0d1b11asatok 2116e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani updateCorrectionMode(); 21170ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok updateAutoTextEnabled(); 211827d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa updateSuggestionVisibility(prefs); 211927d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa SubtypeSwitcher.getInstance().loadSettings(); 212036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 212136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 2122b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda /** 21231b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka * Load Auto correction threshold from SharedPreferences, and modify mSuggest's threshold. 2124b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda */ 21251b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka private void loadAndSetAutoCorrectionThreshold(SharedPreferences sp) { 2126b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda // When mSuggest is not initialized, cannnot modify mSuggest's threshold. 2127b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda if (mSuggest == null) return; 21281b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka // When auto correction setting is turned off, the threshold is ignored. 2129b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda if (!isAutoCorrectEnabled(sp)) return; 2130b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda 21311b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final String currentAutoCorrectionSetting = sp.getString( 21321b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka Settings.PREF_AUTO_CORRECTION_THRESHOLD, 21339ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka mResources.getString(R.string.auto_correction_threshold_mode_index_modest)); 21341b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final String[] autoCorrectionThresholdValues = mResources.getStringArray( 21359ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka R.array.auto_correction_threshold_values); 21361b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka // When autoCrrectionThreshold is greater than 1.0, auto correction is virtually turned off. 21371b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka double autoCorrectionThreshold = Double.MAX_VALUE; 2138b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda try { 21391b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final int arrayIndex = Integer.valueOf(currentAutoCorrectionSetting); 21401b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (arrayIndex >= 0 && arrayIndex < autoCorrectionThresholdValues.length) { 21411b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka autoCorrectionThreshold = Double.parseDouble( 21421b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka autoCorrectionThresholdValues[arrayIndex]); 2143b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda } 2144b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda } catch (NumberFormatException e) { 21451b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka // Whenever the threshold settings are correct, never come here. 21461b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka autoCorrectionThreshold = Double.MAX_VALUE; 21471b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka Log.w(TAG, "Cannot load auto correction threshold setting." 21481b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka + " currentAutoCorrectionSetting: " + currentAutoCorrectionSetting 21491b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka + ", autoCorrectionThresholdValues: " 21501b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka + Arrays.toString(autoCorrectionThresholdValues)); 2151b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda } 2152b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda // TODO: This should be refactored : 21531b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka // setAutoCorrectionThreshold should be called outside of this method. 21541b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mSuggest.setAutoCorrectionThreshold(autoCorrectionThreshold); 2155b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda } 2156b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda 2157728115493e14f84d5f02a4812c8086a378813364Jean Chalard private boolean isPopupEnabled(SharedPreferences sp) { 2158728115493e14f84d5f02a4812c8086a378813364Jean Chalard final boolean showPopupOption = getResources().getBoolean( 2159728115493e14f84d5f02a4812c8086a378813364Jean Chalard R.bool.config_enable_show_popup_on_keypress_option); 2160728115493e14f84d5f02a4812c8086a378813364Jean Chalard if (!showPopupOption) return mResources.getBoolean(R.bool.config_default_popup_preview); 2161728115493e14f84d5f02a4812c8086a378813364Jean Chalard return sp.getBoolean(Settings.PREF_POPUP_ON, 2162728115493e14f84d5f02a4812c8086a378813364Jean Chalard mResources.getBoolean(R.bool.config_default_popup_preview)); 2163728115493e14f84d5f02a4812c8086a378813364Jean Chalard } 2164728115493e14f84d5f02a4812c8086a378813364Jean Chalard 216589764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard private boolean isQuickFixesEnabled(SharedPreferences sp) { 216689764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard final boolean showQuickFixesOption = mResources.getBoolean( 216789764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard R.bool.config_enable_quick_fixes_option); 216889764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard if (!showQuickFixesOption) { 216989764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard return isAutoCorrectEnabled(sp); 217089764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard } 217189764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard return sp.getBoolean(Settings.PREF_QUICK_FIXES, mResources.getBoolean( 217289764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard R.bool.config_default_quick_fixes)); 217389764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard } 217489764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard 2175b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda private boolean isAutoCorrectEnabled(SharedPreferences sp) { 21761b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final String currentAutoCorrectionSetting = sp.getString( 21771b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka Settings.PREF_AUTO_CORRECTION_THRESHOLD, 21789ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka mResources.getString(R.string.auto_correction_threshold_mode_index_modest)); 21791b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final String autoCorrectionOff = mResources.getString( 21809ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka R.string.auto_correction_threshold_mode_index_off); 21811b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka return !currentAutoCorrectionSetting.equals(autoCorrectionOff); 2182b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda } 2183b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda 2184b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda private boolean isBigramSuggestionEnabled(SharedPreferences sp) { 218589764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard final boolean showBigramSuggestionsOption = mResources.getBoolean( 218689764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard R.bool.config_enable_bigram_suggestions_option); 218789764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard if (!showBigramSuggestionsOption) { 218889764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard return isAutoCorrectEnabled(sp); 218989764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard } 219089764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard return sp.getBoolean(Settings.PREF_BIGRAM_SUGGESTIONS, mResources.getBoolean( 219189764ad4ac5415fb9753c38671b1fa18b9cdd390Jean Chalard R.bool.config_default_bigram_suggestions)); 2192b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda } 2193b1abda8d62d654e876c4f781a07d724922c736e4Mitsuhiro Shimoda 21946a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani private void initSuggestPuncList() { 21957e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka if (mSuggestPuncs != null || mSuggestPuncList != null) 21967e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka return; 21977e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords.Builder builder = new SuggestedWords.Builder(); 21987e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka String puncs = mResources.getString(R.string.suggested_punctuations); 21997e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka if (puncs != null) { 22007e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka for (int i = 0; i < puncs.length(); i++) { 22017e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka builder.addWord(puncs.subSequence(i, i + 1)); 22026a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 22036a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 22047e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka mSuggestPuncList = builder.build(); 22057e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka mSuggestPuncs = puncs; 22066a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 22076a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 2208979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private boolean isSuggestedPunctuation(int code) { 2209979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return mSuggestPuncs.contains(String.valueOf((char)code)); 2210979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 2211979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 22122fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private void showSubtypeSelectorAndSettings() { 221385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence title = getString(R.string.english_ime_input_options); 221485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence[] items = new CharSequence[] { 221585996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka // TODO: Should use new string "Select active input modes". 221685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.language_selection_title), 221785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.english_ime_settings), 221885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 221985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 22202fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka @Override 22212fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka public void onClick(DialogInterface di, int position) { 22222fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka di.dismiss(); 22232fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka switch (position) { 222485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 0: 22252fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka Intent intent = new Intent( 22262fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka android.provider.Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS); 22272fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 22282fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 22292fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_CLEAR_TOP); 22302fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka intent.putExtra(android.provider.Settings.EXTRA_INPUT_METHOD_ID, 22312fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka mInputMethodId); 22322fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka startActivity(intent); 22332fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 2234aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa case 1: 2235aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa launchSettings(); 2236aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa break; 22372fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 22382fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 223985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 224085996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka showOptionsMenuInternal(title, items, listener); 22412fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 2242923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 22432fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private void showOptionsMenu() { 224485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence title = getString(R.string.english_ime_input_options); 224585996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence[] items = new CharSequence[] { 224685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.selectInputMethod), 224785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.english_ime_settings), 224885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 224985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 22505a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 2251923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onClick(DialogInterface di, int position) { 2252923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project di.dismiss(); 2253923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (position) { 225485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 0: 2255ea55bf5df7d26d12b36c47141bfbac5730c3929aTadashi G. Takaoka mImm.showInputMethodPicker(); 22562fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 225785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 1: 2258ea55bf5df7d26d12b36c47141bfbac5730c3929aTadashi G. Takaoka launchSettings(); 22592fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 2260923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2261923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 226285996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 226385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka showOptionsMenuInternal(title, items, listener); 22642fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 22652fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka 226685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka private void showOptionsMenuInternal(CharSequence title, CharSequence[] items, 226785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka DialogInterface.OnClickListener listener) { 226818e15a1e5e30cf200e935e43a73edef25682de27Ken Wakasa final IBinder windowToken = mKeyboardSwitcher.getInputView().getWindowToken(); 226918e15a1e5e30cf200e935e43a73edef25682de27Ken Wakasa if (windowToken == null) return; 22702fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka AlertDialog.Builder builder = new AlertDialog.Builder(this); 22712fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka builder.setCancelable(true); 22722fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka builder.setIcon(R.drawable.ic_dialog_keyboard); 22732fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka builder.setNegativeButton(android.R.string.cancel, null); 227485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka builder.setItems(items, listener); 227585996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka builder.setTitle(title); 2276923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mOptionsDialog = builder.create(); 2277a2ad96d95986eb61c3d2d5abce154fb4c3803cacTadashi G. Takaoka mOptionsDialog.setCanceledOnTouchOutside(true); 2278923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Window window = mOptionsDialog.getWindow(); 2279923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project WindowManager.LayoutParams lp = window.getAttributes(); 228018e15a1e5e30cf200e935e43a73edef25682de27Ken Wakasa lp.token = windowToken; 2281923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 2282923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project window.setAttributes(lp); 2283923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 2284923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mOptionsDialog.show(); 2285923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2286923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 22877e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 22887e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { 2289923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.dump(fd, fout, args); 2290a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2291923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final Printer p = new PrintWriterPrinter(fout); 2292923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println("LatinIME state :"); 2293923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" Keyboard mode = " + mKeyboardSwitcher.getKeyboardMode()); 2294923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mComposing=" + mComposing.toString()); 22959fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka p.println(" mIsSuggestionsRequested=" + mIsSettingsSuggestionStripOn); 2296923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mCorrectionMode=" + mCorrectionMode); 22979fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka p.println(" mHasValidSuggestions=" + mHasValidSuggestions); 2298923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mAutoCorrectOn=" + mAutoCorrectOn); 2299923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mAutoSpace=" + mAutoSpace); 23001b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka p.println(" mApplicationSpecifiedCompletionOn=" + mApplicationSpecifiedCompletionOn); 2301923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" TextEntryState.state=" + TextEntryState.getState()); 2302923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mSoundOn=" + mSoundOn); 2303923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mVibrateOn=" + mVibrateOn); 2304979f8690967ff5409fe18f5085858ccdb8e0ccf1satok p.println(" mPopupOn=" + mPopupOn); 2305923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 23066e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani 2307923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Characters per second measurement 2308a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2309923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long mLastCpsTime; 2310923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int CPS_BUFFER_SIZE = 16; 2311923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long[] mCpsIntervals = new long[CPS_BUFFER_SIZE]; 2312923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mCpsIndex; 2313a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2314923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void measureCps() { 2315923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long now = System.currentTimeMillis(); 2316923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mLastCpsTime == 0) mLastCpsTime = now - 100; // Initial 2317923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCpsIntervals[mCpsIndex] = now - mLastCpsTime; 2318923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mLastCpsTime = now; 2319923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCpsIndex = (mCpsIndex + 1) % CPS_BUFFER_SIZE; 2320923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long total = 0; 2321923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project for (int i = 0; i < CPS_BUFFER_SIZE; i++) total += mCpsIntervals[i]; 2322923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project System.out.println("CPS = " + ((CPS_BUFFER_SIZE * 1000f) / total)); 2323923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 232434386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani 23250ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok @Override 23260ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) { 23274ab730dbd34fad323063f2ffd31ce33de746668dsatok SubtypeSwitcher.getInstance().updateSubtype(subtype); 23280ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok } 2329923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 2330