LatinIME.java revision 9318d33b6e501d4dd9ea860de04160ccb23a7501
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 19923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.app.AlertDialog; 20923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.BroadcastReceiver; 21923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Context; 22923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.DialogInterface; 23923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Intent; 24923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.IntentFilter; 25923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.SharedPreferences; 26923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.res.Configuration; 2736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasaniimport android.content.res.Resources; 28923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.inputmethodservice.InputMethodService; 29923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.media.AudioManager; 30123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaokaimport android.net.ConnectivityManager; 31923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Debug; 3218e15a1e5e30cf200e935e43a73edef25682de27Ken Wakasaimport android.os.IBinder; 33923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Message; 34923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.SystemClock; 35bf96661d33d0126adb60a48880ceba1ff055d4a4satokimport android.preference.PreferenceActivity; 36923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.preference.PreferenceManager; 37e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaokaimport android.text.InputType; 38923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.text.TextUtils; 39979f8690967ff5409fe18f5085858ccdb8e0ccf1satokimport android.util.DisplayMetrics; 40923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Log; 41923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.PrintWriterPrinter; 42923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Printer; 4366a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasaniimport android.view.HapticFeedbackConstants; 44923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.KeyEvent; 45923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.View; 468e09172df1bb176cc899940862c56bed9b9aec4esatokimport android.view.ViewGroup; 478e09172df1bb176cc899940862c56bed9b9aec4esatokimport android.view.ViewParent; 48923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.Window; 49923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.WindowManager; 50923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.CompletionInfo; 51923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.EditorInfo; 52466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport android.view.inputmethod.ExtractedText; 53923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.InputConnection; 54c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka 555ac4638f999db4fea8a9e24171dbceb640a10858Alan Viveretteimport com.android.inputmethod.accessibility.AccessibilityUtils; 56c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.CompatUtils; 57c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.EditorInfoCompatUtils; 58c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputConnectionCompatUtils; 59c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputMethodManagerCompatWrapper; 60c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputMethodServiceCompatWrapper; 61c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputTypeCompatUtils; 621fef530ec7626fa16777f52b48191e61db8f46d4satokimport com.android.inputmethod.compat.SuggestionSpanUtils; 63c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.deprecated.LanguageSwitcherProxy; 64c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.deprecated.VoiceProxy; 65c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.deprecated.recorrection.Recorrection; 66c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.Keyboard; 67c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardActionListener; 68c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardSwitcher; 69f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardView; 70c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.LatinKeyboard; 71c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.LatinKeyboardView; 72923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 73466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.FileDescriptor; 74466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.PrintWriter; 75466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.util.Locale; 76466741d8a78965b8509bf527344f289e50873092Mike LeBeau 77923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/** 78923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Input method implementation for Qwerty'ish keyboard. 79923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 80c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaokapublic class LatinIME extends InputMethodServiceCompatWrapper implements KeyboardActionListener, 81c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka CandidateView.Listener { 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; 859e2d810dc524380ca1db6b384cfb00b4401585e5Tadashi G. Takaoka private static boolean DEBUG; 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; 1584ff60be170872503cca0275ef3488b7379b5311bAmith Yamasani private AutoDictionary mAutoDictionary; 15936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 1600730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard // TODO: Create an inner class to group options and pseudo-options to improve readability. 161c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // These variables are initialized according to the {@link EditorInfo#inputType}. 1620730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard private boolean mShouldInsertMagicSpace; 163c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mInputTypeNoAutoCorrect; 164c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mIsSettingsSuggestionStripOn; 165c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mApplicationSpecifiedCompletionOn; 166c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 1679318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa private final StringBuilder mComposingStringBuilder = new StringBuilder(); 1689318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa private WordComposer mWordComposer = new WordComposer(); 169923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private CharSequence mBestWord; 170f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard private boolean mHasUncommittedTypedChars; 171e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private boolean mHasDictionary; 1720730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard // Magic space: a space that should disappear on space/apostrophe insertion, move after the 1730730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard // punctuation on punctuation insertion, and become a real space on alpha char insertion. 1740730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard private boolean mJustAddedMagicSpace; // This indicates whether the last char is a magic space. 1754733609947c0ec74e460bd714fffca0518ade93aJean Chalard // This indicates whether the last keypress resulted in processing of double space replacement 1764733609947c0ec74e460bd714fffca0518ade93aJean Chalard // with period-space. 1774733609947c0ec74e460bd714fffca0518ade93aJean Chalard private boolean mJustReplacedDoubleSpace; 178409220583333bdf06290dd9fd42f91b5c0d1b11asatok 17979efbed76f638be298493107fa2d0cd1b5eb529esatok private int mCorrectionMode; 18079efbed76f638be298493107fa2d0cd1b5eb529esatok private int mCommittedLength; 18179efbed76f638be298493107fa2d0cd1b5eb529esatok private int mOrientation; 182979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Keep track of the last selection range to decide if we need to show word alternatives 18379efbed76f638be298493107fa2d0cd1b5eb529esatok private int mLastSelectionStart; 18479efbed76f638be298493107fa2d0cd1b5eb529esatok private int mLastSelectionEnd; 185979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1864733609947c0ec74e460bd714fffca0518ade93aJean Chalard // Whether we are expecting an onUpdateSelection event to fire. If it does when we don't 1874733609947c0ec74e460bd714fffca0518ade93aJean Chalard // "expect" it, it means the user actually moved the cursor. 1884733609947c0ec74e460bd714fffca0518ade93aJean Chalard private boolean mExpectingUpdateSelection; 189923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mDeleteCount; 190923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long mLastKeyTime; 191a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 192923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private AudioManager mAudioManager; 1932296317b8f0209789f797ac8a2fcb70e03f6d001Eric Laurent // Align sound effect volume on music volume 19471c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka private static final float FX_VOLUME = -1.0f; 19517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard private boolean mSilentModeOn; // System-wide current configuration 196923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 197b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok // TODO: Move this flag to VoiceProxy 19881c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani private boolean mConfigurationChanging; 199466741d8a78965b8509bf527344f289e50873092Mike LeBeau 200cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Object for reacting to adding/removing a dictionary pack. 201cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard private BroadcastReceiver mDictionaryPackInstallReceiver = 202cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard new DictionaryPackInstallBroadcastReceiver(this); 203cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 204dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani // Keeps track of most recently inserted text (multi-character key) for reverting 205dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani private CharSequence mEnteredText; 206dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 20736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 2084f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public final UIHandler mHandler = new UIHandler(this); 209d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 2104f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public static class UIHandler extends StaticInnerHandlerWrapper<LatinIME> { 211d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_UPDATE_SUGGESTIONS = 0; 212d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_UPDATE_OLD_SUGGESTIONS = 1; 213d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_UPDATE_SHIFT_STATE = 2; 214d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_VOICE_RESULTS = 3; 215de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka private static final int MSG_FADEOUT_LANGUAGE_ON_SPACEBAR = 4; 216de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 5; 217fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka private static final int MSG_SPACE_TYPED = 6; 218cb3320179d39a7983874697a0aa428b127675c9dJean Chalard private static final int MSG_SET_BIGRAM_PREDICTIONS = 7; 219d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 2204f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public UIHandler(LatinIME outerInstance) { 2214f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa super(outerInstance); 2224f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa } 2234f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa 224923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 225923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void handleMessage(Message msg) { 2264f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final LatinIME latinIme = getOuterInstance(); 2274f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final KeyboardSwitcher switcher = latinIme.mKeyboardSwitcher; 228c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka final LatinKeyboardView inputView = switcher.getKeyboardView(); 229923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (msg.what) { 230d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SUGGESTIONS: 2314f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.updateSuggestions(); 232d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 233d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_OLD_SUGGESTIONS: 2344f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mRecorrection.fetchAndDisplayRecorrectionSuggestions( 2354f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mVoiceProxy, latinIme.mCandidateView, 2369318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa latinIme.mSuggest, latinIme.mKeyboardSwitcher, latinIme.mWordComposer, 2374f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mHasUncommittedTypedChars, latinIme.mLastSelectionStart, 2384f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mLastSelectionEnd, latinIme.mSettingsValues.mWordSeparators); 239d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 240d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SHIFT_STATE: 241de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka switcher.updateShiftState(); 242d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 243cb3320179d39a7983874697a0aa428b127675c9dJean Chalard case MSG_SET_BIGRAM_PREDICTIONS: 2444f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.updateBigramPredictions(); 24589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard break; 246d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_VOICE_RESULTS: 2474f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mVoiceProxy.handleVoiceResults(latinIme.preferCapitalization() 248de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka || (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked())); 249de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka break; 250de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka case MSG_FADEOUT_LANGUAGE_ON_SPACEBAR: 25117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (inputView != null) { 25266432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka inputView.setSpacebarTextFadeFactor( 2534f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa (1.0f + latinIme.mSettingsValues. 2544f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa mFinalFadeoutFactorOfLanguageOnSpacebar) / 2, 25566432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka (LatinKeyboard)msg.obj); 25617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 257de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_DISMISS_LANGUAGE_ON_SPACEBAR, msg.obj), 2584f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mSettingsValues.mDurationOfFadeoutLanguageOnSpacebar); 259de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka break; 260de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka case MSG_DISMISS_LANGUAGE_ON_SPACEBAR: 26117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (inputView != null) { 26266432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka inputView.setSpacebarTextFadeFactor( 2634f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar, 26417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard (LatinKeyboard)msg.obj); 26517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 266d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 267923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 268923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 269d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 270d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateSuggestions() { 271d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 2729b2192bfd2d3a06df3c685ed4287e192dbaabf32Ken Wakasa sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTIONS), 2734f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa getOuterInstance().mSettingsValues.mDelayUpdateSuggestions); 274d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 275d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 276d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateSuggestions() { 277d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 278d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 279d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 280d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public boolean hasPendingUpdateSuggestions() { 281d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka return hasMessages(MSG_UPDATE_SUGGESTIONS); 282d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 283d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 284d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateOldSuggestions() { 285d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_OLD_SUGGESTIONS); 286d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_UPDATE_OLD_SUGGESTIONS), 2874f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa getOuterInstance().mSettingsValues.mDelayUpdateOldSuggestions); 288d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 289d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 290d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateOldSuggestions() { 291d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_OLD_SUGGESTIONS); 292d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 293d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 294d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateShiftKeyState() { 295d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 29617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard sendMessageDelayed(obtainMessage(MSG_UPDATE_SHIFT_STATE), 2974f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa getOuterInstance().mSettingsValues.mDelayUpdateShiftState); 298d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 299d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 300d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateShiftState() { 301d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 302d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 303d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 304cb3320179d39a7983874697a0aa428b127675c9dJean Chalard public void postUpdateBigramPredictions() { 305cb3320179d39a7983874697a0aa428b127675c9dJean Chalard removeMessages(MSG_SET_BIGRAM_PREDICTIONS); 3069b2192bfd2d3a06df3c685ed4287e192dbaabf32Ken Wakasa sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_PREDICTIONS), 3074f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa getOuterInstance().mSettingsValues.mDelayUpdateSuggestions); 30889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 30989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 310cb3320179d39a7983874697a0aa428b127675c9dJean Chalard public void cancelUpdateBigramPredictions() { 311cb3320179d39a7983874697a0aa428b127675c9dJean Chalard removeMessages(MSG_SET_BIGRAM_PREDICTIONS); 31289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 31389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 314d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void updateVoiceResults() { 315d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka sendMessage(obtainMessage(MSG_VOICE_RESULTS)); 316d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 317de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka 318d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka public void startDisplayLanguageOnSpacebar(boolean localeChanged) { 3194f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final LatinIME latinIme = getOuterInstance(); 320de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka removeMessages(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR); 321de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka removeMessages(MSG_DISMISS_LANGUAGE_ON_SPACEBAR); 3224f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final LatinKeyboardView inputView = latinIme.mKeyboardSwitcher.getKeyboardView(); 323de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka if (inputView != null) { 3244f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final LatinKeyboard keyboard = latinIme.mKeyboardSwitcher.getLatinKeyboard(); 325c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka // The language is always displayed when the delay is negative. 326c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka final boolean needsToDisplayLanguage = localeChanged 3274f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa || latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar < 0; 328de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka // The language is never displayed when the delay is zero. 3294f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa if (latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar != 0) { 330c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka inputView.setSpacebarTextFadeFactor(needsToDisplayLanguage ? 1.0f 3314f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa : latinIme.mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar, 3324f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa keyboard); 33317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 334c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka // The fadeout animation will start when the delay is positive. 3354f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa if (localeChanged 3364f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa && latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar > 0) { 337de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR, keyboard), 3384f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar); 339de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 340de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 341de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 342fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 343fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public void startDoubleSpacesTimer() { 344fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka removeMessages(MSG_SPACE_TYPED); 345fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_SPACE_TYPED), 3464f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa getOuterInstance().mSettingsValues.mDoubleSpacesTurnIntoPeriodTimeout); 347fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 348fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 349fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public void cancelDoubleSpacesTimer() { 350fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka removeMessages(MSG_SPACE_TYPED); 351fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 352fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 353fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public boolean isAcceptingDoubleSpaces() { 354fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka return hasMessages(MSG_SPACE_TYPED); 355fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 356d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 357923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 3587e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 3597e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka public void onCreate() { 36027d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 36127d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa mPrefs = prefs; 36227d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa LatinImeLogger.init(this, prefs); 3636d9021527a38ba1e94225020389621a0d7227aa1satok LanguageSwitcherProxy.init(this, prefs); 36427d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa SubtypeSwitcher.init(this, prefs); 36527d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa KeyboardSwitcher.init(this, prefs); 3667a8dac55278cedd838be325f56b4c52d973c61f5satok Recorrection.init(this, prefs); 3675ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette AccessibilityUtils.init(this, prefs); 368363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 369923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onCreate(); 370363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 371610f1dc8553cf2ed97e763a06a19380c4a6cd636satok mImm = InputMethodManagerCompatWrapper.getInstance(this); 3728efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka mInputMethodId = Utils.getInputMethodId(mImm, getPackageName()); 3730ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mSubtypeSwitcher = SubtypeSwitcher.getInstance(); 3740ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mKeyboardSwitcher = KeyboardSwitcher.getInstance(); 3757a8dac55278cedd838be325f56b4c52d973c61f5satok mRecorrection = Recorrection.getInstance(); 3769e2d810dc524380ca1db6b384cfb00b4401585e5Tadashi G. Takaoka DEBUG = LatinImeLogger.sDBG; 377363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 37817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard loadSettings(); 37917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 380363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka final Resources res = getResources(); 381363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka mResources = res; 382fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard 3839502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka Utils.GCUtils.getInstance().reset(); 384979f8690967ff5409fe18f5085858ccdb8e0ccf1satok boolean tryGC = true; 3859502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { 386979f8690967ff5409fe18f5085858ccdb8e0ccf1satok try { 3870ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 388979f8690967ff5409fe18f5085858ccdb8e0ccf1satok tryGC = false; 389979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } catch (OutOfMemoryError e) { 3909502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka tryGC = Utils.GCUtils.getInstance().tryGCOrWait("InitSuggest", e); 391979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 392979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 393979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 394363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka mOrientation = res.getConfiguration().orientation; 395b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 396cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Register to receive ringer mode change and network state change. 397cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Also receive installation and removal of a dictionary pack. 398123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final IntentFilter filter = new IntentFilter(); 399123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); 400123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 401923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project registerReceiver(mReceiver, filter); 402b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy = VoiceProxy.init(this, prefs, mHandler); 403cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 404cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final IntentFilter packageFilter = new IntentFilter(); 405cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 406cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 407cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addDataScheme(SCHEME_PACKAGE); 408cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard registerReceiver(mDictionaryPackInstallReceiver, packageFilter); 409646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard 410646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard final IntentFilter newDictFilter = new IntentFilter(); 411646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard newDictFilter.addAction( 412646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard DictionaryPackInstallBroadcastReceiver.NEW_DICTIONARY_INTENT_ACTION); 413646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard registerReceiver(mDictionaryPackInstallReceiver, newDictFilter); 414923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 41536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 41617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard // Has to be package-visible for unit tests 41717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard /* package */ void loadSettings() { 41817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this); 41917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (null == mSubtypeSwitcher) mSubtypeSwitcher = SubtypeSwitcher.getInstance(); 42017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues = new Settings.Values(mPrefs, this, mSubtypeSwitcher.getInputLocaleStr()); 421699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard resetContactsDictionary(); 42217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 42317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 4240ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private void initSuggest() { 425cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); 426eaa10f44a4a0108a90803b1b28238842d3fb5addsatok final Locale keyboardLocale = Utils.constructLocaleFromString(localeStr); 42736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 428309bff562fbaf47488e6bf6636840f00574187d8Jean Chalard final Resources res = mResources; 429309bff562fbaf47488e6bf6636840f00574187d8Jean Chalard final Locale savedLocale = Utils.setSystemLocale(res, keyboardLocale); 43036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani if (mSuggest != null) { 43136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mSuggest.close(); 43236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 433979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 4348efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka int mainDicResId = Utils.getMainDictionaryResourceId(res); 435cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mSuggest = new Suggest(this, mainDicResId, keyboardLocale); 43617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.mAutoCorrectEnabled) { 43717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); 43817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 43927023341658b4cf5430d18ddb94fd9502ecfe3cbTadashi G. Takaoka updateAutoTextEnabled(); 440e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 441cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mUserDictionary = new UserDictionary(this, localeStr); 442923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mSuggest.setUserDictionary(mUserDictionary); 443e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 444699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard resetContactsDictionary(); 445e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 446cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mAutoDictionary = new AutoDictionary(this, this, localeStr, Suggest.DIC_AUTO); 44734386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani mSuggest.setAutoDictionary(mAutoDictionary); 448e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 449cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mUserBigramDictionary = new UserBigramDictionary(this, this, localeStr, Suggest.DIC_USER); 450e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest.setUserBigramDictionary(mUserBigramDictionary); 451e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 452e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani updateCorrectionMode(); 45336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 454309bff562fbaf47488e6bf6636840f00574187d8Jean Chalard Utils.setSystemLocale(res, savedLocale); 455923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 45636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 457699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard private void resetContactsDictionary() { 458699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard if (null == mSuggest) return; 459699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard ContactsDictionary contactsDictionary = mSettingsValues.mUseContactsDict 460699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard ? new ContactsDictionary(this, Suggest.DIC_CONTACTS) : null; 461699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard mSuggest.setContactsDictionary(contactsDictionary); 462699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard } 463699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard 464cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard /* package private */ void resetSuggestMainDict() { 465cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); 466eaa10f44a4a0108a90803b1b28238842d3fb5addsatok final Locale keyboardLocale = Utils.constructLocaleFromString(localeStr); 467cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard int mainDicResId = Utils.getMainDictionaryResourceId(mResources); 468cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mSuggest.resetMainDict(this, mainDicResId, keyboardLocale); 469cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard } 470cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 471466741d8a78965b8509bf527344f289e50873092Mike LeBeau @Override 472466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onDestroy() { 473e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa if (mSuggest != null) { 474e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest.close(); 475e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest = null; 476979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 477923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project unregisterReceiver(mReceiver); 478cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard unregisterReceiver(mDictionaryPackInstallReceiver); 479b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.destroy(); 480979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 481979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.onDestroy(); 482923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onDestroy(); 483923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 484923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 485923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 486923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onConfigurationChanged(Configuration conf) { 487dc64b138b5e3fb3706c0818d0a308fe6e36985b0Tadashi G. Takaoka mSubtypeSwitcher.onConfigurationChanged(conf); 488b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani // If orientation changed while predicting, commit the change 489b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani if (conf.orientation != mOrientation) { 490466741d8a78965b8509bf527344f289e50873092Mike LeBeau InputConnection ic = getCurrentInputConnection(); 491466741d8a78965b8509bf527344f289e50873092Mike LeBeau commitTyped(ic); 492466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (ic != null) ic.finishComposingText(); // For voice input 493b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani mOrientation = conf.orientation; 4942fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka if (isShowingOptionDialog()) 4952fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka mOptionsDialog.dismiss(); 496b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 4978b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka 49881c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani mConfigurationChanging = true; 499923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onConfigurationChanged(conf); 500b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.onConfigurationChanged(conf); 50181c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani mConfigurationChanging = false; 50288fc9d44186120f9edc5cf7ec0e2af85260fed04satok 50388fc9d44186120f9edc5cf7ec0e2af85260fed04satok // This will work only when the subtype is not supported. 50488fc9d44186120f9edc5cf7ec0e2af85260fed04satok LanguageSwitcherProxy.onConfigurationChanged(conf); 505923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 506b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 507923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 508923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public View onCreateInputView() { 5096c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka return mKeyboardSwitcher.onCreateInputView(); 5106c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka } 5116c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka 5126c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka @Override 5136c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka public void setInputView(View view) { 5146c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka super.setInputView(view); 5156c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka mCandidateViewContainer = view.findViewById(R.id.candidates_container); 5166c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka mCandidateView = (CandidateView) view.findViewById(R.id.candidates); 517281e180c33b1dd88e8eae48f279736c529f529d2Tadashi G. Takaoka if (mCandidateView != null) 518281e180c33b1dd88e8eae48f279736c529f529d2Tadashi G. Takaoka mCandidateView.setListener(this, view); 519c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka mCandidateStripHeight = (int)mResources.getDimension(R.dimen.candidate_strip_height); 520923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 521923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 522923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 523c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka public void setCandidatesView(View view) { 524c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka // To ensure that CandidatesView will never be set. 525c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka return; 526923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 527923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 528a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker @Override 529923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onStartInputView(EditorInfo attribute, boolean restarting) { 53045911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 531c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka LatinKeyboardView inputView = switcher.getKeyboardView(); 5328e09172df1bb176cc899940862c56bed9b9aec4esatok 53389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (DEBUG) { 534f0f726464dcb5b3cef4f8e703659b35ca62430b5Tadashi G. Takaoka Log.d(TAG, "onStartInputView: attribute:" + ((attribute == null) ? "none" 535f0f726464dcb5b3cef4f8e703659b35ca62430b5Tadashi G. Takaoka : String.format("inputType=0x%08x imeOptions=0x%08x", 536f0f726464dcb5b3cef4f8e703659b35ca62430b5Tadashi G. Takaoka attribute.inputType, attribute.imeOptions))); 537910b73127fa207dd26ec8124000262523b0aac0csatok } 538923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In landscape mode, this method gets called without the input view being created. 539979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (inputView == null) { 540923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 541923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 542923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 5438d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka mSubtypeSwitcher.updateParametersOnStartInputView(); 5444ab730dbd34fad323063f2ffd31ce33de746668dsatok 545662bb7c26cadd5026cb3d4e5d081aae163bd5a3aTadashi G. Takaoka TextEntryState.reset(); 5466c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani 547c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // Most such things we decide below in initializeInputAttributesAndGetMode, but we need to 548c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // know now whether this is a password text field, because we need to know now whether we 549c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // want to enable the voice button. 550b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok final VoiceProxy voiceIme = mVoiceProxy; 551e9957752bcaad048746c7a57bbd2c0a59e1918a0satok voiceIme.resetVoiceStates(InputTypeCompatUtils.isPasswordInputType(attribute.inputType) 552e9957752bcaad048746c7a57bbd2c0a59e1918a0satok || InputTypeCompatUtils.isVisiblePasswordInputType(attribute.inputType)); 553c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 554cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka initializeInputAttributes(attribute); 555c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 556c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.closing(); 557c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mEnteredText = null; 5589318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mComposingStringBuilder.setLength(0); 559f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = false; 560c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mDeleteCount = 0; 5610730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard mJustAddedMagicSpace = false; 5624733609947c0ec74e460bd714fffca0518ade93aJean Chalard mJustReplacedDoubleSpace = false; 563c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 56417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard loadSettings(); 56517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard updateCorrectionMode(); 56617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard updateAutoTextEnabled(); 56717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard updateSuggestionVisibility(mPrefs, mResources); 56817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 56917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSuggest != null && mSettingsValues.mAutoCorrectEnabled) { 57017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); 57117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 57217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mVoiceProxy.loadSettings(attribute, mPrefs); 57317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard // This will work only when the subtype is not supported. 57417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard LanguageSwitcherProxy.loadSettings(); 57517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 576c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if (mSubtypeSwitcher.isKeyboardMode()) { 577cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka switcher.loadKeyboard(attribute, 5784503e2ea9853c1573f60903d8639d82e39e07c56Tadashi G. Takaoka mSubtypeSwitcher.isShortcutImeEnabled() && voiceIme.isVoiceButtonEnabled(), 5794503e2ea9853c1573f60903d8639d82e39e07c56Tadashi G. Takaoka voiceIme.isVoiceButtonOnPrimary()); 580c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka switcher.updateShiftState(); 581c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka } 582c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 58388110d1799146943c627916ffaa94bbc4dd6f2aeTadashi G. Takaoka if (mCandidateView != null) 58488110d1799146943c627916ffaa94bbc4dd6f2aeTadashi G. Takaoka mCandidateView.clear(); 585c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShownInternal(isCandidateStripVisible(), /* needsInputViewShown */ false); 586c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // Delay updating suggestions because keyboard input view may not be shown at this point. 587c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mHandler.postUpdateSuggestions(); 588c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 589c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka updateCorrectionMode(); 590c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 591240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard inputView.setKeyPreviewPopupEnabled(mSettingsValues.mKeyPreviewPopupOn, 592240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard mSettingsValues.mKeyPreviewPopupDismissDelay); 593c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.setProximityCorrectionEnabled(true); 594c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // If we just entered a text field, maybe it has some old text that requires correction 5957a8dac55278cedd838be325f56b4c52d973c61f5satok mRecorrection.checkRecorrectionOnStart(); 596c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 5974503e2ea9853c1573f60903d8639d82e39e07c56Tadashi G. Takaoka voiceIme.onStartInputView(inputView.getWindowToken()); 598c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 599c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); 600c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka } 601c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 602cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka private void initializeInputAttributes(EditorInfo attribute) { 603cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if (attribute == null) 604cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka return; 6054b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka final int inputType = attribute.inputType; 606c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka final int variation = inputType & InputType.TYPE_MASK_VARIATION; 6070730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard mShouldInsertMagicSpace = false; 608e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mInputTypeNoAutoCorrect = false; 6099fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 6101b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletionOn = false; 6111b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletions = null; 612dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 613cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_MASK_CLASS) == InputType.TYPE_CLASS_TEXT) { 614cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = true; 615cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // Make sure that passwords are not displayed in candidate view 616e9957752bcaad048746c7a57bbd2c0a59e1918a0satok if (InputTypeCompatUtils.isPasswordInputType(inputType) 617e9957752bcaad048746c7a57bbd2c0a59e1918a0satok || InputTypeCompatUtils.isVisiblePasswordInputType(inputType)) { 618cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 619cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 620e9957752bcaad048746c7a57bbd2c0a59e1918a0satok if (InputTypeCompatUtils.isEmailVariation(variation) 621cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka || variation == InputType.TYPE_TEXT_VARIATION_PERSON_NAME) { 6220730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard mShouldInsertMagicSpace = false; 623cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else { 6240730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard mShouldInsertMagicSpace = true; 625cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 626e9957752bcaad048746c7a57bbd2c0a59e1918a0satok if (InputTypeCompatUtils.isEmailVariation(variation)) { 627cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 628cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) { 629cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 630cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) { 631cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 632cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else if (variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) { 633cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // If it's a browser edit field and auto correct is not ON explicitly, then 634cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // disable auto correction, but keep suggestions on. 635cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) { 636e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mInputTypeNoAutoCorrect = true; 63736ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani } 638cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 639cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka 640cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // If NO_SUGGESTIONS is set, don't do prediction. 641cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) { 642cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 643cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mInputTypeNoAutoCorrect = true; 644cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 645cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // If it's not multiline and the autoCorrect flag is not set, then don't correct 646cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 647cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka && (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) == 0) { 648cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mInputTypeNoAutoCorrect = true; 649cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 650cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { 651cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 652cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mApplicationSpecifiedCompletionOn = isFullscreenMode(); 653cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 654923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 655923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 656923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 657923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 658e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka public void onWindowHidden() { 659e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka super.onWindowHidden(); 660f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 661e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka if (inputView != null) inputView.closing(); 662e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka } 663e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka 664e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka @Override 665923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onFinishInput() { 666923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onFinishInput(); 667a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 668979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 6691b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mKeyboardSwitcher.onAutoCorrectionStateChanged(false); 670979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 671b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.flushVoiceInputLogs(mConfigurationChanging); 672409220583333bdf06290dd9fd42f91b5c0d1b11asatok 673f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 674d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa if (inputView != null) inputView.closing(); 6754ff60be170872503cca0275ef3488b7379b5311bAmith Yamasani if (mAutoDictionary != null) mAutoDictionary.flushPendingWrites(); 676979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mUserBigramDictionary != null) mUserBigramDictionary.flushPendingWrites(); 677466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 678466741d8a78965b8509bf527344f289e50873092Mike LeBeau 679466741d8a78965b8509bf527344f289e50873092Mike LeBeau @Override 6806495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa public void onFinishInputView(boolean finishingInput) { 6816495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa super.onFinishInputView(finishingInput); 682f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 6835f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka if (inputView != null) inputView.cancelAllMessages(); 684d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka // Remove pending messages related to update suggestions 685d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 686d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateOldSuggestions(); 6876495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa } 6886495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa 6896495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa @Override 690466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onUpdateExtractedText(int token, ExtractedText text) { 691466741d8a78965b8509bf527344f289e50873092Mike LeBeau super.onUpdateExtractedText(token, text); 692b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.showPunctuationHintIfNecessary(); 693923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 694923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 695923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 696923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onUpdateSelection(int oldSelStart, int oldSelEnd, 697923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int newSelStart, int newSelEnd, 698923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int candidatesStart, int candidatesEnd) { 699923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, 700923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project candidatesStart, candidatesEnd); 701466741d8a78965b8509bf527344f289e50873092Mike LeBeau 702466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (DEBUG) { 703466741d8a78965b8509bf527344f289e50873092Mike LeBeau Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart 704466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", ose=" + oldSelEnd 705025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa + ", lss=" + mLastSelectionStart 706025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa + ", lse=" + mLastSelectionEnd 707466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nss=" + newSelStart 708466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nse=" + newSelEnd 709466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", cs=" + candidatesStart 710466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", ce=" + candidatesEnd); 711466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 712466741d8a78965b8509bf527344f289e50873092Mike LeBeau 713b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.setCursorAndSelection(newSelEnd, newSelStart); 7144f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 715923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // If the current selection in the text view changes, we should 716923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // clear whatever candidate text we have. 717025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa final boolean selectionChanged = (newSelStart != candidatesEnd 718025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa || newSelEnd != candidatesEnd) && mLastSelectionStart != newSelStart; 719025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa final boolean candidatesCleared = candidatesStart == -1 && candidatesEnd == -1; 7209318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa if (((mComposingStringBuilder.length() > 0 && mHasUncommittedTypedChars) 721b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok || mVoiceProxy.isVoiceInputHighlighted()) 722025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa && (selectionChanged || candidatesCleared)) { 723025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa if (candidatesCleared) { 724025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa // If the composing span has been cleared, save the typed word in the history for 725025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa // recorrection before we reset the candidate strip. Then, we'll be able to show 726025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa // suggestions for recorrection right away. 7279318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mRecorrection.saveRecorrectionSuggestion(mWordComposer, mComposingStringBuilder); 728025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa } 7299318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mComposingStringBuilder.setLength(0); 730f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = false; 73189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (isCursorTouchingWord()) { 732cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.cancelUpdateBigramPredictions(); 73389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.postUpdateSuggestions(); 73489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 73589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard setPunctuationSuggestions(); 73689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 737923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.reset(); 738923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 739923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 740923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.finishComposingText(); 741923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 742b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.setVoiceInputHighlighted(false); 7434733609947c0ec74e460bd714fffca0518ade93aJean Chalard } else if (!mHasUncommittedTypedChars && !mExpectingUpdateSelection) { 744662bb7c26cadd5026cb3d4e5d081aae163bd5a3aTadashi G. Takaoka if (TextEntryState.isAcceptedDefault() || TextEntryState.isSpaceAfterPicked()) { 745662bb7c26cadd5026cb3d4e5d081aae163bd5a3aTadashi G. Takaoka if (TextEntryState.isAcceptedDefault()) 746662bb7c26cadd5026cb3d4e5d081aae163bd5a3aTadashi G. Takaoka TextEntryState.reset(); 7479a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 748923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 7494733609947c0ec74e460bd714fffca0518ade93aJean Chalard if (!mExpectingUpdateSelection) { 7509318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mJustAddedMagicSpace = false; // The user moved the cursor. 7519318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mJustReplacedDoubleSpace = false; 7524733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 7534733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = false; 754d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateShiftKeyState(); 755466741d8a78965b8509bf527344f289e50873092Mike LeBeau 756979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Make a note of the cursor position 757979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionStart = newSelStart; 758979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionEnd = newSelEnd; 759466741d8a78965b8509bf527344f289e50873092Mike LeBeau 7607a8dac55278cedd838be325f56b4c52d973c61f5satok mRecorrection.updateRecorrectionSelection(mKeyboardSwitcher, 7617a8dac55278cedd838be325f56b4c52d973c61f5satok mCandidateView, candidatesStart, candidatesEnd, newSelStart, 7627a8dac55278cedd838be325f56b4c52d973c61f5satok newSelEnd, oldSelStart, mLastSelectionStart, 7637a8dac55278cedd838be325f56b4c52d973c61f5satok mLastSelectionEnd, mHasUncommittedTypedChars); 7647a8dac55278cedd838be325f56b4c52d973c61f5satok } 7657a8dac55278cedd838be325f56b4c52d973c61f5satok 7667a8dac55278cedd838be325f56b4c52d973c61f5satok public void setLastSelection(int start, int end) { 7677a8dac55278cedd838be325f56b4c52d973c61f5satok mLastSelectionStart = start; 7687a8dac55278cedd838be325f56b4c52d973c61f5satok mLastSelectionEnd = end; 769923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 770923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 771c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 772c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has clicked on the extracted text view, 773c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * when running in fullscreen mode. The default implementation hides 774c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * the candidates view when this happens, but only if the extracted text 775c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * editor has a vertical scroll bar because its text doesn't fit. 776c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * Here we override the behavior due to the possibility that a re-correction could 777c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * cause the candidate strip to disappear and re-appear. 778c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani */ 779c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani @Override 780c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani public void onExtractedTextClicked() { 7817a8dac55278cedd838be325f56b4c52d973c61f5satok if (mRecorrection.isRecorrectionEnabled() && isSuggestionsRequested()) return; 782c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 783c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedTextClicked(); 784c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 785c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 786c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 787c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has performed a cursor movement in the 788c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * extracted text view, when it is running in fullscreen mode. The default 789c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * implementation hides the candidates view when a vertical movement 790c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * happens, but only if the extracted text editor has a vertical scroll bar 791c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * because its text doesn't fit. 792c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * Here we override the behavior due to the possibility that a re-correction could 793c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * cause the candidate strip to disappear and re-appear. 794c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani */ 795c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani @Override 796c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani public void onExtractedCursorMovement(int dx, int dy) { 7977a8dac55278cedd838be325f56b4c52d973c61f5satok if (mRecorrection.isRecorrectionEnabled() && isSuggestionsRequested()) return; 798c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 799c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedCursorMovement(dx, dy); 800c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 801c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 802923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 803923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void hideWindow() { 804979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 8051b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mKeyboardSwitcher.onAutoCorrectionStateChanged(false); 806979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 807923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (TRACE) Debug.stopMethodTracing(); 8086e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (mOptionsDialog != null && mOptionsDialog.isShowing()) { 8096e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog.dismiss(); 8106e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog = null; 8116e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 812b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.hideVoiceWindow(mConfigurationChanging); 8139fbfd5877305ed19a20663630b498b6b3fdae942satok mRecorrection.clearWordsInHistory(); 814923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.hideWindow(); 815923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 816923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 817923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 8181b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka public void onDisplayCompletions(CompletionInfo[] applicationSpecifiedCompletions) { 819979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (DEBUG) { 820a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa Log.i(TAG, "Received completions:"); 821bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok if (applicationSpecifiedCompletions != null) { 822bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok for (int i = 0; i < applicationSpecifiedCompletions.length; i++) { 823bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok Log.i(TAG, " #" + i + ": " + applicationSpecifiedCompletions[i]); 824bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok } 825923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 826923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 8271b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (mApplicationSpecifiedCompletionOn) { 8281b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletions = applicationSpecifiedCompletions; 8291b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (applicationSpecifiedCompletions == null) { 830b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani clearSuggestions(); 831923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 832923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 833a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 8347e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords.Builder builder = new SuggestedWords.Builder() 8351b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka .setApplicationSpecifiedCompletions(applicationSpecifiedCompletions) 8365238df54ad3f648d09d5288f00b0a9d3c0593832Tadashi G. Takaoka .setTypedWordValid(false) 8375238df54ad3f648d09d5288f00b0a9d3c0593832Tadashi G. Takaoka .setHasMinimalSuggestion(false); 838979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // When in fullscreen mode, show completions generated by the application 8397e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(builder.build()); 840923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = null; 841c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShown(true); 842923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 843923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 844923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 845c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka private void setSuggestionStripShownInternal(boolean shown, boolean needsInputViewShown) { 8467a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // TODO: Modify this if we support candidates with hard keyboard 8477e9615f218630d14ae5666ede2efd5f12d0a23c3Tadashi G. Takaoka if (onEvaluateInputViewShown() && mCandidateViewContainer != null) { 8487a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka final boolean shouldShowCandidates = shown 8497a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka && (needsInputViewShown ? mKeyboardSwitcher.isInputViewShown() : true); 8507a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka if (isExtractViewShown()) { 8517a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // No need to have extra space to show the key preview. 8527a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka mCandidateViewContainer.setMinimumHeight(0); 853c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka mCandidateViewContainer.setVisibility( 854c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka shouldShowCandidates ? View.VISIBLE : View.GONE); 8557a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka } else { 8567a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // We must control the visibility of the suggestion strip in order to avoid clipped 8577a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // key previews, even when we don't show the suggestion strip. 8587a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka mCandidateViewContainer.setVisibility( 8597a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka shouldShowCandidates ? View.VISIBLE : View.INVISIBLE); 8607a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka } 861923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 862923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 863a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 864c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka private void setSuggestionStripShown(boolean shown) { 865c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShownInternal(shown, /* needsInputViewShown */true); 866543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa } 867543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa 868543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa @Override 869923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onComputeInsets(InputMethodService.Insets outInsets) { 870923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onComputeInsets(outInsets); 871f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka final KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 8722951aa7e93c36fbbaff48139f3ff0ff6b67d05b7Tadashi G. Takaoka if (inputView == null || mCandidateViewContainer == null) 87346ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka return; 87446ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka final int containerHeight = mCandidateViewContainer.getHeight(); 87546ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka int touchY = containerHeight; 8769e347d3d448e48229c46aad394ec9bd60cd5807bsatok // Need to set touchable region only if input view is being shown 87746ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka if (mKeyboardSwitcher.isInputViewShown()) { 8787a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka if (mCandidateViewContainer.getVisibility() == View.VISIBLE) { 8797a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka touchY -= mCandidateStripHeight; 8809e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 8817a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka final int touchWidth = inputView.getWidth(); 8827a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka final int touchHeight = inputView.getHeight() + containerHeight 8837a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // Extend touchable region below the keyboard. 8847a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka + EXTENDED_TOUCHABLE_REGION_HEIGHT; 8859e347d3d448e48229c46aad394ec9bd60cd5807bsatok if (DEBUG) { 8867a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka Log.d(TAG, "Touchable region: y=" + touchY + " width=" + touchWidth 8877a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka + " height=" + touchHeight); 8889e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 8897a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka setTouchableRegionCompat(outInsets, 0, touchY, touchWidth, touchHeight); 8909e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 89146ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka outInsets.contentTopInsets = touchY; 89246ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka outInsets.visibleTopInsets = touchY; 893923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 894a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 895923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 896979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public boolean onEvaluateFullscreenMode() { 897458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa final Resources res = mResources; 898458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa DisplayMetrics dm = res.getDisplayMetrics(); 899979f8690967ff5409fe18f5085858ccdb8e0ccf1satok float displayHeight = dm.heightPixels; 900979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // If the display is more than X inches high, don't go to fullscreen mode 901458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa float dimen = res.getDimension(R.dimen.max_height_for_fullscreen); 902979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (displayHeight > dimen) { 903979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return false; 904979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } else { 905979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return super.onEvaluateFullscreenMode(); 906979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 907979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 908979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 909979f8690967ff5409fe18f5085858ccdb8e0ccf1satok @Override 910923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 911923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 912e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_BACK: 913c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka if (event.getRepeatCount() == 0 && mKeyboardSwitcher.getKeyboardView() != null) { 914c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka if (mKeyboardSwitcher.getKeyboardView().handleBack()) { 9156e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani return true; 9166e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 917e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 918e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 919923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 920923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyDown(keyCode, event); 921923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 922923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 923923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 924923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 925923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 926e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_DOWN: 927e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_UP: 928e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_LEFT: 929e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_RIGHT: 930e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka // Enable shift key and DPAD to do selections 931e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mKeyboardSwitcher.isInputViewShown() 932e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka && mKeyboardSwitcher.isShiftedOrShiftLocked()) { 933e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka KeyEvent newEvent = new KeyEvent(event.getDownTime(), event.getEventTime(), 934e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka event.getAction(), event.getKeyCode(), event.getRepeatCount(), 935e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka event.getDeviceId(), event.getScanCode(), 936e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON); 937e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka InputConnection ic = getCurrentInputConnection(); 938e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (ic != null) 939e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka ic.sendKeyEvent(newEvent); 940e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka return true; 941e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 942e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 943923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 944923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyUp(keyCode, event); 945923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 946923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 947409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void commitTyped(InputConnection inputConnection) { 948f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (mHasUncommittedTypedChars) { 949f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = false; 9509318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa if (mComposingStringBuilder.length() > 0) { 951923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (inputConnection != null) { 9529318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa inputConnection.commitText(mComposingStringBuilder, 1); 953923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 9549318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mCommittedLength = mComposingStringBuilder.length(); 9559318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa TextEntryState.acceptedTyped(mComposingStringBuilder); 9569318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa addToAutoAndUserBigramDictionaries(mComposingStringBuilder, 9579318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa AutoDictionary.FREQUENCY_FOR_TYPED); 958923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 959923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateSuggestions(); 960923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 961923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 962923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 963b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public boolean getCurrentAutoCapsState() { 964923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 9651c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani EditorInfo ei = getCurrentInputEditorInfo(); 96617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.mAutoCap && ic != null && ei != null 96717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && ei.inputType != InputType.TYPE_NULL) { 968b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return ic.getCursorCapsMode(ei.inputType) != 0; 9691c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 970b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return false; 9711c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 9721c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 973863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard private void swapSwapperAndSpace() { 974923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final InputConnection ic = getCurrentInputConnection(); 975923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 976923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence lastTwo = ic.getTextBeforeCursor(2, 0); 977863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // It is guaranteed lastTwo.charAt(1) is a swapper - else this method is not called. 978923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastTwo != null && lastTwo.length() == 2 979863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard && lastTwo.charAt(0) == Keyboard.CODE_SPACE) { 980923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 981923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 982923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(lastTwo.charAt(1) + " ", 1); 983923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 984b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 9854ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 9864ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 9874ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 988863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard private void maybeDoubleSpace() { 989923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mCorrectionMode == Suggest.CORRECTION_NONE) return; 990923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final InputConnection ic = getCurrentInputConnection(); 991923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 992923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence lastThree = ic.getTextBeforeCursor(3, 0); 993923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastThree != null && lastThree.length() == 3 994923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project && Character.isLetterOrDigit(lastThree.charAt(0)) 995571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastThree.charAt(1) == Keyboard.CODE_SPACE 996fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka && lastThree.charAt(2) == Keyboard.CODE_SPACE 997fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka && mHandler.isAcceptingDoubleSpaces()) { 998fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka mHandler.cancelDoubleSpacesTimer(); 999923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 1000923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 1001923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(". ", 1); 1002923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1003b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 10044733609947c0ec74e460bd714fffca0518ade93aJean Chalard mJustReplacedDoubleSpace = true; 1005fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } else { 1006fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka mHandler.startDoubleSpacesTimer(); 1007923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1008923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1009a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 101041a519729505a877844f2c57a33509c302dddbceKen Wakasa private void maybeRemovePreviousPeriod(CharSequence text) { 101141a519729505a877844f2c57a33509c302dddbceKen Wakasa final InputConnection ic = getCurrentInputConnection(); 101241a519729505a877844f2c57a33509c302dddbceKen Wakasa if (ic == null) return; 101341a519729505a877844f2c57a33509c302dddbceKen Wakasa 101441a519729505a877844f2c57a33509c302dddbceKen Wakasa // When the text's first character is '.', remove the previous period 101541a519729505a877844f2c57a33509c302dddbceKen Wakasa // if there is one. 101641a519729505a877844f2c57a33509c302dddbceKen Wakasa CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 10174ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa if (lastOne != null && lastOne.length() == 1 1018571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastOne.charAt(0) == Keyboard.CODE_PERIOD 1019571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && text.charAt(0) == Keyboard.CODE_PERIOD) { 102041a519729505a877844f2c57a33509c302dddbceKen Wakasa ic.deleteSurroundingText(1, 0); 102141a519729505a877844f2c57a33509c302dddbceKen Wakasa } 102241a519729505a877844f2c57a33509c302dddbceKen Wakasa } 102341a519729505a877844f2c57a33509c302dddbceKen Wakasa 10249a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa private void removeTrailingSpace() { 10259a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa final InputConnection ic = getCurrentInputConnection(); 10269a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic == null) return; 10279a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa 10289a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 10299a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (lastOne != null && lastOne.length() == 1 1030571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastOne.charAt(0) == Keyboard.CODE_SPACE) { 10319a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.deleteSurroundingText(1, 0); 10329a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 10339a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 10349a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa 1035c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka @Override 1036923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean addWordToDictionary(String word) { 1037923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mUserDictionary.addWord(word, 128); 10386558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // Suggestion strip should be updated after the operation of adding word to the 10396558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // user dictionary 1040d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1041923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1042923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1043923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1044923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean isAlphabet(int code) { 1045923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (Character.isLetter(code)) { 1046923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1047923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1048923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return false; 1049923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1050923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1051a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1052e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka private void onSettingsKeyPressed() { 1053d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka if (isShowingOptionDialog()) 1054d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka return; 1055d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) { 1056d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka showSubtypeSelectorAndSettings(); 1057d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka } else if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm)) { 1058d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka showOptionsMenu(); 1059d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka } else { 1060d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka launchSettings(); 10619a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10629a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10639a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 1064e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka private void onSettingsKeyLongPressed() { 10659a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok if (!isShowingOptionDialog()) { 10669502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm)) { 106779efbed76f638be298493107fa2d0cd1b5eb529esatok mImm.showInputMethodPicker(); 10689a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } else { 10699a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok launchSettings(); 10709a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10719a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10729a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10739a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 10749a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok private boolean isShowingOptionDialog() { 10759a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok return mOptionsDialog != null && mOptionsDialog.isShowing(); 10769a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 10779a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 10785f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // Implementation of {@link KeyboardActionListener}. 10795a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 10808aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { 1081923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long when = SystemClock.uptimeMillis(); 1082571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (primaryCode != Keyboard.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) { 1083923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mDeleteCount = 0; 1084923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1085923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mLastKeyTime = when; 1086b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 1087b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); 10884733609947c0ec74e460bd714fffca0518ade93aJean Chalard final boolean lastStateOfJustReplacedDoubleSpace = mJustReplacedDoubleSpace; 10894733609947c0ec74e460bd714fffca0518ade93aJean Chalard mJustReplacedDoubleSpace = false; 1090923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 1091571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_DELETE: 10924733609947c0ec74e460bd714fffca0518ade93aJean Chalard handleBackspace(lastStateOfJustReplacedDoubleSpace); 10934189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka mDeleteCount++; 10944733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 10954189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka LatinImeLogger.logOnDelete(); 10964189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1097571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_SHIFT: 10984189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka // Shift key is handled in onPress() when device has distinct multi-touch panel. 1099101a00e3d4b1c29ef2ecdecd1b72b43efde7791aTadashi G. Takaoka if (!distinctMultiTouch) 1100b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.toggleShift(); 11014189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1102e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: 11034189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka // Symbol key is handled in onPress() when device has distinct multi-touch panel. 1104101a00e3d4b1c29ef2ecdecd1b72b43efde7791aTadashi G. Takaoka if (!distinctMultiTouch) 1105b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.changeKeyboardMode(); 11064189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1107571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_CANCEL: 11084189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka if (!isShowingOptionDialog()) { 11094189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka handleClose(); 11104189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } 11114189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1112e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SETTINGS: 1113e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka onSettingsKeyPressed(); 11144189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1115e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SETTINGS_LONGPRESS: 1116e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka onSettingsKeyLongPressed(); 11174189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1118d2c5fdda862f6dd2a1e020cf674c35fbbc63fc92Tadashi G. Takaoka case LatinKeyboard.CODE_NEXT_LANGUAGE: 111988fc9d44186120f9edc5cf7ec0e2af85260fed04satok toggleLanguage(true); 11204189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1121d2c5fdda862f6dd2a1e020cf674c35fbbc63fc92Tadashi G. Takaoka case LatinKeyboard.CODE_PREV_LANGUAGE: 112288fc9d44186120f9edc5cf7ec0e2af85260fed04satok toggleLanguage(false); 11234189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1124571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_CAPSLOCK: 1125b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.toggleCapsLock(); 11264189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1127d2c5fdda862f6dd2a1e020cf674c35fbbc63fc92Tadashi G. Takaoka case Keyboard.CODE_SHORTCUT: 112820cdb37bd062ae6cb6d42ad6229a19733476cd55satok mSubtypeSwitcher.switchToShortcutIME(); 11294189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1130571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_TAB: 113145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka handleTab(); 11324733609947c0ec74e460bd714fffca0518ade93aJean Chalard // There are two cases for tab. Either we send a "next" event, that may change the 11334733609947c0ec74e460bd714fffca0518ade93aJean Chalard // focus but will never move the cursor. Or, we send a real tab keycode, which some 11344733609947c0ec74e460bd714fffca0518ade93aJean Chalard // applications may accept or ignore, and we don't know whether this will move the 11354733609947c0ec74e460bd714fffca0518ade93aJean Chalard // cursor or not. So actually, we don't really know. 11364733609947c0ec74e460bd714fffca0518ade93aJean Chalard // So to go with the safer option, we'd rather behave as if the user moved the 11374733609947c0ec74e460bd714fffca0518ade93aJean Chalard // cursor when they didn't than the opposite. We also expect that most applications 11384733609947c0ec74e460bd714fffca0518ade93aJean Chalard // will actually use tab only for focus movement. 11394733609947c0ec74e460bd714fffca0518ade93aJean Chalard // To sum it up: do not update mExpectingUpdateSelection here. 11404189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 11414189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka default: 114217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.isWordSeparator(primaryCode)) { 1143b5d17e52fcda39d540822e615bfb7ed5074e0034satok handleSeparator(primaryCode, x, y); 11444189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } else { 11458fbd55229243cb66c03d5ea1f79dfb39f596590dsatok handleCharacter(primaryCode, keyCodes, x, y); 11464189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } 11474733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 11484733609947c0ec74e460bd714fffca0518ade93aJean Chalard break; 1149923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1150b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.onKey(primaryCode); 1151dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani // Reset after any single keystroke 1152dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = null; 1153923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1154a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 11555a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 11568aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onTextInput(CharSequence text) { 1157b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.commitVoiceInput(); 1158923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1159923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 11609fbfd5877305ed19a20663630b498b6b3fdae942satok mRecorrection.abortRecorrection(false); 1161923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 116255b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka commitTyped(ic); 116341a519729505a877844f2c57a33509c302dddbceKen Wakasa maybeRemovePreviousPeriod(text); 1164923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(text, 1); 1165923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1166b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 11675f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka mKeyboardSwitcher.onKey(Keyboard.CODE_DUMMY); 11680730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard mJustAddedMagicSpace = false; 1169dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = text; 1170923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1171923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 11725a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 11738aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onCancelInput() { 117483e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka // User released a finger outside any key 11755f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka mKeyboardSwitcher.onCancelInput(); 117683e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka } 117783e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka 11784733609947c0ec74e460bd714fffca0518ade93aJean Chalard private void handleBackspace(boolean justReplacedDoubleSpace) { 1179b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok if (mVoiceProxy.logAndRevertVoiceInput()) return; 11804f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1181504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1182504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka if (ic == null) return; 1183979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.beginBatchEdit(); 1184979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1185b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleBackspace(); 11864f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 11879ae24750f462cbd94b362fe54a952c86cfb05e5fKen Wakasa final boolean deleteChar = !mHasUncommittedTypedChars; 1188f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (mHasUncommittedTypedChars) { 11899318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa final int length = mComposingStringBuilder.length(); 1190923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (length > 0) { 11919318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mComposingStringBuilder.delete(length - 1, length); 11929318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.deleteLast(); 11939318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa ic.setComposingText(mComposingStringBuilder, 1); 11949318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa if (mComposingStringBuilder.length() == 0) { 1195f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = false; 1196923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 119789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (1 == length) { 119889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // 1 == length means we are about to erase the last character of the word, 119989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // so we can show bigrams. 1200cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.postUpdateBigramPredictions(); 120189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 120289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // length > 1, so we still have letters to deduce a suggestion from. 120389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.postUpdateSuggestions(); 120489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 1205923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1206923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(1, 0); 1207923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1208923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1209d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateShiftKeyState(); 1210504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka 1211923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.backspace(); 1212662bb7c26cadd5026cb3d4e5d081aae163bd5a3aTadashi G. Takaoka if (TextEntryState.isUndoCommit()) { 1213923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project revertLastWord(deleteChar); 1214979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.endBatchEdit(); 1215923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1216504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka } 12174733609947c0ec74e460bd714fffca0518ade93aJean Chalard if (justReplacedDoubleSpace) { 12184733609947c0ec74e460bd714fffca0518ade93aJean Chalard if (revertDoubleSpace()) { 12194733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.endBatchEdit(); 12204733609947c0ec74e460bd714fffca0518ade93aJean Chalard return; 12214733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 12224733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 1223504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka 1224504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) { 1225dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani ic.deleteSurroundingText(mEnteredText.length(), 0); 1226923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else if (deleteChar) { 12276558253160e2039c87f424bd814f402ecd31de3bKen Wakasa if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) { 12286558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // Go back to the suggestion mode if the user canceled the 122955b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // "Touch again to save". 12306558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // NOTE: In gerenal, we don't revert the word when backspacing 12316558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // from a manual suggestion pick. We deliberately chose a 12326558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // different behavior only in the case of picking the first 12336558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // suggestion (typed word). It's intentional to have made this 12346558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // inconsistent with backspacing after selecting other suggestions. 12359ae24750f462cbd94b362fe54a952c86cfb05e5fKen Wakasa revertLastWord(true /* deleteChar */); 12366558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } else { 1237923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 12386558253160e2039c87f424bd814f402ecd31de3bKen Wakasa if (mDeleteCount > DELETE_ACCELERATE_AT) { 12396558253160e2039c87f424bd814f402ecd31de3bKen Wakasa sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 12406558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 1241923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1242923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1243979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.endBatchEdit(); 1244923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1245923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 124645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka private void handleTab() { 124745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final int imeOptions = getCurrentInputEditorInfo().imeOptions; 1248b2707856aba4fc9b063f26305f1fb603b19c1701satok if (!EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) 1249b2707856aba4fc9b063f26305f1fb603b19c1701satok && !EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions)) { 125045911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB); 125145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka return; 125245911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 125345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 125445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 125545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (ic == null) 125645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka return; 125745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 125845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka // True if keyboard is in either chording shift or manual temporary upper case mode. 125945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final boolean isManualTemporaryUpperCase = mKeyboardSwitcher.isManualTemporaryUpperCase(); 1260b2707856aba4fc9b063f26305f1fb603b19c1701satok if (EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) 126145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka && !isManualTemporaryUpperCase) { 1262b2707856aba4fc9b063f26305f1fb603b19c1701satok EditorInfoCompatUtils.performEditorActionNext(ic); 1263b2707856aba4fc9b063f26305f1fb603b19c1701satok } else if (EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions) 126445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka && isManualTemporaryUpperCase) { 1265b2707856aba4fc9b063f26305f1fb603b19c1701satok EditorInfoCompatUtils.performEditorActionPrevious(ic); 126645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 126745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 126845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 12698fbd55229243cb66c03d5ea1f79dfb39f596590dsatok private void handleCharacter(int primaryCode, int[] keyCodes, int x, int y) { 1270b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleCharacter(); 12714f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 127217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mJustAddedMagicSpace && mSettingsValues.isMagicSpaceStripper(primaryCode)) { 12730730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard removeTrailingSpace(); 12740730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard } 12750730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard 1276863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard if (mLastSelectionStart == mLastSelectionEnd) { 12779fbfd5877305ed19a20663630b498b6b3fdae942satok mRecorrection.abortRecorrection(false); 1278b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 12794f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1280e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka int code = primaryCode; 12819fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (isAlphabet(code) && isSuggestionsRequested() && !isCursorTouchingWord()) { 1282f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (!mHasUncommittedTypedChars) { 1283f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = true; 12849318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mComposingStringBuilder.setLength(0); 12859318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mRecorrection.saveRecorrectionSuggestion(mWordComposer, mBestWord); 12869318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.reset(); 12877e99a28dfcc14f5b19220442db972ca8d786b4feKen Wakasa clearSuggestions(); 1288923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1289923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 129035f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 1291f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (switcher.isShiftedOrShiftLocked()) { 1292eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT 1293eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani || keyCodes[0] > Character.MAX_CODE_POINT) { 1294eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani return; 1295eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani } 1296e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka code = keyCodes[0]; 1297e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (switcher.isAlphabetMode() && Character.isLowerCase(code)) { 129835f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka // In some locales, such as Turkish, Character.toUpperCase() may return a wrong 129935f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka // character because it doesn't take care of locale. 130035f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka final String upperCaseString = new String(new int[] {code}, 0, 1) 130135f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka .toUpperCase(mSubtypeSwitcher.getInputLocale()); 130235f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka if (upperCaseString.codePointCount(0, upperCaseString.length()) == 1) { 130335f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka code = upperCaseString.codePointAt(0); 130412a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka } else { 130512a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka // Some keys, such as [eszett], have upper case as multi-characters. 130635f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka onTextInput(upperCaseString); 130712a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka return; 130812a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka } 1309979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1310923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1311f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (mHasUncommittedTypedChars) { 13129318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa if (mComposingStringBuilder.length() == 0 && switcher.isAlphabetMode() 1313f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka && switcher.isShiftedOrShiftLocked()) { 13149318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.setFirstCharCapitalized(true); 1315923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 13169318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mComposingStringBuilder.append((char) code); 13179318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.add(code, keyCodes, x, y); 1318923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1319923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 13201c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani // If it's the first letter, make note of auto-caps state 13219318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa if (mWordComposer.size() == 1) { 13229318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.setAutoCapitalized(getCurrentAutoCapsState()); 13231c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 13249318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa ic.setComposingText(mComposingStringBuilder, 1); 1325923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1326d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1327923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1328e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka sendKeyChar((char)code); 1329923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 133017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mJustAddedMagicSpace && mSettingsValues.isMagicSpaceSwapper(primaryCode)) { 1331863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard swapSwapperAndSpace(); 1332863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } else { 1333863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard mJustAddedMagicSpace = false; 1334863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } 1335863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard 1336b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.updateShiftState(); 1337979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (LatinIME.PERF_DEBUG) measureCps(); 133817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard TextEntryState.typedCharacter((char) code, mSettingsValues.isWordSeparator(code), x, y); 1339923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1340923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1341b5d17e52fcda39d540822e615bfb7ed5074e0034satok private void handleSeparator(int primaryCode, int x, int y) { 1342b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleSeparator(); 13434f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 134455b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // Should dismiss the "Touch again to save" message when handling separator 13456558253160e2039c87f424bd814f402ecd31de3bKen Wakasa if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) { 1346cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.cancelUpdateBigramPredictions(); 1347d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 13486558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 13496558253160e2039c87f424bd814f402ecd31de3bKen Wakasa 1350923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project boolean pickedDefault = false; 1351923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Handle separator 13521b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1353923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1354923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 13559fbfd5877305ed19a20663630b498b6b3fdae942satok mRecorrection.abortRecorrection(false); 1356923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1357f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (mHasUncommittedTypedChars) { 1358923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In certain languages where single quote is a separator, it's better 1359a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker // not to auto correct, but accept the typed word. For instance, 1360923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // in Italian dov' should not be expanded to dove' because the elision 1361923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // requires the last vowel to be removed. 136217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard final boolean shouldAutoCorrect = 136317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard (mSettingsValues.mAutoCorrectEnabled || mSettingsValues.mQuickFixes) 136417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mInputTypeNoAutoCorrect && mHasDictionary; 136517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (shouldAutoCorrect && primaryCode != Keyboard.CODE_SINGLE_QUOTE) { 1366b5d17e52fcda39d540822e615bfb7ed5074e0034satok pickedDefault = pickDefaultSuggestion(primaryCode); 1367923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1368923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project commitTyped(ic); 1369923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1370923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 13714ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1372863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard if (mJustAddedMagicSpace) { 137317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.isMagicSpaceSwapper(primaryCode)) { 1374863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard sendKeyChar((char)primaryCode); 1375863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard swapSwapperAndSpace(); 1376863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } else { 137717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.isMagicSpaceStripper(primaryCode)) removeTrailingSpace(); 1378863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard sendKeyChar((char)primaryCode); 1379863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard mJustAddedMagicSpace = false; 1380863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } 13810730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard } else { 13820730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard sendKeyChar((char)primaryCode); 13834ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 13844ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1385863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard if (isSuggestionsRequested() && primaryCode == Keyboard.CODE_SPACE) { 1386863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard maybeDoubleSpace(); 1387863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } 1388863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard 1389b5d17e52fcda39d540822e615bfb7ed5074e0034satok TextEntryState.typedCharacter((char) primaryCode, true, x, y); 139089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 1391979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (pickedDefault) { 13929318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa CharSequence typedWord = mWordComposer.getTypedWord(); 139355b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka TextEntryState.backToAcceptedDefault(typedWord); 139455b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka if (!TextUtils.isEmpty(typedWord) && !typedWord.equals(mBestWord)) { 1395b2707856aba4fc9b063f26305f1fb603b19c1701satok InputConnectionCompatUtils.commitCorrection( 139689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard ic, mLastSelectionEnd - typedWord.length(), typedWord, mBestWord); 139755b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka if (mCandidateView != null) 139855b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka mCandidateView.onAutoCorrectionInverted(mBestWord); 139955b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka } 140089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 140189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (Keyboard.CODE_SPACE == primaryCode) { 140289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (!isCursorTouchingWord()) { 140389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.cancelUpdateSuggestions(); 140489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.cancelUpdateOldSuggestions(); 1405cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.postUpdateBigramPredictions(); 140689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 140789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 140889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // Set punctuation right away. onUpdateSelection will fire but tests whether it is 140989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // already displayed or not, so it's okay. 141055b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka setPunctuationSuggestions(); 1411923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1412b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 1413923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1414923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1415923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1416923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1417466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1418923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleClose() { 1419923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project commitTyped(getCurrentInputConnection()); 1420b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleClose(); 1421923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project requestHideSelf(0); 1422c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 14231679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka if (inputView != null) 14241679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka inputView.closing(); 1425923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1426923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 14277a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isSuggestionsRequested() { 1428c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka return mIsSettingsSuggestionStripOn 1429c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka && (mCorrectionMode > 0 || isShowingSuggestionsStrip()); 1430923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1431a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 14327a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isShowingPunctuationList() { 143317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard return mSettingsValues.mSuggestPuncList == mCandidateView.getSuggestions(); 14347599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 14357599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 14367a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isShowingSuggestionsStrip() { 14377599cfea4a2d56f4779452ec8e8742f7b9629cc0satok return (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_VALUE) 14387599cfea4a2d56f4779452ec8e8742f7b9629cc0satok || (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE 14397599cfea4a2d56f4779452ec8e8742f7b9629cc0satok && mOrientation == Configuration.ORIENTATION_PORTRAIT); 14407599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 14417599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 14429fbfd5877305ed19a20663630b498b6b3fdae942satok public boolean isCandidateStripVisible() { 1443b5e00d5841b946de8970875231456228ae0eb6b1Ken Wakasa if (mCandidateView == null) 1444b5e00d5841b946de8970875231456228ae0eb6b1Ken Wakasa return false; 1445952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa if (mCandidateView.isShowingAddToDictionaryHint() || TextEntryState.isRecorrecting()) 14469fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 14479fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (!isShowingSuggestionsStrip()) 14489fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return false; 14499fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (mApplicationSpecifiedCompletionOn) 14509fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 14519fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return isSuggestionsRequested(); 1452923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1453923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1454409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void switchToKeyboardView() { 1455060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (DEBUG) { 1456060efb6d82af1f896d90cb845c8ae07c726f85e1satok Log.d(TAG, "Switch to keyboard view."); 1457060efb6d82af1f896d90cb845c8ae07c726f85e1satok } 1458c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka View v = mKeyboardSwitcher.getKeyboardView(); 1459060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (v != null) { 1460060efb6d82af1f896d90cb845c8ae07c726f85e1satok // Confirms that the keyboard view doesn't have parent view. 1461060efb6d82af1f896d90cb845c8ae07c726f85e1satok ViewParent p = v.getParent(); 1462060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (p != null && p instanceof ViewGroup) { 1463060efb6d82af1f896d90cb845c8ae07c726f85e1satok ((ViewGroup) p).removeView(v); 14645a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka } 1465060efb6d82af1f896d90cb845c8ae07c726f85e1satok setInputView(v); 1466060efb6d82af1f896d90cb845c8ae07c726f85e1satok } 1467c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShown(isCandidateStripVisible()); 1468060efb6d82af1f896d90cb845c8ae07c726f85e1satok updateInputViewShown(); 1469060efb6d82af1f896d90cb845c8ae07c726f85e1satok mHandler.postUpdateSuggestions(); 1470466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1471466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1472409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void clearSuggestions() { 14737e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(SuggestedWords.EMPTY); 1474466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1475466741d8a78965b8509bf527344f289e50873092Mike LeBeau 14767e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka public void setSuggestions(SuggestedWords words) { 1477466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mCandidateView != null) { 14787e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka mCandidateView.setSuggestions(words); 14795e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka mKeyboardSwitcher.onAutoCorrectionStateChanged( 14805e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka words.hasWordAboveAutoCorrectionScoreThreshold()); 1481466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1482466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1483466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1484409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void updateSuggestions() { 1485923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Check if we have a suggestion engine attached. 14869fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if ((mSuggest == null || !isSuggestionsRequested()) 1487b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok && !mVoiceProxy.isVoiceInputHighlighted()) { 1488923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1489923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1490466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1491f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (!mHasUncommittedTypedChars) { 1492ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setPunctuationSuggestions(); 1493923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1494923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1495979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 14969318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa final WordComposer wordComposer = mWordComposer; 14979f67e12a0e3f77985fb8bafe0db4c00e32317b9asatok // TODO: May need a better way of retrieving previous word 1498e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(), 149917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mWordSeparators); 15007e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder( 15019318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mKeyboardSwitcher.getKeyboardView(), wordComposer, prevWord); 1502923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 15036f99d12b0752ecdbceda7e5fddead214f939f533Tadashi G. Takaoka boolean correctionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasAutoCorrection(); 15049318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa final CharSequence typedWord = wordComposer.getTypedWord(); 1505bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // Here, we want to promote a whitelisted word if exists. 1506bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok final boolean typedWordValid = AutoCorrection.isValidWordForAutoCorrection( 1507bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok mSuggest.getUnigramDictionaries(), typedWord, preferCapitalization()); 1508979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mCorrectionMode == Suggest.CORRECTION_FULL 1509979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) { 1510923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project correctionAvailable |= typedWordValid; 1511923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 15124a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani // Don't auto-correct words with multiple capital letter 15139318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa correctionAvailable &= !wordComposer.isMostlyCaps(); 1514952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa correctionAvailable &= !TextEntryState.isRecorrecting(); 1515979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1516a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // Basically, we update the suggestion strip only when suggestion count > 1. However, 1517a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // there is an exception: We update the suggestion strip whenever typed word's length 1518f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // is 1 or typed word is found in dictionary, regardless of suggestion count. Actually, 1519f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // in most cases, suggestion count is 1 when typed word's length is 1, but we do always 1520f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // need to clear the previous state when the user starts typing a word (i.e. typed word's 1521f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // length == 1). 1522fe1a6d961cf039357f061482461e4d2e951ad346satok if (typedWord != null) { 1523fe1a6d961cf039357f061482461e4d2e951ad346satok if (builder.size() > 1 || typedWord.length() == 1 || typedWordValid 1524fe1a6d961cf039357f061482461e4d2e951ad346satok || mCandidateView.isShowingAddToDictionaryHint()) { 1525fe1a6d961cf039357f061482461e4d2e951ad346satok builder.setTypedWordValid(typedWordValid).setHasMinimalSuggestion( 1526fe1a6d961cf039357f061482461e4d2e951ad346satok correctionAvailable); 1527fe1a6d961cf039357f061482461e4d2e951ad346satok } else { 1528fe1a6d961cf039357f061482461e4d2e951ad346satok final SuggestedWords previousSuggestions = mCandidateView.getSuggestions(); 1529fe1a6d961cf039357f061482461e4d2e951ad346satok if (previousSuggestions == mSettingsValues.mSuggestPuncList) 1530fe1a6d961cf039357f061482461e4d2e951ad346satok return; 1531fe1a6d961cf039357f061482461e4d2e951ad346satok builder.addTypedWordAndPreviousSuggestions(typedWord, previousSuggestions); 1532fe1a6d961cf039357f061482461e4d2e951ad346satok } 15339fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka } 15347e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka showSuggestions(builder.build(), typedWord); 1535979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 15364a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani 15379fbfd5877305ed19a20663630b498b6b3fdae942satok public void showSuggestions(SuggestedWords suggestedWords, CharSequence typedWord) { 15387e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(suggestedWords); 15397e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka if (suggestedWords.size() > 0) { 154014e427d5bb13d59d23fb317ef90a6c44ae279425satok if (Utils.shouldBlockedBySafetyNetForAutoCorrection(suggestedWords, mSuggest)) { 154182411d47ba7e8133ed2390c6920945e139a738cesatok mBestWord = typedWord; 154282411d47ba7e8133ed2390c6920945e139a738cesatok } else if (suggestedWords.hasAutoCorrectionWord()) { 15437e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka mBestWord = suggestedWords.getWord(1); 1544923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1545923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = typedWord; 1546923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1547923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1548923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = null; 1549923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1550c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShown(isCandidateStripVisible()); 1551923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1552923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1553b5d17e52fcda39d540822e615bfb7ed5074e0034satok private boolean pickDefaultSuggestion(int separatorCode) { 1554923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Complete any pending candidate query first 1555d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka if (mHandler.hasPendingUpdateSuggestions()) { 1556d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 1557923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateSuggestions(); 1558923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 15596780b898ec2647a21319601a03ae1c393c0e1b29Amith Yamasani if (mBestWord != null && mBestWord.length() > 0) { 15609318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa TextEntryState.acceptedDefault(mWordComposer.getTypedWord(), mBestWord, separatorCode); 15614733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 15621fef530ec7626fa16777f52b48191e61db8f46d4satok commitBestWord(mBestWord); 15639468335a06d2b0e3ef15f4f57f8c1b0857b34ebeAmith Yamasani // Add the word to the auto dictionary if it's not a known word 1564bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok addToAutoAndUserBigramDictionaries(mBestWord, AutoDictionary.FREQUENCY_FOR_TYPED); 1565979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return true; 1566923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1567979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return false; 1568923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1569923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1570c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka @Override 1571923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void pickSuggestionManually(int index, CharSequence suggestion) { 15727e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords suggestions = mCandidateView.getSuggestions(); 157317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mVoiceProxy.flushAndLogAllTextModificationCounters(index, suggestion, 157417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mWordSeparators); 15754f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1576952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa final boolean recorrecting = TextEntryState.isRecorrecting(); 15779a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa InputConnection ic = getCurrentInputConnection(); 15789a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 15799a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.beginBatchEdit(); 15809a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 15811b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (mApplicationSpecifiedCompletionOn && mApplicationSpecifiedCompletions != null 15821b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka && index >= 0 && index < mApplicationSpecifiedCompletions.length) { 15831b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka CompletionInfo ci = mApplicationSpecifiedCompletions[index]; 1584923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1585923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitCompletion(ci); 1586923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1587923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCommittedLength = suggestion.length(); 1588923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mCandidateView != null) { 1589923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCandidateView.clear(); 1590923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1591b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 15929a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 15939a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 15949a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1595923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1596923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 15976a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 15986a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani // If this is a punctuation, apply it through the normal key press 159917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (suggestion.length() == 1 && (mSettingsValues.isWordSeparator(suggestion.charAt(0)) 160017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard || mSettingsValues.isSuggestedPunctuation(suggestion.charAt(0)))) { 1601979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Word separators are suggested before the user inputs something. 1602979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // So, LatinImeLogger logs "" as a user's input. 1603979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.logOnManualSuggestion( 16047e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka "", suggestion.toString(), index, suggestions.mWords); 1605863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // Find out whether the previous character is a space. If it is, as a special case 1606863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // for punctuation entered through the suggestion strip, it should be considered 1607863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // a magic space even if it was a normal space. This is meant to help in case the user 1608863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // pressed space on purpose of displaying the suggestion strip punctuation. 160955b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa final char primaryCode = suggestion.charAt(0); 1610eaa10f44a4a0108a90803b1b28238842d3fb5addsatok final CharSequence beforeText = ic != null ? ic.getTextBeforeCursor(1, 0) : ""; 16111f050f634820a1d980e8a91f3a962bcd1fc242e3satok final int toLeft = (ic == null || TextUtils.isEmpty(beforeText)) 16121f050f634820a1d980e8a91f3a962bcd1fc242e3satok ? 0 : beforeText.charAt(0); 16134f3b59711f6985d39e0cc908d2431ae6715d9b26Jean Chalard final boolean oldMagicSpace = mJustAddedMagicSpace; 1614863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard if (Keyboard.CODE_SPACE == toLeft) mJustAddedMagicSpace = true; 1615a96574fdd5e38a237a35b21a2b7c20a29138c648Tadashi G. Takaoka onCodeInput(primaryCode, new int[] { primaryCode }, 1616a96574fdd5e38a237a35b21a2b7c20a29138c648Tadashi G. Takaoka KeyboardActionListener.NOT_A_TOUCH_COORDINATE, 1617a96574fdd5e38a237a35b21a2b7c20a29138c648Tadashi G. Takaoka KeyboardActionListener.NOT_A_TOUCH_COORDINATE); 16184f3b59711f6985d39e0cc908d2431ae6715d9b26Jean Chalard mJustAddedMagicSpace = oldMagicSpace; 16199a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 16209a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 16219a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 16226a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani return; 16236a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 1624f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (!mHasUncommittedTypedChars) { 162589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // If we are not composing a word, then it was a suggestion inferred from 162689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // context - no user input. We should reset the word composer. 16279318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.reset(); 162889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 16294733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 16301fef530ec7626fa16777f52b48191e61db8f46d4satok commitBestWord(suggestion); 16319468335a06d2b0e3ef15f4f57f8c1b0857b34ebeAmith Yamasani // Add the word to the auto dictionary if it's not a known word 16320c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani if (index == 0) { 1633bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok addToAutoAndUserBigramDictionaries(suggestion, AutoDictionary.FREQUENCY_FOR_PICKED); 1634979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } else { 1635bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok addToOnlyBigramDictionary(suggestion, 1); 16360c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani } 16379318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa LatinImeLogger.logOnManualSuggestion(mComposingStringBuilder.toString(), 16389318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa suggestion.toString(), index, suggestions.mWords); 16399318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa TextEntryState.acceptedSuggestion(mComposingStringBuilder.toString(), suggestion); 1640923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Follow it with a space 16410730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard if (mShouldInsertMagicSpace && !recorrecting) { 16420730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard sendMagicSpace(); 1643923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1644979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 16457f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // We should show the hint if the user pressed the first entry AND either: 16467f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // - There is no dictionary (we know that because we tried to load it => null != mSuggest 16477f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // AND mHasDictionary is false) 16487f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // - There is a dictionary and the word is not in it 16497f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // Please note that if mSuggest is null, it means that everything is off: suggestion 16507f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // and correction, so we shouldn't try to show the hint 16517f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // We used to look at mCorrectionMode here, but showing the hint should have nothing 16527f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // to do with the autocorrection setting. 1653bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok final boolean showingAddToDictionaryHint = index == 0 && mSuggest != null 1654bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // If there is no dictionary the hint should be shown. 1655bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok && (!mHasDictionary 1656bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // If "suggestion" is not in the dictionary, the hint should be shown. 1657bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok || !AutoCorrection.isValidWord( 1658bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok mSuggest.getUnigramDictionaries(), suggestion, true)); 1659b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani 1660952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa if (!recorrecting) { 1661b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // Fool the state watcher so that a subsequent backspace will not do a revert, unless 1662b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // we just did a correction, in which case we need to stay in 1663b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // TextEntryState.State.PICKED_SUGGESTION state. 1664b5d17e52fcda39d540822e615bfb7ed5074e0034satok TextEntryState.typedCharacter((char) Keyboard.CODE_SPACE, true, 1665b5d17e52fcda39d540822e615bfb7ed5074e0034satok WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); 1666777118a40a363ccab69a00016d3156066513cb78Jean Chalard } 1667777118a40a363ccab69a00016d3156066513cb78Jean Chalard if (!showingAddToDictionaryHint) { 1668364da8c618303a7764595d2c15ee034a7671365dKen Wakasa // If we're not showing the "Touch again to save", then show corrections again. 1669979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // In case the cursor position doesn't change, make sure we show the suggestions again. 167041ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard updateBigramPredictions(); 167141ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // Updating the predictions right away may be slow and feel unresponsive on slower 167241ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // terminals. On the other hand if we just postUpdateBigramPredictions() it will 167341ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // take a noticeable delay to update them which may feel uneasy. 1674979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1675b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani if (showingAddToDictionaryHint) { 167666a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani mCandidateView.showAddToDictionaryHint(suggestion); 167766a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani } 16789a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 16799a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 16809a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1681923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1682a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1683979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 1684979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * Commits the chosen word to the text field and saves it for later 1685979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * retrieval. 1686979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 16871fef530ec7626fa16777f52b48191e61db8f46d4satok private void commitBestWord(CharSequence bestWord) { 1688b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 1689b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (!switcher.isKeyboardAvailable()) 16901679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka return; 1691923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1692923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 16931fef530ec7626fa16777f52b48191e61db8f46d4satok mVoiceProxy.rememberReplacedWord(bestWord, mSettingsValues.mWordSeparators); 16941fef530ec7626fa16777f52b48191e61db8f46d4satok SuggestedWords suggestedWords = mCandidateView.getSuggestions(); 16951fef530ec7626fa16777f52b48191e61db8f46d4satok ic.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan( 16961fef530ec7626fa16777f52b48191e61db8f46d4satok this, bestWord, suggestedWords), 1); 1697923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 16989318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mRecorrection.saveRecorrectionSuggestion(mWordComposer, bestWord); 1699f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = false; 17001fef530ec7626fa16777f52b48191e61db8f46d4satok mCommittedLength = bestWord.length(); 1701923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1702923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 170389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard private static final WordComposer sEmptyWordComposer = new WordComposer(); 170441ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard public void updateBigramPredictions() { 170589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (mSuggest == null || !isSuggestionsRequested()) 170689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard return; 170789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 170817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (!mSettingsValues.mBigramPredictionEnabled) { 1709cb3320179d39a7983874697a0aa428b127675c9dJean Chalard setPunctuationSuggestions(); 1710cb3320179d39a7983874697a0aa428b127675c9dJean Chalard return; 1711cb3320179d39a7983874697a0aa428b127675c9dJean Chalard } 1712cb3320179d39a7983874697a0aa428b127675c9dJean Chalard 171389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard final CharSequence prevWord = EditingUtils.getThisWord(getCurrentInputConnection(), 171417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mWordSeparators); 171589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder( 1716c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka mKeyboardSwitcher.getKeyboardView(), sEmptyWordComposer, prevWord); 171789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 171889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (builder.size() > 0) { 171989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // Explicitly supply an empty typed word (the no-second-arg version of 172089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // showSuggestions will retrieve the word near the cursor, we don't want that here) 172189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard showSuggestions(builder.build(), ""); 172289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 172389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (!isShowingPunctuationList()) setPunctuationSuggestions(); 172489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 172589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 172689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 17277a8dac55278cedd838be325f56b4c52d973c61f5satok public void setPunctuationSuggestions() { 172817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard setSuggestions(mSettingsValues.mSuggestPuncList); 1729c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShown(isCandidateStripVisible()); 17306a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 17316a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 1732bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok private void addToAutoAndUserBigramDictionaries(CharSequence suggestion, int frequencyDelta) { 1733979f8690967ff5409fe18f5085858ccdb8e0ccf1satok checkAddToDictionary(suggestion, frequencyDelta, false); 1734979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1735979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1736bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok private void addToOnlyBigramDictionary(CharSequence suggestion, int frequencyDelta) { 1737979f8690967ff5409fe18f5085858ccdb8e0ccf1satok checkAddToDictionary(suggestion, frequencyDelta, true); 1738979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1739979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1740979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 1741979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * Adds to the UserBigramDictionary and/or AutoDictionary 1742bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok * @param selectedANotTypedWord true if it should be added to bigram dictionary if possible 1743979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 1744979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void checkAddToDictionary(CharSequence suggestion, int frequencyDelta, 1745bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok boolean selectedANotTypedWord) { 1746979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (suggestion == null || suggestion.length() < 1) return; 1747bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok 17480c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // Only auto-add to dictionary if auto-correct is ON. Otherwise we'll be 17490c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // adding words in situations where the user or application really didn't 17500c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // want corrections enabled or learned. 1751979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (!(mCorrectionMode == Suggest.CORRECTION_FULL 1752979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM)) { 1753979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return; 1754979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1755bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok 1756bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok final boolean selectedATypedWordAndItsInAutoDic = 1757bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok !selectedANotTypedWord && mAutoDictionary.isValidWord(suggestion); 1758bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok final boolean isValidWord = AutoCorrection.isValidWord( 1759bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok mSuggest.getUnigramDictionaries(), suggestion, true); 1760bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok final boolean needsToAddToAutoDictionary = selectedATypedWordAndItsInAutoDic 1761bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok || !isValidWord; 1762bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok if (needsToAddToAutoDictionary) { 1763e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mAutoDictionary.addWord(suggestion.toString(), frequencyDelta); 1764e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 1765979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1766e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mUserBigramDictionary != null) { 1767863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // We don't want to register as bigrams words separated by a separator. 1768863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // For example "I will, and you too" : we don't want the pair ("will" "and") to be 1769863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // a bigram. 1770e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(), 177117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mWordSeparators); 1772e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (!TextUtils.isEmpty(prevWord)) { 1773e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mUserBigramDictionary.addBigrams(prevWord.toString(), suggestion.toString()); 1774979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 177532e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 177632e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 177732e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani 17787a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isCursorTouchingWord() { 1779923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project InputConnection ic = getCurrentInputConnection(); 1780923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return false; 1781923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence toLeft = ic.getTextBeforeCursor(1, 0); 1782923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence toRight = ic.getTextAfterCursor(1, 0); 1783923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (!TextUtils.isEmpty(toLeft) 178417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isWordSeparator(toLeft.charAt(0)) 178517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isSuggestedPunctuation(toLeft.charAt(0))) { 1786923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1787923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1788a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker if (!TextUtils.isEmpty(toRight) 178917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isWordSeparator(toRight.charAt(0)) 179017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isSuggestedPunctuation(toRight.charAt(0))) { 1791923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1792923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1793923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return false; 1794923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1795a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1796dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani private boolean sameAsTextBeforeCursor(InputConnection ic, CharSequence text) { 1797dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani CharSequence beforeText = ic.getTextBeforeCursor(text.length(), 0); 1798dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani return TextUtils.equals(text, beforeText); 1799dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani } 1800dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 18019ae24750f462cbd94b362fe54a952c86cfb05e5fKen Wakasa private void revertLastWord(boolean deleteChar) { 18029318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa final int length = mComposingStringBuilder.length(); 1803f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (!mHasUncommittedTypedChars && length > 0) { 1804923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final InputConnection ic = getCurrentInputConnection(); 1805504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka final CharSequence punctuation = ic.getTextBeforeCursor(1, 0); 1806923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (deleteChar) ic.deleteSurroundingText(1, 0); 1807923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int toDelete = mCommittedLength; 1808504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka final CharSequence toTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0); 180917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (!TextUtils.isEmpty(toTheLeft) 181017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && mSettingsValues.isWordSeparator(toTheLeft.charAt(0))) { 1811923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project toDelete--; 1812923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1813923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(toDelete, 0); 181430be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka // Re-insert punctuation only when the deleted character was word separator and the 181530be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka // composing text wasn't equal to the auto-corrected text. 181630be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka if (deleteChar 181717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !TextUtils.isEmpty(punctuation) 181817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && mSettingsValues.isWordSeparator(punctuation.charAt(0)) 18199318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa && !TextUtils.equals(mComposingStringBuilder, toTheLeft)) { 18209318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa ic.commitText(mComposingStringBuilder, 1); 18219318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa TextEntryState.acceptedTyped(mComposingStringBuilder); 182230be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka ic.commitText(punctuation, 1); 1823b5d17e52fcda39d540822e615bfb7ed5074e0034satok TextEntryState.typedCharacter(punctuation.charAt(0), true, 1824b5d17e52fcda39d540822e615bfb7ed5074e0034satok WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); 182530be3f9845c7b1d5ae14036f816e0f7c55939f37Tadashi G. Takaoka // Clear composing text 18269318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mComposingStringBuilder.setLength(0); 1827504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka } else { 1828f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = true; 18299318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa ic.setComposingText(mComposingStringBuilder, 1); 1830504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka TextEntryState.backspace(); 1831504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka } 1832cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.cancelUpdateBigramPredictions(); 1833d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1834923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1835923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 1836923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1837923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1838923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 18399ae24750f462cbd94b362fe54a952c86cfb05e5fKen Wakasa private boolean revertDoubleSpace() { 18404733609947c0ec74e460bd714fffca0518ade93aJean Chalard mHandler.cancelDoubleSpacesTimer(); 18414733609947c0ec74e460bd714fffca0518ade93aJean Chalard final InputConnection ic = getCurrentInputConnection(); 18424733609947c0ec74e460bd714fffca0518ade93aJean Chalard // Here we test whether we indeed have a period and a space before us. This should not 18434733609947c0ec74e460bd714fffca0518ade93aJean Chalard // be needed, but it's there just in case something went wrong. 18444733609947c0ec74e460bd714fffca0518ade93aJean Chalard final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0); 18454733609947c0ec74e460bd714fffca0518ade93aJean Chalard if (!". ".equals(textBeforeCursor)) 18464733609947c0ec74e460bd714fffca0518ade93aJean Chalard return false; 18474733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.beginBatchEdit(); 18484733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.deleteSurroundingText(2, 0); 18494733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.commitText(" ", 1); 18504733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.endBatchEdit(); 18514733609947c0ec74e460bd714fffca0518ade93aJean Chalard return true; 18524733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 18534733609947c0ec74e460bd714fffca0518ade93aJean Chalard 1854923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean isWordSeparator(int code) { 185517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard return mSettingsValues.isWordSeparator(code); 1856923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1857923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 18580730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard private void sendMagicSpace() { 1859571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka sendKeyChar((char)Keyboard.CODE_SPACE); 18600730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard mJustAddedMagicSpace = true; 1861b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 1862923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1863923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1864923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean preferCapitalization() { 18659318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa return mWordComposer.isFirstCharCapitalized(); 1866923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1867923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 186888fc9d44186120f9edc5cf7ec0e2af85260fed04satok // Notify that language or mode have been changed and toggleLanguage will update KeyboardID 1869c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // according to new language or mode. 1870c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka public void onRefreshKeyboard() { 187155303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka if (!CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) { 187255303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka // Before Honeycomb, Voice IME is in LatinIME and it changes the current input view, 187355303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka // so that we need to re-create the keyboard input view here. 187455303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka setInputView(mKeyboardSwitcher.onCreateInputView()); 187555303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka } 18764ab730dbd34fad323063f2ffd31ce33de746668dsatok // Reload keyboard because the current language has been changed. 1877cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), 1878b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mSubtypeSwitcher.isShortcutImeEnabled() && mVoiceProxy.isVoiceButtonEnabled(), 1879b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.isVoiceButtonOnPrimary()); 18800ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 188117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard loadSettings(); 18824b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 188336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 188436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 188588fc9d44186120f9edc5cf7ec0e2af85260fed04satok // "reset" and "next" are used only for USE_SPACEBAR_LANGUAGE_SWITCHER. 188688fc9d44186120f9edc5cf7ec0e2af85260fed04satok private void toggleLanguage(boolean next) { 188788fc9d44186120f9edc5cf7ec0e2af85260fed04satok if (mSubtypeSwitcher.useSpacebarLanguageSwitcher()) { 188888fc9d44186120f9edc5cf7ec0e2af85260fed04satok mSubtypeSwitcher.toggleLanguage(next); 188988fc9d44186120f9edc5cf7ec0e2af85260fed04satok } 189017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard // The following is necessary because on API levels < 10, we don't get notified when 189117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard // subtype changes. 18925a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka if (!CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) 18935a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka onRefreshKeyboard(); 1894923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1895923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 18965a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 1897e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka public void onPress(int primaryCode, boolean withSliding) { 1898cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka if (mKeyboardSwitcher.isVibrateAndSoundFeedbackRequired()) { 1899cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka vibrate(); 1900cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka playKeyClick(primaryCode); 1901cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka } 19021679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 19031679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); 1904571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { 1905e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka switcher.onPressShift(withSliding); 1906e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { 19076c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka switcher.onPressSymbol(); 190840a05f62edc6cdedb4365a722b48a72826ef2bf6Tadashi G. Takaoka } else { 19096c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka switcher.onOtherKeyPressed(); 1910681b102a492b7d5301c1ca87985b4c391eb5eb14Tadashi G. Takaoka } 1911923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1912923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 19135a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 1914e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka public void onRelease(int primaryCode, boolean withSliding) { 19151679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 19163f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani // Reset any drag flags in the keyboard 19171679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); 1918571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { 1919e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka switcher.onReleaseShift(withSliding); 1920e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { 19216c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka switcher.onReleaseSymbol(); 192240a05f62edc6cdedb4365a722b48a72826ef2bf6Tadashi G. Takaoka } 1923923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1924a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1925a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1926123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka // receive ringer mode change and network state change. 1927923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private BroadcastReceiver mReceiver = new BroadcastReceiver() { 1928923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 1929923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onReceive(Context context, Intent intent) { 1930123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final String action = intent.getAction(); 1931123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { 1932123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka updateRingerMode(); 1933123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 1934123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka mSubtypeSwitcher.onNetworkStateChanged(intent); 1935123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka } 1936923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1937923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project }; 1938923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1939923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // update flags for silent mode 1940923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void updateRingerMode() { 1941923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager == null) { 1942923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 1943923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1944923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager != null) { 194517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSilentModeOn = (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL); 1946923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1947923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1948923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1949923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void playKeyClick(int primaryCode) { 1950923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // if mAudioManager is null, we don't have the ringer state yet 1951923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // mAudioManager will be set by updateRingerMode 1952923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager == null) { 1953c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka if (mKeyboardSwitcher.getKeyboardView() != null) { 1954923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateRingerMode(); 1955923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1956923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 195717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (isSoundOn()) { 1958923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // FIXME: Volume and enable should come from UI settings 1959923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // FIXME: These should be triggered after auto-repeat logic 1960923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int sound = AudioManager.FX_KEYPRESS_STANDARD; 1961923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 1962571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_DELETE: 1963923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sound = AudioManager.FX_KEYPRESS_DELETE; 1964923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 1965571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_ENTER: 1966923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sound = AudioManager.FX_KEYPRESS_RETURN; 1967923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 1968571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_SPACE: 1969923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sound = AudioManager.FX_KEYPRESS_SPACEBAR; 1970923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 1971923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1972923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAudioManager.playSoundEffect(sound, FX_VOLUME); 1973923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1974923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1975923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1976409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void vibrate() { 197717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (!mSettingsValues.mVibrateOn) { 1978923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1979923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1980c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 19811679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka if (inputView != null) { 19821679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka inputView.performHapticFeedback( 1983979f8690967ff5409fe18f5085858ccdb8e0ccf1satok HapticFeedbackConstants.KEYBOARD_TAP, 198466a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); 1985923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1986923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1987923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 198871c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka public WordComposer getCurrentWord() { 19899318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa return mWordComposer; 19906516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani } 19916516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani 199217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard boolean isSoundOn() { 199317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard return mSettingsValues.mSoundOn && !mSilentModeOn; 1994979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1995979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1996e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private void updateCorrectionMode() { 19979f67e12a0e3f77985fb8bafe0db4c00e32317b9asatok // TODO: cleanup messy flags 1998e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mHasDictionary = mSuggest != null ? mSuggest.hasMainDictionary() : false; 199917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard final boolean shouldAutoCorrect = (mSettingsValues.mAutoCorrectEnabled 200017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard || mSettingsValues.mQuickFixes) && !mInputTypeNoAutoCorrect && mHasDictionary; 200117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mCorrectionMode = (shouldAutoCorrect && mSettingsValues.mAutoCorrectEnabled) 2002e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani ? Suggest.CORRECTION_FULL 200317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard : (shouldAutoCorrect ? Suggest.CORRECTION_BASIC : Suggest.CORRECTION_NONE); 200417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mCorrectionMode = (mSettingsValues.mBigramSuggestionEnabled && shouldAutoCorrect 200517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && mSettingsValues.mAutoCorrectEnabled) 2006979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ? Suggest.CORRECTION_FULL_BIGRAM : mCorrectionMode; 2007e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani if (mSuggest != null) { 2008e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mSuggest.setCorrectionMode(mCorrectionMode); 2009e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani } 2010e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani } 2011e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani 20120ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private void updateAutoTextEnabled() { 201332e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani if (mSuggest == null) return; 201417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSuggest.setQuickFixesEnabled(mSettingsValues.mQuickFixes 20154ab730dbd34fad323063f2ffd31ce33de746668dsatok && SubtypeSwitcher.getInstance().isSystemLanguageSameAsInputLanguage()); 201632e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 201732e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani 201817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard private void updateSuggestionVisibility(final SharedPreferences prefs, final Resources res) { 20197599cfea4a2d56f4779452ec8e8742f7b9629cc0satok final String suggestionVisiblityStr = prefs.getString( 20209502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka Settings.PREF_SHOW_SUGGESTIONS_SETTING, 2021458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa res.getString(R.string.prefs_suggestion_visibility_default_value)); 20227599cfea4a2d56f4779452ec8e8742f7b9629cc0satok for (int visibility : SUGGESTION_VISIBILITY_VALUE_ARRAY) { 2023458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa if (suggestionVisiblityStr.equals(res.getString(visibility))) { 20247599cfea4a2d56f4779452ec8e8742f7b9629cc0satok mSuggestionVisibility = visibility; 20257599cfea4a2d56f4779452ec8e8742f7b9629cc0satok break; 20267599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 20277599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 20287599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 20297599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 2030466741d8a78965b8509bf527344f289e50873092Mike LeBeau protected void launchSettings() { 20314a0c343dbdcf04245e6d5a94e68a0461efb78e83satok launchSettings(Settings.class); 2032466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 2033466741d8a78965b8509bf527344f289e50873092Mike LeBeau 2034bf96661d33d0126adb60a48880ceba1ff055d4a4satok public void launchDebugSettings() { 20359502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka launchSettings(DebugSettings.class); 2036bf96661d33d0126adb60a48880ceba1ff055d4a4satok } 2037bf96661d33d0126adb60a48880ceba1ff055d4a4satok 2038507495efd57074994fdc2fda78db9d5345f4a3a8Tadashi G. Takaoka protected void launchSettings(Class<? extends PreferenceActivity> settingsClass) { 2039923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project handleClose(); 2040923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Intent intent = new Intent(); 2041466741d8a78965b8509bf527344f289e50873092Mike LeBeau intent.setClass(LatinIME.this, settingsClass); 2042923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2043923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project startActivity(intent); 2044923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2045923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 20462fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private void showSubtypeSelectorAndSettings() { 204785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence title = getString(R.string.english_ime_input_options); 204885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence[] items = new CharSequence[] { 204985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka // TODO: Should use new string "Select active input modes". 205085996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.language_selection_title), 205185996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.english_ime_settings), 205285996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 205385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 20542fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka @Override 20552fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka public void onClick(DialogInterface di, int position) { 20562fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka di.dismiss(); 20572fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka switch (position) { 205885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 0: 20592cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok Intent intent = CompatUtils.getInputLanguageSelectionIntent( 20602cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok mInputMethodId, Intent.FLAG_ACTIVITY_NEW_TASK 20612fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 20622fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_CLEAR_TOP); 20632fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka startActivity(intent); 20642fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 2065aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa case 1: 2066aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa launchSettings(); 2067aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa break; 20682fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 20692fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 207085996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 207185996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka showOptionsMenuInternal(title, items, listener); 20722fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 2073923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 20742fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private void showOptionsMenu() { 207585996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence title = getString(R.string.english_ime_input_options); 207685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence[] items = new CharSequence[] { 207785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.selectInputMethod), 207885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.english_ime_settings), 207985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 208085996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 20815a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 2082923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onClick(DialogInterface di, int position) { 2083923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project di.dismiss(); 2084923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (position) { 208585996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 0: 2086ea55bf5df7d26d12b36c47141bfbac5730c3929aTadashi G. Takaoka mImm.showInputMethodPicker(); 20872fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 208885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 1: 2089ea55bf5df7d26d12b36c47141bfbac5730c3929aTadashi G. Takaoka launchSettings(); 20902fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 2091923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2092923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 209385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 209485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka showOptionsMenuInternal(title, items, listener); 20952fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 20962fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka 209785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka private void showOptionsMenuInternal(CharSequence title, CharSequence[] items, 209885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka DialogInterface.OnClickListener listener) { 2099c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka final IBinder windowToken = mKeyboardSwitcher.getKeyboardView().getWindowToken(); 210018e15a1e5e30cf200e935e43a73edef25682de27Ken Wakasa if (windowToken == null) return; 21012fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka AlertDialog.Builder builder = new AlertDialog.Builder(this); 21022fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka builder.setCancelable(true); 21032fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka builder.setIcon(R.drawable.ic_dialog_keyboard); 21042fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka builder.setNegativeButton(android.R.string.cancel, null); 210585996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka builder.setItems(items, listener); 210685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka builder.setTitle(title); 2107923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mOptionsDialog = builder.create(); 2108a2ad96d95986eb61c3d2d5abce154fb4c3803cacTadashi G. Takaoka mOptionsDialog.setCanceledOnTouchOutside(true); 2109923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Window window = mOptionsDialog.getWindow(); 2110923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project WindowManager.LayoutParams lp = window.getAttributes(); 211118e15a1e5e30cf200e935e43a73edef25682de27Ken Wakasa lp.token = windowToken; 2112923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 2113923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project window.setAttributes(lp); 2114923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 2115923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mOptionsDialog.show(); 2116923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2117923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 21187e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 21197e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { 2120923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.dump(fd, fout, args); 2121a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2122923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final Printer p = new PrintWriterPrinter(fout); 2123923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println("LatinIME state :"); 2124923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" Keyboard mode = " + mKeyboardSwitcher.getKeyboardMode()); 21259318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa p.println(" mComposingStringBuilder=" + mComposingStringBuilder.toString()); 21269fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka p.println(" mIsSuggestionsRequested=" + mIsSettingsSuggestionStripOn); 2127923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mCorrectionMode=" + mCorrectionMode); 2128f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard p.println(" mHasUncommittedTypedChars=" + mHasUncommittedTypedChars); 212917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mAutoCorrectEnabled=" + mSettingsValues.mAutoCorrectEnabled); 21300730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard p.println(" mShouldInsertMagicSpace=" + mShouldInsertMagicSpace); 21311b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka p.println(" mApplicationSpecifiedCompletionOn=" + mApplicationSpecifiedCompletionOn); 2132923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" TextEntryState.state=" + TextEntryState.getState()); 213317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mSoundOn=" + mSettingsValues.mSoundOn); 213417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mVibrateOn=" + mSettingsValues.mVibrateOn); 2135240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard p.println(" mKeyPreviewPopupOn=" + mSettingsValues.mKeyPreviewPopupOn); 2136923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 21376e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani 2138923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Characters per second measurement 2139a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2140923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long mLastCpsTime; 2141923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int CPS_BUFFER_SIZE = 16; 2142923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long[] mCpsIntervals = new long[CPS_BUFFER_SIZE]; 2143923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mCpsIndex; 2144a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2145923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void measureCps() { 2146923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long now = System.currentTimeMillis(); 2147923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mLastCpsTime == 0) mLastCpsTime = now - 100; // Initial 2148923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCpsIntervals[mCpsIndex] = now - mLastCpsTime; 2149923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mLastCpsTime = now; 2150923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCpsIndex = (mCpsIndex + 1) % CPS_BUFFER_SIZE; 2151923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long total = 0; 2152923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project for (int i = 0; i < CPS_BUFFER_SIZE; i++) total += mCpsIntervals[i]; 2153923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project System.out.println("CPS = " + ((CPS_BUFFER_SIZE * 1000f) / total)); 2154923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2155923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 2156