LatinIME.java revision 644d33d60ea5a87501274488013d65f55238895e
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; 32923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Message; 33923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.SystemClock; 34bf96661d33d0126adb60a48880ceba1ff055d4a4satokimport android.preference.PreferenceActivity; 35923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.preference.PreferenceManager; 36e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaokaimport android.text.InputType; 37923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.text.TextUtils; 38923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Log; 39923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.PrintWriterPrinter; 40923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Printer; 4166a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasaniimport android.view.HapticFeedbackConstants; 42923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.KeyEvent; 43923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.View; 448e09172df1bb176cc899940862c56bed9b9aec4esatokimport android.view.ViewGroup; 458e09172df1bb176cc899940862c56bed9b9aec4esatokimport android.view.ViewParent; 46923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.CompletionInfo; 47923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.EditorInfo; 48466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport android.view.inputmethod.ExtractedText; 49923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.InputConnection; 50c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka 515ac4638f999db4fea8a9e24171dbceb640a10858Alan Viveretteimport com.android.inputmethod.accessibility.AccessibilityUtils; 52c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.CompatUtils; 53c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.EditorInfoCompatUtils; 54c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputConnectionCompatUtils; 55c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputMethodManagerCompatWrapper; 56c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputMethodServiceCompatWrapper; 57c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputTypeCompatUtils; 581fef530ec7626fa16777f52b48191e61db8f46d4satokimport com.android.inputmethod.compat.SuggestionSpanUtils; 5928f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasaimport com.android.inputmethod.compat.VibratorCompatWrapper; 60c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.deprecated.LanguageSwitcherProxy; 61c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.deprecated.VoiceProxy; 6283ffff2a49beeb41874b7cb40819a75001f708e2Ken Wakasaimport com.android.inputmethod.keyboard.Key; 63c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.Keyboard; 64c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardActionListener; 65c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardSwitcher; 66f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardView; 67c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.LatinKeyboard; 68c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaokaimport com.android.inputmethod.keyboard.LatinKeyboardView; 69923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 70466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.FileDescriptor; 71466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.PrintWriter; 72466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.util.Locale; 73466741d8a78965b8509bf527344f289e50873092Mike LeBeau 74923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/** 75923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Input method implementation for Qwerty'ish keyboard. 76923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 77c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaokapublic class LatinIME extends InputMethodServiceCompatWrapper implements KeyboardActionListener, 78913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka SuggestionsView.Listener { 798efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka private static final String TAG = LatinIME.class.getSimpleName(); 80979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private static final boolean PERF_DEBUG = false; 81409220583333bdf06290dd9fd42f91b5c0d1b11asatok private static final boolean TRACE = false; 829e2d810dc524380ca1db6b384cfb00b4401585e5Tadashi G. Takaoka private static boolean DEBUG; 83a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 848efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka /** 858efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * The private IME option used to indicate that no microphone should be 868efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * shown for a given text field. For instance, this is specified by the 878efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * search dialog when the dialog is already showing a voice search button. 888efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * 898efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * @deprecated Use {@link LatinIME#IME_OPTION_NO_MICROPHONE} with package name prefixed. 908efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka */ 9110dd34de0ffcde0104f7d2dae3a3c9fd66abffccsatok @SuppressWarnings("dep-ann") 928efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka public static final String IME_OPTION_NO_MICROPHONE_COMPAT = "nm"; 938efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka 948efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka /** 958efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * The private IME option used to indicate that no microphone should be 968efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * shown for a given text field. For instance, this is specified by the 978efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * search dialog when the dialog is already showing a voice search button. 988efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka */ 994199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka public static final String IME_OPTION_NO_MICROPHONE = "noMicrophoneKey"; 1004199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka 1014199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka /** 1024199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka * The private IME option used to indicate that no settings key should be 1034199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka * shown for a given text field. 1044199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka */ 1054199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka public static final String IME_OPTION_NO_SETTINGS_KEY = "noSettingsKey"; 1068efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka 107af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka /** 108af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka * The private IME option used to indicate that the given text field needs 109af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka * ASCII code points input. 110af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka */ 111af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka public static final String IME_OPTION_FORCE_ASCII = "forceAscii"; 112af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka 113af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka /** 114af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka * The subtype extra value used to indicate that the subtype keyboard layout is capable for 115af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka * typing ASCII characters. 116af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka */ 117af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka public static final String SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE = "AsciiCapable"; 118af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka 119d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka /** 120294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima * The subtype extra value used to indicate that the subtype keyboard layout supports touch 121294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima * position correction. 122294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima */ 123294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima public static final String SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION = 124294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima "SupportTouchPositionCorrection"; 125294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima /** 126d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka * The subtype extra value used to indicate that the subtype keyboard layout should be loaded 127d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka * from the specified locale. 128d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka */ 129d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka public static final String SUBTYPE_EXTRA_VALUE_KEYBOARD_LOCALE = "KeyboardLocale"; 130d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka 1319e347d3d448e48229c46aad394ec9bd60cd5807bsatok private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100; 132fd0bd57deb53c4cce32810a61133fa44b45dbb7bKen Wakasa 133923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // How many continuous deletes at which to start deleting at a higher speed. 134923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int DELETE_ACCELERATE_AT = 20; 135923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Key events coming any faster than this are long-presses. 136d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani private static final int QUICK_PRESS = 200; 137a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 13859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private static final int PENDING_IMS_CALLBACK_DURATION = 800; 139055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 140cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard /** 141cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard * The name of the scheme used by the Package Manager to warn of a new package installation, 142cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard * replacement or removal. 143cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard */ 144cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard private static final String SCHEME_PACKAGE = "package"; 145cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 1467599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private int mSuggestionVisibility; 1477599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_SHOW_VALUE 1487599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_show_value; 1497599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE 1507599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_show_only_portrait_value; 1517599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_HIDE_VALUE 1527599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_hide_value; 1537599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 1547599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int[] SUGGESTION_VISIBILITY_VALUE_ARRAY = new int[] { 1557599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_SHOW_VALUE, 1567599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE, 1577599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_HIDE_VALUE 1587599cfea4a2d56f4779452ec8e8742f7b9629cc0satok }; 1597599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 160120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Magic space: a space that should disappear on space/apostrophe insertion, move after the 161120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // punctuation on punctuation insertion, and become a real space on alpha char insertion. 162120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Weak space: a space that be swapped only by suggestion strip punctuation. 163120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Double space: the state where the user pressed space twice quickly, which LatinIME 164120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // resolved as period-space. Undoing this converts the period to a space. 165120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Swap punctuation: the state where a (weak or magic) space and a punctuation from the 166120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // suggestion strip have just been swapped. Undoing this swaps them back. 167120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private static final int SPACE_STATE_NONE = 0; 168120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private static final int SPACE_STATE_DOUBLE = 1; 169120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private static final int SPACE_STATE_SWAP_PUNCTUATION = 2; 170120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private static final int SPACE_STATE_MAGIC = 3; 171120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private static final int SPACE_STATE_WEAK = 4; 172120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 173120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Current space state of the input method. This can be any of the above constants. 174120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private int mSpaceState; 175126698fdd256a2e3734634d3b923cabd800064baJean Chalard 17617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard private Settings.Values mSettingsValues; 17717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 178d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka private View mExtractArea; 179abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka private View mKeyPreviewBackingView; 180913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka private View mSuggestionsContainer; 181913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka private SuggestionsView mSuggestionsView; 182923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private Suggest mSuggest; 1831b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka private CompletionInfo[] mApplicationSpecifiedCompletions; 184a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 185610f1dc8553cf2ed97e763a06a19380c4a6cd636satok private InputMethodManagerCompatWrapper mImm; 1862fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private Resources mResources; 1872fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private SharedPreferences mPrefs; 1882fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private String mInputMethodId; 18971c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka private KeyboardSwitcher mKeyboardSwitcher; 1900ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private SubtypeSwitcher mSubtypeSwitcher; 191b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok private VoiceProxy mVoiceProxy; 192a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 193923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private UserDictionary mUserDictionary; 194979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private UserBigramDictionary mUserBigramDictionary; 195f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard private UserUnigramDictionary mUserUnigramDictionary; 196ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka private boolean mIsUserDictionaryAvaliable; 19736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 1980730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard // TODO: Create an inner class to group options and pseudo-options to improve readability. 199c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // These variables are initialized according to the {@link EditorInfo#inputType}. 20026a531c6fe2a6e058803b7102e2bc9e7ea12d8f3Jean Chalard private boolean mInsertSpaceOnPickSuggestionManually; 201c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mInputTypeNoAutoCorrect; 202c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mIsSettingsSuggestionStripOn; 203c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mApplicationSpecifiedCompletionOn; 204c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 2059318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa private final StringBuilder mComposingStringBuilder = new StringBuilder(); 2069318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa private WordComposer mWordComposer = new WordComposer(); 207923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private CharSequence mBestWord; 208f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard private boolean mHasUncommittedTypedChars; 209409220583333bdf06290dd9fd42f91b5c0d1b11asatok 21079efbed76f638be298493107fa2d0cd1b5eb529esatok private int mCorrectionMode; 21179efbed76f638be298493107fa2d0cd1b5eb529esatok private int mCommittedLength; 212979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Keep track of the last selection range to decide if we need to show word alternatives 21379efbed76f638be298493107fa2d0cd1b5eb529esatok private int mLastSelectionStart; 21479efbed76f638be298493107fa2d0cd1b5eb529esatok private int mLastSelectionEnd; 215979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2164733609947c0ec74e460bd714fffca0518ade93aJean Chalard // Whether we are expecting an onUpdateSelection event to fire. If it does when we don't 2174733609947c0ec74e460bd714fffca0518ade93aJean Chalard // "expect" it, it means the user actually moved the cursor. 2184733609947c0ec74e460bd714fffca0518ade93aJean Chalard private boolean mExpectingUpdateSelection; 219923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mDeleteCount; 220923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long mLastKeyTime; 221a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 222923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private AudioManager mAudioManager; 223f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa private float mFxVolume = -1.0f; // default volume 22417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard private boolean mSilentModeOn; // System-wide current configuration 225923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 22628f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa private VibratorCompatWrapper mVibrator; 22728f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa private long mKeypressVibrationDuration = -1; 22828f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa 229b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok // TODO: Move this flag to VoiceProxy 23081c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani private boolean mConfigurationChanging; 231466741d8a78965b8509bf527344f289e50873092Mike LeBeau 23238f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka // Member variables for remembering the current device orientation. 23338f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka private int mDisplayOrientation; 23438f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 235cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Object for reacting to adding/removing a dictionary pack. 236cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard private BroadcastReceiver mDictionaryPackInstallReceiver = 237cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard new DictionaryPackInstallBroadcastReceiver(this); 238cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 239dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani // Keeps track of most recently inserted text (multi-character key) for reverting 240dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani private CharSequence mEnteredText; 241dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 242604d80c67185954d4691ac775be59c499eee3b1csatok private final ComposingStateManager mComposingStateManager = 243fe2d90798ea409ee39d6f63942eb01bb7eed98e3satok ComposingStateManager.getInstance(); 244604d80c67185954d4691ac775be59c499eee3b1csatok 2454f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public final UIHandler mHandler = new UIHandler(this); 246d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 2474f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public static class UIHandler extends StaticInnerHandlerWrapper<LatinIME> { 248d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_UPDATE_SUGGESTIONS = 0; 24945f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_UPDATE_SHIFT_STATE = 1; 25045f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_VOICE_RESULTS = 2; 25145f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_FADEOUT_LANGUAGE_ON_SPACEBAR = 3; 25245f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 4; 25345f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_SPACE_TYPED = 5; 25445f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_SET_BIGRAM_PREDICTIONS = 6; 25545f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_PENDING_IMS_CALLBACK = 7; 25638f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 2574f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public UIHandler(LatinIME outerInstance) { 2584f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa super(outerInstance); 2594f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa } 2604f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa 261923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 262923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void handleMessage(Message msg) { 2634f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final LatinIME latinIme = getOuterInstance(); 2644f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final KeyboardSwitcher switcher = latinIme.mKeyboardSwitcher; 265c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka final LatinKeyboardView inputView = switcher.getKeyboardView(); 266923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (msg.what) { 267d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SUGGESTIONS: 2684f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.updateSuggestions(); 269d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 270d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SHIFT_STATE: 271de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka switcher.updateShiftState(); 272d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 273cb3320179d39a7983874697a0aa428b127675c9dJean Chalard case MSG_SET_BIGRAM_PREDICTIONS: 2744f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.updateBigramPredictions(); 27589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard break; 276d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_VOICE_RESULTS: 2774f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mVoiceProxy.handleVoiceResults(latinIme.preferCapitalization() 278de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka || (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked())); 279de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka break; 280de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka case MSG_FADEOUT_LANGUAGE_ON_SPACEBAR: 28117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (inputView != null) { 28266432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka inputView.setSpacebarTextFadeFactor( 2834f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa (1.0f + latinIme.mSettingsValues. 2844f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa mFinalFadeoutFactorOfLanguageOnSpacebar) / 2, 28566432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka (LatinKeyboard)msg.obj); 28617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 287de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_DISMISS_LANGUAGE_ON_SPACEBAR, msg.obj), 2884f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mSettingsValues.mDurationOfFadeoutLanguageOnSpacebar); 289de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka break; 290de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka case MSG_DISMISS_LANGUAGE_ON_SPACEBAR: 29117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (inputView != null) { 29266432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka inputView.setSpacebarTextFadeFactor( 2934f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar, 29417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard (LatinKeyboard)msg.obj); 29517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 296d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 297923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 298923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 299d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 300d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateSuggestions() { 301d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 3029b2192bfd2d3a06df3c685ed4287e192dbaabf32Ken Wakasa sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTIONS), 3034f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa getOuterInstance().mSettingsValues.mDelayUpdateSuggestions); 304d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 305d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 306d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateSuggestions() { 307d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 308d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 309d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 310d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public boolean hasPendingUpdateSuggestions() { 311d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka return hasMessages(MSG_UPDATE_SUGGESTIONS); 312d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 313d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 314d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateShiftKeyState() { 315d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 31617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard sendMessageDelayed(obtainMessage(MSG_UPDATE_SHIFT_STATE), 3174f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa getOuterInstance().mSettingsValues.mDelayUpdateShiftState); 318d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 319d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 320d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateShiftState() { 321d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 322d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 323d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 324cb3320179d39a7983874697a0aa428b127675c9dJean Chalard public void postUpdateBigramPredictions() { 325cb3320179d39a7983874697a0aa428b127675c9dJean Chalard removeMessages(MSG_SET_BIGRAM_PREDICTIONS); 3269b2192bfd2d3a06df3c685ed4287e192dbaabf32Ken Wakasa sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_PREDICTIONS), 3274f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa getOuterInstance().mSettingsValues.mDelayUpdateSuggestions); 32889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 32989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 330cb3320179d39a7983874697a0aa428b127675c9dJean Chalard public void cancelUpdateBigramPredictions() { 331cb3320179d39a7983874697a0aa428b127675c9dJean Chalard removeMessages(MSG_SET_BIGRAM_PREDICTIONS); 33289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 33389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 334d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void updateVoiceResults() { 335d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka sendMessage(obtainMessage(MSG_VOICE_RESULTS)); 336d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 337de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka 338d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka public void startDisplayLanguageOnSpacebar(boolean localeChanged) { 3394f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final LatinIME latinIme = getOuterInstance(); 340de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka removeMessages(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR); 341de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka removeMessages(MSG_DISMISS_LANGUAGE_ON_SPACEBAR); 342c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka final LatinKeyboardView inputView = latinIme.mKeyboardSwitcher.getKeyboardView(); 343de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka if (inputView != null) { 3444f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final LatinKeyboard keyboard = latinIme.mKeyboardSwitcher.getLatinKeyboard(); 345c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka // The language is always displayed when the delay is negative. 346c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka final boolean needsToDisplayLanguage = localeChanged 3474f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa || latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar < 0; 348de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka // The language is never displayed when the delay is zero. 3494f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa if (latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar != 0) { 350c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka inputView.setSpacebarTextFadeFactor(needsToDisplayLanguage ? 1.0f 3514f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa : latinIme.mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar, 3524f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa keyboard); 35317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 354c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka // The fadeout animation will start when the delay is positive. 3554f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa if (localeChanged 3564f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa && latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar > 0) { 357de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR, keyboard), 3584f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar); 359de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 360de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 361de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 362fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 363fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public void startDoubleSpacesTimer() { 364fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka removeMessages(MSG_SPACE_TYPED); 365fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_SPACE_TYPED), 3664f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa getOuterInstance().mSettingsValues.mDoubleSpacesTurnIntoPeriodTimeout); 367fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 368fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 369fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public void cancelDoubleSpacesTimer() { 370fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka removeMessages(MSG_SPACE_TYPED); 371fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 372fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 373fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public boolean isAcceptingDoubleSpaces() { 374fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka return hasMessages(MSG_SPACE_TYPED); 375fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 37638f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 37759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Working variables for the following methods. 37859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mIsOrientationChanging; 37959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mPendingSuccesiveImsCallback; 38059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mHasPendingStartInput; 38159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mHasPendingFinishInputView; 38259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mHasPendingFinishInput; 38359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 38459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void startOrientationChanging() { 38559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mIsOrientationChanging = true; 386055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 38759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.mKeyboardSwitcher.saveKeyboardState(); 38859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 38959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 39059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private void resetPendingImsCallback() { 39159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInputView = false; 39259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInput = false; 39359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingStartInput = false; 39459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 39559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 39659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private void executePendingImsCallback(LatinIME latinIme, EditorInfo attribute, 39759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka boolean restarting) { 39859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mHasPendingFinishInputView) 39959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputViewInternal(mHasPendingFinishInput); 40059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mHasPendingFinishInput) 40159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputInternal(); 40259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mHasPendingStartInput) 40359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onStartInputInternal(attribute, restarting); 40459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka resetPendingImsCallback(); 40559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 40659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 40759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onStartInput(EditorInfo attribute, boolean restarting) { 40859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK)) { 40959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Typically this is the second onStartInput after orientation changed. 41059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingStartInput = true; 41159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } else { 41259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mIsOrientationChanging && restarting) { 41359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // This is the first onStartInput after orientation changed. 41459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mIsOrientationChanging = false; 41559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mPendingSuccesiveImsCallback = true; 41659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 41759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 41859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka executePendingImsCallback(latinIme, attribute, restarting); 41959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onStartInputInternal(attribute, restarting); 420055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 421055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 422055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 42359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onStartInputView(EditorInfo attribute, boolean restarting) { 42459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK)) { 42559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Typically this is the second onStartInputView after orientation changed. 42659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka resetPendingImsCallback(); 42759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } else { 42859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mPendingSuccesiveImsCallback) { 42959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // This is the first onStartInputView after orientation changed. 43059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mPendingSuccesiveImsCallback = false; 43159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka resetPendingImsCallback(); 43259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_PENDING_IMS_CALLBACK), 43359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka PENDING_IMS_CALLBACK_DURATION); 43459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 43559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 43659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka executePendingImsCallback(latinIme, attribute, restarting); 43759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onStartInputViewInternal(attribute, restarting); 43859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 43959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 44059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 44159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInputView(boolean finishingInput) { 44259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK)) { 44359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Typically this is the first onFinishInputView after orientation changed. 44459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInputView = true; 44559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } else { 44659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 44759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputViewInternal(finishingInput); 44838f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 44938f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 450ffd156c77e93a54b704780b46886ba597d1c77cbTadashi G. Takaoka 45159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInput() { 45259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK)) { 45359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Typically this is the first onFinishInput after orientation changed. 45459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInput = true; 45559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } else { 45659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 45759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka executePendingImsCallback(latinIme, null, false); 45859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputInternal(); 459ffd156c77e93a54b704780b46886ba597d1c77cbTadashi G. Takaoka } 460ffd156c77e93a54b704780b46886ba597d1c77cbTadashi G. Takaoka } 46138f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 46238f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 4637e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 4647e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka public void onCreate() { 46527d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 46627d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa mPrefs = prefs; 46727d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa LatinImeLogger.init(this, prefs); 4686d9021527a38ba1e94225020389621a0d7227aa1satok LanguageSwitcherProxy.init(this, prefs); 469bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka InputMethodManagerCompatWrapper.init(this); 470ef5dfc480c7a3e3e34a20b7aacc731942e7a0578Tadashi G. Takaoka SubtypeSwitcher.init(this); 47127d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa KeyboardSwitcher.init(this, prefs); 4725ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette AccessibilityUtils.init(this, prefs); 473363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 474923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onCreate(); 475363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 476bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka mImm = InputMethodManagerCompatWrapper.getInstance(); 4778efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka mInputMethodId = Utils.getInputMethodId(mImm, getPackageName()); 4780ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mSubtypeSwitcher = SubtypeSwitcher.getInstance(); 4790ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mKeyboardSwitcher = KeyboardSwitcher.getInstance(); 48028f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa mVibrator = VibratorCompatWrapper.getInstance(this); 4819e2d810dc524380ca1db6b384cfb00b4401585e5Tadashi G. Takaoka DEBUG = LatinImeLogger.sDBG; 482363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 483363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka final Resources res = getResources(); 484363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka mResources = res; 485fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard 48628f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa loadSettings(); 48728f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa 4889502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka Utils.GCUtils.getInstance().reset(); 489979f8690967ff5409fe18f5085858ccdb8e0ccf1satok boolean tryGC = true; 4909502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { 491979f8690967ff5409fe18f5085858ccdb8e0ccf1satok try { 4920ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 493979f8690967ff5409fe18f5085858ccdb8e0ccf1satok tryGC = false; 494979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } catch (OutOfMemoryError e) { 4959502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka tryGC = Utils.GCUtils.getInstance().tryGCOrWait("InitSuggest", e); 496979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 497979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 498979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 499f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka mDisplayOrientation = res.getConfiguration().orientation; 500b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 501cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Register to receive ringer mode change and network state change. 502cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Also receive installation and removal of a dictionary pack. 503123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final IntentFilter filter = new IntentFilter(); 504123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); 505123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 506923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project registerReceiver(mReceiver, filter); 507b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy = VoiceProxy.init(this, prefs, mHandler); 508cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 509cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final IntentFilter packageFilter = new IntentFilter(); 510cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 511cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 512cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addDataScheme(SCHEME_PACKAGE); 513cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard registerReceiver(mDictionaryPackInstallReceiver, packageFilter); 514646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard 515646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard final IntentFilter newDictFilter = new IntentFilter(); 516646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard newDictFilter.addAction( 517646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard DictionaryPackInstallBroadcastReceiver.NEW_DICTIONARY_INTENT_ACTION); 518646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard registerReceiver(mDictionaryPackInstallReceiver, newDictFilter); 519923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 52036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 52117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard // Has to be package-visible for unit tests 52217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard /* package */ void loadSettings() { 52317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this); 52417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (null == mSubtypeSwitcher) mSubtypeSwitcher = SubtypeSwitcher.getInstance(); 52517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues = new Settings.Values(mPrefs, this, mSubtypeSwitcher.getInputLocaleStr()); 52614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary()); 527bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa updateSoundEffectVolume(); 52828f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa updateKeypressVibrationDuration(); 52917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 53017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 5310ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private void initSuggest() { 532cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); 533ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963Jean Chalard final Locale keyboardLocale = LocaleUtils.constructLocaleFromString(localeStr); 53436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 535309bff562fbaf47488e6bf6636840f00574187d8Jean Chalard final Resources res = mResources; 536ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963Jean Chalard final Locale savedLocale = LocaleUtils.setSystemLocale(res, keyboardLocale); 53714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard final ContactsDictionary oldContactsDictionary; 53836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani if (mSuggest != null) { 53914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard oldContactsDictionary = mSuggest.getContactsDictionary(); 54036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mSuggest.close(); 54114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } else { 54214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard oldContactsDictionary = null; 54336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 544979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 5458efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka int mainDicResId = Utils.getMainDictionaryResourceId(res); 546cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mSuggest = new Suggest(this, mainDicResId, keyboardLocale); 54717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.mAutoCorrectEnabled) { 54817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); 54917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 550e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 551cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mUserDictionary = new UserDictionary(this, localeStr); 552923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mSuggest.setUserDictionary(mUserDictionary); 553ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka mIsUserDictionaryAvaliable = mUserDictionary.isEnabled(); 554e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 55514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard resetContactsDictionary(oldContactsDictionary); 556e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 557f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard mUserUnigramDictionary 558f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard = new UserUnigramDictionary(this, this, localeStr, Suggest.DIC_USER_UNIGRAM); 559f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard mSuggest.setUserUnigramDictionary(mUserUnigramDictionary); 560e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 561f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard mUserBigramDictionary 562f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard = new UserBigramDictionary(this, this, localeStr, Suggest.DIC_USER_BIGRAM); 563e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest.setUserBigramDictionary(mUserBigramDictionary); 564e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 565e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani updateCorrectionMode(); 56636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 567ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963Jean Chalard LocaleUtils.setSystemLocale(res, savedLocale); 568923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 56936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 57014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard /** 57114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * Resets the contacts dictionary in mSuggest according to the user settings. 57214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * 57314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * This method takes an optional contacts dictionary to use. Since the contacts dictionary 57414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * does not depend on the locale, it can be reused across different instances of Suggest. 57514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * The dictionary will also be opened or closed as necessary depending on the settings. 57614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * 57714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * @param oldContactsDictionary an optional dictionary to use, or null 57814051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard */ 57914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard private void resetContactsDictionary(final ContactsDictionary oldContactsDictionary) { 58014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard final boolean shouldSetDictionary = (null != mSuggest && mSettingsValues.mUseContactsDict); 58114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard 58214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard final ContactsDictionary dictionaryToUse; 58314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard if (!shouldSetDictionary) { 58414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // Make sure the dictionary is closed. If it is already closed, this is a no-op, 58514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // so it's safe to call it anyways. 58614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard if (null != oldContactsDictionary) oldContactsDictionary.close(); 58714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard dictionaryToUse = null; 58814051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } else if (null != oldContactsDictionary) { 58914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // Make sure the old contacts dictionary is opened. If it is already open, this is a 59014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // no-op, so it's safe to call it anyways. 59114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard oldContactsDictionary.reopen(this); 59214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard dictionaryToUse = oldContactsDictionary; 59314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } else { 59414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard dictionaryToUse = new ContactsDictionary(this, Suggest.DIC_CONTACTS); 59514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } 59614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard 59714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard if (null != mSuggest) { 59814051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard mSuggest.setContactsDictionary(dictionaryToUse); 59914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } 600699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard } 601699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard 602cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard /* package private */ void resetSuggestMainDict() { 603cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); 604ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963Jean Chalard final Locale keyboardLocale = LocaleUtils.constructLocaleFromString(localeStr); 605cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard int mainDicResId = Utils.getMainDictionaryResourceId(mResources); 606cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mSuggest.resetMainDict(this, mainDicResId, keyboardLocale); 607cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard } 608cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 609466741d8a78965b8509bf527344f289e50873092Mike LeBeau @Override 610466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onDestroy() { 611e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa if (mSuggest != null) { 612e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest.close(); 613e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest = null; 614979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 615923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project unregisterReceiver(mReceiver); 616cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard unregisterReceiver(mDictionaryPackInstallReceiver); 617b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.destroy(); 618979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 619979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.onDestroy(); 620923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onDestroy(); 621923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 622923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 623923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 624923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onConfigurationChanged(Configuration conf) { 625dc64b138b5e3fb3706c0818d0a308fe6e36985b0Tadashi G. Takaoka mSubtypeSwitcher.onConfigurationChanged(conf); 626604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.onFinishComposingText(); 627b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani // If orientation changed while predicting, commit the change 628f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka if (mDisplayOrientation != conf.orientation) { 629f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka mDisplayOrientation = conf.orientation; 630f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka mHandler.startOrientationChanging(); 6319351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 632466741d8a78965b8509bf527344f289e50873092Mike LeBeau commitTyped(ic); 633466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (ic != null) ic.finishComposingText(); // For voice input 6342fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka if (isShowingOptionDialog()) 6352fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka mOptionsDialog.dismiss(); 636b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 6378b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka 63881c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani mConfigurationChanging = true; 639923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onConfigurationChanged(conf); 640b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.onConfigurationChanged(conf); 64181c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani mConfigurationChanging = false; 64288fc9d44186120f9edc5cf7ec0e2af85260fed04satok 64388fc9d44186120f9edc5cf7ec0e2af85260fed04satok // This will work only when the subtype is not supported. 64488fc9d44186120f9edc5cf7ec0e2af85260fed04satok LanguageSwitcherProxy.onConfigurationChanged(conf); 645923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 646b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 647923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 648923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public View onCreateInputView() { 6496c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka return mKeyboardSwitcher.onCreateInputView(); 6506c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka } 6516c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka 6526c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka @Override 6536c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka public void setInputView(View view) { 6546c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka super.setInputView(view); 655d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka mExtractArea = getWindow().getWindow().getDecorView() 656d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka .findViewById(android.R.id.extractArea); 657abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka mKeyPreviewBackingView = view.findViewById(R.id.key_preview_backing); 658913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsContainer = view.findViewById(R.id.suggestions_container); 659913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView = (SuggestionsView) view.findViewById(R.id.suggestions_view); 660913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) 661913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.setListener(this, view); 662f5fe245df0548ea0a8ec607f2392de0fe02c141dTadashi G. Takaoka if (LatinImeLogger.sVISUALDEBUG) { 663f5fe245df0548ea0a8ec607f2392de0fe02c141dTadashi G. Takaoka mKeyPreviewBackingView.setBackgroundColor(0x10FF0000); 664f5fe245df0548ea0a8ec607f2392de0fe02c141dTadashi G. Takaoka } 665923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 666923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 667923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 668c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka public void setCandidatesView(View view) { 669c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka // To ensure that CandidatesView will never be set. 670c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka return; 671923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 672923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 673a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker @Override 67459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onStartInput(EditorInfo attribute, boolean restarting) { 67559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHandler.onStartInput(attribute, restarting); 67659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 67759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 67859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka @Override 679923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onStartInputView(EditorInfo attribute, boolean restarting) { 68059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHandler.onStartInputView(attribute, restarting); 68159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 68259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 68359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka @Override 68459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInputView(boolean finishingInput) { 68559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHandler.onFinishInputView(finishingInput); 68659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 68738f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 68859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka @Override 68959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInput() { 69059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHandler.onFinishInput(); 69159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 69259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 69359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private void onStartInputInternal(EditorInfo attribute, boolean restarting) { 69459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka super.onStartInput(attribute, restarting); 69559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 69659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 69759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private void onStartInputViewInternal(EditorInfo attribute, boolean restarting) { 69859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka super.onStartInputView(attribute, restarting); 69945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 700c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka LatinKeyboardView inputView = switcher.getKeyboardView(); 7018e09172df1bb176cc899940862c56bed9b9aec4esatok 70289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (DEBUG) { 703f0f726464dcb5b3cef4f8e703659b35ca62430b5Tadashi G. Takaoka Log.d(TAG, "onStartInputView: attribute:" + ((attribute == null) ? "none" 704f0f726464dcb5b3cef4f8e703659b35ca62430b5Tadashi G. Takaoka : String.format("inputType=0x%08x imeOptions=0x%08x", 705f0f726464dcb5b3cef4f8e703659b35ca62430b5Tadashi G. Takaoka attribute.inputType, attribute.imeOptions))); 706910b73127fa207dd26ec8124000262523b0aac0csatok } 707923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In landscape mode, this method gets called without the input view being created. 708979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (inputView == null) { 709923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 710923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 711923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 712b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette // Forward this event to the accessibility utilities, if enabled. 713b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette final AccessibilityUtils accessUtils = AccessibilityUtils.getInstance(); 714b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette if (accessUtils.isTouchExplorationEnabled()) { 715b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette accessUtils.onStartInputViewInternal(attribute, restarting); 716b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette } 717b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette 7188d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka mSubtypeSwitcher.updateParametersOnStartInputView(); 7194ab730dbd34fad323063f2ffd31ce33de746668dsatok 720662bb7c26cadd5026cb3d4e5d081aae163bd5a3aTadashi G. Takaoka TextEntryState.reset(); 7216c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani 722055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka // Most such things we decide below in initializeInputAttributesAndGetMode, but we need to 723055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka // know now whether this is a password text field, because we need to know now whether we 724055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka // want to enable the voice button. 725055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka final VoiceProxy voiceIme = mVoiceProxy; 7263be0039164f5e2060b83d0699e293ffc76384732Tadashi G. Takaoka final int inputType = (attribute != null) ? attribute.inputType : 0; 7273be0039164f5e2060b83d0699e293ffc76384732Tadashi G. Takaoka voiceIme.resetVoiceStates(InputTypeCompatUtils.isPasswordInputType(inputType) 7283be0039164f5e2060b83d0699e293ffc76384732Tadashi G. Takaoka || InputTypeCompatUtils.isVisiblePasswordInputType(inputType)); 729c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 730b2b1eb5ca5a52648eea70920b9bd745b07d3ddfaTadashi G. Takaoka // The EditorInfo might have a flag that affects fullscreen mode. 731b2b1eb5ca5a52648eea70920b9bd745b07d3ddfaTadashi G. Takaoka // Note: This call should be done by InputMethodService? 732b2b1eb5ca5a52648eea70920b9bd745b07d3ddfaTadashi G. Takaoka updateFullscreenMode(); 733cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka initializeInputAttributes(attribute); 734c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 735c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.closing(); 736c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mEnteredText = null; 7379318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mComposingStringBuilder.setLength(0); 738f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = false; 739c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mDeleteCount = 0; 740120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 741c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 74217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard loadSettings(); 74317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard updateCorrectionMode(); 74417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard updateSuggestionVisibility(mPrefs, mResources); 74517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 74617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSuggest != null && mSettingsValues.mAutoCorrectEnabled) { 74717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); 74817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 74917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mVoiceProxy.loadSettings(attribute, mPrefs); 75017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard // This will work only when the subtype is not supported. 75117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard LanguageSwitcherProxy.loadSettings(); 75217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 753c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if (mSubtypeSwitcher.isKeyboardMode()) { 754255486a5d067469e074f3649b3d2747e7a08aaa2Tadashi G. Takaoka switcher.loadKeyboard(attribute, mSettingsValues); 755c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka } 756c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 757913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) 758913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.clear(); 759913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShownInternal( 760913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka isSuggestionsStripVisible(), /* needsInputViewShown */ false); 761c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // Delay updating suggestions because keyboard input view may not be shown at this point. 762c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mHandler.postUpdateSuggestions(); 763c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 764240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard inputView.setKeyPreviewPopupEnabled(mSettingsValues.mKeyPreviewPopupOn, 765240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard mSettingsValues.mKeyPreviewPopupDismissDelay); 766c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.setProximityCorrectionEnabled(true); 767c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 768055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka voiceIme.onStartInputView(inputView.getWindowToken()); 769c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 770c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); 771c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka } 772c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 773cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka private void initializeInputAttributes(EditorInfo attribute) { 774cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if (attribute == null) 775cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka return; 7764b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka final int inputType = attribute.inputType; 77782c8c2e6c00386ae9925fff68ea77bc448897cbdTadashi G. Takaoka if (inputType == InputType.TYPE_NULL) { 77882c8c2e6c00386ae9925fff68ea77bc448897cbdTadashi G. Takaoka // TODO: We should honor TYPE_NULL specification. 77982c8c2e6c00386ae9925fff68ea77bc448897cbdTadashi G. Takaoka Log.i(TAG, "InputType.TYPE_NULL is specified"); 78082c8c2e6c00386ae9925fff68ea77bc448897cbdTadashi G. Takaoka } 78182c8c2e6c00386ae9925fff68ea77bc448897cbdTadashi G. Takaoka final int inputClass = inputType & InputType.TYPE_MASK_CLASS; 782c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka final int variation = inputType & InputType.TYPE_MASK_VARIATION; 78382c8c2e6c00386ae9925fff68ea77bc448897cbdTadashi G. Takaoka if (inputClass == 0) { 78482c8c2e6c00386ae9925fff68ea77bc448897cbdTadashi G. Takaoka Log.w(TAG, String.format("Unexpected input class: inputType=0x%08x imeOptions=0x%08x", 78582c8c2e6c00386ae9925fff68ea77bc448897cbdTadashi G. Takaoka inputType, attribute.imeOptions)); 78682c8c2e6c00386ae9925fff68ea77bc448897cbdTadashi G. Takaoka } 78782c8c2e6c00386ae9925fff68ea77bc448897cbdTadashi G. Takaoka 78826a531c6fe2a6e058803b7102e2bc9e7ea12d8f3Jean Chalard mInsertSpaceOnPickSuggestionManually = false; 789e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mInputTypeNoAutoCorrect = false; 7909fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 7911b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletionOn = false; 7921b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletions = null; 793dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 79482c8c2e6c00386ae9925fff68ea77bc448897cbdTadashi G. Takaoka if (inputClass == InputType.TYPE_CLASS_TEXT) { 795cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = true; 796913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka // Make sure that passwords are not displayed in {@link SuggestionsView}. 797e9957752bcaad048746c7a57bbd2c0a59e1918a0satok if (InputTypeCompatUtils.isPasswordInputType(inputType) 798e9957752bcaad048746c7a57bbd2c0a59e1918a0satok || InputTypeCompatUtils.isVisiblePasswordInputType(inputType)) { 799cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 800cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 801e9957752bcaad048746c7a57bbd2c0a59e1918a0satok if (InputTypeCompatUtils.isEmailVariation(variation) 802cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka || variation == InputType.TYPE_TEXT_VARIATION_PERSON_NAME) { 80326a531c6fe2a6e058803b7102e2bc9e7ea12d8f3Jean Chalard // The point in turning this off is that we don't want to insert a space after 80426a531c6fe2a6e058803b7102e2bc9e7ea12d8f3Jean Chalard // a name when filling a form: we can't delete trailing spaces when changing fields 80526a531c6fe2a6e058803b7102e2bc9e7ea12d8f3Jean Chalard mInsertSpaceOnPickSuggestionManually = false; 806cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else { 80726a531c6fe2a6e058803b7102e2bc9e7ea12d8f3Jean Chalard mInsertSpaceOnPickSuggestionManually = true; 808cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 809e9957752bcaad048746c7a57bbd2c0a59e1918a0satok if (InputTypeCompatUtils.isEmailVariation(variation)) { 810cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 811cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) { 812cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 813cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) { 814cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 815cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else if (variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) { 816cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // If it's a browser edit field and auto correct is not ON explicitly, then 817cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // disable auto correction, but keep suggestions on. 818cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) { 819e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mInputTypeNoAutoCorrect = true; 82036ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani } 821cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 822cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka 823cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // If NO_SUGGESTIONS is set, don't do prediction. 824cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) { 825cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 826cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mInputTypeNoAutoCorrect = true; 827cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 828cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // If it's not multiline and the autoCorrect flag is not set, then don't correct 829cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 830cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka && (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) == 0) { 831cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mInputTypeNoAutoCorrect = true; 832cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 833cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { 834cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 835cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mApplicationSpecifiedCompletionOn = isFullscreenMode(); 836cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 837923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 838923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 839923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 840923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 841e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka public void onWindowHidden() { 842e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka super.onWindowHidden(); 843f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 844e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka if (inputView != null) inputView.closing(); 845e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka } 846e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka 84759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private void onFinishInputInternal() { 848923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onFinishInput(); 849a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 850979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 851979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 852b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.flushVoiceInputLogs(mConfigurationChanging); 853409220583333bdf06290dd9fd42f91b5c0d1b11asatok 854f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 855d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa if (inputView != null) inputView.closing(); 856f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard if (mUserUnigramDictionary != null) mUserUnigramDictionary.flushPendingWrites(); 857979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mUserBigramDictionary != null) mUserBigramDictionary.flushPendingWrites(); 858466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 859466741d8a78965b8509bf527344f289e50873092Mike LeBeau 86059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private void onFinishInputViewInternal(boolean finishingInput) { 8616495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa super.onFinishInputView(finishingInput); 862055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka mKeyboardSwitcher.onFinishInputView(); 863f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 8645f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka if (inputView != null) inputView.cancelAllMessages(); 865d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka // Remove pending messages related to update suggestions 866d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 8676495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa } 8686495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa 8696495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa @Override 870466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onUpdateExtractedText(int token, ExtractedText text) { 871466741d8a78965b8509bf527344f289e50873092Mike LeBeau super.onUpdateExtractedText(token, text); 872b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.showPunctuationHintIfNecessary(); 873923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 874923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 875923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 876923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onUpdateSelection(int oldSelStart, int oldSelEnd, 877923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int newSelStart, int newSelEnd, 878923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int candidatesStart, int candidatesEnd) { 879923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, 880923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project candidatesStart, candidatesEnd); 881466741d8a78965b8509bf527344f289e50873092Mike LeBeau 882466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (DEBUG) { 883466741d8a78965b8509bf527344f289e50873092Mike LeBeau Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart 884466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", ose=" + oldSelEnd 885025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa + ", lss=" + mLastSelectionStart 886025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa + ", lse=" + mLastSelectionEnd 887466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nss=" + newSelStart 888466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nse=" + newSelEnd 889466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", cs=" + candidatesStart 890466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", ce=" + candidatesEnd); 891466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 892466741d8a78965b8509bf527344f289e50873092Mike LeBeau 893b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.setCursorAndSelection(newSelEnd, newSelStart); 8944f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 895923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // If the current selection in the text view changes, we should 896923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // clear whatever candidate text we have. 897025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa final boolean selectionChanged = (newSelStart != candidatesEnd 898025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa || newSelEnd != candidatesEnd) && mLastSelectionStart != newSelStart; 899025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa final boolean candidatesCleared = candidatesStart == -1 && candidatesEnd == -1; 9004733609947c0ec74e460bd714fffca0518ade93aJean Chalard if (!mExpectingUpdateSelection) { 901120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (SPACE_STATE_WEAK == mSpaceState) { 902120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Test for no WEAK_SPACE action because there is a race condition that may end up 903120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // in coming here on a normal key press. We set this to NONE because after 904120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // a cursor move, we don't want the suggestion strip to swap the space with the 905120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // newly inserted punctuation. 906120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 907126698fdd256a2e3734634d3b923cabd800064baJean Chalard } 9084c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard if (((mComposingStringBuilder.length() > 0 && mHasUncommittedTypedChars) 9094c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard || mVoiceProxy.isVoiceInputHighlighted()) 9104c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard && (selectionChanged || candidatesCleared)) { 9114c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard mComposingStringBuilder.setLength(0); 9124c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard mHasUncommittedTypedChars = false; 9134c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard TextEntryState.reset(); 914cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard updateSuggestions(); 9154c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard final InputConnection ic = getCurrentInputConnection(); 9164c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard if (ic != null) { 9174c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard ic.finishComposingText(); 9184c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard } 919604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.onFinishComposingText(); 9204c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard mVoiceProxy.setVoiceInputHighlighted(false); 921cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard } else if (!mHasUncommittedTypedChars) { 9224c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard TextEntryState.reset(); 923cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard updateSuggestions(); 9244c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard } 9254733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 9264733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = false; 927d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateShiftKeyState(); 928466741d8a78965b8509bf527344f289e50873092Mike LeBeau 929979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Make a note of the cursor position 930979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionStart = newSelStart; 931979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionEnd = newSelEnd; 9327a8dac55278cedd838be325f56b4c52d973c61f5satok } 9337a8dac55278cedd838be325f56b4c52d973c61f5satok 9347a8dac55278cedd838be325f56b4c52d973c61f5satok public void setLastSelection(int start, int end) { 9357a8dac55278cedd838be325f56b4c52d973c61f5satok mLastSelectionStart = start; 9367a8dac55278cedd838be325f56b4c52d973c61f5satok mLastSelectionEnd = end; 937923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 938923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 939c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 940c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has clicked on the extracted text view, 941c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * when running in fullscreen mode. The default implementation hides 942913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * the suggestions view when this happens, but only if the extracted text 943c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * editor has a vertical scroll bar because its text doesn't fit. 944c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * Here we override the behavior due to the possibility that a re-correction could 945913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * cause the suggestions strip to disappear and re-appear. 946c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani */ 947c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani @Override 948c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani public void onExtractedTextClicked() { 949fe5364c825058f6c34c0f42135a5520b77525a28Jean Chalard if (isSuggestionsRequested()) return; 950c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 951c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedTextClicked(); 952c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 953c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 954c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 955c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has performed a cursor movement in the 956c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * extracted text view, when it is running in fullscreen mode. The default 957913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * implementation hides the suggestions view when a vertical movement 958c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * happens, but only if the extracted text editor has a vertical scroll bar 959c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * because its text doesn't fit. 960c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * Here we override the behavior due to the possibility that a re-correction could 961913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * cause the suggestions strip to disappear and re-appear. 962c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani */ 963c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani @Override 964c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani public void onExtractedCursorMovement(int dx, int dy) { 965fe5364c825058f6c34c0f42135a5520b77525a28Jean Chalard if (isSuggestionsRequested()) return; 966c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 967c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedCursorMovement(dx, dy); 968c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 969c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 970923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 971923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void hideWindow() { 972979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 973c3d175c01ff1956ddb1c2d608d69af1793b4ad8aTadashi G. Takaoka mKeyboardSwitcher.onHideWindow(); 974979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 975923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (TRACE) Debug.stopMethodTracing(); 9766e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (mOptionsDialog != null && mOptionsDialog.isShowing()) { 9776e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog.dismiss(); 9786e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog = null; 9796e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 980b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.hideVoiceWindow(mConfigurationChanging); 981923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.hideWindow(); 982923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 983923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 984923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 9851b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka public void onDisplayCompletions(CompletionInfo[] applicationSpecifiedCompletions) { 986979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (DEBUG) { 987a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa Log.i(TAG, "Received completions:"); 988bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok if (applicationSpecifiedCompletions != null) { 989bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok for (int i = 0; i < applicationSpecifiedCompletions.length; i++) { 990bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok Log.i(TAG, " #" + i + ": " + applicationSpecifiedCompletions[i]); 991bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok } 992923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 993923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 9941b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (mApplicationSpecifiedCompletionOn) { 9951b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletions = applicationSpecifiedCompletions; 9961b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (applicationSpecifiedCompletions == null) { 997b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani clearSuggestions(); 998923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 999923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1000a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 10017e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords.Builder builder = new SuggestedWords.Builder() 10021b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka .setApplicationSpecifiedCompletions(applicationSpecifiedCompletions) 10035238df54ad3f648d09d5288f00b0a9d3c0593832Tadashi G. Takaoka .setTypedWordValid(false) 10045238df54ad3f648d09d5288f00b0a9d3c0593832Tadashi G. Takaoka .setHasMinimalSuggestion(false); 1005979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // When in fullscreen mode, show completions generated by the application 10067e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(builder.build()); 1007923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = null; 1008c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShown(true); 1009923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1010923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1011923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1012c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka private void setSuggestionStripShownInternal(boolean shown, boolean needsInputViewShown) { 1013913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka // TODO: Modify this if we support suggestions with hard keyboard 1014913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (onEvaluateInputViewShown() && mSuggestionsContainer != null) { 1015913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka final boolean shouldShowSuggestions = shown 10167a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka && (needsInputViewShown ? mKeyboardSwitcher.isInputViewShown() : true); 10174b1780fa9571409d65d9797d47949ffafaf0f083Tadashi G. Takaoka if (isFullscreenMode()) { 1018913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsContainer.setVisibility( 1019913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka shouldShowSuggestions ? View.VISIBLE : View.GONE); 10207a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka } else { 1021913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsContainer.setVisibility( 1022913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka shouldShowSuggestions ? View.VISIBLE : View.INVISIBLE); 10237a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka } 1024923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1025923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1026a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1027c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka private void setSuggestionStripShown(boolean shown) { 1028c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShownInternal(shown, /* needsInputViewShown */true); 1029543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa } 1030543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa 1031543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa @Override 1032923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onComputeInsets(InputMethodService.Insets outInsets) { 1033923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onComputeInsets(outInsets); 1034f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka final KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 1035913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (inputView == null || mSuggestionsContainer == null) 103646ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka return; 1037d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka // In fullscreen mode, the height of the extract area managed by InputMethodService should 1038d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka // be considered. 1039d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka // See {@link android.inputmethodservice.InputMethodService#onComputeInsets}. 1040d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka final int extractHeight = isFullscreenMode() ? mExtractArea.getHeight() : 0; 1041abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka final int backingHeight = (mKeyPreviewBackingView.getVisibility() == View.GONE) ? 0 1042abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka : mKeyPreviewBackingView.getHeight(); 104359010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka final int suggestionsHeight = (mSuggestionsContainer.getVisibility() == View.GONE) ? 0 104459010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka : mSuggestionsContainer.getHeight(); 1045d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka final int extraHeight = extractHeight + backingHeight + suggestionsHeight; 1046abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka int touchY = extraHeight; 10479e347d3d448e48229c46aad394ec9bd60cd5807bsatok // Need to set touchable region only if input view is being shown 104846ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka if (mKeyboardSwitcher.isInputViewShown()) { 1049913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsContainer.getVisibility() == View.VISIBLE) { 105059010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka touchY -= suggestionsHeight; 10519e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 10527a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka final int touchWidth = inputView.getWidth(); 1053abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka final int touchHeight = inputView.getHeight() + extraHeight 10547a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // Extend touchable region below the keyboard. 10557a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka + EXTENDED_TOUCHABLE_REGION_HEIGHT; 10569e347d3d448e48229c46aad394ec9bd60cd5807bsatok if (DEBUG) { 10577a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka Log.d(TAG, "Touchable region: y=" + touchY + " width=" + touchWidth 10587a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka + " height=" + touchHeight); 10599e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 10607a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka setTouchableRegionCompat(outInsets, 0, touchY, touchWidth, touchHeight); 10619e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 106246ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka outInsets.contentTopInsets = touchY; 106346ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka outInsets.visibleTopInsets = touchY; 1064923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1065a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1066923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 1067979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public boolean onEvaluateFullscreenMode() { 1068d874ac581e7f9bb6b93918390aa56fb02d1b66e8Tadashi G. Takaoka return super.onEvaluateFullscreenMode() 1069d874ac581e7f9bb6b93918390aa56fb02d1b66e8Tadashi G. Takaoka && mResources.getBoolean(R.bool.config_use_fullscreen_mode); 107059010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka } 107159010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka 107259010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka @Override 107359010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka public void updateFullscreenMode() { 107459010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka super.updateFullscreenMode(); 1075f80b6a06992ae08ca3601f4fbc6da550fd9ac730Tadashi G. Takaoka 107659010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka if (mKeyPreviewBackingView == null) return; 1077d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka // In extract mode, no need to have extra space to show the key preview. 107859010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka // If not, we should have extra space above the keyboard to show the key preview. 1079d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka mKeyPreviewBackingView.setVisibility(isExtractViewShown() ? View.GONE : View.VISIBLE); 1080979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1081979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1082979f8690967ff5409fe18f5085858ccdb8e0ccf1satok @Override 1083923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 1084923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 1085e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_BACK: 10862cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka if (event.getRepeatCount() == 0) { 10872cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka if (mSuggestionsView != null && mSuggestionsView.handleBack()) { 10882cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka return true; 10892cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka } 10902cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka final LatinKeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView(); 10912cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka if (keyboardView != null && keyboardView.handleBack()) { 10926e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani return true; 10936e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 1094e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 1095e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 1096923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1097923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyDown(keyCode, event); 1098923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1099923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1100923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 1101923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 1102923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 1103e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_DOWN: 1104e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_UP: 1105e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_LEFT: 1106e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_RIGHT: 1107e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka // Enable shift key and DPAD to do selections 1108e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mKeyboardSwitcher.isInputViewShown() 1109e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka && mKeyboardSwitcher.isShiftedOrShiftLocked()) { 1110e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka KeyEvent newEvent = new KeyEvent(event.getDownTime(), event.getEventTime(), 1111e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka event.getAction(), event.getKeyCode(), event.getRepeatCount(), 1112e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka event.getDeviceId(), event.getScanCode(), 1113e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON); 11149351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 1115e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (ic != null) 1116e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka ic.sendKeyEvent(newEvent); 1117e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka return true; 1118e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 1119e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 1120923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1121923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyUp(keyCode, event); 1122923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1123923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 11249351550dc6af7859e5280e16144c9386a37b976dKen Wakasa public void commitTyped(final InputConnection ic) { 11258558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa if (!mHasUncommittedTypedChars) return; 11268558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa mHasUncommittedTypedChars = false; 11278558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa if (mComposingStringBuilder.length() > 0) { 11289351550dc6af7859e5280e16144c9386a37b976dKen Wakasa if (ic != null) { 11299351550dc6af7859e5280e16144c9386a37b976dKen Wakasa ic.commitText(mComposingStringBuilder, 1); 1130923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 11318558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa mCommittedLength = mComposingStringBuilder.length(); 11328558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa TextEntryState.acceptedTyped(mComposingStringBuilder); 1133f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard addToUserUnigramAndBigramDictionaries(mComposingStringBuilder, 1134f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard UserUnigramDictionary.FREQUENCY_FOR_TYPED); 1135923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 11368558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa updateSuggestions(); 1137923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1138923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1139b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public boolean getCurrentAutoCapsState() { 11409351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 11411c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani EditorInfo ei = getCurrentInputEditorInfo(); 114217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.mAutoCap && ic != null && ei != null 114317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && ei.inputType != InputType.TYPE_NULL) { 1144b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return ic.getCursorCapsMode(ei.inputType) != 0; 11451c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 1146b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return false; 11471c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 11481c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 1149b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard // "ic" may be null 1150b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard private void swapSwapperAndSpaceWhileInBatchEdit(final InputConnection ic) { 1151b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard if (null == ic) return; 1152923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence lastTwo = ic.getTextBeforeCursor(2, 0); 1153863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // It is guaranteed lastTwo.charAt(1) is a swapper - else this method is not called. 1154923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastTwo != null && lastTwo.length() == 2 1155863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard && lastTwo.charAt(0) == Keyboard.CODE_SPACE) { 1156923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 1157923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(lastTwo.charAt(1) + " ", 1); 1158b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 11594ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 11604ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 11614ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1162120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private boolean maybeDoubleSpaceWhileInBatchEdit(final InputConnection ic) { 1163120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (mCorrectionMode == Suggest.CORRECTION_NONE) return false; 1164120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (ic == null) return false; 11652b4eabed2bfe982b91a994c145401d98894e6ef5Jean Chalard final CharSequence lastThree = ic.getTextBeforeCursor(3, 0); 1166923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastThree != null && lastThree.length() == 3 11679351550dc6af7859e5280e16144c9386a37b976dKen Wakasa && Utils.canBeFollowedByPeriod(lastThree.charAt(0)) 1168571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastThree.charAt(1) == Keyboard.CODE_SPACE 1169fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka && lastThree.charAt(2) == Keyboard.CODE_SPACE 1170fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka && mHandler.isAcceptingDoubleSpaces()) { 1171fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka mHandler.cancelDoubleSpacesTimer(); 1172923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 1173923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(". ", 1); 1174b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 1175120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return true; 1176923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1177120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return false; 1178923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1179a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1180b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard // "ic" must not be null 11819351550dc6af7859e5280e16144c9386a37b976dKen Wakasa private void maybeRemovePreviousPeriod(final InputConnection ic, CharSequence text) { 118241a519729505a877844f2c57a33509c302dddbceKen Wakasa // When the text's first character is '.', remove the previous period 118341a519729505a877844f2c57a33509c302dddbceKen Wakasa // if there is one. 1184b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard final CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 11854ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa if (lastOne != null && lastOne.length() == 1 1186571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastOne.charAt(0) == Keyboard.CODE_PERIOD 1187571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && text.charAt(0) == Keyboard.CODE_PERIOD) { 118841a519729505a877844f2c57a33509c302dddbceKen Wakasa ic.deleteSurroundingText(1, 0); 118941a519729505a877844f2c57a33509c302dddbceKen Wakasa } 119041a519729505a877844f2c57a33509c302dddbceKen Wakasa } 119141a519729505a877844f2c57a33509c302dddbceKen Wakasa 1192b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard // "ic" may be null 1193b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard private void removeTrailingSpaceWhileInBatchEdit(final InputConnection ic) { 11949a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic == null) return; 1195b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard final CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 11969a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (lastOne != null && lastOne.length() == 1 1197571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastOne.charAt(0) == Keyboard.CODE_SPACE) { 11989a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.deleteSurroundingText(1, 0); 11999a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 12009a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 12019a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa 1202c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka @Override 1203923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean addWordToDictionary(String word) { 1204923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mUserDictionary.addWord(word, 128); 12056558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // Suggestion strip should be updated after the operation of adding word to the 12066558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // user dictionary 1207d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1208923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1209923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1210923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1211923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean isAlphabet(int code) { 1212923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (Character.isLetter(code)) { 1213923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1214923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1215923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return false; 1216923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1217923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1218a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1219e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka private void onSettingsKeyPressed() { 1220cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa if (isShowingOptionDialog()) return; 1221d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) { 1222d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka showSubtypeSelectorAndSettings(); 122311b7febc0bea46a6afb30d7fa040b841eadd7410Ken Wakasa } else if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm, false /* exclude aux subtypes */)) { 1224d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka showOptionsMenu(); 1225d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka } else { 1226d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka launchSettings(); 12279a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 12289a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 12299a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 1230cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa // Virtual codes representing custom requests. These are used in onCustomRequest() below. 1231cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa public static final int CODE_SHOW_INPUT_METHOD_PICKER = 1; 1232d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka public static final int CODE_HAPTIC_AND_AUDIO_FEEDBACK = 2; 1233cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa 1234cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa @Override 1235cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa public boolean onCustomRequest(int requestCode) { 1236cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa if (isShowingOptionDialog()) return false; 1237cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa switch (requestCode) { 1238cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa case CODE_SHOW_INPUT_METHOD_PICKER: 123911b7febc0bea46a6afb30d7fa040b841eadd7410Ken Wakasa if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm, true /* include aux subtypes */)) { 124079efbed76f638be298493107fa2d0cd1b5eb529esatok mImm.showInputMethodPicker(); 1241cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa return true; 12429a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 1243cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa return false; 1244d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka case CODE_HAPTIC_AND_AUDIO_FEEDBACK: 1245d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka hapticAndAudioFeedback(Keyboard.CODE_UNSPECIFIED); 1246d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka return true; 12479a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 1248cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa return false; 12499a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 12509a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 12519a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok private boolean isShowingOptionDialog() { 12529a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok return mOptionsDialog != null && mOptionsDialog.isShowing(); 12539a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 12549a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 1255120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private void insertPunctuationFromSuggestionStrip(final InputConnection ic, final int code) { 1256120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final CharSequence beforeText = ic != null ? ic.getTextBeforeCursor(1, 0) : null; 1257120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final int toLeft = TextUtils.isEmpty(beforeText) ? 0 : beforeText.charAt(0); 1258120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final boolean shouldRegisterSwapPunctuation; 1259120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // If we have a space left of the cursor and it's a weak or a magic space, then we should 1260120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // swap it, and override the space state with SPACESTATE_SWAP_PUNCTUATION. 1261120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // To swap it, we fool handleSeparator to think the previous space state was a 1262120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // magic space. 1263120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (Keyboard.CODE_SPACE == toLeft && mSpaceState == SPACE_STATE_WEAK) { 1264120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_MAGIC; 1265120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard shouldRegisterSwapPunctuation = true; 1266120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } else { 1267120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard shouldRegisterSwapPunctuation = false; 1268120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1269120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard onCodeInput(code, new int[] { code }, 1270120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard KeyboardActionListener.NOT_A_TOUCH_COORDINATE, 1271120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard KeyboardActionListener.NOT_A_TOUCH_COORDINATE); 1272120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (shouldRegisterSwapPunctuation) { 1273120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_SWAP_PUNCTUATION; 1274120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1275126698fdd256a2e3734634d3b923cabd800064baJean Chalard } 1276126698fdd256a2e3734634d3b923cabd800064baJean Chalard 12775f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // Implementation of {@link KeyboardActionListener}. 12785a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 12798aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { 1280923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long when = SystemClock.uptimeMillis(); 1281571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (primaryCode != Keyboard.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) { 1282923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mDeleteCount = 0; 1283923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1284923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mLastKeyTime = when; 1285b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 1286b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); 1287120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // The space state depends only on the last character pressed and its own previous 1288120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // state. Here, we revert the space state to neutral if the key is actually modifying 1289120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // the input contents (any non-shift key), which is what we should do for 1290120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // all inputs that do not result in a special state. Each character handling is then 1291120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // free to override the state as they see fit. 1292120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final int spaceState = mSpaceState; 1293923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 1294571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_DELETE: 1295120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 1296120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard handleBackspace(spaceState); 12974189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka mDeleteCount++; 12984733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 12994189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka LatinImeLogger.logOnDelete(); 13004189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1301571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_SHIFT: 13024189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka // Shift key is handled in onPress() when device has distinct multi-touch panel. 1303101a00e3d4b1c29ef2ecdecd1b72b43efde7791aTadashi G. Takaoka if (!distinctMultiTouch) 1304b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.toggleShift(); 13054189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1306e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: 13074189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka // Symbol key is handled in onPress() when device has distinct multi-touch panel. 1308101a00e3d4b1c29ef2ecdecd1b72b43efde7791aTadashi G. Takaoka if (!distinctMultiTouch) 1309b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.changeKeyboardMode(); 13104189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1311571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_CANCEL: 13124189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka if (!isShowingOptionDialog()) { 13134189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka handleClose(); 13144189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } 13154189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1316e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SETTINGS: 1317e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka onSettingsKeyPressed(); 13184189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1319571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_CAPSLOCK: 1320b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.toggleCapsLock(); 1321d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka hapticAndAudioFeedback(primaryCode); 13224189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1323d2c5fdda862f6dd2a1e020cf674c35fbbc63fc92Tadashi G. Takaoka case Keyboard.CODE_SHORTCUT: 132420cdb37bd062ae6cb6d42ad6229a19733476cd55satok mSubtypeSwitcher.switchToShortcutIME(); 13254189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1326571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_TAB: 132745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka handleTab(); 13284733609947c0ec74e460bd714fffca0518ade93aJean Chalard // There are two cases for tab. Either we send a "next" event, that may change the 13294733609947c0ec74e460bd714fffca0518ade93aJean Chalard // focus but will never move the cursor. Or, we send a real tab keycode, which some 13304733609947c0ec74e460bd714fffca0518ade93aJean Chalard // applications may accept or ignore, and we don't know whether this will move the 13314733609947c0ec74e460bd714fffca0518ade93aJean Chalard // cursor or not. So actually, we don't really know. 13324733609947c0ec74e460bd714fffca0518ade93aJean Chalard // So to go with the safer option, we'd rather behave as if the user moved the 13334733609947c0ec74e460bd714fffca0518ade93aJean Chalard // cursor when they didn't than the opposite. We also expect that most applications 13344733609947c0ec74e460bd714fffca0518ade93aJean Chalard // will actually use tab only for focus movement. 13354733609947c0ec74e460bd714fffca0518ade93aJean Chalard // To sum it up: do not update mExpectingUpdateSelection here. 13364189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 13374189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka default: 1338120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 133917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.isWordSeparator(primaryCode)) { 1340120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard handleSeparator(primaryCode, x, y, spaceState); 13414189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } else { 1342120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard handleCharacter(primaryCode, keyCodes, x, y, spaceState); 13434189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } 13444733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 13454733609947c0ec74e460bd714fffca0518ade93aJean Chalard break; 1346923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1347b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.onKey(primaryCode); 1348dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani // Reset after any single keystroke 1349dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = null; 1350923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1351a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 13525a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 13538aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onTextInput(CharSequence text) { 1354b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.commitVoiceInput(); 13559351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 1356923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 1357923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 135855b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka commitTyped(ic); 13599351550dc6af7859e5280e16144c9386a37b976dKen Wakasa maybeRemovePreviousPeriod(ic, text); 1360923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(text, 1); 1361923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1362b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 13635f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka mKeyboardSwitcher.onKey(Keyboard.CODE_DUMMY); 1364120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 1365dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = text; 1366923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1367923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 13685a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 13698aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onCancelInput() { 137083e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka // User released a finger outside any key 13715f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka mKeyboardSwitcher.onCancelInput(); 137283e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka } 137383e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka 1374120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private void handleBackspace(final int spaceState) { 1375b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok if (mVoiceProxy.logAndRevertVoiceInput()) return; 13764f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1377504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1378504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka if (ic == null) return; 1379979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.beginBatchEdit(); 1380979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1381b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleBackspace(); 13824f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 13839ae24750f462cbd94b362fe54a952c86cfb05e5fKen Wakasa final boolean deleteChar = !mHasUncommittedTypedChars; 1384f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (mHasUncommittedTypedChars) { 13859318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa final int length = mComposingStringBuilder.length(); 1386923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (length > 0) { 13879318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mComposingStringBuilder.delete(length - 1, length); 13889318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.deleteLast(); 1389604d80c67185954d4691ac775be59c499eee3b1csatok final CharSequence textWithUnderline = 1390604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.isAutoCorrectionIndicatorOn() 1391604d80c67185954d4691ac775be59c499eee3b1csatok ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline( 1392604d80c67185954d4691ac775be59c499eee3b1csatok this, mComposingStringBuilder) 1393604d80c67185954d4691ac775be59c499eee3b1csatok : mComposingStringBuilder; 1394604d80c67185954d4691ac775be59c499eee3b1csatok ic.setComposingText(textWithUnderline, 1); 13959318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa if (mComposingStringBuilder.length() == 0) { 1396f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = false; 1397923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 139889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (1 == length) { 139989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // 1 == length means we are about to erase the last character of the word, 140089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // so we can show bigrams. 1401cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.postUpdateBigramPredictions(); 140289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 140389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // length > 1, so we still have letters to deduce a suggestion from. 140489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.postUpdateSuggestions(); 140589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 1406923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1407923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(1, 0); 1408923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1409923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1410d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateShiftKeyState(); 1411504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka 1412120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // TODO: Merge space state with TextEntryState 1413923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.backspace(); 1414662bb7c26cadd5026cb3d4e5d081aae163bd5a3aTadashi G. Takaoka if (TextEntryState.isUndoCommit()) { 14159351550dc6af7859e5280e16144c9386a37b976dKen Wakasa revertLastWord(ic); 1416979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.endBatchEdit(); 1417923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1418504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka } 1419120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (SPACE_STATE_DOUBLE == spaceState) { 14209351550dc6af7859e5280e16144c9386a37b976dKen Wakasa if (revertDoubleSpace(ic)) { 14219351550dc6af7859e5280e16144c9386a37b976dKen Wakasa ic.endBatchEdit(); 1422120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // No need to reset mSpaceState, it has already be done (that's why we 1423120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // receive it as a parameter) 1424120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return; 1425120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1426120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } else if (SPACE_STATE_SWAP_PUNCTUATION == spaceState) { 1427120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (revertSwapPunctuation(ic)) { 1428120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.endBatchEdit(); 1429120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Likewise 14309351550dc6af7859e5280e16144c9386a37b976dKen Wakasa return; 14314733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 14324733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 1433504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka 1434504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) { 1435dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani ic.deleteSurroundingText(mEnteredText.length(), 0); 1436923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else if (deleteChar) { 1437913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) { 14386558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // Go back to the suggestion mode if the user canceled the 143955b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // "Touch again to save". 14406558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // NOTE: In gerenal, we don't revert the word when backspacing 14416558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // from a manual suggestion pick. We deliberately chose a 14426558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // different behavior only in the case of picking the first 14436558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // suggestion (typed word). It's intentional to have made this 14446558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // inconsistent with backspacing after selecting other suggestions. 14459351550dc6af7859e5280e16144c9386a37b976dKen Wakasa revertLastWord(ic); 14466558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } else { 1447923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 14486558253160e2039c87f424bd814f402ecd31de3bKen Wakasa if (mDeleteCount > DELETE_ACCELERATE_AT) { 14496558253160e2039c87f424bd814f402ecd31de3bKen Wakasa sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 14506558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 1451923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1452923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1453979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.endBatchEdit(); 1454923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1455923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 145645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka private void handleTab() { 145745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final int imeOptions = getCurrentInputEditorInfo().imeOptions; 1458b2707856aba4fc9b063f26305f1fb603b19c1701satok if (!EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) 1459b2707856aba4fc9b063f26305f1fb603b19c1701satok && !EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions)) { 146045911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB); 146145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka return; 146245911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 146345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 146445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 146545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (ic == null) 146645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka return; 146745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 146845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka // True if keyboard is in either chording shift or manual temporary upper case mode. 146945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final boolean isManualTemporaryUpperCase = mKeyboardSwitcher.isManualTemporaryUpperCase(); 1470b2707856aba4fc9b063f26305f1fb603b19c1701satok if (EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) 147145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka && !isManualTemporaryUpperCase) { 1472b2707856aba4fc9b063f26305f1fb603b19c1701satok EditorInfoCompatUtils.performEditorActionNext(ic); 1473b2707856aba4fc9b063f26305f1fb603b19c1701satok } else if (EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions) 147445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka && isManualTemporaryUpperCase) { 1475b2707856aba4fc9b063f26305f1fb603b19c1701satok EditorInfoCompatUtils.performEditorActionPrevious(ic); 147645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 147745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 147845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 1479120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private void handleCharacter(final int primaryCode, final int[] keyCodes, final int x, 1480120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final int y, final int spaceState) { 1481b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleCharacter(); 14824f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1483b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard final InputConnection ic = getCurrentInputConnection(); 1484b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard if (ic != null) ic.beginBatchEdit(); 1485120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (SPACE_STATE_MAGIC == spaceState 1486126698fdd256a2e3734634d3b923cabd800064baJean Chalard && mSettingsValues.isMagicSpaceStripper(primaryCode)) { 1487b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard removeTrailingSpaceWhileInBatchEdit(ic); 14880730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard } 14890730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard 1490e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka int code = primaryCode; 14913889462439357fd76c0b82dfd52e1ca6e0bafd2dKen Wakasa if ((isAlphabet(code) || mSettingsValues.isSymbolExcludedFromWordSeparators(code)) 14923889462439357fd76c0b82dfd52e1ca6e0bafd2dKen Wakasa && isSuggestionsRequested() && !isCursorTouchingWord()) { 1493f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (!mHasUncommittedTypedChars) { 1494f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = true; 14959318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mComposingStringBuilder.setLength(0); 14969318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.reset(); 14977e99a28dfcc14f5b19220442db972ca8d786b4feKen Wakasa clearSuggestions(); 1498604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.onFinishComposingText(); 1499923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1500923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 150135f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 1502f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (switcher.isShiftedOrShiftLocked()) { 1503eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT 1504eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani || keyCodes[0] > Character.MAX_CODE_POINT) { 1505b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard if (null != ic) ic.endBatchEdit(); 1506eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani return; 1507eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani } 1508e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka code = keyCodes[0]; 1509e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (switcher.isAlphabetMode() && Character.isLowerCase(code)) { 151035f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka // In some locales, such as Turkish, Character.toUpperCase() may return a wrong 151135f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka // character because it doesn't take care of locale. 151235f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka final String upperCaseString = new String(new int[] {code}, 0, 1) 151335f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka .toUpperCase(mSubtypeSwitcher.getInputLocale()); 151435f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka if (upperCaseString.codePointCount(0, upperCaseString.length()) == 1) { 151535f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka code = upperCaseString.codePointAt(0); 151612a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka } else { 151712a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka // Some keys, such as [eszett], have upper case as multi-characters. 151835f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka onTextInput(upperCaseString); 1519b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard if (null != ic) ic.endBatchEdit(); 152012a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka return; 152112a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka } 1522979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1523923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1524f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (mHasUncommittedTypedChars) { 15259318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mComposingStringBuilder.append((char) code); 15269318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.add(code, keyCodes, x, y); 1527923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 15281c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani // If it's the first letter, make note of auto-caps state 15299318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa if (mWordComposer.size() == 1) { 15309318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.setAutoCapitalized(getCurrentAutoCapsState()); 1531604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.onStartComposingText(); 15321c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 1533604d80c67185954d4691ac775be59c499eee3b1csatok final CharSequence textWithUnderline = 1534604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.isAutoCorrectionIndicatorOn() 1535604d80c67185954d4691ac775be59c499eee3b1csatok ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline( 1536604d80c67185954d4691ac775be59c499eee3b1csatok this, mComposingStringBuilder) 1537604d80c67185954d4691ac775be59c499eee3b1csatok : mComposingStringBuilder; 1538604d80c67185954d4691ac775be59c499eee3b1csatok ic.setComposingText(textWithUnderline, 1); 1539923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1540d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1541923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1542e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka sendKeyChar((char)code); 1543923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1544120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (SPACE_STATE_MAGIC == spaceState 1545126698fdd256a2e3734634d3b923cabd800064baJean Chalard && mSettingsValues.isMagicSpaceSwapper(primaryCode)) { 1546b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard if (null != ic) swapSwapperAndSpaceWhileInBatchEdit(ic); 1547863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } 1548863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard 1549b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.updateShiftState(); 1550979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (LatinIME.PERF_DEBUG) measureCps(); 155117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard TextEntryState.typedCharacter((char) code, mSettingsValues.isWordSeparator(code), x, y); 1552b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard if (null != ic) ic.endBatchEdit(); 1553923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1554923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1555120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private void handleSeparator(final int primaryCode, final int x, final int y, 1556120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final int spaceState) { 1557b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleSeparator(); 1558604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.onFinishComposingText(); 15594f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 156055b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // Should dismiss the "Touch again to save" message when handling separator 1561913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) { 1562cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.cancelUpdateBigramPredictions(); 1563d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 15646558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 15656558253160e2039c87f424bd814f402ecd31de3bKen Wakasa 1566923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project boolean pickedDefault = false; 1567923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Handle separator 15681b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1569923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1570923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 1571923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1572f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (mHasUncommittedTypedChars) { 1573923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In certain languages where single quote is a separator, it's better 1574a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker // not to auto correct, but accept the typed word. For instance, 1575923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // in Italian dov' should not be expanded to dove' because the elision 1576923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // requires the last vowel to be removed. 1577f50aa193377492e9c4afb3cc6e7f3448ab5a97a4Jean Chalard final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled 1578c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa && !mInputTypeNoAutoCorrect; 157917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (shouldAutoCorrect && primaryCode != Keyboard.CODE_SINGLE_QUOTE) { 1580b5d17e52fcda39d540822e615bfb7ed5074e0034satok pickedDefault = pickDefaultSuggestion(primaryCode); 1581923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1582923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project commitTyped(ic); 1583923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1584923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 15854ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1586120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final boolean swapMagicSpace; 1587120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (SPACE_STATE_MAGIC == spaceState) { 158817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.isMagicSpaceSwapper(primaryCode)) { 1589120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard swapMagicSpace = true; 1590863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } else { 1591120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard swapMagicSpace = false; 1592b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard if (mSettingsValues.isMagicSpaceStripper(primaryCode)) { 1593b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard removeTrailingSpaceWhileInBatchEdit(ic); 1594b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard } 1595863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } 15960730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard } else { 1597120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard swapMagicSpace = false; 1598863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } 1599863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard 1600120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard sendKeyChar((char)primaryCode); 160189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 160289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (Keyboard.CODE_SPACE == primaryCode) { 1603120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (isSuggestionsRequested()) { 1604120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (maybeDoubleSpaceWhileInBatchEdit(ic)) { 1605120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_DOUBLE; 1606120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } else if (!isShowingPunctuationList()) { 1607120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_WEAK; 1608120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1609126698fdd256a2e3734634d3b923cabd800064baJean Chalard } 1610120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 1611120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mHandler.startDoubleSpacesTimer(); 161289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (!isCursorTouchingWord()) { 161389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.cancelUpdateSuggestions(); 1614cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.postUpdateBigramPredictions(); 161589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 161689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 1617120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (swapMagicSpace) { 1618120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard swapSwapperAndSpaceWhileInBatchEdit(ic); 1619120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_MAGIC; 1620120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1621120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 162289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // Set punctuation right away. onUpdateSelection will fire but tests whether it is 162389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // already displayed or not, so it's okay. 162455b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka setPunctuationSuggestions(); 1625923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1626120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 1627120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard TextEntryState.typedCharacter((char) primaryCode, true, x, y); 1628120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 1629120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (pickedDefault) { 1630120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard CharSequence typedWord = mWordComposer.getTypedWord(); 1631120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard TextEntryState.backToAcceptedDefault(typedWord); 1632120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (!TextUtils.isEmpty(typedWord) && !typedWord.equals(mBestWord)) { 1633120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard InputConnectionCompatUtils.commitCorrection( 1634120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic, mLastSelectionEnd - typedWord.length(), typedWord, mBestWord); 1635120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1636120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1637b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 1638923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1639923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1640923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1641923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1642466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1643923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleClose() { 1644923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project commitTyped(getCurrentInputConnection()); 1645b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleClose(); 1646923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project requestHideSelf(0); 1647c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 16481679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka if (inputView != null) 16491679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka inputView.closing(); 1650923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1651923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 16527a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isSuggestionsRequested() { 1653c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka return mIsSettingsSuggestionStripOn 1654c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka && (mCorrectionMode > 0 || isShowingSuggestionsStrip()); 1655923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1656a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 16577a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isShowingPunctuationList() { 1658cb8cb95d0afd340de9f1a0e15948f0068d2450bcKen Wakasa if (mSuggestionsView == null) return false; 1659913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka return mSettingsValues.mSuggestPuncList == mSuggestionsView.getSuggestions(); 16607599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 16617599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 16627a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isShowingSuggestionsStrip() { 16637599cfea4a2d56f4779452ec8e8742f7b9629cc0satok return (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_VALUE) 16647599cfea4a2d56f4779452ec8e8742f7b9629cc0satok || (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE 166538f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka && mDisplayOrientation == Configuration.ORIENTATION_PORTRAIT); 16667599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 16677599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 1668913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka public boolean isSuggestionsStripVisible() { 1669913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView == null) 1670b5e00d5841b946de8970875231456228ae0eb6b1Ken Wakasa return false; 1671d0c5f9395a1b94e8425982e353d090f972dc44f0Jean Chalard if (mSuggestionsView.isShowingAddToDictionaryHint()) 16729fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 16739fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (!isShowingSuggestionsStrip()) 16749fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return false; 16759fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (mApplicationSpecifiedCompletionOn) 16769fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 16779fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return isSuggestionsRequested(); 1678923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1679923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1680409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void switchToKeyboardView() { 1681060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (DEBUG) { 1682060efb6d82af1f896d90cb845c8ae07c726f85e1satok Log.d(TAG, "Switch to keyboard view."); 1683060efb6d82af1f896d90cb845c8ae07c726f85e1satok } 1684c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka View v = mKeyboardSwitcher.getKeyboardView(); 1685060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (v != null) { 1686060efb6d82af1f896d90cb845c8ae07c726f85e1satok // Confirms that the keyboard view doesn't have parent view. 1687060efb6d82af1f896d90cb845c8ae07c726f85e1satok ViewParent p = v.getParent(); 1688060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (p != null && p instanceof ViewGroup) { 1689060efb6d82af1f896d90cb845c8ae07c726f85e1satok ((ViewGroup) p).removeView(v); 16905a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka } 1691060efb6d82af1f896d90cb845c8ae07c726f85e1satok setInputView(v); 1692060efb6d82af1f896d90cb845c8ae07c726f85e1satok } 1693913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShown(isSuggestionsStripVisible()); 1694060efb6d82af1f896d90cb845c8ae07c726f85e1satok updateInputViewShown(); 1695060efb6d82af1f896d90cb845c8ae07c726f85e1satok mHandler.postUpdateSuggestions(); 1696466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1697466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1698409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void clearSuggestions() { 16997e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(SuggestedWords.EMPTY); 1700466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1701466741d8a78965b8509bf527344f289e50873092Mike LeBeau 17027e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka public void setSuggestions(SuggestedWords words) { 1703913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) { 1704913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.setSuggestions(words); 17055e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka mKeyboardSwitcher.onAutoCorrectionStateChanged( 17065e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka words.hasWordAboveAutoCorrectionScoreThreshold()); 1707466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1708ec780e2868962bf17f0dfd35d36895f543bde40asatok 1709ec780e2868962bf17f0dfd35d36895f543bde40asatok // Put a blue underline to a word in TextView which will be auto-corrected. 1710ec780e2868962bf17f0dfd35d36895f543bde40asatok final InputConnection ic = getCurrentInputConnection(); 1711604d80c67185954d4691ac775be59c499eee3b1csatok if (ic != null) { 1712604d80c67185954d4691ac775be59c499eee3b1csatok final boolean oldAutoCorrectionIndicator = 1713604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.isAutoCorrectionIndicatorOn(); 1714604d80c67185954d4691ac775be59c499eee3b1csatok final boolean newAutoCorrectionIndicator = Utils.willAutoCorrect(words); 1715604d80c67185954d4691ac775be59c499eee3b1csatok if (oldAutoCorrectionIndicator != newAutoCorrectionIndicator) { 1716fe2d90798ea409ee39d6f63942eb01bb7eed98e3satok if (LatinImeLogger.sDBG) { 1717fe2d90798ea409ee39d6f63942eb01bb7eed98e3satok Log.d(TAG, "Flip the indicator. " + oldAutoCorrectionIndicator 1718fe2d90798ea409ee39d6f63942eb01bb7eed98e3satok + " -> " + newAutoCorrectionIndicator); 1719fe2d90798ea409ee39d6f63942eb01bb7eed98e3satok } 1720604d80c67185954d4691ac775be59c499eee3b1csatok final CharSequence textWithUnderline = newAutoCorrectionIndicator 1721604d80c67185954d4691ac775be59c499eee3b1csatok ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline( 1722604d80c67185954d4691ac775be59c499eee3b1csatok this, mComposingStringBuilder) 1723604d80c67185954d4691ac775be59c499eee3b1csatok : mComposingStringBuilder; 1724604d80c67185954d4691ac775be59c499eee3b1csatok if (!TextUtils.isEmpty(textWithUnderline)) { 1725604d80c67185954d4691ac775be59c499eee3b1csatok ic.setComposingText(textWithUnderline, 1); 1726604d80c67185954d4691ac775be59c499eee3b1csatok } 1727604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.setAutoCorrectionIndicatorOn(newAutoCorrectionIndicator); 1728ec780e2868962bf17f0dfd35d36895f543bde40asatok } 1729ec780e2868962bf17f0dfd35d36895f543bde40asatok } 1730466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1731466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1732409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void updateSuggestions() { 1733923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Check if we have a suggestion engine attached. 17349fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if ((mSuggest == null || !isSuggestionsRequested()) 1735b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok && !mVoiceProxy.isVoiceInputHighlighted()) { 1736923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1737923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1738466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1739cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard mHandler.cancelUpdateSuggestions(); 1740cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard mHandler.cancelUpdateBigramPredictions(); 1741cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard 1742f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (!mHasUncommittedTypedChars) { 1743ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setPunctuationSuggestions(); 1744923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1745923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1746979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 17479318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa final WordComposer wordComposer = mWordComposer; 17489f67e12a0e3f77985fb8bafe0db4c00e32317b9asatok // TODO: May need a better way of retrieving previous word 174940f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final InputConnection ic = getCurrentInputConnection(); 175040f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final CharSequence prevWord; 175140f7efc172928bdd6048e91421a766abe5b22996Jean Chalard if (null == ic) { 175240f7efc172928bdd6048e91421a766abe5b22996Jean Chalard prevWord = null; 175340f7efc172928bdd6048e91421a766abe5b22996Jean Chalard } else { 175440f7efc172928bdd6048e91421a766abe5b22996Jean Chalard prevWord = EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators); 175540f7efc172928bdd6048e91421a766abe5b22996Jean Chalard } 175640f7efc172928bdd6048e91421a766abe5b22996Jean Chalard // getSuggestedWordBuilder handles gracefully a null value of prevWord 175740f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder( 1758904baab25a4c6ec5d9c4bf7e562154e3f544d296satok wordComposer, prevWord, mKeyboardSwitcher.getLatinKeyboard().getProximityInfo()); 1759923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 17608558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa boolean autoCorrectionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasAutoCorrection(); 17619318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa final CharSequence typedWord = wordComposer.getTypedWord(); 1762bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // Here, we want to promote a whitelisted word if exists. 17635f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard // TODO: Change this scheme - a boolean is not enough. A whitelisted word may be "valid" 17645f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard // but still autocorrected from - in the case the whitelist only capitalizes the word. 17655f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard // The whitelist should be case-insensitive, so it's not possible to be consistent with 17665f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard // a boolean flag. Right now this is handled with a slight hack in 17675f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard // WhitelistDictionary#shouldForciblyAutoCorrectFrom. 17685f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard final boolean allowsToBeAutoCorrected = AutoCorrection.allowsToBeAutoCorrected( 1769bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok mSuggest.getUnigramDictionaries(), typedWord, preferCapitalization()); 1770979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mCorrectionMode == Suggest.CORRECTION_FULL 1771979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) { 17725f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard autoCorrectionAvailable |= (!allowsToBeAutoCorrected); 1773923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 17744a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani // Don't auto-correct words with multiple capital letter 17758558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa autoCorrectionAvailable &= !wordComposer.isMostlyCaps(); 1776979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1777a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // Basically, we update the suggestion strip only when suggestion count > 1. However, 1778a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // there is an exception: We update the suggestion strip whenever typed word's length 1779f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // is 1 or typed word is found in dictionary, regardless of suggestion count. Actually, 1780f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // in most cases, suggestion count is 1 when typed word's length is 1, but we do always 1781f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // need to clear the previous state when the user starts typing a word (i.e. typed word's 1782f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // length == 1). 1783fe1a6d961cf039357f061482461e4d2e951ad346satok if (typedWord != null) { 17845f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard if (builder.size() > 1 || typedWord.length() == 1 || (!allowsToBeAutoCorrected) 1785913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka || mSuggestionsView.isShowingAddToDictionaryHint()) { 17865f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard builder.setTypedWordValid(!allowsToBeAutoCorrected).setHasMinimalSuggestion( 17878558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa autoCorrectionAvailable); 1788fe1a6d961cf039357f061482461e4d2e951ad346satok } else { 1789074cda4d266b5d034d4348961c9183e32b16af5asatok SuggestedWords previousSuggestions = mSuggestionsView.getSuggestions(); 1790074cda4d266b5d034d4348961c9183e32b16af5asatok if (previousSuggestions == mSettingsValues.mSuggestPuncList) { 1791074cda4d266b5d034d4348961c9183e32b16af5asatok if (builder.size() == 0) { 1792074cda4d266b5d034d4348961c9183e32b16af5asatok return; 1793074cda4d266b5d034d4348961c9183e32b16af5asatok } 1794074cda4d266b5d034d4348961c9183e32b16af5asatok previousSuggestions = SuggestedWords.EMPTY; 1795074cda4d266b5d034d4348961c9183e32b16af5asatok } 1796fe1a6d961cf039357f061482461e4d2e951ad346satok builder.addTypedWordAndPreviousSuggestions(typedWord, previousSuggestions); 1797fe1a6d961cf039357f061482461e4d2e951ad346satok } 17989fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka } 17997e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka showSuggestions(builder.build(), typedWord); 1800979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 18014a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani 18029fbfd5877305ed19a20663630b498b6b3fdae942satok public void showSuggestions(SuggestedWords suggestedWords, CharSequence typedWord) { 18032aa1dd45c44295e2f7e8ece1b520032d86b9f908satok final boolean shouldBlockAutoCorrectionBySafetyNet = 18042aa1dd45c44295e2f7e8ece1b520032d86b9f908satok Utils.shouldBlockAutoCorrectionBySafetyNet(suggestedWords, mSuggest); 18052aa1dd45c44295e2f7e8ece1b520032d86b9f908satok if (shouldBlockAutoCorrectionBySafetyNet) { 18062aa1dd45c44295e2f7e8ece1b520032d86b9f908satok suggestedWords.setShouldBlockAutoCorrection(); 18072aa1dd45c44295e2f7e8ece1b520032d86b9f908satok } 18087e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(suggestedWords); 18097e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka if (suggestedWords.size() > 0) { 18102aa1dd45c44295e2f7e8ece1b520032d86b9f908satok if (shouldBlockAutoCorrectionBySafetyNet) { 181182411d47ba7e8133ed2390c6920945e139a738cesatok mBestWord = typedWord; 181282411d47ba7e8133ed2390c6920945e139a738cesatok } else if (suggestedWords.hasAutoCorrectionWord()) { 18137e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka mBestWord = suggestedWords.getWord(1); 1814923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1815923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = typedWord; 1816923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1817923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1818923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = null; 1819923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1820913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShown(isSuggestionsStripVisible()); 1821923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1822923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1823b5d17e52fcda39d540822e615bfb7ed5074e0034satok private boolean pickDefaultSuggestion(int separatorCode) { 1824913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka // Complete any pending suggestions query first 1825d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka if (mHandler.hasPendingUpdateSuggestions()) { 1826d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 1827923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateSuggestions(); 1828923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 18296780b898ec2647a21319601a03ae1c393c0e1b29Amith Yamasani if (mBestWord != null && mBestWord.length() > 0) { 18309318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa TextEntryState.acceptedDefault(mWordComposer.getTypedWord(), mBestWord, separatorCode); 18314733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 18321fef530ec7626fa16777f52b48191e61db8f46d4satok commitBestWord(mBestWord); 1833f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard // Add the word to the user unigram dictionary if it's not a known word 1834f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard addToUserUnigramAndBigramDictionaries(mBestWord, 1835f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard UserUnigramDictionary.FREQUENCY_FOR_TYPED); 1836979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return true; 1837923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1838979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return false; 1839923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1840923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1841c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka @Override 1842923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void pickSuggestionManually(int index, CharSequence suggestion) { 1843604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.onFinishComposingText(); 1844913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka SuggestedWords suggestions = mSuggestionsView.getSuggestions(); 184517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mVoiceProxy.flushAndLogAllTextModificationCounters(index, suggestion, 184617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mWordSeparators); 18474f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 18489351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 18499a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 18509a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.beginBatchEdit(); 18519a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 18521b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (mApplicationSpecifiedCompletionOn && mApplicationSpecifiedCompletions != null 18531b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka && index >= 0 && index < mApplicationSpecifiedCompletions.length) { 1854923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 18559351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index]; 18569351550dc6af7859e5280e16144c9386a37b976dKen Wakasa ic.commitCompletion(completionInfo); 1857923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1858923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCommittedLength = suggestion.length(); 1859913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) { 1860913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.clear(); 1861923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1862b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 18639a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 18649a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 18659a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1866923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1867923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 18686a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 18696a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani // If this is a punctuation, apply it through the normal key press 187017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (suggestion.length() == 1 && (mSettingsValues.isWordSeparator(suggestion.charAt(0)) 187117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard || mSettingsValues.isSuggestedPunctuation(suggestion.charAt(0)))) { 1872979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Word separators are suggested before the user inputs something. 1873979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // So, LatinImeLogger logs "" as a user's input. 1874979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.logOnManualSuggestion( 18757e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka "", suggestion.toString(), index, suggestions.mWords); 1876863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // Find out whether the previous character is a space. If it is, as a special case 1877120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // for punctuation entered through the suggestion strip, it should be swapped 1878120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // if it was a magic or a weak space. This is meant to help in case the user 1879863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // pressed space on purpose of displaying the suggestion strip punctuation. 188083ffff2a49beeb41874b7cb40819a75001f708e2Ken Wakasa final int rawPrimaryCode = suggestion.charAt(0); 188183ffff2a49beeb41874b7cb40819a75001f708e2Ken Wakasa // Maybe apply the "bidi mirrored" conversions for parentheses 188283ffff2a49beeb41874b7cb40819a75001f708e2Ken Wakasa final LatinKeyboard keyboard = mKeyboardSwitcher.getLatinKeyboard(); 188349426a1ea941c0331a6e573e36cff3c3a8e8849cTadashi G. Takaoka final boolean isRtl = keyboard != null && keyboard.mIsRtlKeyboard; 188449426a1ea941c0331a6e573e36cff3c3a8e8849cTadashi G. Takaoka final int primaryCode = Key.getRtlParenthesisCode(rawPrimaryCode, isRtl); 188583ffff2a49beeb41874b7cb40819a75001f708e2Ken Wakasa 1886120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard insertPunctuationFromSuggestionStrip(ic, primaryCode); 1887120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // TODO: the following endBatchEdit seems useless, check 18889a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 18899a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 18909a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 18916a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani return; 18926a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 1893f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (!mHasUncommittedTypedChars) { 189489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // If we are not composing a word, then it was a suggestion inferred from 189589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // context - no user input. We should reset the word composer. 18969318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.reset(); 189789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 18984733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 18991fef530ec7626fa16777f52b48191e61db8f46d4satok commitBestWord(suggestion); 19009468335a06d2b0e3ef15f4f57f8c1b0857b34ebeAmith Yamasani // Add the word to the auto dictionary if it's not a known word 19010c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani if (index == 0) { 1902f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard addToUserUnigramAndBigramDictionaries(suggestion, 1903f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard UserUnigramDictionary.FREQUENCY_FOR_PICKED); 1904979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } else { 1905bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok addToOnlyBigramDictionary(suggestion, 1); 19060c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani } 19079318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa LatinImeLogger.logOnManualSuggestion(mComposingStringBuilder.toString(), 19089318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa suggestion.toString(), index, suggestions.mWords); 19099318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa TextEntryState.acceptedSuggestion(mComposingStringBuilder.toString(), suggestion); 1910923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Follow it with a space 1911d0c5f9395a1b94e8425982e353d090f972dc44f0Jean Chalard if (mInsertSpaceOnPickSuggestionManually) { 19120730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard sendMagicSpace(); 1913923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1914979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1915c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa // We should show the "Touch again to save" hint if the user pressed the first entry 1916c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa // AND either: 19177f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // - There is no dictionary (we know that because we tried to load it => null != mSuggest 1918c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa // AND mSuggest.hasMainDictionary() is false) 19197f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // - There is a dictionary and the word is not in it 19207f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // Please note that if mSuggest is null, it means that everything is off: suggestion 19217f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // and correction, so we shouldn't try to show the hint 19227f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // We used to look at mCorrectionMode here, but showing the hint should have nothing 19237f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // to do with the autocorrection setting. 1924bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok final boolean showingAddToDictionaryHint = index == 0 && mSuggest != null 1925bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // If there is no dictionary the hint should be shown. 1926c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa && (!mSuggest.hasMainDictionary() 1927bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // If "suggestion" is not in the dictionary, the hint should be shown. 1928bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok || !AutoCorrection.isValidWord( 1929bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok mSuggest.getUnigramDictionaries(), suggestion, true)); 1930b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani 1931d0c5f9395a1b94e8425982e353d090f972dc44f0Jean Chalard // Fool the state watcher so that a subsequent backspace will not do a revert, unless 1932d0c5f9395a1b94e8425982e353d090f972dc44f0Jean Chalard // we just did a correction, in which case we need to stay in 1933d0c5f9395a1b94e8425982e353d090f972dc44f0Jean Chalard // TextEntryState.State.PICKED_SUGGESTION state. 1934d0c5f9395a1b94e8425982e353d090f972dc44f0Jean Chalard TextEntryState.typedCharacter((char) Keyboard.CODE_SPACE, true, 1935d0c5f9395a1b94e8425982e353d090f972dc44f0Jean Chalard WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); 1936777118a40a363ccab69a00016d3156066513cb78Jean Chalard if (!showingAddToDictionaryHint) { 1937364da8c618303a7764595d2c15ee034a7671365dKen Wakasa // If we're not showing the "Touch again to save", then show corrections again. 1938979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // In case the cursor position doesn't change, make sure we show the suggestions again. 193941ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard updateBigramPredictions(); 194041ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // Updating the predictions right away may be slow and feel unresponsive on slower 194141ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // terminals. On the other hand if we just postUpdateBigramPredictions() it will 194241ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // take a noticeable delay to update them which may feel uneasy. 1943979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1944b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani if (showingAddToDictionaryHint) { 1945ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka if (mIsUserDictionaryAvaliable) { 1946644d33d60ea5a87501274488013d65f55238895eKen Wakasa mSuggestionsView.showAddToDictionaryHint( 1947644d33d60ea5a87501274488013d65f55238895eKen Wakasa suggestion, mSettingsValues.mHintToSaveText); 1948ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka } else { 1949ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1950ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka } 195166a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani } 19529a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 19539a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 19549a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1955923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1956a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1957979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 19588558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa * Commits the chosen word to the text field and saves it for later retrieval. 1959979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 19601fef530ec7626fa16777f52b48191e61db8f46d4satok private void commitBestWord(CharSequence bestWord) { 19619351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final KeyboardSwitcher switcher = mKeyboardSwitcher; 1962b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (!switcher.isKeyboardAvailable()) 19631679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka return; 19649351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 1965923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 19661fef530ec7626fa16777f52b48191e61db8f46d4satok mVoiceProxy.rememberReplacedWord(bestWord, mSettingsValues.mWordSeparators); 19671531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard if (mSettingsValues.mEnableSuggestionSpanInsertion) { 19681531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions(); 19691531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard ic.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan( 19701531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard this, bestWord, suggestedWords), 1); 19711531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard } else { 19721531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard ic.commitText(bestWord, 1); 19731531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard } 1974923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1975f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = false; 19761fef530ec7626fa16777f52b48191e61db8f46d4satok mCommittedLength = bestWord.length(); 1977923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1978923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 197989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard private static final WordComposer sEmptyWordComposer = new WordComposer(); 198041ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard public void updateBigramPredictions() { 198189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (mSuggest == null || !isSuggestionsRequested()) 198289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard return; 198389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 198417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (!mSettingsValues.mBigramPredictionEnabled) { 1985cb3320179d39a7983874697a0aa428b127675c9dJean Chalard setPunctuationSuggestions(); 1986cb3320179d39a7983874697a0aa428b127675c9dJean Chalard return; 1987cb3320179d39a7983874697a0aa428b127675c9dJean Chalard } 1988cb3320179d39a7983874697a0aa428b127675c9dJean Chalard 198989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard final CharSequence prevWord = EditingUtils.getThisWord(getCurrentInputConnection(), 199017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mWordSeparators); 1991904baab25a4c6ec5d9c4bf7e562154e3f544d296satok SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(sEmptyWordComposer, 1992904baab25a4c6ec5d9c4bf7e562154e3f544d296satok prevWord, mKeyboardSwitcher.getLatinKeyboard().getProximityInfo()); 199389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 199489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (builder.size() > 0) { 199589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // Explicitly supply an empty typed word (the no-second-arg version of 199689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // showSuggestions will retrieve the word near the cursor, we don't want that here) 199789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard showSuggestions(builder.build(), ""); 199889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 199989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (!isShowingPunctuationList()) setPunctuationSuggestions(); 200089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 200189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 200289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 20037a8dac55278cedd838be325f56b4c52d973c61f5satok public void setPunctuationSuggestions() { 200417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard setSuggestions(mSettingsValues.mSuggestPuncList); 2005913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShown(isSuggestionsStripVisible()); 20066a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 20076a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 2008f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard private void addToUserUnigramAndBigramDictionaries(CharSequence suggestion, 2009f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard int frequencyDelta) { 2010979f8690967ff5409fe18f5085858ccdb8e0ccf1satok checkAddToDictionary(suggestion, frequencyDelta, false); 2011979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 2012979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2013bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok private void addToOnlyBigramDictionary(CharSequence suggestion, int frequencyDelta) { 2014979f8690967ff5409fe18f5085858ccdb8e0ccf1satok checkAddToDictionary(suggestion, frequencyDelta, true); 2015979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 2016979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2017979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 2018f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard * Adds to the UserBigramDictionary and/or UserUnigramDictionary 2019bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok * @param selectedANotTypedWord true if it should be added to bigram dictionary if possible 2020979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 2021979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void checkAddToDictionary(CharSequence suggestion, int frequencyDelta, 2022bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok boolean selectedANotTypedWord) { 2023979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (suggestion == null || suggestion.length() < 1) return; 2024bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok 20250c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // Only auto-add to dictionary if auto-correct is ON. Otherwise we'll be 20260c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // adding words in situations where the user or application really didn't 20270c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // want corrections enabled or learned. 2028979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (!(mCorrectionMode == Suggest.CORRECTION_FULL 2029979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM)) { 2030979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return; 2031979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 2032bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok 20335955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard if (null != mSuggest && null != mUserUnigramDictionary) { 20345955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard final boolean selectedATypedWordAndItsInUserUnigramDic = 20355955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard !selectedANotTypedWord && mUserUnigramDictionary.isValidWord(suggestion); 20365955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard final boolean isValidWord = AutoCorrection.isValidWord( 20375955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard mSuggest.getUnigramDictionaries(), suggestion, true); 20385955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard final boolean needsToAddToUserUnigramDictionary = 20395955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard selectedATypedWordAndItsInUserUnigramDic || !isValidWord; 20405955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard if (needsToAddToUserUnigramDictionary) { 20415955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard mUserUnigramDictionary.addWord(suggestion.toString(), frequencyDelta); 20425955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard } 2043e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 2044979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2045e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mUserBigramDictionary != null) { 2046863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // We don't want to register as bigrams words separated by a separator. 2047863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // For example "I will, and you too" : we don't want the pair ("will" "and") to be 2048863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // a bigram. 204940f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final InputConnection ic = getCurrentInputConnection(); 205040f7efc172928bdd6048e91421a766abe5b22996Jean Chalard if (null != ic) { 205140f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final CharSequence prevWord = 205240f7efc172928bdd6048e91421a766abe5b22996Jean Chalard EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators); 205340f7efc172928bdd6048e91421a766abe5b22996Jean Chalard if (!TextUtils.isEmpty(prevWord)) { 205440f7efc172928bdd6048e91421a766abe5b22996Jean Chalard mUserBigramDictionary.addBigrams(prevWord.toString(), suggestion.toString()); 205540f7efc172928bdd6048e91421a766abe5b22996Jean Chalard } 2056979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 205732e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 205832e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 205932e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani 20607a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isCursorTouchingWord() { 20619351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 2062923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return false; 2063923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence toLeft = ic.getTextBeforeCursor(1, 0); 2064923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence toRight = ic.getTextAfterCursor(1, 0); 2065923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (!TextUtils.isEmpty(toLeft) 206617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isWordSeparator(toLeft.charAt(0)) 206717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isSuggestedPunctuation(toLeft.charAt(0))) { 2068923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 2069923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2070a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker if (!TextUtils.isEmpty(toRight) 207117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isWordSeparator(toRight.charAt(0)) 207217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isSuggestedPunctuation(toRight.charAt(0))) { 2073923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 2074923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2075923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return false; 2076923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2077a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2078120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // "ic" must not be null 20799351550dc6af7859e5280e16144c9386a37b976dKen Wakasa private boolean sameAsTextBeforeCursor(final InputConnection ic, CharSequence text) { 2080dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani CharSequence beforeText = ic.getTextBeforeCursor(text.length(), 0); 2081dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani return TextUtils.equals(text, beforeText); 2082dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani } 2083dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 2084120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // "ic" must not be null 20859351550dc6af7859e5280e16144c9386a37b976dKen Wakasa private void revertLastWord(final InputConnection ic) { 20868558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa if (mHasUncommittedTypedChars || mComposingStringBuilder.length() <= 0) { 2087923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 20888558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa return; 20898558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa } 20908558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa 20919351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final CharSequence separator = ic.getTextBeforeCursor(1, 0); 209220c4aec82719b5e9b5ddfa990970f19d399aaa2cKen Wakasa ic.deleteSurroundingText(1, 0); 209320c4aec82719b5e9b5ddfa990970f19d399aaa2cKen Wakasa final CharSequence textToTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0); 209420c4aec82719b5e9b5ddfa990970f19d399aaa2cKen Wakasa ic.deleteSurroundingText(mCommittedLength, 0); 20959351550dc6af7859e5280e16144c9386a37b976dKen Wakasa 20969351550dc6af7859e5280e16144c9386a37b976dKen Wakasa // Re-insert "separator" only when the deleted character was word separator and the 20979351550dc6af7859e5280e16144c9386a37b976dKen Wakasa // composing text wasn't equal to the auto-corrected text which can be found before 20989351550dc6af7859e5280e16144c9386a37b976dKen Wakasa // the cursor. 20999351550dc6af7859e5280e16144c9386a37b976dKen Wakasa if (!TextUtils.isEmpty(separator) 21009351550dc6af7859e5280e16144c9386a37b976dKen Wakasa && mSettingsValues.isWordSeparator(separator.charAt(0)) 210120c4aec82719b5e9b5ddfa990970f19d399aaa2cKen Wakasa && !TextUtils.equals(mComposingStringBuilder, textToTheLeft)) { 21028558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa ic.commitText(mComposingStringBuilder, 1); 21038558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa TextEntryState.acceptedTyped(mComposingStringBuilder); 21049351550dc6af7859e5280e16144c9386a37b976dKen Wakasa ic.commitText(separator, 1); 21059351550dc6af7859e5280e16144c9386a37b976dKen Wakasa TextEntryState.typedCharacter(separator.charAt(0), true, 21068558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); 21078558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa // Clear composing text 21088558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa mComposingStringBuilder.setLength(0); 21098558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa } else { 21108558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa mHasUncommittedTypedChars = true; 21118558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa ic.setComposingText(mComposingStringBuilder, 1); 21128558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa TextEntryState.backspace(); 2113923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 21148558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa mHandler.cancelUpdateBigramPredictions(); 21158558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa mHandler.postUpdateSuggestions(); 2116923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2117923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2118120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // "ic" must not be null 21199351550dc6af7859e5280e16144c9386a37b976dKen Wakasa private boolean revertDoubleSpace(final InputConnection ic) { 21204733609947c0ec74e460bd714fffca0518ade93aJean Chalard mHandler.cancelDoubleSpacesTimer(); 21214733609947c0ec74e460bd714fffca0518ade93aJean Chalard // Here we test whether we indeed have a period and a space before us. This should not 21224733609947c0ec74e460bd714fffca0518ade93aJean Chalard // be needed, but it's there just in case something went wrong. 21234733609947c0ec74e460bd714fffca0518ade93aJean Chalard final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0); 21244733609947c0ec74e460bd714fffca0518ade93aJean Chalard if (!". ".equals(textBeforeCursor)) 21254733609947c0ec74e460bd714fffca0518ade93aJean Chalard return false; 21264733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.beginBatchEdit(); 21274733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.deleteSurroundingText(2, 0); 21284733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.commitText(" ", 1); 21294733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.endBatchEdit(); 21304733609947c0ec74e460bd714fffca0518ade93aJean Chalard return true; 21314733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 21324733609947c0ec74e460bd714fffca0518ade93aJean Chalard 2133120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private boolean revertSwapPunctuation(final InputConnection ic) { 2134120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Here we test whether we indeed have a space and something else before us. This should not 2135120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // be needed, but it's there just in case something went wrong. 2136120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0); 2137120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // NOTE: This does not work with surrogate pairs. Hopefully when the keyboard is able to 2138120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // enter surrogate pairs this code will have been removed. 2139120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (Keyboard.CODE_SPACE != textBeforeCursor.charAt(1)) 2140120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return false; 2141120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.beginBatchEdit(); 2142120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.deleteSurroundingText(2, 0); 2143120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.commitText(" " + textBeforeCursor.subSequence(0, 1), 1); 2144120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.endBatchEdit(); 2145120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return true; 2146120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 2147120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 2148923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean isWordSeparator(int code) { 214917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard return mSettingsValues.isWordSeparator(code); 2150923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2151923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 21520730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard private void sendMagicSpace() { 2153571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka sendKeyChar((char)Keyboard.CODE_SPACE); 2154120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_MAGIC; 2155b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 2156923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2157923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2158923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean preferCapitalization() { 21599318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa return mWordComposer.isFirstCharCapitalized(); 2160923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2161923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 216288fc9d44186120f9edc5cf7ec0e2af85260fed04satok // Notify that language or mode have been changed and toggleLanguage will update KeyboardID 2163c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // according to new language or mode. 2164c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka public void onRefreshKeyboard() { 216555303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka if (!CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) { 216655303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka // Before Honeycomb, Voice IME is in LatinIME and it changes the current input view, 216755303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka // so that we need to re-create the keyboard input view here. 216855303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka setInputView(mKeyboardSwitcher.onCreateInputView()); 216955303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka } 21704ab730dbd34fad323063f2ffd31ce33de746668dsatok // Reload keyboard because the current language has been changed. 2171255486a5d067469e074f3649b3d2747e7a08aaa2Tadashi G. Takaoka mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettingsValues); 21720ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 217317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard loadSettings(); 217436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 217536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 2176d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka private void hapticAndAudioFeedback(int primaryCode) { 2177d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka vibrate(); 2178d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka playKeyClick(primaryCode); 2179d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka } 2180d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka 21815a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 2182e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka public void onPress(int primaryCode, boolean withSliding) { 2183055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 2184055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka if (switcher.isVibrateAndSoundFeedbackRequired()) { 2185d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka hapticAndAudioFeedback(primaryCode); 2186cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka } 21871679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); 2188571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { 2189e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka switcher.onPressShift(withSliding); 2190e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { 21916c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka switcher.onPressSymbol(); 219240a05f62edc6cdedb4365a722b48a72826ef2bf6Tadashi G. Takaoka } else { 21936c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka switcher.onOtherKeyPressed(); 2194681b102a492b7d5301c1ca87985b4c391eb5eb14Tadashi G. Takaoka } 2195923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2196923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 21975a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 2198e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka public void onRelease(int primaryCode, boolean withSliding) { 21991679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 22003f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani // Reset any drag flags in the keyboard 22011679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); 2202571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { 2203e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka switcher.onReleaseShift(withSliding); 2204e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { 22056c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka switcher.onReleaseSymbol(); 220640a05f62edc6cdedb4365a722b48a72826ef2bf6Tadashi G. Takaoka } 2207923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2208a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2209a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2210123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka // receive ringer mode change and network state change. 2211923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private BroadcastReceiver mReceiver = new BroadcastReceiver() { 2212923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 2213923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onReceive(Context context, Intent intent) { 2214123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final String action = intent.getAction(); 2215123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { 2216123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka updateRingerMode(); 2217123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 2218123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka mSubtypeSwitcher.onNetworkStateChanged(intent); 2219123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka } 2220923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2221923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project }; 2222923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 222379c0acf51984256d640b38ea3c394f308cc3b314satok // update keypress sound volume 2224bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa private void updateSoundEffectVolume() { 222579c0acf51984256d640b38ea3c394f308cc3b314satok mFxVolume = Utils.getCurrentKeypressSoundVolume(mPrefs, mResources); 2226bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa } 2227bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa 2228923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // update flags for silent mode 2229923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void updateRingerMode() { 2230923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager == null) { 2231923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 2232bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa if (mAudioManager == null) return; 2233923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2234bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa mSilentModeOn = (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL); 2235923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2236923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 223728f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa private void updateKeypressVibrationDuration() { 2238433965784dca1a2cd801e1aab8c8258f64d8c7e0satok mKeypressVibrationDuration = Utils.getCurrentVibrationDuration(mPrefs, mResources); 223928f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa } 224028f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa 2241923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void playKeyClick(int primaryCode) { 2242923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // if mAudioManager is null, we don't have the ringer state yet 2243923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // mAudioManager will be set by updateRingerMode 2244923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager == null) { 2245c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka if (mKeyboardSwitcher.getKeyboardView() != null) { 2246923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateRingerMode(); 2247923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2248923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 224917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (isSoundOn()) { 2250f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa final int sound; 2251923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 2252f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa case Keyboard.CODE_DELETE: 2253f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa sound = AudioManager.FX_KEYPRESS_DELETE; 2254f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa break; 2255f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa case Keyboard.CODE_ENTER: 2256f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa sound = AudioManager.FX_KEYPRESS_RETURN; 2257f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa break; 2258f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa case Keyboard.CODE_SPACE: 2259f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa sound = AudioManager.FX_KEYPRESS_SPACEBAR; 2260f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa break; 2261f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa default: 2262f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa sound = AudioManager.FX_KEYPRESS_STANDARD; 2263f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa break; 2264923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2265bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa mAudioManager.playSoundEffect(sound, mFxVolume); 2266923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2267923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2268923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2269409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void vibrate() { 227017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (!mSettingsValues.mVibrateOn) { 2271923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 2272923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 227328f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa if (mKeypressVibrationDuration < 0) { 227428f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa // Go ahead with the system default 227528f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 227628f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa if (inputView != null) { 227728f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa inputView.performHapticFeedback( 227828f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa HapticFeedbackConstants.KEYBOARD_TAP, 227928f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); 228028f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa } 228128f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa } else if (mVibrator != null) { 228228f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa mVibrator.vibrate(mKeypressVibrationDuration); 2283923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2284923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2285923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 228671c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka public WordComposer getCurrentWord() { 22879318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa return mWordComposer; 22886516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani } 22896516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani 229017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard boolean isSoundOn() { 229117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard return mSettingsValues.mSoundOn && !mSilentModeOn; 2292979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 2293979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2294e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private void updateCorrectionMode() { 22959f67e12a0e3f77985fb8bafe0db4c00e32317b9asatok // TODO: cleanup messy flags 2296f50aa193377492e9c4afb3cc6e7f3448ab5a97a4Jean Chalard final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled 2297c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa && !mInputTypeNoAutoCorrect; 229817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mCorrectionMode = (shouldAutoCorrect && mSettingsValues.mAutoCorrectEnabled) 2299e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani ? Suggest.CORRECTION_FULL 230017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard : (shouldAutoCorrect ? Suggest.CORRECTION_BASIC : Suggest.CORRECTION_NONE); 230117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mCorrectionMode = (mSettingsValues.mBigramSuggestionEnabled && shouldAutoCorrect 230217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && mSettingsValues.mAutoCorrectEnabled) 2303979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ? Suggest.CORRECTION_FULL_BIGRAM : mCorrectionMode; 2304e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani if (mSuggest != null) { 2305e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mSuggest.setCorrectionMode(mCorrectionMode); 2306e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani } 2307e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani } 2308e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani 230917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard private void updateSuggestionVisibility(final SharedPreferences prefs, final Resources res) { 23107599cfea4a2d56f4779452ec8e8742f7b9629cc0satok final String suggestionVisiblityStr = prefs.getString( 23119502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka Settings.PREF_SHOW_SUGGESTIONS_SETTING, 2312458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa res.getString(R.string.prefs_suggestion_visibility_default_value)); 23137599cfea4a2d56f4779452ec8e8742f7b9629cc0satok for (int visibility : SUGGESTION_VISIBILITY_VALUE_ARRAY) { 2314458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa if (suggestionVisiblityStr.equals(res.getString(visibility))) { 23157599cfea4a2d56f4779452ec8e8742f7b9629cc0satok mSuggestionVisibility = visibility; 23167599cfea4a2d56f4779452ec8e8742f7b9629cc0satok break; 23177599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 23187599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 23197599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 23207599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 2321466741d8a78965b8509bf527344f289e50873092Mike LeBeau protected void launchSettings() { 2322cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa launchSettingsClass(Settings.class); 2323466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 2324466741d8a78965b8509bf527344f289e50873092Mike LeBeau 2325bf96661d33d0126adb60a48880ceba1ff055d4a4satok public void launchDebugSettings() { 2326cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa launchSettingsClass(DebugSettings.class); 2327bf96661d33d0126adb60a48880ceba1ff055d4a4satok } 2328bf96661d33d0126adb60a48880ceba1ff055d4a4satok 2329cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa protected void launchSettingsClass(Class<? extends PreferenceActivity> settingsClass) { 2330923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project handleClose(); 2331923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Intent intent = new Intent(); 2332466741d8a78965b8509bf527344f289e50873092Mike LeBeau intent.setClass(LatinIME.this, settingsClass); 2333923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2334923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project startActivity(intent); 2335923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2336923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 23372fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private void showSubtypeSelectorAndSettings() { 233885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence title = getString(R.string.english_ime_input_options); 233985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence[] items = new CharSequence[] { 234085996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka // TODO: Should use new string "Select active input modes". 234185996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.language_selection_title), 234285996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.english_ime_settings), 234385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 234485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 23452fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka @Override 23462fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka public void onClick(DialogInterface di, int position) { 23472fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka di.dismiss(); 23482fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka switch (position) { 234985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 0: 23502cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok Intent intent = CompatUtils.getInputLanguageSelectionIntent( 23512cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok mInputMethodId, Intent.FLAG_ACTIVITY_NEW_TASK 23522fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 23532fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_CLEAR_TOP); 23542fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka startActivity(intent); 23552fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 2356aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa case 1: 2357aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa launchSettings(); 2358aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa break; 23592fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 23602fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 236185996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 2362bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka final AlertDialog.Builder builder = new AlertDialog.Builder(this) 2363bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setItems(items, listener) 2364bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setTitle(title); 2365bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka showOptionDialogInternal(builder.create()); 23662fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 2367923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 23682fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private void showOptionsMenu() { 236985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence title = getString(R.string.english_ime_input_options); 237085996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence[] items = new CharSequence[] { 237185996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.selectInputMethod), 237285996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.english_ime_settings), 237385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 237485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 23755a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 2376923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onClick(DialogInterface di, int position) { 2377923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project di.dismiss(); 2378923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (position) { 237985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 0: 2380ea55bf5df7d26d12b36c47141bfbac5730c3929aTadashi G. Takaoka mImm.showInputMethodPicker(); 23812fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 238285996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 1: 2383ea55bf5df7d26d12b36c47141bfbac5730c3929aTadashi G. Takaoka launchSettings(); 23842fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 2385923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2386923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 238785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 2388bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka final AlertDialog.Builder builder = new AlertDialog.Builder(this) 2389bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setItems(items, listener) 2390bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setTitle(title); 2391bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka showOptionDialogInternal(builder.create()); 2392923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2393923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 23947e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 23957e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { 2396923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.dump(fd, fout, args); 2397a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2398923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final Printer p = new PrintWriterPrinter(fout); 2399923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println("LatinIME state :"); 2400923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" Keyboard mode = " + mKeyboardSwitcher.getKeyboardMode()); 24019318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa p.println(" mComposingStringBuilder=" + mComposingStringBuilder.toString()); 24029fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka p.println(" mIsSuggestionsRequested=" + mIsSettingsSuggestionStripOn); 2403923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mCorrectionMode=" + mCorrectionMode); 2404f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard p.println(" mHasUncommittedTypedChars=" + mHasUncommittedTypedChars); 240517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mAutoCorrectEnabled=" + mSettingsValues.mAutoCorrectEnabled); 240626a531c6fe2a6e058803b7102e2bc9e7ea12d8f3Jean Chalard p.println(" mInsertSpaceOnPickSuggestionManually=" + mInsertSpaceOnPickSuggestionManually); 24071b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka p.println(" mApplicationSpecifiedCompletionOn=" + mApplicationSpecifiedCompletionOn); 2408923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" TextEntryState.state=" + TextEntryState.getState()); 240917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mSoundOn=" + mSettingsValues.mSoundOn); 241017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mVibrateOn=" + mSettingsValues.mVibrateOn); 2411240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard p.println(" mKeyPreviewPopupOn=" + mSettingsValues.mKeyPreviewPopupOn); 2412923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 24136e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani 2414923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Characters per second measurement 2415a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2416923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long mLastCpsTime; 2417923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int CPS_BUFFER_SIZE = 16; 2418923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long[] mCpsIntervals = new long[CPS_BUFFER_SIZE]; 2419923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mCpsIndex; 2420a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2421923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void measureCps() { 2422923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long now = System.currentTimeMillis(); 2423923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mLastCpsTime == 0) mLastCpsTime = now - 100; // Initial 2424923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCpsIntervals[mCpsIndex] = now - mLastCpsTime; 2425923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mLastCpsTime = now; 2426923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCpsIndex = (mCpsIndex + 1) % CPS_BUFFER_SIZE; 2427923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long total = 0; 2428923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project for (int i = 0; i < CPS_BUFFER_SIZE; i++) total += mCpsIntervals[i]; 2429923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project System.out.println("CPS = " + ((CPS_BUFFER_SIZE * 1000f) / total)); 2430923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2431923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 2432