LatinIME.java revision 240297d0ee186b14e795016e9b1bd168c8d8acf8
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 192cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatokimport com.android.inputmethod.compat.CompatUtils; 20b2707856aba4fc9b063f26305f1fb603b19c1701satokimport com.android.inputmethod.compat.EditorInfoCompatUtils; 21b2707856aba4fc9b063f26305f1fb603b19c1701satokimport com.android.inputmethod.compat.InputConnectionCompatUtils; 22610f1dc8553cf2ed97e763a06a19380c4a6cd636satokimport com.android.inputmethod.compat.InputMethodManagerCompatWrapper; 2310dd34de0ffcde0104f7d2dae3a3c9fd66abffccsatokimport com.android.inputmethod.compat.InputMethodServiceCompatWrapper; 24e9957752bcaad048746c7a57bbd2c0a59e1918a0satokimport com.android.inputmethod.compat.InputTypeCompatUtils; 2588fc9d44186120f9edc5cf7ec0e2af85260fed04satokimport com.android.inputmethod.deprecated.LanguageSwitcherProxy; 26e9957752bcaad048746c7a57bbd2c0a59e1918a0satokimport com.android.inputmethod.deprecated.VoiceProxy; 27f733074aaecdfd6e89cfee2daff8a9c1233b60f1satokimport com.android.inputmethod.deprecated.recorrection.Recorrection; 285a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokaimport com.android.inputmethod.keyboard.Keyboard; 295a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardActionListener; 30571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardSwitcher; 315a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardView; 32de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaokaimport com.android.inputmethod.keyboard.LatinKeyboard; 335a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokaimport com.android.inputmethod.keyboard.LatinKeyboardView; 34388ce92ab8a635c5ad44620dad59baf05dfea510Amith Yamasani 35923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.app.AlertDialog; 36923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.BroadcastReceiver; 37923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Context; 38923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.DialogInterface; 39923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Intent; 40923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.IntentFilter; 41923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.SharedPreferences; 42923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.res.Configuration; 4336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasaniimport android.content.res.Resources; 44923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.inputmethodservice.InputMethodService; 45923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.media.AudioManager; 46123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaokaimport android.net.ConnectivityManager; 47923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Debug; 48923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Handler; 4918e15a1e5e30cf200e935e43a73edef25682de27Ken Wakasaimport android.os.IBinder; 50923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Message; 51923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.SystemClock; 52bf96661d33d0126adb60a48880ceba1ff055d4a4satokimport android.preference.PreferenceActivity; 53923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.preference.PreferenceManager; 54e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaokaimport android.text.InputType; 55923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.text.TextUtils; 56979f8690967ff5409fe18f5085858ccdb8e0ccf1satokimport android.util.DisplayMetrics; 57923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Log; 58923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.PrintWriterPrinter; 59923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Printer; 6066a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasaniimport android.view.HapticFeedbackConstants; 61923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.KeyEvent; 62e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaokaimport android.view.LayoutInflater; 63923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.View; 648e09172df1bb176cc899940862c56bed9b9aec4esatokimport android.view.ViewGroup; 658e09172df1bb176cc899940862c56bed9b9aec4esatokimport android.view.ViewParent; 66923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.Window; 67923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.WindowManager; 68923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.CompletionInfo; 69923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.EditorInfo; 70466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport android.view.inputmethod.ExtractedText; 71923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.InputConnection; 7240ac45ebdcd71940394dda00371d4847f7db0f26Ken Wakasaimport android.widget.LinearLayout; 73923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 74466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.FileDescriptor; 75466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.PrintWriter; 76466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.util.Locale; 77466741d8a78965b8509bf527344f289e50873092Mike LeBeau 78923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/** 79923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Input method implementation for Qwerty'ish keyboard. 80923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 8110dd34de0ffcde0104f7d2dae3a3c9fd66abffccsatokpublic class LatinIME extends InputMethodServiceCompatWrapper implements KeyboardActionListener { 828efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka private static final String TAG = LatinIME.class.getSimpleName(); 83979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private static final boolean PERF_DEBUG = false; 84409220583333bdf06290dd9fd42f91b5c0d1b11asatok private static final boolean TRACE = false; 85910b73127fa207dd26ec8124000262523b0aac0csatok private static boolean DEBUG = LatinImeLogger.sDBG; 86a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 878efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka /** 888efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * The private IME option used to indicate that no microphone should be 898efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * shown for a given text field. For instance, this is specified by the 908efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * search dialog when the dialog is already showing a voice search button. 918efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * 928efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * @deprecated Use {@link LatinIME#IME_OPTION_NO_MICROPHONE} with package name prefixed. 938efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka */ 9410dd34de0ffcde0104f7d2dae3a3c9fd66abffccsatok @SuppressWarnings("dep-ann") 958efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka public static final String IME_OPTION_NO_MICROPHONE_COMPAT = "nm"; 968efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka 978efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka /** 988efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * The private IME option used to indicate that no microphone should be 998efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * shown for a given text field. For instance, this is specified by the 1008efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * search dialog when the dialog is already showing a voice search button. 1018efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka */ 1024199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka public static final String IME_OPTION_NO_MICROPHONE = "noMicrophoneKey"; 1034199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka 1044199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka /** 1054199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka * The private IME option used to indicate that no settings key should be 1064199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka * shown for a given text field. 1074199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka */ 1084199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka public static final String IME_OPTION_NO_SETTINGS_KEY = "noSettingsKey"; 1098efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka 1109e347d3d448e48229c46aad394ec9bd60cd5807bsatok private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100; 111fd0bd57deb53c4cce32810a61133fa44b45dbb7bKen Wakasa 112923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // How many continuous deletes at which to start deleting at a higher speed. 113923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int DELETE_ACCELERATE_AT = 20; 114923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Key events coming any faster than this are long-presses. 115d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani private static final int QUICK_PRESS = 200; 116a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 117cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard /** 118cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard * The name of the scheme used by the Package Manager to warn of a new package installation, 119cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard * replacement or removal. 120cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard */ 121cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard private static final String SCHEME_PACKAGE = "package"; 122cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 1237599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private int mSuggestionVisibility; 1247599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_SHOW_VALUE 1257599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_show_value; 1267599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE 1277599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_show_only_portrait_value; 1287599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_HIDE_VALUE 1297599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_hide_value; 1307599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 1317599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int[] SUGGESTION_VISIBILITY_VALUE_ARRAY = new int[] { 1327599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_SHOW_VALUE, 1337599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE, 1347599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_HIDE_VALUE 1357599cfea4a2d56f4779452ec8e8742f7b9629cc0satok }; 1367599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 13717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard private Settings.Values mSettingsValues; 13817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 139e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka private View mCandidateViewContainer; 1407a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka private int mCandidateStripHeight; 141923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private CandidateView mCandidateView; 142923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private Suggest mSuggest; 1431b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka private CompletionInfo[] mApplicationSpecifiedCompletions; 144a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 145923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private AlertDialog mOptionsDialog; 146a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 147610f1dc8553cf2ed97e763a06a19380c4a6cd636satok private InputMethodManagerCompatWrapper mImm; 1482fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private Resources mResources; 1492fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private SharedPreferences mPrefs; 1502fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private String mInputMethodId; 15171c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka private KeyboardSwitcher mKeyboardSwitcher; 1520ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private SubtypeSwitcher mSubtypeSwitcher; 153b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok private VoiceProxy mVoiceProxy; 1547a8dac55278cedd838be325f56b4c52d973c61f5satok private Recorrection mRecorrection; 155a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 156923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private UserDictionary mUserDictionary; 157979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private UserBigramDictionary mUserBigramDictionary; 1582bed1531c2c9bd48096bfa97dd1a39e04bd15e7bEric Fischer private ContactsDictionary mContactsDictionary; 1594ff60be170872503cca0275ef3488b7379b5311bAmith Yamasani private AutoDictionary mAutoDictionary; 16036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 1610730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard // TODO: Create an inner class to group options and pseudo-options to improve readability. 162c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // These variables are initialized according to the {@link EditorInfo#inputType}. 1630730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard private boolean mShouldInsertMagicSpace; 164c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mInputTypeNoAutoCorrect; 165c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mIsSettingsSuggestionStripOn; 166c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mApplicationSpecifiedCompletionOn; 167c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 16871c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka private final StringBuilder mComposing = new StringBuilder(); 169923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private WordComposer mWord = new WordComposer(); 170923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private CharSequence mBestWord; 171f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard private boolean mHasUncommittedTypedChars; 172e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private boolean mHasDictionary; 1730730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard // Magic space: a space that should disappear on space/apostrophe insertion, move after the 1740730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard // punctuation on punctuation insertion, and become a real space on alpha char insertion. 1750730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard private boolean mJustAddedMagicSpace; // This indicates whether the last char is a magic space. 176409220583333bdf06290dd9fd42f91b5c0d1b11asatok 17779efbed76f638be298493107fa2d0cd1b5eb529esatok private int mCorrectionMode; 17879efbed76f638be298493107fa2d0cd1b5eb529esatok private int mCommittedLength; 17979efbed76f638be298493107fa2d0cd1b5eb529esatok private int mOrientation; 180979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Keep track of the last selection range to decide if we need to show word alternatives 18179efbed76f638be298493107fa2d0cd1b5eb529esatok private int mLastSelectionStart; 18279efbed76f638be298493107fa2d0cd1b5eb529esatok private int mLastSelectionEnd; 183979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 184923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Indicates whether the suggestion strip is to be on in landscape 185923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mJustAccepted; 186923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mDeleteCount; 187923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long mLastKeyTime; 188a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 189923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private AudioManager mAudioManager; 1902296317b8f0209789f797ac8a2fcb70e03f6d001Eric Laurent // Align sound effect volume on music volume 19171c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka private static final float FX_VOLUME = -1.0f; 19217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard private boolean mSilentModeOn; // System-wide current configuration 193923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 194b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok // TODO: Move this flag to VoiceProxy 19581c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani private boolean mConfigurationChanging; 196466741d8a78965b8509bf527344f289e50873092Mike LeBeau 197cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Object for reacting to adding/removing a dictionary pack. 198cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard private BroadcastReceiver mDictionaryPackInstallReceiver = 199cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard new DictionaryPackInstallBroadcastReceiver(this); 200cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 201dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani // Keeps track of most recently inserted text (multi-character key) for reverting 202dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani private CharSequence mEnteredText; 203dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 20436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 205571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka public final UIHandler mHandler = new UIHandler(); 206d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 207409220583333bdf06290dd9fd42f91b5c0d1b11asatok public class UIHandler extends Handler { 208d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_UPDATE_SUGGESTIONS = 0; 209d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_UPDATE_OLD_SUGGESTIONS = 1; 210d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_UPDATE_SHIFT_STATE = 2; 211d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_VOICE_RESULTS = 3; 212de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka private static final int MSG_FADEOUT_LANGUAGE_ON_SPACEBAR = 4; 213de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 5; 214fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka private static final int MSG_SPACE_TYPED = 6; 215cb3320179d39a7983874697a0aa428b127675c9dJean Chalard private static final int MSG_SET_BIGRAM_PREDICTIONS = 7; 216d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 217923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 218923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void handleMessage(Message msg) { 219de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 220de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka final LatinKeyboardView inputView = switcher.getInputView(); 221923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (msg.what) { 222d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SUGGESTIONS: 223d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka updateSuggestions(); 224d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 225d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_OLD_SUGGESTIONS: 2269fbfd5877305ed19a20663630b498b6b3fdae942satok mRecorrection.setRecorrectionSuggestions(mVoiceProxy, mCandidateView, mSuggest, 2279fbfd5877305ed19a20663630b498b6b3fdae942satok mKeyboardSwitcher, mWord, mHasUncommittedTypedChars, mLastSelectionStart, 22817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mLastSelectionEnd, mSettingsValues.mWordSeparators); 229d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 230d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SHIFT_STATE: 231de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka switcher.updateShiftState(); 232d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 233cb3320179d39a7983874697a0aa428b127675c9dJean Chalard case MSG_SET_BIGRAM_PREDICTIONS: 234cb3320179d39a7983874697a0aa428b127675c9dJean Chalard updateBigramPredictions(); 23589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard break; 236d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_VOICE_RESULTS: 237b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleVoiceResults(preferCapitalization() 238de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka || (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked())); 239de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka break; 240de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka case MSG_FADEOUT_LANGUAGE_ON_SPACEBAR: 24117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (inputView != null) { 24266432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka inputView.setSpacebarTextFadeFactor( 24317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard (1.0f + mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar) / 2, 24466432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka (LatinKeyboard)msg.obj); 24517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 246de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_DISMISS_LANGUAGE_ON_SPACEBAR, msg.obj), 24717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mDurationOfFadeoutLanguageOnSpacebar); 248de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka break; 249de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka case MSG_DISMISS_LANGUAGE_ON_SPACEBAR: 25017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (inputView != null) { 25166432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka inputView.setSpacebarTextFadeFactor( 25217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar, 25317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard (LatinKeyboard)msg.obj); 25417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 255d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 256923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 257923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 258d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 259d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateSuggestions() { 260d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 2619b2192bfd2d3a06df3c685ed4287e192dbaabf32Ken Wakasa sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTIONS), 26217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mDelayUpdateSuggestions); 263d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 264d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 265d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateSuggestions() { 266d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 267d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 268d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 269d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public boolean hasPendingUpdateSuggestions() { 270d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka return hasMessages(MSG_UPDATE_SUGGESTIONS); 271d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 272d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 273d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateOldSuggestions() { 274d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_OLD_SUGGESTIONS); 275d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_UPDATE_OLD_SUGGESTIONS), 27617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mDelayUpdateOldSuggestions); 277d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 278d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 279d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateOldSuggestions() { 280d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_OLD_SUGGESTIONS); 281d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 282d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 283d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateShiftKeyState() { 284d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 28517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard sendMessageDelayed(obtainMessage(MSG_UPDATE_SHIFT_STATE), 28617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mDelayUpdateShiftState); 287d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 288d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 289d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateShiftState() { 290d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 291d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 292d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 293cb3320179d39a7983874697a0aa428b127675c9dJean Chalard public void postUpdateBigramPredictions() { 294cb3320179d39a7983874697a0aa428b127675c9dJean Chalard removeMessages(MSG_SET_BIGRAM_PREDICTIONS); 2959b2192bfd2d3a06df3c685ed4287e192dbaabf32Ken Wakasa sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_PREDICTIONS), 29617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mDelayUpdateSuggestions); 29789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 29889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 299cb3320179d39a7983874697a0aa428b127675c9dJean Chalard public void cancelUpdateBigramPredictions() { 300cb3320179d39a7983874697a0aa428b127675c9dJean Chalard removeMessages(MSG_SET_BIGRAM_PREDICTIONS); 30189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 30289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 303d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void updateVoiceResults() { 304d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka sendMessage(obtainMessage(MSG_VOICE_RESULTS)); 305d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 306de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka 307d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka public void startDisplayLanguageOnSpacebar(boolean localeChanged) { 308de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka removeMessages(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR); 309de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka removeMessages(MSG_DISMISS_LANGUAGE_ON_SPACEBAR); 310de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka final LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); 311de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka if (inputView != null) { 312050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka final LatinKeyboard keyboard = mKeyboardSwitcher.getLatinKeyboard(); 313c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka // The language is always displayed when the delay is negative. 314c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka final boolean needsToDisplayLanguage = localeChanged 31517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard || mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar < 0; 316de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka // The language is never displayed when the delay is zero. 31717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar != 0) { 318c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka inputView.setSpacebarTextFadeFactor(needsToDisplayLanguage ? 1.0f 31917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard : mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar, keyboard); 32017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 321c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka // The fadeout animation will start when the delay is positive. 32217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (localeChanged && mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar > 0) { 323de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR, keyboard), 32417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar); 325de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 326de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 327de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 328fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 329fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public void startDoubleSpacesTimer() { 330fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka removeMessages(MSG_SPACE_TYPED); 331fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_SPACE_TYPED), 33217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mDoubleSpacesTurnIntoPeriodTimeout); 333fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 334fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 335fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public void cancelDoubleSpacesTimer() { 336fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka removeMessages(MSG_SPACE_TYPED); 337fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 338fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 339fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public boolean isAcceptingDoubleSpaces() { 340fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka return hasMessages(MSG_SPACE_TYPED); 341fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 342d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 343923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 3447e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 3457e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka public void onCreate() { 34627d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 34727d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa mPrefs = prefs; 34827d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa LatinImeLogger.init(this, prefs); 3496d9021527a38ba1e94225020389621a0d7227aa1satok LanguageSwitcherProxy.init(this, prefs); 35027d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa SubtypeSwitcher.init(this, prefs); 35127d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa KeyboardSwitcher.init(this, prefs); 3527a8dac55278cedd838be325f56b4c52d973c61f5satok Recorrection.init(this, prefs); 353363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 354923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onCreate(); 355363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 356610f1dc8553cf2ed97e763a06a19380c4a6cd636satok mImm = InputMethodManagerCompatWrapper.getInstance(this); 3578efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka mInputMethodId = Utils.getInputMethodId(mImm, getPackageName()); 3580ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mSubtypeSwitcher = SubtypeSwitcher.getInstance(); 3590ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mKeyboardSwitcher = KeyboardSwitcher.getInstance(); 3607a8dac55278cedd838be325f56b4c52d973c61f5satok mRecorrection = Recorrection.getInstance(); 361363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 36217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard loadSettings(); 36317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 364363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka final Resources res = getResources(); 365363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka mResources = res; 366fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard 3679502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka Utils.GCUtils.getInstance().reset(); 368979f8690967ff5409fe18f5085858ccdb8e0ccf1satok boolean tryGC = true; 3699502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { 370979f8690967ff5409fe18f5085858ccdb8e0ccf1satok try { 3710ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 372979f8690967ff5409fe18f5085858ccdb8e0ccf1satok tryGC = false; 373979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } catch (OutOfMemoryError e) { 3749502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka tryGC = Utils.GCUtils.getInstance().tryGCOrWait("InitSuggest", e); 375979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 376979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 377979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 378363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka mOrientation = res.getConfiguration().orientation; 379b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 380cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Register to receive ringer mode change and network state change. 381cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Also receive installation and removal of a dictionary pack. 382123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final IntentFilter filter = new IntentFilter(); 383123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); 384123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 385923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project registerReceiver(mReceiver, filter); 386b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy = VoiceProxy.init(this, prefs, mHandler); 387cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 388cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final IntentFilter packageFilter = new IntentFilter(); 389cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 390cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 391cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addDataScheme(SCHEME_PACKAGE); 392cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard registerReceiver(mDictionaryPackInstallReceiver, packageFilter); 393646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard 394646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard final IntentFilter newDictFilter = new IntentFilter(); 395646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard newDictFilter.addAction( 396646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard DictionaryPackInstallBroadcastReceiver.NEW_DICTIONARY_INTENT_ACTION); 397646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard registerReceiver(mDictionaryPackInstallReceiver, newDictFilter); 398923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 39936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 40017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard // Has to be package-visible for unit tests 40117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard /* package */ void loadSettings() { 40217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this); 40317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (null == mSubtypeSwitcher) mSubtypeSwitcher = SubtypeSwitcher.getInstance(); 40417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues = new Settings.Values(mPrefs, this, mSubtypeSwitcher.getInputLocaleStr()); 40517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 40617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 4070ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private void initSuggest() { 408cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); 409cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final Locale keyboardLocale = new Locale(localeStr); 41036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 411309bff562fbaf47488e6bf6636840f00574187d8Jean Chalard final Resources res = mResources; 412309bff562fbaf47488e6bf6636840f00574187d8Jean Chalard final Locale savedLocale = Utils.setSystemLocale(res, keyboardLocale); 41336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani if (mSuggest != null) { 41436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mSuggest.close(); 41536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 416979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 4178efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka int mainDicResId = Utils.getMainDictionaryResourceId(res); 418cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mSuggest = new Suggest(this, mainDicResId, keyboardLocale); 41917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.mAutoCorrectEnabled) { 42017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); 42117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 42227023341658b4cf5430d18ddb94fd9502ecfe3cbTadashi G. Takaoka updateAutoTextEnabled(); 423e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 424cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mUserDictionary = new UserDictionary(this, localeStr); 425923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mSuggest.setUserDictionary(mUserDictionary); 426e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 427e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mContactsDictionary = new ContactsDictionary(this, Suggest.DIC_CONTACTS); 4282bed1531c2c9bd48096bfa97dd1a39e04bd15e7bEric Fischer mSuggest.setContactsDictionary(mContactsDictionary); 429e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 430cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mAutoDictionary = new AutoDictionary(this, this, localeStr, Suggest.DIC_AUTO); 43134386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani mSuggest.setAutoDictionary(mAutoDictionary); 432e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 433cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mUserBigramDictionary = new UserBigramDictionary(this, this, localeStr, Suggest.DIC_USER); 434e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest.setUserBigramDictionary(mUserBigramDictionary); 435e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 436e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani updateCorrectionMode(); 43736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 438309bff562fbaf47488e6bf6636840f00574187d8Jean Chalard Utils.setSystemLocale(res, savedLocale); 439923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 44036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 441cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard /* package private */ void resetSuggestMainDict() { 442cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); 443cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final Locale keyboardLocale = new Locale(localeStr); 444cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard int mainDicResId = Utils.getMainDictionaryResourceId(mResources); 445cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mSuggest.resetMainDict(this, mainDicResId, keyboardLocale); 446cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard } 447cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 448466741d8a78965b8509bf527344f289e50873092Mike LeBeau @Override 449466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onDestroy() { 450e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa if (mSuggest != null) { 451e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest.close(); 452e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest = null; 453979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 454923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project unregisterReceiver(mReceiver); 455cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard unregisterReceiver(mDictionaryPackInstallReceiver); 456b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.destroy(); 457979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 458979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.onDestroy(); 459923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onDestroy(); 460923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 461923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 462923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 463923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onConfigurationChanged(Configuration conf) { 464dc64b138b5e3fb3706c0818d0a308fe6e36985b0Tadashi G. Takaoka mSubtypeSwitcher.onConfigurationChanged(conf); 465b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani // If orientation changed while predicting, commit the change 466b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani if (conf.orientation != mOrientation) { 467466741d8a78965b8509bf527344f289e50873092Mike LeBeau InputConnection ic = getCurrentInputConnection(); 468466741d8a78965b8509bf527344f289e50873092Mike LeBeau commitTyped(ic); 469466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (ic != null) ic.finishComposingText(); // For voice input 470b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani mOrientation = conf.orientation; 4712fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka if (isShowingOptionDialog()) 4722fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka mOptionsDialog.dismiss(); 473b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 4748b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka 47581c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani mConfigurationChanging = true; 476923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onConfigurationChanged(conf); 477b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.onConfigurationChanged(conf); 47881c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani mConfigurationChanging = false; 47988fc9d44186120f9edc5cf7ec0e2af85260fed04satok 48088fc9d44186120f9edc5cf7ec0e2af85260fed04satok // This will work only when the subtype is not supported. 48188fc9d44186120f9edc5cf7ec0e2af85260fed04satok LanguageSwitcherProxy.onConfigurationChanged(conf); 482923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 483b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 484923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 485923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public View onCreateInputView() { 4868d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka return mKeyboardSwitcher.onCreateInputView(); 487923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 488923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 489923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 490923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public View onCreateCandidatesView() { 491e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka LayoutInflater inflater = getLayoutInflater(); 492e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka LinearLayout container = (LinearLayout)inflater.inflate(R.layout.candidates, null); 493e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka mCandidateViewContainer = container; 4947a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka mCandidateStripHeight = (int)mResources.getDimension(R.dimen.candidate_strip_height); 495e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka mCandidateView = (CandidateView) container.findViewById(R.id.candidates); 496923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCandidateView.setService(this); 497923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project setCandidatesViewShown(true); 498e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka return container; 499923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 500923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 501a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker @Override 502923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onStartInputView(EditorInfo attribute, boolean restarting) { 50345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 50445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka LatinKeyboardView inputView = switcher.getInputView(); 5058e09172df1bb176cc899940862c56bed9b9aec4esatok 50689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (DEBUG) { 507910b73127fa207dd26ec8124000262523b0aac0csatok Log.d(TAG, "onStartInputView: " + inputView); 508910b73127fa207dd26ec8124000262523b0aac0csatok } 509923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In landscape mode, this method gets called without the input view being created. 510979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (inputView == null) { 511923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 512923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 513923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 5148d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka mSubtypeSwitcher.updateParametersOnStartInputView(); 5154ab730dbd34fad323063f2ffd31ce33de746668dsatok 516662bb7c26cadd5026cb3d4e5d081aae163bd5a3aTadashi G. Takaoka TextEntryState.reset(); 5176c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani 518c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // Most such things we decide below in initializeInputAttributesAndGetMode, but we need to 519c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // know now whether this is a password text field, because we need to know now whether we 520c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // want to enable the voice button. 521b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok final VoiceProxy voiceIme = mVoiceProxy; 522e9957752bcaad048746c7a57bbd2c0a59e1918a0satok voiceIme.resetVoiceStates(InputTypeCompatUtils.isPasswordInputType(attribute.inputType) 523e9957752bcaad048746c7a57bbd2c0a59e1918a0satok || InputTypeCompatUtils.isVisiblePasswordInputType(attribute.inputType)); 524c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 525cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka initializeInputAttributes(attribute); 526c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 527c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.closing(); 528c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mEnteredText = null; 529c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mComposing.setLength(0); 530f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = false; 531c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mDeleteCount = 0; 5320730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard mJustAddedMagicSpace = false; 533c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 53417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard loadSettings(); 53517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard updateCorrectionMode(); 53617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard updateAutoTextEnabled(); 53717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard updateSuggestionVisibility(mPrefs, mResources); 53817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 53917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSuggest != null && mSettingsValues.mAutoCorrectEnabled) { 54017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); 54117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 54217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mVoiceProxy.loadSettings(attribute, mPrefs); 54317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard // This will work only when the subtype is not supported. 54417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard LanguageSwitcherProxy.loadSettings(); 54517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 546c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if (mSubtypeSwitcher.isKeyboardMode()) { 547cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka switcher.loadKeyboard(attribute, 5484503e2ea9853c1573f60903d8639d82e39e07c56Tadashi G. Takaoka mSubtypeSwitcher.isShortcutImeEnabled() && voiceIme.isVoiceButtonEnabled(), 5494503e2ea9853c1573f60903d8639d82e39e07c56Tadashi G. Takaoka voiceIme.isVoiceButtonOnPrimary()); 550c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka switcher.updateShiftState(); 551c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka } 552c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 5537a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka setCandidatesViewShownInternal(isCandidateStripVisible(), false /* needsInputViewShown */ ); 554c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // Delay updating suggestions because keyboard input view may not be shown at this point. 555c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mHandler.postUpdateSuggestions(); 556c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 557c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka updateCorrectionMode(); 558c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 559240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard inputView.setKeyPreviewPopupEnabled(mSettingsValues.mKeyPreviewPopupOn, 560240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard mSettingsValues.mKeyPreviewPopupDismissDelay); 561c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.setProximityCorrectionEnabled(true); 562c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // If we just entered a text field, maybe it has some old text that requires correction 5637a8dac55278cedd838be325f56b4c52d973c61f5satok mRecorrection.checkRecorrectionOnStart(); 564c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.setForeground(true); 565c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 5664503e2ea9853c1573f60903d8639d82e39e07c56Tadashi G. Takaoka voiceIme.onStartInputView(inputView.getWindowToken()); 567c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 568c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); 569c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka } 570c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 571cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka private void initializeInputAttributes(EditorInfo attribute) { 572cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if (attribute == null) 573cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka return; 5744b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka final int inputType = attribute.inputType; 575c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka final int variation = inputType & InputType.TYPE_MASK_VARIATION; 5760730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard mShouldInsertMagicSpace = false; 577e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mInputTypeNoAutoCorrect = false; 5789fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 5791b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletionOn = false; 5801b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletions = null; 581dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 582cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_MASK_CLASS) == InputType.TYPE_CLASS_TEXT) { 583cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = true; 584cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // Make sure that passwords are not displayed in candidate view 585e9957752bcaad048746c7a57bbd2c0a59e1918a0satok if (InputTypeCompatUtils.isPasswordInputType(inputType) 586e9957752bcaad048746c7a57bbd2c0a59e1918a0satok || InputTypeCompatUtils.isVisiblePasswordInputType(inputType)) { 587cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 588cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 589e9957752bcaad048746c7a57bbd2c0a59e1918a0satok if (InputTypeCompatUtils.isEmailVariation(variation) 590cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka || variation == InputType.TYPE_TEXT_VARIATION_PERSON_NAME) { 5910730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard mShouldInsertMagicSpace = false; 592cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else { 5930730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard mShouldInsertMagicSpace = true; 594cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 595e9957752bcaad048746c7a57bbd2c0a59e1918a0satok if (InputTypeCompatUtils.isEmailVariation(variation)) { 596cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 597cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) { 598cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 599cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) { 600cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 601cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else if (variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) { 602cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // If it's a browser edit field and auto correct is not ON explicitly, then 603cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // disable auto correction, but keep suggestions on. 604cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) { 605e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mInputTypeNoAutoCorrect = true; 60636ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani } 607cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 608cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka 609cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // If NO_SUGGESTIONS is set, don't do prediction. 610cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) { 611cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 612cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mInputTypeNoAutoCorrect = true; 613cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 614cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // If it's not multiline and the autoCorrect flag is not set, then don't correct 615cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 616cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka && (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) == 0) { 617cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mInputTypeNoAutoCorrect = true; 618cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 619cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { 620cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 621cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mApplicationSpecifiedCompletionOn = isFullscreenMode(); 622cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 623923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 624923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 625923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 626923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 627923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onFinishInput() { 628923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onFinishInput(); 629a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 630979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 6311b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mKeyboardSwitcher.onAutoCorrectionStateChanged(false); 632979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 633b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.flushVoiceInputLogs(mConfigurationChanging); 634409220583333bdf06290dd9fd42f91b5c0d1b11asatok 6355a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getInputView(); 636d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa if (inputView != null) inputView.closing(); 6374ff60be170872503cca0275ef3488b7379b5311bAmith Yamasani if (mAutoDictionary != null) mAutoDictionary.flushPendingWrites(); 638979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mUserBigramDictionary != null) mUserBigramDictionary.flushPendingWrites(); 639466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 640466741d8a78965b8509bf527344f289e50873092Mike LeBeau 641466741d8a78965b8509bf527344f289e50873092Mike LeBeau @Override 6426495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa public void onFinishInputView(boolean finishingInput) { 6436495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa super.onFinishInputView(finishingInput); 6445a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getInputView(); 645d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa if (inputView != null) inputView.setForeground(false); 646d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka // Remove pending messages related to update suggestions 647d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 648d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateOldSuggestions(); 6496495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa } 6506495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa 6516495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa @Override 652466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onUpdateExtractedText(int token, ExtractedText text) { 653466741d8a78965b8509bf527344f289e50873092Mike LeBeau super.onUpdateExtractedText(token, text); 654b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.showPunctuationHintIfNecessary(); 655923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 656923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 657923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 658923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onUpdateSelection(int oldSelStart, int oldSelEnd, 659923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int newSelStart, int newSelEnd, 660923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int candidatesStart, int candidatesEnd) { 661923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, 662923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project candidatesStart, candidatesEnd); 663466741d8a78965b8509bf527344f289e50873092Mike LeBeau 664466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (DEBUG) { 665466741d8a78965b8509bf527344f289e50873092Mike LeBeau Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart 666466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", ose=" + oldSelEnd 667025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa + ", lss=" + mLastSelectionStart 668025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa + ", lse=" + mLastSelectionEnd 669466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nss=" + newSelStart 670466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nse=" + newSelEnd 671466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", cs=" + candidatesStart 672466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", ce=" + candidatesEnd); 673466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 674466741d8a78965b8509bf527344f289e50873092Mike LeBeau 675b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.setCursorAndSelection(newSelEnd, newSelStart); 6764f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 677923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // If the current selection in the text view changes, we should 678923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // clear whatever candidate text we have. 679025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa final boolean selectionChanged = (newSelStart != candidatesEnd 680025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa || newSelEnd != candidatesEnd) && mLastSelectionStart != newSelStart; 681025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa final boolean candidatesCleared = candidatesStart == -1 && candidatesEnd == -1; 682f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (((mComposing.length() > 0 && mHasUncommittedTypedChars) 683b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok || mVoiceProxy.isVoiceInputHighlighted()) 684025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa && (selectionChanged || candidatesCleared)) { 685025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa if (candidatesCleared) { 686025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa // If the composing span has been cleared, save the typed word in the history for 687025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa // recorrection before we reset the candidate strip. Then, we'll be able to show 688025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa // suggestions for recorrection right away. 689f733074aaecdfd6e89cfee2daff8a9c1233b60f1satok mRecorrection.saveRecorrectionSuggestion(mWord, mComposing); 690025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa } 691923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mComposing.setLength(0); 692f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = false; 69389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (isCursorTouchingWord()) { 694cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.cancelUpdateBigramPredictions(); 69589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.postUpdateSuggestions(); 69689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 69789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard setPunctuationSuggestions(); 69889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 699923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.reset(); 700923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 701923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 702923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.finishComposingText(); 703923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 704b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.setVoiceInputHighlighted(false); 705f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard } else if (!mHasUncommittedTypedChars && !mJustAccepted) { 706662bb7c26cadd5026cb3d4e5d081aae163bd5a3aTadashi G. Takaoka if (TextEntryState.isAcceptedDefault() || TextEntryState.isSpaceAfterPicked()) { 707662bb7c26cadd5026cb3d4e5d081aae163bd5a3aTadashi G. Takaoka if (TextEntryState.isAcceptedDefault()) 708662bb7c26cadd5026cb3d4e5d081aae163bd5a3aTadashi G. Takaoka TextEntryState.reset(); 7090730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard mJustAddedMagicSpace = false; // The user moved the cursor. 7109a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 711923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 712923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mJustAccepted = false; 713d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateShiftKeyState(); 714466741d8a78965b8509bf527344f289e50873092Mike LeBeau 715979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Make a note of the cursor position 716979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionStart = newSelStart; 717979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionEnd = newSelEnd; 718466741d8a78965b8509bf527344f289e50873092Mike LeBeau 7197a8dac55278cedd838be325f56b4c52d973c61f5satok mRecorrection.updateRecorrectionSelection(mKeyboardSwitcher, 7207a8dac55278cedd838be325f56b4c52d973c61f5satok mCandidateView, candidatesStart, candidatesEnd, newSelStart, 7217a8dac55278cedd838be325f56b4c52d973c61f5satok newSelEnd, oldSelStart, mLastSelectionStart, 7227a8dac55278cedd838be325f56b4c52d973c61f5satok mLastSelectionEnd, mHasUncommittedTypedChars); 7237a8dac55278cedd838be325f56b4c52d973c61f5satok } 7247a8dac55278cedd838be325f56b4c52d973c61f5satok 7257a8dac55278cedd838be325f56b4c52d973c61f5satok public void setLastSelection(int start, int end) { 7267a8dac55278cedd838be325f56b4c52d973c61f5satok mLastSelectionStart = start; 7277a8dac55278cedd838be325f56b4c52d973c61f5satok mLastSelectionEnd = end; 728923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 729923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 730c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 731c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has clicked on the extracted text view, 732c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * when running in fullscreen mode. The default implementation hides 733c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * the candidates view when this happens, but only if the extracted text 734c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * editor has a vertical scroll bar because its text doesn't fit. 735c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * Here we override the behavior due to the possibility that a re-correction could 736c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * cause the candidate strip to disappear and re-appear. 737c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani */ 738c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani @Override 739c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani public void onExtractedTextClicked() { 7407a8dac55278cedd838be325f56b4c52d973c61f5satok if (mRecorrection.isRecorrectionEnabled() && isSuggestionsRequested()) return; 741c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 742c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedTextClicked(); 743c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 744c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 745c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 746c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has performed a cursor movement in the 747c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * extracted text view, when it is running in fullscreen mode. The default 748c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * implementation hides the candidates view when a vertical movement 749c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * happens, but only if the extracted text editor has a vertical scroll bar 750c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * because its text doesn't fit. 751c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * Here we override the behavior due to the possibility that a re-correction could 752c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * cause the candidate strip to disappear and re-appear. 753c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani */ 754c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani @Override 755c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani public void onExtractedCursorMovement(int dx, int dy) { 7567a8dac55278cedd838be325f56b4c52d973c61f5satok if (mRecorrection.isRecorrectionEnabled() && isSuggestionsRequested()) return; 757c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 758c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedCursorMovement(dx, dy); 759c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 760c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 761923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 762923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void hideWindow() { 763979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 7641b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mKeyboardSwitcher.onAutoCorrectionStateChanged(false); 765979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 766923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (TRACE) Debug.stopMethodTracing(); 7676e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (mOptionsDialog != null && mOptionsDialog.isShowing()) { 7686e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog.dismiss(); 7696e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog = null; 7706e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 771b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.hideVoiceWindow(mConfigurationChanging); 7729fbfd5877305ed19a20663630b498b6b3fdae942satok mRecorrection.clearWordsInHistory(); 773923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.hideWindow(); 774923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 775923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 776923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 7771b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka public void onDisplayCompletions(CompletionInfo[] applicationSpecifiedCompletions) { 778979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (DEBUG) { 779a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa Log.i(TAG, "Received completions:"); 780bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok if (applicationSpecifiedCompletions != null) { 781bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok for (int i = 0; i < applicationSpecifiedCompletions.length; i++) { 782bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok Log.i(TAG, " #" + i + ": " + applicationSpecifiedCompletions[i]); 783bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok } 784923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 785923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 7861b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (mApplicationSpecifiedCompletionOn) { 7871b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletions = applicationSpecifiedCompletions; 7881b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (applicationSpecifiedCompletions == null) { 789b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani clearSuggestions(); 790923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 791923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 792a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 7937e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords.Builder builder = new SuggestedWords.Builder() 7941b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka .setApplicationSpecifiedCompletions(applicationSpecifiedCompletions) 7957e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka .setTypedWordValid(true) 7967e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka .setHasMinimalSuggestion(true); 797979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // When in fullscreen mode, show completions generated by the application 7987e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(builder.build()); 799923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = null; 800543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa setCandidatesViewShown(true); 801923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 802923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 803923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 804543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa private void setCandidatesViewShownInternal(boolean shown, boolean needsInputViewShown) { 8057a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // TODO: Modify this if we support candidates with hard keyboard 806923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (onEvaluateInputViewShown()) { 8077a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka final boolean shouldShowCandidates = shown 8087a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka && (needsInputViewShown ? mKeyboardSwitcher.isInputViewShown() : true); 8097a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka if (isExtractViewShown()) { 8107a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // No need to have extra space to show the key preview. 8117a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka mCandidateViewContainer.setMinimumHeight(0); 8127a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka super.setCandidatesViewShown(shown); 8137a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka } else { 8147a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // We must control the visibility of the suggestion strip in order to avoid clipped 8157a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // key previews, even when we don't show the suggestion strip. 8167a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka mCandidateViewContainer.setVisibility( 8177a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka shouldShowCandidates ? View.VISIBLE : View.INVISIBLE); 8187a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka super.setCandidatesViewShown(true); 8197a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka } 820923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 821923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 822a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 823923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 824543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa public void setCandidatesViewShown(boolean shown) { 825543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa setCandidatesViewShownInternal(shown, true /* needsInputViewShown */ ); 826543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa } 827543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa 828543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa @Override 829923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onComputeInsets(InputMethodService.Insets outInsets) { 830923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onComputeInsets(outInsets); 8317a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka final KeyboardView inputView = mKeyboardSwitcher.getInputView(); 83246ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka if (inputView == null) 83346ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka return; 83446ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka final int containerHeight = mCandidateViewContainer.getHeight(); 83546ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka int touchY = containerHeight; 8369e347d3d448e48229c46aad394ec9bd60cd5807bsatok // Need to set touchable region only if input view is being shown 83746ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka if (mKeyboardSwitcher.isInputViewShown()) { 8387a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka if (mCandidateViewContainer.getVisibility() == View.VISIBLE) { 8397a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka touchY -= mCandidateStripHeight; 8409e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 8417a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka final int touchWidth = inputView.getWidth(); 8427a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka final int touchHeight = inputView.getHeight() + containerHeight 8437a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // Extend touchable region below the keyboard. 8447a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka + EXTENDED_TOUCHABLE_REGION_HEIGHT; 8459e347d3d448e48229c46aad394ec9bd60cd5807bsatok if (DEBUG) { 8467a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka Log.d(TAG, "Touchable region: y=" + touchY + " width=" + touchWidth 8477a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka + " height=" + touchHeight); 8489e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 8497a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka setTouchableRegionCompat(outInsets, 0, touchY, touchWidth, touchHeight); 8509e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 85146ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka outInsets.contentTopInsets = touchY; 85246ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka outInsets.visibleTopInsets = touchY; 853923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 854a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 855923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 856979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public boolean onEvaluateFullscreenMode() { 857458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa final Resources res = mResources; 858458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa DisplayMetrics dm = res.getDisplayMetrics(); 859979f8690967ff5409fe18f5085858ccdb8e0ccf1satok float displayHeight = dm.heightPixels; 860979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // If the display is more than X inches high, don't go to fullscreen mode 861458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa float dimen = res.getDimension(R.dimen.max_height_for_fullscreen); 862979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (displayHeight > dimen) { 863979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return false; 864979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } else { 865979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return super.onEvaluateFullscreenMode(); 866979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 867979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 868979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 869979f8690967ff5409fe18f5085858ccdb8e0ccf1satok @Override 870923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 871923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 872e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_BACK: 873e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (event.getRepeatCount() == 0 && mKeyboardSwitcher.getInputView() != null) { 874e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mKeyboardSwitcher.getInputView().handleBack()) { 8756e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani return true; 8766e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 877e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 878e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 879923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 880923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyDown(keyCode, event); 881923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 882923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 883923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 884923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 885923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 886e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_DOWN: 887e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_UP: 888e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_LEFT: 889e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_RIGHT: 890e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka // Enable shift key and DPAD to do selections 891e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mKeyboardSwitcher.isInputViewShown() 892e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka && mKeyboardSwitcher.isShiftedOrShiftLocked()) { 893e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka KeyEvent newEvent = new KeyEvent(event.getDownTime(), event.getEventTime(), 894e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka event.getAction(), event.getKeyCode(), event.getRepeatCount(), 895e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka event.getDeviceId(), event.getScanCode(), 896e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON); 897e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka InputConnection ic = getCurrentInputConnection(); 898e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (ic != null) 899e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka ic.sendKeyEvent(newEvent); 900e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka return true; 901e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 902e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 903923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 904923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyUp(keyCode, event); 905923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 906923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 907409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void commitTyped(InputConnection inputConnection) { 908f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (mHasUncommittedTypedChars) { 909f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = false; 910923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mComposing.length() > 0) { 911923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (inputConnection != null) { 912923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project inputConnection.commitText(mComposing, 1); 913923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 914923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCommittedLength = mComposing.length(); 915923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.acceptedTyped(mComposing); 916bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok addToAutoAndUserBigramDictionaries(mComposing, AutoDictionary.FREQUENCY_FOR_TYPED); 917923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 918923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateSuggestions(); 919923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 920923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 921923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 922b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public boolean getCurrentAutoCapsState() { 923923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 9241c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani EditorInfo ei = getCurrentInputEditorInfo(); 92517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.mAutoCap && ic != null && ei != null 92617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && ei.inputType != InputType.TYPE_NULL) { 927b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return ic.getCursorCapsMode(ei.inputType) != 0; 9281c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 929b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return false; 9301c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 9311c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 932863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard private void swapSwapperAndSpace() { 933923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final InputConnection ic = getCurrentInputConnection(); 934923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 935923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence lastTwo = ic.getTextBeforeCursor(2, 0); 936863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // It is guaranteed lastTwo.charAt(1) is a swapper - else this method is not called. 937923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastTwo != null && lastTwo.length() == 2 938863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard && lastTwo.charAt(0) == Keyboard.CODE_SPACE) { 939923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 940923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 941923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(lastTwo.charAt(1) + " ", 1); 942923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 943b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 9444ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 9454ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 9464ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 947863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard private void maybeDoubleSpace() { 948923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mCorrectionMode == Suggest.CORRECTION_NONE) return; 949923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final InputConnection ic = getCurrentInputConnection(); 950923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 951923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence lastThree = ic.getTextBeforeCursor(3, 0); 952923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastThree != null && lastThree.length() == 3 953923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project && Character.isLetterOrDigit(lastThree.charAt(0)) 954571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastThree.charAt(1) == Keyboard.CODE_SPACE 955fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka && lastThree.charAt(2) == Keyboard.CODE_SPACE 956fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka && mHandler.isAcceptingDoubleSpaces()) { 957fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka mHandler.cancelDoubleSpacesTimer(); 958923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 959923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 960923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(". ", 1); 961923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 962b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 963fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } else { 964fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka mHandler.startDoubleSpacesTimer(); 965923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 966923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 967a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 96841a519729505a877844f2c57a33509c302dddbceKen Wakasa private void maybeRemovePreviousPeriod(CharSequence text) { 96941a519729505a877844f2c57a33509c302dddbceKen Wakasa final InputConnection ic = getCurrentInputConnection(); 97041a519729505a877844f2c57a33509c302dddbceKen Wakasa if (ic == null) return; 97141a519729505a877844f2c57a33509c302dddbceKen Wakasa 97241a519729505a877844f2c57a33509c302dddbceKen Wakasa // When the text's first character is '.', remove the previous period 97341a519729505a877844f2c57a33509c302dddbceKen Wakasa // if there is one. 97441a519729505a877844f2c57a33509c302dddbceKen Wakasa CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 9754ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa if (lastOne != null && lastOne.length() == 1 976571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastOne.charAt(0) == Keyboard.CODE_PERIOD 977571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && text.charAt(0) == Keyboard.CODE_PERIOD) { 97841a519729505a877844f2c57a33509c302dddbceKen Wakasa ic.deleteSurroundingText(1, 0); 97941a519729505a877844f2c57a33509c302dddbceKen Wakasa } 98041a519729505a877844f2c57a33509c302dddbceKen Wakasa } 98141a519729505a877844f2c57a33509c302dddbceKen Wakasa 9829a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa private void removeTrailingSpace() { 9839a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa final InputConnection ic = getCurrentInputConnection(); 9849a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic == null) return; 9859a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa 9869a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 9879a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (lastOne != null && lastOne.length() == 1 988571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastOne.charAt(0) == Keyboard.CODE_SPACE) { 9899a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.deleteSurroundingText(1, 0); 9909a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 9919a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 9929a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa 993923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean addWordToDictionary(String word) { 994923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mUserDictionary.addWord(word, 128); 9956558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // Suggestion strip should be updated after the operation of adding word to the 9966558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // user dictionary 997d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 998923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 999923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1000923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1001923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean isAlphabet(int code) { 1002923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (Character.isLetter(code)) { 1003923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1004923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1005923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return false; 1006923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1007923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1008a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1009e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka private void onSettingsKeyPressed() { 10109a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok if (!isShowingOptionDialog()) { 101117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (!mSettingsValues.mEnableShowSubtypeSettings) { 10122fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka showSubtypeSelectorAndSettings(); 10132fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } else if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm)) { 10149a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok showOptionsMenu(); 10159a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } else { 10169a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok launchSettings(); 10179a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10189a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10199a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10209a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 1021e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka private void onSettingsKeyLongPressed() { 10229a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok if (!isShowingOptionDialog()) { 10239502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm)) { 102479efbed76f638be298493107fa2d0cd1b5eb529esatok mImm.showInputMethodPicker(); 10259a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } else { 10269a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok launchSettings(); 10279a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10289a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10299a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10309a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 10319a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok private boolean isShowingOptionDialog() { 10329a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok return mOptionsDialog != null && mOptionsDialog.isShowing(); 10339a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10349a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 10355f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // Implementation of {@link KeyboardActionListener}. 10365a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 10378aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { 1038923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long when = SystemClock.uptimeMillis(); 1039571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (primaryCode != Keyboard.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) { 1040923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mDeleteCount = 0; 1041923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1042923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mLastKeyTime = when; 1043b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 1044b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); 1045923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 1046571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_DELETE: 10474189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka handleBackspace(); 10484189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka mDeleteCount++; 10494189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka LatinImeLogger.logOnDelete(); 10504189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1051571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_SHIFT: 10524189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka // Shift key is handled in onPress() when device has distinct multi-touch panel. 1053101a00e3d4b1c29ef2ecdecd1b72b43efde7791aTadashi G. Takaoka if (!distinctMultiTouch) 1054b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.toggleShift(); 10554189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1056e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: 10574189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka // Symbol key is handled in onPress() when device has distinct multi-touch panel. 1058101a00e3d4b1c29ef2ecdecd1b72b43efde7791aTadashi G. Takaoka if (!distinctMultiTouch) 1059b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.changeKeyboardMode(); 10604189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1061571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_CANCEL: 10624189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka if (!isShowingOptionDialog()) { 10634189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka handleClose(); 10644189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } 10654189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1066e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SETTINGS: 1067e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka onSettingsKeyPressed(); 10684189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1069e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SETTINGS_LONGPRESS: 1070e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka onSettingsKeyLongPressed(); 10714189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1072d2c5fdda862f6dd2a1e020cf674c35fbbc63fc92Tadashi G. Takaoka case LatinKeyboard.CODE_NEXT_LANGUAGE: 107388fc9d44186120f9edc5cf7ec0e2af85260fed04satok toggleLanguage(true); 10744189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1075d2c5fdda862f6dd2a1e020cf674c35fbbc63fc92Tadashi G. Takaoka case LatinKeyboard.CODE_PREV_LANGUAGE: 107688fc9d44186120f9edc5cf7ec0e2af85260fed04satok toggleLanguage(false); 10774189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1078571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_CAPSLOCK: 1079b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.toggleCapsLock(); 10804189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1081d2c5fdda862f6dd2a1e020cf674c35fbbc63fc92Tadashi G. Takaoka case Keyboard.CODE_SHORTCUT: 108220cdb37bd062ae6cb6d42ad6229a19733476cd55satok mSubtypeSwitcher.switchToShortcutIME(); 10834189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1084571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_TAB: 108545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka handleTab(); 10864189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 10874189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka default: 108817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.isWordSeparator(primaryCode)) { 1089b5d17e52fcda39d540822e615bfb7ed5074e0034satok handleSeparator(primaryCode, x, y); 10904189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } else { 10918fbd55229243cb66c03d5ea1f79dfb39f596590dsatok handleCharacter(primaryCode, keyCodes, x, y); 10924189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } 1093923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1094b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.onKey(primaryCode); 1095dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani // Reset after any single keystroke 1096dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = null; 1097923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1098a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 10995a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 11008aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onTextInput(CharSequence text) { 1101b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.commitVoiceInput(); 1102923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1103923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 11049fbfd5877305ed19a20663630b498b6b3fdae942satok mRecorrection.abortRecorrection(false); 1105923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 110655b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka commitTyped(ic); 110741a519729505a877844f2c57a33509c302dddbceKen Wakasa maybeRemovePreviousPeriod(text); 1108923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(text, 1); 1109923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1110b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 11115f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka mKeyboardSwitcher.onKey(Keyboard.CODE_DUMMY); 11120730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard mJustAddedMagicSpace = false; 1113dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = text; 1114923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1115923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 11165a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 11178aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onCancelInput() { 111883e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka // User released a finger outside any key 11195f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka mKeyboardSwitcher.onCancelInput(); 112083e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka } 112183e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka 1122923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleBackspace() { 1123b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok if (mVoiceProxy.logAndRevertVoiceInput()) return; 11244f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1125504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1126504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka if (ic == null) return; 1127979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.beginBatchEdit(); 1128979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1129b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleBackspace(); 11304f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1131504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka boolean deleteChar = false; 1132f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (mHasUncommittedTypedChars) { 1133923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final int length = mComposing.length(); 1134923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (length > 0) { 1135923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mComposing.delete(length - 1, length); 1136923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mWord.deleteLast(); 1137923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.setComposingText(mComposing, 1); 1138923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mComposing.length() == 0) { 1139f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = false; 1140923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 114189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (1 == length) { 114289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // 1 == length means we are about to erase the last character of the word, 114389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // so we can show bigrams. 1144cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.postUpdateBigramPredictions(); 114589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 114689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // length > 1, so we still have letters to deduce a suggestion from. 114789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.postUpdateSuggestions(); 114889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 1149923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1150923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(1, 0); 1151923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1152923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1153923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project deleteChar = true; 1154923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1155d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateShiftKeyState(); 1156504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka 1157923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.backspace(); 1158662bb7c26cadd5026cb3d4e5d081aae163bd5a3aTadashi G. Takaoka if (TextEntryState.isUndoCommit()) { 1159923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project revertLastWord(deleteChar); 1160979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.endBatchEdit(); 1161923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1162504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka } 1163504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka 1164504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) { 1165dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani ic.deleteSurroundingText(mEnteredText.length(), 0); 1166923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else if (deleteChar) { 11676558253160e2039c87f424bd814f402ecd31de3bKen Wakasa if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) { 11686558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // Go back to the suggestion mode if the user canceled the 116955b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // "Touch again to save". 11706558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // NOTE: In gerenal, we don't revert the word when backspacing 11716558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // from a manual suggestion pick. We deliberately chose a 11726558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // different behavior only in the case of picking the first 11736558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // suggestion (typed word). It's intentional to have made this 11746558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // inconsistent with backspacing after selecting other suggestions. 11756558253160e2039c87f424bd814f402ecd31de3bKen Wakasa revertLastWord(deleteChar); 11766558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } else { 1177923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 11786558253160e2039c87f424bd814f402ecd31de3bKen Wakasa if (mDeleteCount > DELETE_ACCELERATE_AT) { 11796558253160e2039c87f424bd814f402ecd31de3bKen Wakasa sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 11806558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 1181923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1182923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1183979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.endBatchEdit(); 1184923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1185923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 118645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka private void handleTab() { 118745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final int imeOptions = getCurrentInputEditorInfo().imeOptions; 1188b2707856aba4fc9b063f26305f1fb603b19c1701satok if (!EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) 1189b2707856aba4fc9b063f26305f1fb603b19c1701satok && !EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions)) { 119045911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB); 119145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka return; 119245911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 119345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 119445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 119545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (ic == null) 119645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka return; 119745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 119845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka // True if keyboard is in either chording shift or manual temporary upper case mode. 119945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final boolean isManualTemporaryUpperCase = mKeyboardSwitcher.isManualTemporaryUpperCase(); 1200b2707856aba4fc9b063f26305f1fb603b19c1701satok if (EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) 120145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka && !isManualTemporaryUpperCase) { 1202b2707856aba4fc9b063f26305f1fb603b19c1701satok EditorInfoCompatUtils.performEditorActionNext(ic); 120345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka ic.performEditorAction(EditorInfo.IME_ACTION_NEXT); 1204b2707856aba4fc9b063f26305f1fb603b19c1701satok } else if (EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions) 120545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka && isManualTemporaryUpperCase) { 1206b2707856aba4fc9b063f26305f1fb603b19c1701satok EditorInfoCompatUtils.performEditorActionPrevious(ic); 120745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 120845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 120945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 12108fbd55229243cb66c03d5ea1f79dfb39f596590dsatok private void handleCharacter(int primaryCode, int[] keyCodes, int x, int y) { 1211b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleCharacter(); 12124f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 121317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mJustAddedMagicSpace && mSettingsValues.isMagicSpaceStripper(primaryCode)) { 12140730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard removeTrailingSpace(); 12150730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard } 12160730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard 1217863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard if (mLastSelectionStart == mLastSelectionEnd) { 12189fbfd5877305ed19a20663630b498b6b3fdae942satok mRecorrection.abortRecorrection(false); 1219b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 12204f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1221e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka int code = primaryCode; 12229fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (isAlphabet(code) && isSuggestionsRequested() && !isCursorTouchingWord()) { 1223f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (!mHasUncommittedTypedChars) { 1224f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = true; 1225923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mComposing.setLength(0); 1226f733074aaecdfd6e89cfee2daff8a9c1233b60f1satok mRecorrection.saveRecorrectionSuggestion(mWord, mBestWord); 1227923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mWord.reset(); 12287e99a28dfcc14f5b19220442db972ca8d786b4feKen Wakasa clearSuggestions(); 1229923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1230923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 12311679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 1232f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (switcher.isShiftedOrShiftLocked()) { 1233eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT 1234eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani || keyCodes[0] > Character.MAX_CODE_POINT) { 1235eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani return; 1236eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani } 1237e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka code = keyCodes[0]; 1238e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (switcher.isAlphabetMode() && Character.isLowerCase(code)) { 1239e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka int upperCaseCode = Character.toUpperCase(code); 1240e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (upperCaseCode != code) { 1241e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka code = upperCaseCode; 124212a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka } else { 124312a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka // Some keys, such as [eszett], have upper case as multi-characters. 1244e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka String upperCase = new String(new int[] {code}, 0, 1).toUpperCase(); 12458aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka onTextInput(upperCase); 124612a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka return; 124712a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka } 1248979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1249923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1250f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (mHasUncommittedTypedChars) { 1251f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (mComposing.length() == 0 && switcher.isAlphabetMode() 1252f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka && switcher.isShiftedOrShiftLocked()) { 12530b4ae1f578e768eec4ada90aeb81d11acb10eb2eKen Wakasa mWord.setFirstCharCapitalized(true); 1254923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1255e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mComposing.append((char) code); 12568fbd55229243cb66c03d5ea1f79dfb39f596590dsatok mWord.add(code, keyCodes, x, y); 1257923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1258923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 12591c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani // If it's the first letter, make note of auto-caps state 12601c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani if (mWord.size() == 1) { 1261b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mWord.setAutoCapitalized(getCurrentAutoCapsState()); 12621c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 1263923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.setComposingText(mComposing, 1); 1264923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1265d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1266923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1267e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka sendKeyChar((char)code); 1268923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 126917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mJustAddedMagicSpace && mSettingsValues.isMagicSpaceSwapper(primaryCode)) { 1270863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard swapSwapperAndSpace(); 1271863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } else { 1272863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard mJustAddedMagicSpace = false; 1273863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } 1274863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard 1275b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.updateShiftState(); 1276979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (LatinIME.PERF_DEBUG) measureCps(); 127717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard TextEntryState.typedCharacter((char) code, mSettingsValues.isWordSeparator(code), x, y); 1278923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1279923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1280b5d17e52fcda39d540822e615bfb7ed5074e0034satok private void handleSeparator(int primaryCode, int x, int y) { 1281b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleSeparator(); 12824f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 128355b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // Should dismiss the "Touch again to save" message when handling separator 12846558253160e2039c87f424bd814f402ecd31de3bKen Wakasa if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) { 1285cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.cancelUpdateBigramPredictions(); 1286d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 12876558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 12886558253160e2039c87f424bd814f402ecd31de3bKen Wakasa 1289923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project boolean pickedDefault = false; 1290923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Handle separator 12911b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1292923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1293923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 12949fbfd5877305ed19a20663630b498b6b3fdae942satok mRecorrection.abortRecorrection(false); 1295923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1296f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (mHasUncommittedTypedChars) { 1297923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In certain languages where single quote is a separator, it's better 1298a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker // not to auto correct, but accept the typed word. For instance, 1299923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // in Italian dov' should not be expanded to dove' because the elision 1300923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // requires the last vowel to be removed. 130117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard final boolean shouldAutoCorrect = 130217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard (mSettingsValues.mAutoCorrectEnabled || mSettingsValues.mQuickFixes) 130317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mInputTypeNoAutoCorrect && mHasDictionary; 130417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (shouldAutoCorrect && primaryCode != Keyboard.CODE_SINGLE_QUOTE) { 1305b5d17e52fcda39d540822e615bfb7ed5074e0034satok pickedDefault = pickDefaultSuggestion(primaryCode); 1306923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1307923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project commitTyped(ic); 1308923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1309923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 13104ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1311863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard if (mJustAddedMagicSpace) { 131217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.isMagicSpaceSwapper(primaryCode)) { 1313863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard sendKeyChar((char)primaryCode); 1314863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard swapSwapperAndSpace(); 1315863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } else { 131617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.isMagicSpaceStripper(primaryCode)) removeTrailingSpace(); 1317863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard sendKeyChar((char)primaryCode); 1318863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard mJustAddedMagicSpace = false; 1319863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } 13200730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard } else { 13210730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard sendKeyChar((char)primaryCode); 13224ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 13234ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1324863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard if (isSuggestionsRequested() && primaryCode == Keyboard.CODE_SPACE) { 1325863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard maybeDoubleSpace(); 1326863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } 1327863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard 1328b5d17e52fcda39d540822e615bfb7ed5074e0034satok TextEntryState.typedCharacter((char) primaryCode, true, x, y); 132989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 1330979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (pickedDefault) { 133155b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka CharSequence typedWord = mWord.getTypedWord(); 133255b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka TextEntryState.backToAcceptedDefault(typedWord); 133355b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka if (!TextUtils.isEmpty(typedWord) && !typedWord.equals(mBestWord)) { 1334b2707856aba4fc9b063f26305f1fb603b19c1701satok InputConnectionCompatUtils.commitCorrection( 133589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard ic, mLastSelectionEnd - typedWord.length(), typedWord, mBestWord); 133655b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka if (mCandidateView != null) 133755b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka mCandidateView.onAutoCorrectionInverted(mBestWord); 133855b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka } 133989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 134089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (Keyboard.CODE_SPACE == primaryCode) { 134189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (!isCursorTouchingWord()) { 134289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.cancelUpdateSuggestions(); 134389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.cancelUpdateOldSuggestions(); 1344cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.postUpdateBigramPredictions(); 134589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 134689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 134789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // Set punctuation right away. onUpdateSelection will fire but tests whether it is 134889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // already displayed or not, so it's okay. 134955b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka setPunctuationSuggestions(); 1350923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1351b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 1352923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1353923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1354923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1355923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1356466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1357923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleClose() { 1358923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project commitTyped(getCurrentInputConnection()); 1359b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleClose(); 1360923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project requestHideSelf(0); 13611679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); 13621679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka if (inputView != null) 13631679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka inputView.closing(); 1364923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1365923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 13667a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isSuggestionsRequested() { 1367c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka return mIsSettingsSuggestionStripOn 1368c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka && (mCorrectionMode > 0 || isShowingSuggestionsStrip()); 1369923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1370a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 13717a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isShowingPunctuationList() { 137217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard return mSettingsValues.mSuggestPuncList == mCandidateView.getSuggestions(); 13737599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 13747599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 13757a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isShowingSuggestionsStrip() { 13767599cfea4a2d56f4779452ec8e8742f7b9629cc0satok return (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_VALUE) 13777599cfea4a2d56f4779452ec8e8742f7b9629cc0satok || (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE 13787599cfea4a2d56f4779452ec8e8742f7b9629cc0satok && mOrientation == Configuration.ORIENTATION_PORTRAIT); 13797599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 13807599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 13819fbfd5877305ed19a20663630b498b6b3fdae942satok public boolean isCandidateStripVisible() { 1382b5e00d5841b946de8970875231456228ae0eb6b1Ken Wakasa if (mCandidateView == null) 1383b5e00d5841b946de8970875231456228ae0eb6b1Ken Wakasa return false; 1384952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa if (mCandidateView.isShowingAddToDictionaryHint() || TextEntryState.isRecorrecting()) 13859fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 13869fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (!isShowingSuggestionsStrip()) 13879fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return false; 13889fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (mApplicationSpecifiedCompletionOn) 13899fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 13909fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return isSuggestionsRequested(); 1391923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1392923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1393409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void switchToKeyboardView() { 1394060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (DEBUG) { 1395060efb6d82af1f896d90cb845c8ae07c726f85e1satok Log.d(TAG, "Switch to keyboard view."); 1396060efb6d82af1f896d90cb845c8ae07c726f85e1satok } 1397060efb6d82af1f896d90cb845c8ae07c726f85e1satok View v = mKeyboardSwitcher.getInputView(); 1398060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (v != null) { 1399060efb6d82af1f896d90cb845c8ae07c726f85e1satok // Confirms that the keyboard view doesn't have parent view. 1400060efb6d82af1f896d90cb845c8ae07c726f85e1satok ViewParent p = v.getParent(); 1401060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (p != null && p instanceof ViewGroup) { 1402060efb6d82af1f896d90cb845c8ae07c726f85e1satok ((ViewGroup) p).removeView(v); 14035a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka } 1404060efb6d82af1f896d90cb845c8ae07c726f85e1satok setInputView(v); 1405060efb6d82af1f896d90cb845c8ae07c726f85e1satok } 1406060efb6d82af1f896d90cb845c8ae07c726f85e1satok setCandidatesViewShown(isCandidateStripVisible()); 1407060efb6d82af1f896d90cb845c8ae07c726f85e1satok updateInputViewShown(); 1408060efb6d82af1f896d90cb845c8ae07c726f85e1satok mHandler.postUpdateSuggestions(); 1409466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1410466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1411409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void clearSuggestions() { 14127e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(SuggestedWords.EMPTY); 1413466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1414466741d8a78965b8509bf527344f289e50873092Mike LeBeau 14157e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka public void setSuggestions(SuggestedWords words) { 1416b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok if (mVoiceProxy.getAndResetIsShowingHint()) { 1417466741d8a78965b8509bf527344f289e50873092Mike LeBeau setCandidatesView(mCandidateViewContainer); 1418466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1419466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1420466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mCandidateView != null) { 14217e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka mCandidateView.setSuggestions(words); 14229ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka if (mCandidateView.isConfigCandidateHighlightFontColorEnabled()) { 14239ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka mKeyboardSwitcher.onAutoCorrectionStateChanged( 14249ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka words.hasWordAboveAutoCorrectionScoreThreshold()); 14259ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka } 1426466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1427466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1428466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1429409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void updateSuggestions() { 1430923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Check if we have a suggestion engine attached. 14319fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if ((mSuggest == null || !isSuggestionsRequested()) 1432b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok && !mVoiceProxy.isVoiceInputHighlighted()) { 1433923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1434923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1435466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1436f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (!mHasUncommittedTypedChars) { 1437ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setPunctuationSuggestions(); 1438923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1439923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1440979f8690967ff5409fe18f5085858ccdb8e0ccf1satok showSuggestions(mWord); 1441979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1442979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1443979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void showSuggestions(WordComposer word) { 14449f67e12a0e3f77985fb8bafe0db4c00e32317b9asatok // TODO: May need a better way of retrieving previous word 1445e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(), 144617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mWordSeparators); 14477e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder( 14489ecad8c2e8571ece6f3f7fbb19ceda5be7866cf0Tadashi G. Takaoka mKeyboardSwitcher.getInputView(), word, prevWord); 1449923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 14506f99d12b0752ecdbceda7e5fddead214f939f533Tadashi G. Takaoka boolean correctionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasAutoCorrection(); 1451a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa final CharSequence typedWord = word.getTypedWord(); 1452bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // Here, we want to promote a whitelisted word if exists. 1453bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok final boolean typedWordValid = AutoCorrection.isValidWordForAutoCorrection( 1454bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok mSuggest.getUnigramDictionaries(), typedWord, preferCapitalization()); 1455979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mCorrectionMode == Suggest.CORRECTION_FULL 1456979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) { 1457923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project correctionAvailable |= typedWordValid; 1458923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 14594a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani // Don't auto-correct words with multiple capital letter 1460979f8690967ff5409fe18f5085858ccdb8e0ccf1satok correctionAvailable &= !word.isMostlyCaps(); 1461952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa correctionAvailable &= !TextEntryState.isRecorrecting(); 1462979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1463a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // Basically, we update the suggestion strip only when suggestion count > 1. However, 1464a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // there is an exception: We update the suggestion strip whenever typed word's length 1465f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // is 1 or typed word is found in dictionary, regardless of suggestion count. Actually, 1466f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // in most cases, suggestion count is 1 when typed word's length is 1, but we do always 1467f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // need to clear the previous state when the user starts typing a word (i.e. typed word's 1468f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // length == 1). 1469f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka if (builder.size() > 1 || typedWord.length() == 1 || typedWordValid 1470a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa || mCandidateView.isShowingAddToDictionaryHint()) { 14719fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka builder.setTypedWordValid(typedWordValid).setHasMinimalSuggestion(correctionAvailable); 14729fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka } else { 14739fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka final SuggestedWords previousSuggestions = mCandidateView.getSuggestions(); 147417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (previousSuggestions == mSettingsValues.mSuggestPuncList) 14759fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return; 14769fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka builder.addTypedWordAndPreviousSuggestions(typedWord, previousSuggestions); 14779fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka } 14787e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka showSuggestions(builder.build(), typedWord); 1479979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 14804a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani 14819fbfd5877305ed19a20663630b498b6b3fdae942satok public void showSuggestions(SuggestedWords suggestedWords, CharSequence typedWord) { 14827e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(suggestedWords); 14837e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka if (suggestedWords.size() > 0) { 148414e427d5bb13d59d23fb317ef90a6c44ae279425satok if (Utils.shouldBlockedBySafetyNetForAutoCorrection(suggestedWords, mSuggest)) { 148582411d47ba7e8133ed2390c6920945e139a738cesatok mBestWord = typedWord; 148682411d47ba7e8133ed2390c6920945e139a738cesatok } else if (suggestedWords.hasAutoCorrectionWord()) { 14877e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka mBestWord = suggestedWords.getWord(1); 1488923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1489923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = typedWord; 1490923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1491923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1492923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = null; 1493923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1494ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setCandidatesViewShown(isCandidateStripVisible()); 1495923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1496923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1497b5d17e52fcda39d540822e615bfb7ed5074e0034satok private boolean pickDefaultSuggestion(int separatorCode) { 1498923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Complete any pending candidate query first 1499d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka if (mHandler.hasPendingUpdateSuggestions()) { 1500d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 1501923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateSuggestions(); 1502923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 15036780b898ec2647a21319601a03ae1c393c0e1b29Amith Yamasani if (mBestWord != null && mBestWord.length() > 0) { 1504b5d17e52fcda39d540822e615bfb7ed5074e0034satok TextEntryState.acceptedDefault(mWord.getTypedWord(), mBestWord, separatorCode); 1505923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mJustAccepted = true; 150655b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka pickSuggestion(mBestWord); 15079468335a06d2b0e3ef15f4f57f8c1b0857b34ebeAmith Yamasani // Add the word to the auto dictionary if it's not a known word 1508bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok addToAutoAndUserBigramDictionaries(mBestWord, AutoDictionary.FREQUENCY_FOR_TYPED); 1509979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return true; 1510923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1511979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return false; 1512923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1513923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1514923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void pickSuggestionManually(int index, CharSequence suggestion) { 15157e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords suggestions = mCandidateView.getSuggestions(); 151617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mVoiceProxy.flushAndLogAllTextModificationCounters(index, suggestion, 151717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mWordSeparators); 15184f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1519952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa final boolean recorrecting = TextEntryState.isRecorrecting(); 15209a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa InputConnection ic = getCurrentInputConnection(); 15219a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 15229a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.beginBatchEdit(); 15239a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 15241b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (mApplicationSpecifiedCompletionOn && mApplicationSpecifiedCompletions != null 15251b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka && index >= 0 && index < mApplicationSpecifiedCompletions.length) { 15261b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka CompletionInfo ci = mApplicationSpecifiedCompletions[index]; 1527923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1528923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitCompletion(ci); 1529923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1530923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCommittedLength = suggestion.length(); 1531923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mCandidateView != null) { 1532923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCandidateView.clear(); 1533923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1534b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 15359a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 15369a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 15379a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1538923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1539923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 15406a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 15416a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani // If this is a punctuation, apply it through the normal key press 154217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (suggestion.length() == 1 && (mSettingsValues.isWordSeparator(suggestion.charAt(0)) 154317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard || mSettingsValues.isSuggestedPunctuation(suggestion.charAt(0)))) { 1544979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Word separators are suggested before the user inputs something. 1545979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // So, LatinImeLogger logs "" as a user's input. 1546979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.logOnManualSuggestion( 15477e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka "", suggestion.toString(), index, suggestions.mWords); 1548863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // Find out whether the previous character is a space. If it is, as a special case 1549863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // for punctuation entered through the suggestion strip, it should be considered 1550863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // a magic space even if it was a normal space. This is meant to help in case the user 1551863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // pressed space on purpose of displaying the suggestion strip punctuation. 155255b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa final char primaryCode = suggestion.charAt(0); 1553863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard final int toLeft = (ic == null) ? 0 : ic.getTextBeforeCursor(1, 0).charAt(0); 15544f3b59711f6985d39e0cc908d2431ae6715d9b26Jean Chalard final boolean oldMagicSpace = mJustAddedMagicSpace; 1555863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard if (Keyboard.CODE_SPACE == toLeft) mJustAddedMagicSpace = true; 1556a96574fdd5e38a237a35b21a2b7c20a29138c648Tadashi G. Takaoka onCodeInput(primaryCode, new int[] { primaryCode }, 1557a96574fdd5e38a237a35b21a2b7c20a29138c648Tadashi G. Takaoka KeyboardActionListener.NOT_A_TOUCH_COORDINATE, 1558a96574fdd5e38a237a35b21a2b7c20a29138c648Tadashi G. Takaoka KeyboardActionListener.NOT_A_TOUCH_COORDINATE); 15594f3b59711f6985d39e0cc908d2431ae6715d9b26Jean Chalard mJustAddedMagicSpace = oldMagicSpace; 15609a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 15619a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 15629a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 15636a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani return; 15646a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 1565f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (!mHasUncommittedTypedChars) { 156689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // If we are not composing a word, then it was a suggestion inferred from 156789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // context - no user input. We should reset the word composer. 156889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mWord.reset(); 156989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 15709a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa mJustAccepted = true; 157155b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka pickSuggestion(suggestion); 15729468335a06d2b0e3ef15f4f57f8c1b0857b34ebeAmith Yamasani // Add the word to the auto dictionary if it's not a known word 15730c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani if (index == 0) { 1574bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok addToAutoAndUserBigramDictionaries(suggestion, AutoDictionary.FREQUENCY_FOR_PICKED); 1575979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } else { 1576bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok addToOnlyBigramDictionary(suggestion, 1); 15770c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani } 1578979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.logOnManualSuggestion(mComposing.toString(), suggestion.toString(), 15797e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka index, suggestions.mWords); 1580923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.acceptedSuggestion(mComposing.toString(), suggestion); 1581923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Follow it with a space 15820730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard if (mShouldInsertMagicSpace && !recorrecting) { 15830730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard sendMagicSpace(); 1584923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1585979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 15867f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // We should show the hint if the user pressed the first entry AND either: 15877f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // - There is no dictionary (we know that because we tried to load it => null != mSuggest 15887f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // AND mHasDictionary is false) 15897f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // - There is a dictionary and the word is not in it 15907f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // Please note that if mSuggest is null, it means that everything is off: suggestion 15917f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // and correction, so we shouldn't try to show the hint 15927f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // We used to look at mCorrectionMode here, but showing the hint should have nothing 15937f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // to do with the autocorrection setting. 1594bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok final boolean showingAddToDictionaryHint = index == 0 && mSuggest != null 1595bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // If there is no dictionary the hint should be shown. 1596bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok && (!mHasDictionary 1597bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // If "suggestion" is not in the dictionary, the hint should be shown. 1598bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok || !AutoCorrection.isValidWord( 1599bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok mSuggest.getUnigramDictionaries(), suggestion, true)); 1600b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani 1601952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa if (!recorrecting) { 1602b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // Fool the state watcher so that a subsequent backspace will not do a revert, unless 1603b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // we just did a correction, in which case we need to stay in 1604b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // TextEntryState.State.PICKED_SUGGESTION state. 1605b5d17e52fcda39d540822e615bfb7ed5074e0034satok TextEntryState.typedCharacter((char) Keyboard.CODE_SPACE, true, 1606b5d17e52fcda39d540822e615bfb7ed5074e0034satok WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); 1607777118a40a363ccab69a00016d3156066513cb78Jean Chalard } 1608777118a40a363ccab69a00016d3156066513cb78Jean Chalard if (!showingAddToDictionaryHint) { 1609364da8c618303a7764595d2c15ee034a7671365dKen Wakasa // If we're not showing the "Touch again to save", then show corrections again. 1610979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // In case the cursor position doesn't change, make sure we show the suggestions again. 1611b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani clearSuggestions(); 1612d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateOldSuggestions(); 1613979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1614b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani if (showingAddToDictionaryHint) { 161566a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani mCandidateView.showAddToDictionaryHint(suggestion); 161666a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani } 16179a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 16189a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 16199a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1620923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1621a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1622979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 1623979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * Commits the chosen word to the text field and saves it for later 1624979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * retrieval. 1625979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * @param suggestion the suggestion picked by the user to be committed to 1626979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * the text field 1627979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 162855b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka private void pickSuggestion(CharSequence suggestion) { 1629b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 1630b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (!switcher.isKeyboardAvailable()) 16311679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka return; 1632923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1633923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 163417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mVoiceProxy.rememberReplacedWord(suggestion, mSettingsValues.mWordSeparators); 1635979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.commitText(suggestion, 1); 1636923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1637f733074aaecdfd6e89cfee2daff8a9c1233b60f1satok mRecorrection.saveRecorrectionSuggestion(mWord, suggestion); 1638f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = false; 1639923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCommittedLength = suggestion.length(); 1640923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1641923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 164289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard private static final WordComposer sEmptyWordComposer = new WordComposer(); 1643cb3320179d39a7983874697a0aa428b127675c9dJean Chalard private void updateBigramPredictions() { 164489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (mSuggest == null || !isSuggestionsRequested()) 164589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard return; 164689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 164717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (!mSettingsValues.mBigramPredictionEnabled) { 1648cb3320179d39a7983874697a0aa428b127675c9dJean Chalard setPunctuationSuggestions(); 1649cb3320179d39a7983874697a0aa428b127675c9dJean Chalard return; 1650cb3320179d39a7983874697a0aa428b127675c9dJean Chalard } 1651cb3320179d39a7983874697a0aa428b127675c9dJean Chalard 165289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard final CharSequence prevWord = EditingUtils.getThisWord(getCurrentInputConnection(), 165317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mWordSeparators); 165489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder( 165589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mKeyboardSwitcher.getInputView(), sEmptyWordComposer, prevWord); 165689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 165789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (builder.size() > 0) { 165889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // Explicitly supply an empty typed word (the no-second-arg version of 165989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // showSuggestions will retrieve the word near the cursor, we don't want that here) 166089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard showSuggestions(builder.build(), ""); 166189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 166289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (!isShowingPunctuationList()) setPunctuationSuggestions(); 166389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 166489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 166589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 16667a8dac55278cedd838be325f56b4c52d973c61f5satok public void setPunctuationSuggestions() { 166717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard setSuggestions(mSettingsValues.mSuggestPuncList); 16689fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka setCandidatesViewShown(isCandidateStripVisible()); 16696a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 16706a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 1671bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok private void addToAutoAndUserBigramDictionaries(CharSequence suggestion, int frequencyDelta) { 1672979f8690967ff5409fe18f5085858ccdb8e0ccf1satok checkAddToDictionary(suggestion, frequencyDelta, false); 1673979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1674979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1675bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok private void addToOnlyBigramDictionary(CharSequence suggestion, int frequencyDelta) { 1676979f8690967ff5409fe18f5085858ccdb8e0ccf1satok checkAddToDictionary(suggestion, frequencyDelta, true); 1677979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1678979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1679979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 1680979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * Adds to the UserBigramDictionary and/or AutoDictionary 1681bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok * @param selectedANotTypedWord true if it should be added to bigram dictionary if possible 1682979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 1683979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void checkAddToDictionary(CharSequence suggestion, int frequencyDelta, 1684bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok boolean selectedANotTypedWord) { 1685979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (suggestion == null || suggestion.length() < 1) return; 1686bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok 16870c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // Only auto-add to dictionary if auto-correct is ON. Otherwise we'll be 16880c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // adding words in situations where the user or application really didn't 16890c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // want corrections enabled or learned. 1690979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (!(mCorrectionMode == Suggest.CORRECTION_FULL 1691979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM)) { 1692979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return; 1693979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1694bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok 1695bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok final boolean selectedATypedWordAndItsInAutoDic = 1696bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok !selectedANotTypedWord && mAutoDictionary.isValidWord(suggestion); 1697bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok final boolean isValidWord = AutoCorrection.isValidWord( 1698bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok mSuggest.getUnigramDictionaries(), suggestion, true); 1699bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok final boolean needsToAddToAutoDictionary = selectedATypedWordAndItsInAutoDic 1700bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok || !isValidWord; 1701bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok if (needsToAddToAutoDictionary) { 1702e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mAutoDictionary.addWord(suggestion.toString(), frequencyDelta); 1703e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 1704979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1705e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mUserBigramDictionary != null) { 1706863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // We don't want to register as bigrams words separated by a separator. 1707863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // For example "I will, and you too" : we don't want the pair ("will" "and") to be 1708863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // a bigram. 1709e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(), 171017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mWordSeparators); 1711e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (!TextUtils.isEmpty(prevWord)) { 1712e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mUserBigramDictionary.addBigrams(prevWord.toString(), suggestion.toString()); 1713979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 171432e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 171532e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 171632e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani 17177a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isCursorTouchingWord() { 1718923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1719923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return false; 1720923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence toLeft = ic.getTextBeforeCursor(1, 0); 1721923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence toRight = ic.getTextAfterCursor(1, 0); 1722923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (!TextUtils.isEmpty(toLeft) 172317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isWordSeparator(toLeft.charAt(0)) 172417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isSuggestedPunctuation(toLeft.charAt(0))) { 1725923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1726923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1727a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker if (!TextUtils.isEmpty(toRight) 172817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isWordSeparator(toRight.charAt(0)) 172917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isSuggestedPunctuation(toRight.charAt(0))) { 1730923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1731923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1732923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return false; 1733923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1734a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1735dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani private boolean sameAsTextBeforeCursor(InputConnection ic, CharSequence text) { 1736dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani CharSequence beforeText = ic.getTextBeforeCursor(text.length(), 0); 1737dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani return TextUtils.equals(text, beforeText); 1738dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani } 1739dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 1740923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void revertLastWord(boolean deleteChar) { 1741923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final int length = mComposing.length(); 1742f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (!mHasUncommittedTypedChars && length > 0) { 1743923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final InputConnection ic = getCurrentInputConnection(); 1744504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka final CharSequence punctuation = ic.getTextBeforeCursor(1, 0); 1745923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (deleteChar) ic.deleteSurroundingText(1, 0); 1746923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int toDelete = mCommittedLength; 1747504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka final CharSequence toTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0); 174817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (!TextUtils.isEmpty(toTheLeft) 174917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && mSettingsValues.isWordSeparator(toTheLeft.charAt(0))) { 1750923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project toDelete--; 1751923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1752923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(toDelete, 0); 175330be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka // Re-insert punctuation only when the deleted character was word separator and the 175430be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka // composing text wasn't equal to the auto-corrected text. 175530be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka if (deleteChar 175617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !TextUtils.isEmpty(punctuation) 175717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && mSettingsValues.isWordSeparator(punctuation.charAt(0)) 175830be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka && !TextUtils.equals(mComposing, toTheLeft)) { 1759504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka ic.commitText(mComposing, 1); 1760504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka TextEntryState.acceptedTyped(mComposing); 176130be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka ic.commitText(punctuation, 1); 1762b5d17e52fcda39d540822e615bfb7ed5074e0034satok TextEntryState.typedCharacter(punctuation.charAt(0), true, 1763b5d17e52fcda39d540822e615bfb7ed5074e0034satok WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); 176430be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka // Clear composing text 176530be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka mComposing.setLength(0); 1766504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka } else { 1767f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = true; 1768504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka ic.setComposingText(mComposing, 1); 1769504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka TextEntryState.backspace(); 1770504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka } 1771cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.cancelUpdateBigramPredictions(); 1772d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1773923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1774923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 1775923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1776923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1777923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1778923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean isWordSeparator(int code) { 177917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard return mSettingsValues.isWordSeparator(code); 1780923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1781923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 17820730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard private void sendMagicSpace() { 1783571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka sendKeyChar((char)Keyboard.CODE_SPACE); 17840730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard mJustAddedMagicSpace = true; 1785b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 1786923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1787923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1788923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean preferCapitalization() { 17890b4ae1f578e768eec4ada90aeb81d11acb10eb2eKen Wakasa return mWord.isFirstCharCapitalized(); 1790923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1791923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 179288fc9d44186120f9edc5cf7ec0e2af85260fed04satok // Notify that language or mode have been changed and toggleLanguage will update KeyboardID 1793c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // according to new language or mode. 1794c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka public void onRefreshKeyboard() { 17954ab730dbd34fad323063f2ffd31ce33de746668dsatok // Reload keyboard because the current language has been changed. 1796cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), 1797b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mSubtypeSwitcher.isShortcutImeEnabled() && mVoiceProxy.isVoiceButtonEnabled(), 1798b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.isVoiceButtonOnPrimary()); 17990ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 180017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard loadSettings(); 18014b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 180236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 180336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 180488fc9d44186120f9edc5cf7ec0e2af85260fed04satok // "reset" and "next" are used only for USE_SPACEBAR_LANGUAGE_SWITCHER. 180588fc9d44186120f9edc5cf7ec0e2af85260fed04satok private void toggleLanguage(boolean next) { 180688fc9d44186120f9edc5cf7ec0e2af85260fed04satok if (mSubtypeSwitcher.useSpacebarLanguageSwitcher()) { 180788fc9d44186120f9edc5cf7ec0e2af85260fed04satok mSubtypeSwitcher.toggleLanguage(next); 180888fc9d44186120f9edc5cf7ec0e2af85260fed04satok } 180917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard // The following is necessary because on API levels < 10, we don't get notified when 181017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard // subtype changes. 181117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard onRefreshKeyboard(); 181217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 181388fc9d44186120f9edc5cf7ec0e2af85260fed04satok 18145a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 18158aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onSwipeDown() { 181617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.mSwipeDownDismissKeyboardEnabled) 1817363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka handleClose(); 1818923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1819923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 18205a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 1821e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka public void onPress(int primaryCode, boolean withSliding) { 1822cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka if (mKeyboardSwitcher.isVibrateAndSoundFeedbackRequired()) { 1823cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka vibrate(); 1824cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka playKeyClick(primaryCode); 1825cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka } 18261679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 18271679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); 1828571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { 1829e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka switcher.onPressShift(withSliding); 1830e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { 18316c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka switcher.onPressSymbol(); 183240a05f62edc6cdedb4365a722b48a72826ef2bf6Tadashi G. Takaoka } else { 18336c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka switcher.onOtherKeyPressed(); 1834681b102a492b7d5301c1ca87985b4c391eb5eb14Tadashi G. Takaoka } 1835923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1836923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 18375a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 1838e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka public void onRelease(int primaryCode, boolean withSliding) { 18391679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 18403f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani // Reset any drag flags in the keyboard 18411679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); 1842571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { 1843e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka switcher.onReleaseShift(withSliding); 1844e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { 18456c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka switcher.onReleaseSymbol(); 184640a05f62edc6cdedb4365a722b48a72826ef2bf6Tadashi G. Takaoka } 1847923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1848a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1849a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1850123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka // receive ringer mode change and network state change. 1851923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private BroadcastReceiver mReceiver = new BroadcastReceiver() { 1852923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 1853923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onReceive(Context context, Intent intent) { 1854123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final String action = intent.getAction(); 1855123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { 1856123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka updateRingerMode(); 1857123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 1858123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka mSubtypeSwitcher.onNetworkStateChanged(intent); 1859123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka } 1860923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1861923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project }; 1862923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1863923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // update flags for silent mode 1864923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void updateRingerMode() { 1865923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager == null) { 1866923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 1867923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1868923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager != null) { 186917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSilentModeOn = (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL); 1870923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1871923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1872923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1873923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void playKeyClick(int primaryCode) { 1874923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // if mAudioManager is null, we don't have the ringer state yet 1875923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // mAudioManager will be set by updateRingerMode 1876923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager == null) { 1877979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mKeyboardSwitcher.getInputView() != null) { 1878923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateRingerMode(); 1879923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1880923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 188117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (isSoundOn()) { 1882923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // FIXME: Volume and enable should come from UI settings 1883923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // FIXME: These should be triggered after auto-repeat logic 1884923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int sound = AudioManager.FX_KEYPRESS_STANDARD; 1885923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 1886571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_DELETE: 1887923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sound = AudioManager.FX_KEYPRESS_DELETE; 1888923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 1889571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_ENTER: 1890923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sound = AudioManager.FX_KEYPRESS_RETURN; 1891923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 1892571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_SPACE: 1893923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sound = AudioManager.FX_KEYPRESS_SPACEBAR; 1894923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 1895923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1896923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAudioManager.playSoundEffect(sound, FX_VOLUME); 1897923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1898923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1899923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1900409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void vibrate() { 190117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (!mSettingsValues.mVibrateOn) { 1902923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1903923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 19041679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); 19051679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka if (inputView != null) { 19061679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka inputView.performHapticFeedback( 1907979f8690967ff5409fe18f5085858ccdb8e0ccf1satok HapticFeedbackConstants.KEYBOARD_TAP, 190866a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); 1909923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1910923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1911923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 191271c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka public void promoteToUserDictionary(String word, int frequency) { 191334386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani if (mUserDictionary.isValidWord(word)) return; 191434386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani mUserDictionary.addWord(word, frequency); 191534386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani } 191634386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani 191771c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka public WordComposer getCurrentWord() { 19186516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani return mWord; 19196516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani } 19206516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani 192117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard boolean isSoundOn() { 192217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard return mSettingsValues.mSoundOn && !mSilentModeOn; 1923979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1924979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1925e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private void updateCorrectionMode() { 19269f67e12a0e3f77985fb8bafe0db4c00e32317b9asatok // TODO: cleanup messy flags 1927e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mHasDictionary = mSuggest != null ? mSuggest.hasMainDictionary() : false; 192817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard final boolean shouldAutoCorrect = (mSettingsValues.mAutoCorrectEnabled 192917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard || mSettingsValues.mQuickFixes) && !mInputTypeNoAutoCorrect && mHasDictionary; 193017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mCorrectionMode = (shouldAutoCorrect && mSettingsValues.mAutoCorrectEnabled) 1931e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani ? Suggest.CORRECTION_FULL 193217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard : (shouldAutoCorrect ? Suggest.CORRECTION_BASIC : Suggest.CORRECTION_NONE); 193317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mCorrectionMode = (mSettingsValues.mBigramSuggestionEnabled && shouldAutoCorrect 193417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && mSettingsValues.mAutoCorrectEnabled) 1935979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ? Suggest.CORRECTION_FULL_BIGRAM : mCorrectionMode; 1936e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani if (mSuggest != null) { 1937e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mSuggest.setCorrectionMode(mCorrectionMode); 1938e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani } 1939e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani } 1940e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani 19410ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private void updateAutoTextEnabled() { 194232e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani if (mSuggest == null) return; 194317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSuggest.setQuickFixesEnabled(mSettingsValues.mQuickFixes 19444ab730dbd34fad323063f2ffd31ce33de746668dsatok && SubtypeSwitcher.getInstance().isSystemLanguageSameAsInputLanguage()); 194532e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 194632e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani 194717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard private void updateSuggestionVisibility(final SharedPreferences prefs, final Resources res) { 19487599cfea4a2d56f4779452ec8e8742f7b9629cc0satok final String suggestionVisiblityStr = prefs.getString( 19499502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka Settings.PREF_SHOW_SUGGESTIONS_SETTING, 1950458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa res.getString(R.string.prefs_suggestion_visibility_default_value)); 19517599cfea4a2d56f4779452ec8e8742f7b9629cc0satok for (int visibility : SUGGESTION_VISIBILITY_VALUE_ARRAY) { 1952458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa if (suggestionVisiblityStr.equals(res.getString(visibility))) { 19537599cfea4a2d56f4779452ec8e8742f7b9629cc0satok mSuggestionVisibility = visibility; 19547599cfea4a2d56f4779452ec8e8742f7b9629cc0satok break; 19557599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 19567599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 19577599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 19587599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 1959466741d8a78965b8509bf527344f289e50873092Mike LeBeau protected void launchSettings() { 19609502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka launchSettings(Settings.class); 1961466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1962466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1963bf96661d33d0126adb60a48880ceba1ff055d4a4satok public void launchDebugSettings() { 19649502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka launchSettings(DebugSettings.class); 1965bf96661d33d0126adb60a48880ceba1ff055d4a4satok } 1966bf96661d33d0126adb60a48880ceba1ff055d4a4satok 1967507495efd57074994fdc2fda78db9d5345f4a3a8Tadashi G. Takaoka protected void launchSettings(Class<? extends PreferenceActivity> settingsClass) { 1968923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project handleClose(); 1969923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Intent intent = new Intent(); 1970466741d8a78965b8509bf527344f289e50873092Mike LeBeau intent.setClass(LatinIME.this, settingsClass); 1971923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1972923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project startActivity(intent); 1973923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1974923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 19752fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private void showSubtypeSelectorAndSettings() { 197685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence title = getString(R.string.english_ime_input_options); 197785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence[] items = new CharSequence[] { 197885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka // TODO: Should use new string "Select active input modes". 197985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.language_selection_title), 198085996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.english_ime_settings), 198185996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 198285996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 19832fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka @Override 19842fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka public void onClick(DialogInterface di, int position) { 19852fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka di.dismiss(); 19862fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka switch (position) { 198785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 0: 19882cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok Intent intent = CompatUtils.getInputLanguageSelectionIntent( 19892cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok mInputMethodId, Intent.FLAG_ACTIVITY_NEW_TASK 19902fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 19912fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_CLEAR_TOP); 19922fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka startActivity(intent); 19932fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 1994aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa case 1: 1995aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa launchSettings(); 1996aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa break; 19972fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 19982fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 199985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 200085996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka showOptionsMenuInternal(title, items, listener); 20012fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 2002923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 20032fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private void showOptionsMenu() { 200485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence title = getString(R.string.english_ime_input_options); 200585996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence[] items = new CharSequence[] { 200685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.selectInputMethod), 200785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.english_ime_settings), 200885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 200985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 20105a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 2011923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onClick(DialogInterface di, int position) { 2012923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project di.dismiss(); 2013923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (position) { 201485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 0: 2015ea55bf5df7d26d12b36c47141bfbac5730c3929aTadashi G. Takaoka mImm.showInputMethodPicker(); 20162fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 201785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 1: 2018ea55bf5df7d26d12b36c47141bfbac5730c3929aTadashi G. Takaoka launchSettings(); 20192fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 2020923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2021923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 202285996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 202385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka showOptionsMenuInternal(title, items, listener); 20242fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 20252fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka 202685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka private void showOptionsMenuInternal(CharSequence title, CharSequence[] items, 202785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka DialogInterface.OnClickListener listener) { 202818e15a1e5e30cf200e935e43a73edef25682de27Ken Wakasa final IBinder windowToken = mKeyboardSwitcher.getInputView().getWindowToken(); 202918e15a1e5e30cf200e935e43a73edef25682de27Ken Wakasa if (windowToken == null) return; 20302fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka AlertDialog.Builder builder = new AlertDialog.Builder(this); 20312fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka builder.setCancelable(true); 20322fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka builder.setIcon(R.drawable.ic_dialog_keyboard); 20332fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka builder.setNegativeButton(android.R.string.cancel, null); 203485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka builder.setItems(items, listener); 203585996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka builder.setTitle(title); 2036923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mOptionsDialog = builder.create(); 2037a2ad96d95986eb61c3d2d5abce154fb4c3803cacTadashi G. Takaoka mOptionsDialog.setCanceledOnTouchOutside(true); 2038923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Window window = mOptionsDialog.getWindow(); 2039923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project WindowManager.LayoutParams lp = window.getAttributes(); 204018e15a1e5e30cf200e935e43a73edef25682de27Ken Wakasa lp.token = windowToken; 2041923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 2042923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project window.setAttributes(lp); 2043923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 2044923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mOptionsDialog.show(); 2045923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2046923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 20477e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 20487e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { 2049923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.dump(fd, fout, args); 2050a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2051923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final Printer p = new PrintWriterPrinter(fout); 2052923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println("LatinIME state :"); 2053923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" Keyboard mode = " + mKeyboardSwitcher.getKeyboardMode()); 2054923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mComposing=" + mComposing.toString()); 20559fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka p.println(" mIsSuggestionsRequested=" + mIsSettingsSuggestionStripOn); 2056923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mCorrectionMode=" + mCorrectionMode); 2057f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard p.println(" mHasUncommittedTypedChars=" + mHasUncommittedTypedChars); 205817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mAutoCorrectEnabled=" + mSettingsValues.mAutoCorrectEnabled); 20590730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard p.println(" mShouldInsertMagicSpace=" + mShouldInsertMagicSpace); 20601b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka p.println(" mApplicationSpecifiedCompletionOn=" + mApplicationSpecifiedCompletionOn); 2061923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" TextEntryState.state=" + TextEntryState.getState()); 206217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mSoundOn=" + mSettingsValues.mSoundOn); 206317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mVibrateOn=" + mSettingsValues.mVibrateOn); 2064240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard p.println(" mKeyPreviewPopupOn=" + mSettingsValues.mKeyPreviewPopupOn); 2065923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 20666e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani 2067923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Characters per second measurement 2068a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2069923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long mLastCpsTime; 2070923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int CPS_BUFFER_SIZE = 16; 2071923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long[] mCpsIntervals = new long[CPS_BUFFER_SIZE]; 2072923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mCpsIndex; 2073a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2074923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void measureCps() { 2075923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long now = System.currentTimeMillis(); 2076923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mLastCpsTime == 0) mLastCpsTime = now - 100; // Initial 2077923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCpsIntervals[mCpsIndex] = now - mLastCpsTime; 2078923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mLastCpsTime = now; 2079923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCpsIndex = (mCpsIndex + 1) % CPS_BUFFER_SIZE; 2080923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long total = 0; 2081923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project for (int i = 0; i < CPS_BUFFER_SIZE; i++) total += mCpsIntervals[i]; 2082923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project System.out.println("CPS = " + ((CPS_BUFFER_SIZE * 1000f) / total)); 2083923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2084923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 2085